문제

나는 매니페스트 파일을 사용하여 일부 응용 프로그램 (일부 네이티브, 일부 .NET)이 있습니다. 완전히 격리되어 배포되었습니다, 글로벌 COM 등록이 필요하지 않습니다. 예를 들어, dbgrid32.ocx com 서버에 대한 종속성은 myapp.exe와 동일한 폴더에있는 myapp.exe.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="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는 자체의 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>

이 모든 것이 잘 작동하지만 이러한 매니페스트 파일을 수동으로 유지하는 것은 약간의 고통입니다. 이러한 파일을 자동으로 생성하는 방법이 있습니까? 이상적으로는 COM 서버 목록 (기본 및 .NET)에 대한 응용 프로그램의 종속성을 선언 한 다음 나머지는 자동으로 생성하도록합니다. 가능합니까?

도움이 되었습니까?

해결책

완벽한 솔루션이 아직 존재하지 않는 것 같습니다. 일부 연구를 요약하려면 :

내 명시를 내리십시오 (링크)

이 도구는 VB6 프로젝트를 스캔하여 COM 의존성을 찾지만, 또한 후기 COM 종속성 (즉, CreateObject를 통해 사용 된 것)의 수동 선언도 지원합니다.

흥미롭게 도이 도구는 응용 프로그램 내부의 종속성에 대한 모든 정보를 제공합니다. 응용 프로그램 EXE 및 그 종속성은 여러 파일로 구성된 단일 어셈블리로 설명됩니다. 나는 이것이 가능하다는 것을 깨닫지 못했습니다.

매우 좋은 도구처럼 보이지만 버전 0.6.6은 다음과 같은 한계가 있습니다.

  • VB6 응용 프로그램의 경우에만 VB6 프로젝트 파일에서 시작됩니다. 부끄러운 일이 많기 때문에 실제로 VB6과 관련이 없기 때문입니다.
  • 마법사 스타일 애플리케이션, 빌드 프로세스에 통합하기에 적합하지 않습니다. 의존성이 많이 바뀌지 않으면 큰 문제가 아닙니다.
  • 소스가없는 프리웨어, 언제라도 포기할 수 있기 때문에 의존하는 것이 위험합니다.

.NET COM 라이브러리를 지원하는지 테스트하지 않았습니다.

regsvr42 (CodeProject 링크)

이 명령 줄 도구는 기본 COM 라이브러리에 대한 매니페스트 파일을 생성합니다. DLLREGISTESSERVER를 호출 한 다음 레지스트리에 정보를 추가 할 때 자체 등록에 대해 스파이를 청소합니다. 또한 응용 프로그램에 대한 클라이언트 매니페스트를 생성 할 수도 있습니다.

이 유틸리티는 .NET COM 라이브러리를 지원하지 않습니다. DLLREGISTESSERVER 루틴을 노출시키지 않기 때문입니다.

유틸리티는 C ++로 작성됩니다. 소스 코드를 사용할 수 있습니다.

Mt.exe

Windows SDK의 일부 ( MSDN), 당신이 이미 가지고있는 경우 Visual Studio를 설치 한 경우. 그것은이다 여기에 문서화되었습니다. 다음과 같이 기본 COM 라이브러리에 대한 매니페스트 파일을 생성 할 수 있습니다.

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

다음과 같이 .NET COM 라이브러리에 대한 매니페스트 파일을 생성 할 수 있습니다.

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

그러나이 도구에는 몇 가지 문제가 있습니다.

  • 첫 번째 스 니펫은 Progid 속성을 생성하지 않으며 CreateObject를 사용하여 프로위를 사용하는 클라이언트를 깨뜨립니다.
  • 두 번째 스 니펫이 생성됩니다<runtime> 그리고 <mvid> 매니페스트가 실제로 작동하기 전에 제거 해야하는 요소.
  • 응용 프로그램에 대한 클라이언트 매니페스트 생성은 지원되지 않습니다.

미래의 SDK 릴리스 가이 도구를 향상시킬 것입니다.

다른 팁

MSBuild 작업과 함께 GenerateApplicationManifest 명령 줄에서 매니페스트 비주얼 스튜디오 생성과 동일한 명령 줄을 생성했습니다. Visual Studio가 사용한다고 생각합니다 GenerateApplicationManifest 빌드 중. 아래는 msbuild "msbuild build.xml"을 사용하여 명령 줄에서 실행할 수있는 빌드 스크립트입니다.

Dave Templin과 그의 덕분에 GenerateApplicationManifest 작업을 지적한 게시물, 및 MSDN 작업의 추가 문서.

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>

내 명백함 만들기 (mmm) 이 작업을 수행하기에 좋은 도구입니다. 사용하여 모든 DLL/OCX 파일을 처리하기 위해 스크립트를 작성할 수도 있습니다. Mt.exe 각각에 대한 매니페스트를 생성 한 다음 모두 함께 병합합니다. MMM은 일반적으로 더 나은/더 쉽습니다. 특별한/이상한 사례를 많이 처리하기 때문입니다.

당신이 사용할 수있는 무인은 내 명시를 만들어냅니다 자동화 된 빌드에서 직접 매니페스트를 생성하려면 분사됩니다. 스크립트 파일을 사용하여 COM 구성 요소를 추가합니다. 이것은 사용 가능한 명령과 함께 샘플 INI에서 발췌 한 것입니다.

# 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 또는 64 비트 창에서 실행됩니다.

Mt.exe가 포함하지 않는 프로그램을 작성하려면 ProgIDFromCLSID 레지스트리에서 그들을 찾아보십시오. 이를 위해서는 매니페스트 파일을 완료하기 전에 기존의 COM 등록이 필요하지만, 그 결과 매니페스트 파일은 자급 자족합니다.

이 C# 코드는 매니페스트의 모든 COM 클래스에 Progids를 추가합니다.

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);

코드는 이러한 Interop 정의에 의존합니다.

[DllImport("ole32.dll")] static extern int ProgIDFromCLSID([In] ref Guid clsid, [MarshalAs(UnmanagedType.LPWStr)] out string lplpszProgID);
const int S_OK = 0;
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top