Generowanie plików manifest do Rejestracji-free COM

Mam kilka aplikacji (niektóre natywne, niektóre. NET), które używają plików manifest, dzięki czemu mogą być wdrożone w całkowitej izolacji , bez konieczności globalnej rejestracji COM. Na przykład zależność od dbgrid32.serwer ocx com jest deklarowany w następujący sposób w myapp.exe.plik 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>

Dbgrid32.ocx jest wdrożony do tego samego folderu, wraz z własnym dbgrid32.ocx.plik manifestu:

<?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 utrzymanie tych plików manifest ręcznie jest trochę bólu. Czy istnieje sposób na automatyczne generowanie tych plików? Najlepiej po prostu zadeklarować zależność aplikacji od listy serwerów COM (zarówno natywnych, jak i. NET), a następnie pozostawić resztę wygenerowaną automatycznie. Czy to możliwe?

Author: GSerg, 2009-01-21

5 answers

Wygląda na to, że idealne rozwiązanie jeszcze nie istnieje. Aby podsumować 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 deklaracje opóźnionych zależności COM (tj. tych używanych przez CreateObject).

Co ciekawe, to narzędzie umieszcza wszystkie informacje o zależnościach wewnątrz manifestu aplikacji. Exe aplikacji i jej zależności są opisane jako pojedynczy zespół składający się z wielu plików. Nie zdawałem sobie sprawy, że to możliwe.

Wygląda na bardzo dobre narzędzie, ale od wersji 0.6.6 ma następujące ograniczenia:

  • tylko dla aplikacji VB6, uruchamia z pliku projektu VB6. Wstyd, bo wiele z tego, co robi naprawdę nie ma nic wspólnego z VB6.
  • Aplikacja w stylu kreatora, nie nadaje się do integracji w konstrukcji proces. To nie jest ogromny problem, jeśli twój zależności Nie zmieniają się a Nr serii
  • freeware bez źródeł, ryzykowne jest poleganie na nim, ponieważ w każdej chwili może stać się abandonware.

Nie testowałem, czy obsługuje biblioteki. NET com.

Regsvr42 (codeproject link )

To narzędzie wiersza poleceń generuje pliki manifestów dla natywnych bibliotek COM. Wywołuje DllRegisterServer, a następnie szpieguje na samo-rejestracji, jak dodaje informacje do rejestru. Może również wygenerować manifest klienta dla aplikacje.

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 pobrać z MSDN ), który już masz, jeśli masz zainstalowany program visual studio. Jest to udokumentowane tutaj . Możesz generować pliki manifest dla natywnych bibliotek COM z nim jak to:

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

Możesz generować pliki manifestu dla bibliotek. NET COM z tym w następujący sposób:

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

Jednak są pewne problemy z tym narzędziem:

  • pierwszy fragment nie wygeneruje atrybuty, łamanie klientów które używają CreateObject z progidami.
  • drugi fragment wygeneruje <runtime> i <mvid> elementy które trzeba rozebrać przed manifesty działają.
  • generowanie manifestów klienta dla aplikacje nie są obsługiwane.

Może przyszłe wydania SDK poprawią to narzędzie, testowałem to w Windows SDK 6.0 a (vista).

 56
Author: Wim Coenen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-07 22:04:03

Z zadaniem MSBuild Generateaplicationmanifest wygenerowałem manifest w wierszu poleceń identyczny z manifestem generowanym przez Visual Studio. Podejrzewam, że Visual Studio używa Generateaplicationmanifest podczas budowania. Poniżej znajduje się mój skrypt build, który można uruchomić z linii poleceń przy użyciu msbuild " msbuild build.xml "

Dzięki Dave Templin i jego post, który wskazał mi zadanie Generateaplicationmanifest , i MSDN dalej dokumentacja zadania .

Zbuduj.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>
 23
Author: mcdon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-14 15:22:57

Make My Manifest (MMM) {[2] } jest miłym narzędziem do tego. Możliwe jest również napisanie skryptu do przetwarzania wszystkich plików DLL / OCX przy użyciu mt.exe aby wygenerować manifest dla każdego z nich, a następnie połączyć je wszystkie razem. MMM jest zwykle lepszy / łatwiejszy, ponieważ obsługuje również wiele specjalnych / dziwnych przypadków.

 9
Author: jdve,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-21 16:17:49

Możesz użyćunattended Make My Manifest spin off do generowania manifestów bezpośrednio w zautomatyzowanych kompilacjach. Używa pliku skryptu do dodawania komponentów COM. Jest to fragment przykładowego ini z dostępnymi poleceniami:

# 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
#
 7
Author: wqw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-04 11:27:01

Aby wypełnić Progidy, które mt.exe nie zawiera, możesz wywołać ProgIDFromCLSID, aby wyszukać je z rejestru. Wymaga to tradycyjnej rejestracji COM przed ukończeniem pliku manifest, ale następnie plik manifest będzie samowystarczalny.

Ten kod C# dodaje ProgIDs 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 interpunkcjach:

[DllImport("ole32.dll")] static extern int ProgIDFromCLSID([In] ref Guid clsid, [MarshalAs(UnmanagedType.LPWStr)] out string lplpszProgID);
const int S_OK = 0;
 0
Author: Edward Brey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-06 21:10:54