Kayıtsız COM için bildirim dosyaları oluşturun


87

Herhangi bir genel COM kaydı gerektirmeden tam izolasyon içinde dağıtılabilmeleri için bildirim dosyalarını kullanan bazı uygulamalarım (bazıları yerel, bazı .NET) var . Örneğin, dbgrid32.ocx com sunucusuna bağımlılık, myapp.exe ile aynı klasörde bulunan myapp.exe.manifest dosyasında aşağıdaki gibi bildirilir:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
  <assemblyIdentity type="win32" name="myapp.exe" version="1.2.3.4" />
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="dbgrid32.ocx" version="5.1.81.4" />
    </dependentAssembly>
  </dependency>
</assembly>

Dbgrid32.ocx, kendi dbgrid32.ocx.manifest dosyasıyla birlikte aynı klasöre dağıtılır:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
  <assemblyIdentity type="win32" name="dbgrid32.ocx" version="5.1.81.4" />
  <file name="dbgrid32.ocx">
     <typelib
        tlbid="{00028C01-0000-0000-0000-000000000046}"
        version="1.0"
        helpdir=""/>
    <comClass progid="MSDBGrid.DBGrid"
       clsid="{00028C00-0000-0000-0000-000000000046}"
       description="DBGrid  Control" />
  </file>
</assembly>

Bunların hepsi iyi çalışıyor, ancak bu manifest dosyalarını manuel olarak korumak biraz acı verici. Bu dosyaları otomatik olarak oluşturmanın bir yolu var mı? İdeal olarak, uygulamanın bir COM sunucuları listesine (hem yerel hem de .NET) bağımlılığını bildirmek ve geri kalanının otomatik olarak oluşturulmasına izin vermek istiyorum. Mümkün mü?


+1 ayrıca: regfreecom yeniden etiketlendi çünkü bu etiket
kayıtsız

Manifest dosyasıyla kendi yükleme klasörümde daha yüksek bir mstscax.dll sürümü kullanabilir miyim?
2020

@acewind evet. (Daha fazla ayrıntı içeren yeni bir soru göndermek isteyebilirsiniz.)
UuDdLrLrSs

@UuDdLrLrSs İyi haberler! Burada yeni bir soru
yayınlıyorum

Yanıtlar:


64

Görünüşe göre mükemmel çözüm henüz mevcut değil. Bazı araştırmaları özetlemek gerekirse:

Bildirimi Yap ( bağlantı )

Bu araç, COM bağımlılıklarını aramak için bir VB6 projesini tarar, ancak aynı zamanda geç bağlanan COM bağımlılıklarının (yani CreateObject aracılığıyla kullanılanlar) manuel bildirimini de destekler.

Yeterince ilginç bir şekilde, bu araç bağımlılıklar hakkındaki tüm bilgileri uygulama bildiriminin içine yerleştirir. Uygulama exe ve bağımlılıkları, birden çok dosyadan oluşan tek bir derleme olarak tanımlanır. Bunun mümkün olduğunu daha önce fark etmemiştim.

Çok iyi bir araca benziyor ancak 0.6.6 sürümünden itibaren aşağıdaki sınırlamalara sahip:

  • sadece VB6 uygulamaları için, VB6 proje dosyasından başlar. Yazık, çünkü yaptığı şeylerin çoğunun VB6 ile hiçbir ilgisi yok.
  • sihirbaz tarzı uygulama, bir inşa sürecine entegre etmeye uygun değildir. Bağımlılıklarınız çok fazla değişmezse bu çok büyük bir sorun değildir.
  • kaynak olmadan ücretsiz yazılım, güvenmek risklidir çünkü her an yazılımdan vazgeçilebilir.

.NET com kitaplıklarını destekleyip desteklemediğini test etmedim.

regsvr42 ( kod proje bağlantısı )

Bu komut satırı aracı, yerel COM kitaplıkları için bildirim dosyaları oluşturur. DllRegisterServer'ı çağırır ve sonra kayıt defterine bilgi eklerken kendi kendine kaydı gözetir. Ayrıca uygulamalar için bir istemci bildirimi oluşturabilir.

Bu yardımcı program .NET COM kitaplıklarını desteklemez çünkü bunlar bir DllRegisterServer yordamını açığa çıkarmaz.

Yardımcı program C ++ ile yazılmıştır. Kaynak kodu mevcuttur.

mt.exe

Visual Studio yüklüyse zaten sahip olduğunuz Windows SDK'nın bir kısmı ( MSDN'den indirilebilir ). Burada belgelenmiştir . Aşağıdaki gibi yerel COM kitaplıkları için manifest dosyaları oluşturabilirsiniz:

mt.exe -tlb:mycomlib.ocx -dll:mycomlib.ocx -out:mycomlib.ocx.manifest

Şu şekilde .NET COM kitaplıkları için bildirim dosyaları oluşturabilirsiniz:

mt.exe -managedassemblyname:netlib.dll -nodependency -out:netlib.dll.manifest

Ancak, bu araçla ilgili bazı sorunlar vardır:

  • İlk kod parçası progid öznitelikleri oluşturmayarak CreateObject kullanan istemcileri progids ile bozmaz.
  • İkinci kod parçası üretecek <runtime>ve <mvid>bildirimler gerçekten çalışmadan önce çıkarılması gereken öğeler.
  • Uygulamalar için istemci bildirimlerinin oluşturulması desteklenmez.

Belki gelecekteki SDK sürümleri bu aracı geliştirir, Windows SDK 6.0a'da (vista) test ettim.


1
Sanırım bir seçeneği kaçırdınız: mazecomputer.com ama bu konuda web sitesinin tarif etmediği hiçbir şey bilmiyorum.
Bob

MMM, COM olmayan (standart) DLL'leri de yeniden yönlendirecektir. Diğer araçların bunu yaptığından emin değilim.
Bob

Heyecan için sadece bir not: MMM kaynağı yayınlandı. Olumsuz tarafı, yazarın üzerinde çalışmayı bırakmaya karar vermesinden kaynaklanıyor gibi görünüyor. Yine de olumlu bir işaret.
Gavin

2
MMM sitesi artık mevcut değil, ancak kaynak kodun yerleştirildiği yer v0.9 ve v0.12 için hala mevcut .
Scott Chamberlain

1
Yukarıda açıklandığı gibi .NET COM kitaplıkları için mt.exe'yi denedim ve v7.1A kullanarak bildirimde hiçbir değişiklik yapmadan çalıştı. Ayrıca, MMM bağlantıları çalışmadı ama Unattented Make My Manifest düzgün bir iş çıkarıyor gibi görünüyor.
bzuillsmith

29

MSBuild görevi GenerateApplicationManifest ile Visual Studio'nun ürettiği bildirimle aynı komut satırında bir bildirim oluşturdum. Visual Studio'nun derleme sırasında GenerateApplicationManifest kullandığından şüpheleniyorum . Aşağıda, msbuild "msbuild build.xml" kullanılarak komut satırından çalıştırılabilen derleme betiğim var.

Dave Templin ve bana GenerateApplicationManifest görevini ve MSDN'nin görevle ilgili diğer dokümantasyonunu işaret eden yazısı sayesinde .

build.xml

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <Target Name="Build">
        <ItemGroup>
            <File Include='MyNativeApp.exe'/>
            <ComComponent Include='Com1.ocx;Com2.ocx'/>
        </ItemGroup>
        <GenerateApplicationManifest
            AssemblyName="MyNativeApp.exe"
            AssemblyVersion="1.0.0.0"
            IsolatedComReferences="@(ComComponent)"
            Platform="x86"
            ManifestType="Native">
            <Output
                ItemName="ApplicationManifest"
                TaskParameter="OutputManifest"/>
        </GenerateApplicationManifest>
    </Target>   
</Project>

1
Bunun gerçekten bu sorunun cevabı olarak işaretlenmesi gerektiğini düşünüyorum. Şimdi bunu tüm manifesto üretimimizi otomatikleştirmek için kullanıyorum. Teşekkürler @mcdon, beni çok işten kurtardın.
Pete Magsig

Visual Studio ile derleme yaparken bunun en iyi çözüm olduğuna katılıyorum. Muhtemelen daha yüksek derecelendirilmemiştir çünkü diğer cevaplardan çok daha geç yayınlanmıştır
dschaeffer

bunu bir csproj'a nasıl ekleyebilirim?
jle

@jle Bunu AfterBuild hedefindeki csproj'unuza ekleyebileceğinizi düşünüyorum. İşte msdn'den bir bağlantı ve prebuild ve postbuild olayları konusunda başka bir gönderi . Not Bunu csproj'da dahil etmedim, ancak işe yarayacağından şüpheleniyorum.
mcdon

1
Partiye 11 yıl geç ama söz için teşekkürler!
Dave Templin

9

Manifestimi Yap (MMM) bunu yapmak için güzel bir araçtır. Ayrıca , her biri için bir bildirim oluşturmak ve ardından hepsini bir araya getirmek üzere mt.exe kullanarak tüm DLL / OCX dosyalarınızı işlemek için bir komut dosyası yazmak da mümkündür . MMM genellikle daha iyi / daha kolaydır, çünkü birçok özel / tuhaf durumu da ele alır.


3
Bu MMM meselesi konusunda biraz gerginim; bu sadece bir blog, ücretsiz bir yazılım, ancak kaynak kodu mevcut değil, yalnızca "kendi kendine açılan bir exe" bağlantısı ve XP'nin çökmesine neden olan yardımcı program hakkındaki yorumları görüyorum. mmm ...
Wim Coenen

Bu "çökmeler", MMM programının kendisi ölüyordu. Bu, 0.6.5 sürümünde düzeltildi, ancak yine de 0.6.6'yı isteyeceksiniz, çünkü hala bir beta sürerken süresi dolmuyor. Daha önce önerildiği gibi, bunun yerine her zaman MT.EXE'yi kullanabilirsiniz.
Bob

mt.exe, dbgrid32.ocx gibi yerel com sunucularında kullandığımda progid üretmiyor
Wim Coenen

Reg içermeyen
COM'un

8

Doğrudan otomatikleştirilmiş derlemelerde bildirimler oluşturmak için Katılımsız Yapma Manifestimi döndürmeyi kullanabilirsiniz . Bağımlı COM bileşenlerini eklemek için bir komut dosyası kullanır. Bu, mevcut komutlarla birlikte örnek ini'den bir alıntıdır:

# Unattended MMM script
#
# Command names are case-insensitive. Reference of supported commands:
#
# Command: Identity
#
#   Appends assemblyIdentity and description tags.
#
#   Parameters       <exe_file> [name] [description]
#      exe_file      file name can be quoted if containing spaces. The containing folder 
#                    of the executable sets base path for relative file names
#      name          (optional) assembly name. Defaults to MyAssembly
#      description   (optional) description of assembly
#
# Command: Dependency
#
#   Appends dependency tag for referencing dependent assemblies like Common Controls 6.0, 
#     VC run-time or MFC
#
#   Parameters       {<lib_name>|<assembly_file>} [version] [/update]
#     lib_name       one of { comctl, vc90crt, vc90mfc }
#     assembly_file  file name of .NET DLL exporting COM classes
#     version        (optional) required assembly version. Multiple version of vc90crt can
#                    be required by a single manifest
#     /update        (optional) updates assembly_file assembly manifest. Spawns mt.exe
#
# Command: File
#
#   Appends file tag and collects information about coclasses and interfaces exposed by 
#     the referenced COM component typelib.
#
#   Parameters       <file_name> [interfaces]
#     file_name      file containing typelib. Can be relative to base path
#     interfaces     (optional) pipe (|) separated interfaces with or w/o leading 
#                    underscore
#
# Command: Interface
#
#   Appends comInterfaceExternalProxyStub tag for inter-thread marshaling of interfaces
#
#   Parameters       <file_name> <interfaces>
#     file_name      file containing typelib. Can be relative to base path
#     interfaces     pipe (|) separated interfaces with or w/o leading underscore
#
# Command: TrustInfo
#
#   Appends trustInfo tag for UAC user-rights elevation on Vista and above
#
#   Parameters       [level] [uiaccess]
#     level          (optional) one of { 1, 2, 3 } corresponding to { asInvoker, 
#                    highestAvailable, requireAdministrator }. Default is 1
#     uiaccess       (optional) true/false or 0/1. Allows application to gain access to 
#                    the protected system UI. Default is 0
#
# Command: DpiAware
#
#   Appends dpiAware tag for custom DPI aware applications
#
#   Parameters       [on_off]
#     on_off         (optional) true/false or 0/1. Default is 0
#
# Command: SupportedOS
#
#   Appends supportedOS tag
#
#   Parameters       <os_type>
#     os_type        one of { vista, win7 }. Multiple OSes can be supported by a single 
#                    manifest
#

32 veya 64 bit Windows üzerinde çalışacaktır.


+1 İlginç, özellikle kaynak kodu mevcut olduğu için. İsim benzerliğinden biraz kafam karıştı, görünüşe göre "manifestomu yap" ve "katılımsız manifestimi yap" farklı yazarların farklı araçları.
Wim Coenen

2
Not - 2017 itibarıyla (8 yıl sonra ...) bu proje ara sıra yapılan bakım güncellemeleriyle halen aktiftir. github.com/wqweto/UMMM/commits/master . İyi çalışıyor ve rutin olarak kullanıyorum.
UuDdLrLrSs

0

Mt.exe'nin içermediği ProgID'leri doldurmak için, ProgIDFromCLSIDbunları kayıt defterinden aramak için arayabilirsiniz . Bu, bildirim dosyasını tamamlamadan önce geleneksel COM kaydını gerektirir, ancak daha sonra bildirim dosyası kendi kendine yeterli olacaktır.

Bu C # kodu, ProgID'leri bir bildirimdeki tüm COM sınıflarına ekler:

var manifest = XDocument.Load(fileName);
var namespaceManager = new XmlNamespaceManager(new NameTable());
namespaceManager.AddNamespace("s", "urn:schemas-microsoft-com:asm.v1");
foreach (var classElement in manifest.XPathSelectElements("s:assembly/s:file/s:comClass", namespaceManager)) {
    var clsid = Guid.Parse(classElement.Attribute("clsid").Value);
    int result = ProgIDFromCLSID(ref clsid, out string progId); if (result != S_OK) throw new COMException($"ProgID lookup failed for {clsid}.", result);
    classElement.SetAttributeValue("progid", progId);
}
manifest.Save(fileName);

Kod, bu birlikte çalışma tanımlarına dayanır:

[DllImport("ole32.dll")] static extern int ProgIDFromCLSID([In] ref Guid clsid, [MarshalAs(UnmanagedType.LPWStr)] out string lplpszProgID);
const int S_OK = 0;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.