Mam kilka aplikacji (niektóre natywne, niektóre .NET), które używają plików manifestu, dzięki czemu można je wdrażać w całkowitej izolacji , bez konieczności jakiejkolwiek globalnej rejestracji COM. Na przykład zależność od serwera dbgrid32.ocx com jest zadeklarowana w następujący sposób w pliku myapp.exe.manifest, który znajduje się w tym samym folderze co myapp.exe:
<?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>
Plik dbgrid32.ocx jest wdrażany w tym samym folderze wraz z własnym plikiem dbgrid32.ocx.manifest:
<?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>
To wszystko działa dobrze, ale ręczne utrzymywanie tych plików manifestu jest trochę uciążliwe. Czy istnieje sposób na automatyczne generowanie tych plików? Idealnie chciałbym po prostu zadeklarować zależność aplikacji od listy serwerów COM (zarówno natywnych, jak i .NET), a następnie pozwolić, aby pozostałe zostały wygenerowane automatycznie. Czy to możliwe?
Odpowiedzi:
Wygląda na to, że idealne rozwiązanie jeszcze nie istnieje. Podsumowując niektóre badania:
Make My Manifest ( link )
To narzędzie skanuje projekt VB6 w poszukiwaniu zależności COM, ale obsługuje również ręczne deklarowanie późno wiązanych zależności COM (tj. Tych używanych przez CreateObject).
Co ciekawe, to narzędzie umieszcza wszystkie informacje o zależnościach w manifeście aplikacji. Aplikacja exe i jej zależności są opisane jako pojedynczy zestaw składający się z wielu plików. Wcześniej nie zdawałem sobie sprawy, że to jest możliwe.
Wygląda na bardzo dobre narzędzie, ale od wersji 0.6.6 ma następujące ograniczenia:
Nie testowałem, czy obsługuje biblioteki .NET com.
regsvr42 ( link do projektu code )
To narzędzie wiersza polecenia generuje pliki manifestu dla natywnych bibliotek COM. Wywołuje DllRegisterServer, a następnie szpieguje samo-rejestrację, ponieważ dodaje informacje do rejestru. Może również generować manifest klienta dla aplikacji.
To narzędzie nie obsługuje bibliotek .NET COM, ponieważ nie ujawniają one procedury DllRegisterServer.
Narzędzie jest napisane w C ++. Kod źródłowy jest dostępny.
mt.exe
Część zestawu Windows SDK (można go pobrać z witryny MSDN ), który już masz, jeśli masz zainstalowane oprogramowanie Visual Studio. Jest to udokumentowane tutaj . Za jego pomocą można generować pliki manifestu dla natywnych bibliotek COM w następujący sposób:
Możesz wygenerować pliki manifestu dla bibliotek .NET COM w następujący sposób:
Istnieją jednak pewne problemy z tym narzędziem:
<runtime>
i<mvid>
elementy, które należy usunąć, zanim manifesty zaczną działać.Może przyszłe wydania SDK poprawią to narzędzie, testowałem to w Windows SDK 6.0a (vista).
źródło
Za pomocą zadania GenerateApplicationManifest programu MSBuild wygenerowałem manifest w wierszu polecenia identyczny z manifestem generowanym przez program Visual Studio. Podejrzewam, że Visual Studio używa GenerateApplicationManifest podczas kompilacji. Poniżej znajduje się mój skrypt kompilacji, który można uruchomić z wiersza poleceń za pomocą programu msbuild "msbuild build.xml"
Dziękuję Dave Templinowi i jego postowi, który wskazał mi zadanie GenerateApplicationManifest oraz dalszą dokumentację tego zadania przez MSDN .
build.xml
źródło
Make My Manifest (MMM) jest dobrym narzędziem do tego. Możliwe jest również napisanie skryptu przetwarzającego wszystkie pliki DLL / OCX za pomocą mt.exe w celu wygenerowania manifestu dla każdego z nich, a następnie scalenie ich wszystkich razem. MMM jest zwykle lepsze / łatwiejsze, ponieważ obsługuje również wiele specjalnych / dziwnych przypadków.
źródło
Możesz użyć spin-offu Unattended Make My Manifest do generowania manifestów bezpośrednio w zautomatyzowanych kompilacjach. Używa pliku skryptu do dodawania zależnych składników COM. To jest fragment przykładowego ini z dostępnymi poleceniami:
Będzie działać na 32- lub 64-bitowym systemie Windows.
źródło
Aby wypełnić identyfikatory ProgID, których nie zawiera mt.exe, możesz wywołać
ProgIDFromCLSID
je w celu wyszukania ich w rejestrze. Wymaga to tradycyjnej rejestracji COM przed wypełnieniem pliku manifestu, ale później plik manifestu będzie samowystarczalny.Ten kod C # dodaje identyfikatory ProgID do wszystkich klas COM w manifeście:
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 opiera się na tych definicjach międzyoperacyjnych:
[DllImport("ole32.dll")] static extern int ProgIDFromCLSID([In] ref Guid clsid, [MarshalAs(UnmanagedType.LPWStr)] out string lplpszProgID); const int S_OK = 0;
źródło