등록이 필요없는 COM을위한 매니페스트 파일 생성


87

매니페스트 파일을 사용하는 일부 응용 프로그램 (일부 기본, 일부 .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 모두)에 대한 응용 프로그램의 종속성을 선언 한 다음 나머지는 자동으로 생성되도록하고 싶습니다. 가능합니까?


+1 또한 : 레지스트리가없는 COM에 대해 태그가 더 일반적이므로 regfreecom 태그를 다시 지정했습니다.
MarkJ

매니페스트 파일로 내 설치 폴더에 더 높은 버전의 mstscax.dll을 사용할 수 있습니까?
Acewind

@acewind 예. (자세한 내용이 포함 된 새 질문을 게시 할 수 있습니다.)
UuDdLrLrSs

@UuDdLrLrSs 좋은 소식입니다! 여기에 새 질문을 게시합니다. stackoverflow.com/questions/63575746/…
Acewind

답변:


64

완벽한 솔루션이 아직 존재하지 않는 것 같습니다. 몇 가지 연구를 요약하면 다음과 같습니다.

내 매니페스트 만들기 ( 링크 )

이 도구는 VB6 프로젝트를 검사하여 COM 종속성을 찾지 만 후기 바인딩 된 COM 종속성 (즉, CreateObject를 통해 사용되는 종속성)의 수동 선언도 지원합니다.

흥미롭게도이 도구는 애플리케이션 매니페스트 내부에 종속성에 대한 모든 정보를 넣습니다. 응용 프로그램 exe 및 해당 종속성은 여러 파일로 구성된 단일 어셈블리로 설명됩니다. 나는 이것이 가능하다는 것을 전에 깨닫지 못했습니다.

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

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

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

regsvr42 ( codeproject 링크 )

이 명령 줄 도구는 네이티브 COM 라이브러리에 대한 매니페스트 파일을 생성합니다. DllRegisterServer를 호출 한 다음 레지스트리에 정보를 추가 할 때 자체 등록을 감시합니다. 또한 애플리케이션에 대한 클라이언트 매니페스트를 생성 할 수도 있습니다.

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

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

mt.exe

Visual Studio가 설치되어있는 경우 이미 가지고 있는 Windows SDK ( MSDN 에서 다운로드 가능)의 일부입니다 . 여기에 문서화되어 있습니다 . 다음과 같이 네이티브 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 속성을 생성하지 않고 progid와 함께 CreateObject를 사용하는 클라이언트를 손상시킵니다.
  • 두 번째 스 니펫은 매니페스트가 실제로 작동하기 전에 제거해야하는 요소 <runtime>와 생성됩니다 <mvid>.
  • 응용 프로그램에 대한 클라이언트 매니페스트 생성은 지원되지 않습니다.

향후 SDK 릴리스가이 도구를 개선 할 수있을 것입니다. Windows SDK 6.0a (vista)에서 테스트했습니다.


1
한 가지 옵션을 놓친 것 같습니다. mazecomputer.com 이지만 웹 사이트에서 설명하지 않는 것에 대해 아무것도 모릅니다.

MMM은 비 COM (표준) DLL도 리디렉션합니다. 다른 도구가이 작업을 수행하는지 잘 모르겠습니다.
Bob

긴장된 분들을위한 메모 : MMM의 소스가 공개되었습니다. 단점은 저자가 작업을 중단하기로 결정했기 때문인 것 같습니다. 여전히 긍정적 인 신호입니다.
Gavin

2
MMM 사이트는 더 이상 올라 오지 않지만 소스 코드를 넣은 위치는 v0.9v0.12에서 계속 사용할 수 있습니다 .
Scott Chamberlain

1
위에서 설명한대로 .NET COM 라이브러리에 대해 mt.exe를 시도했으며 v7.1A를 사용하여 매니페스트를 수정하지 않고 작동했습니다. 또한 MMM에 대한 링크가 작동하지 않았지만 Unattented Make My Manifest 는 괜찮은 작업을 수행하는 것 같습니다.
bzuillsmith

28

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

GenerateApplicationManifest 작업 과 MSDN의 작업에 대한 추가 문서를 알려주는 Dave Templin과 그의 게시물 덕분 입니다.

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>

나는 이것이 정말로이 질문에 대한 답으로 표시되어야한다고 생각합니다. 저는 이제 이것을 사용하여 모든 매니페스트 생성을 자동화하고 있습니다. @mcdon 감사합니다. 많은 작업을 절약했습니다.
Pete Magsig 2013

Visual Studio로 빌드 할 때 이것이 최상의 솔루션이라는 데 동의합니다. 아마 훨씬 나중에 다른 답변보다 게시에만 있기 때문에 높은 평가하지 않습니다
dschaeffer

이것을 csproj에 추가하는 방법?
jle

@jle AfterBuild 대상의 csproj에 추가 할 수 있다고 생각합니다. 여기의 MSDN에서 링크다른 포스트 사전 빌드 및 postbuild 이벤트의 주제는. 참고 csproj에 이것을 포함하여 테스트하지 않았지만 작동 할 것이라고 생각합니다.
mcdon

(?보다는 각 EXE 파일에 매니페스트를 생성하고, DLL을 포함) 매니페스트, 그래서 어떤 EXE 그것을 소비 할 수있는 C # COM DLL 생성 가능
GilesDMiddleton

9

MMM (Make My Manifest) 은이를위한 좋은 도구입니다. mt.exe 를 사용하여 모든 DLL / OCX 파일을 처리하는 스크립트를 작성하여 각각에 대한 매니페스트를 생성 한 다음 모두 함께 병합 할 수도 있습니다. MMM은 많은 특수 / 이상한 경우를 처리하기 때문에 일반적으로 더 좋고 / 쉽습니다.


3
이 MMM에 대해 약간 긴장합니다. 그것은 단지 블로그, 프리웨어이지만 사용 가능한 소스 코드는 없으며 "자동 압축 풀기 exe"에 대한 링크 일 뿐이며 XP 충돌을 일으키는 유틸리티에 대한 의견을 봅니다. mmm ...
Wim Coenen

이러한 "충돌"은 MMM 유틸리티 자체가 죽어가는 것입니다. 이것은 버전 0.6.5에서 수정되었지만 여전히 베타 버전이지만 더 이상 만료되지 않기 때문에 어쨌든 0.6.6을 원할 것입니다. 이미 제안한대로 항상 MT.EXE를 대신 사용할 수 있습니다.
Bob

dbgrid32.ocx와 같은 네이티브 com 서버에서 사용할 때 mt.exe가 progid를 생성하지 않습니다.
Wim Coenen

.NET 제작 구성 요소와 함께 reg free COM을 사용하면 XP가 충돌 할 수 있습니다.이 stackoverflow.com/questions/617253/…
MarkJ

8

무인 Make My Manifest 스핀 오프를 사용하여 자동화 된 빌드에서 직접 매니페스트를 생성 할 수 있습니다 . 스크립트 파일을 사용하여 종속 된 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 비트 Windows에서 실행됩니다.


+1 흥미 롭습니다. 특히 소스 코드를 사용할 수 있기 때문입니다. 이름 유사성으로 인해 약간 혼란 스럽습니다. 분명히 "내 매니페스트 만들기"와 "무인 내 매니페스트 만들기"는 작성자마다 다른 도구입니다.
Wim Coenen

2
참고-2017 년 (8 년 후 ...) 현재이 프로젝트는 비정기적인 유지 보수 업데이트로 여전히 활성화됩니다. github.com/wqweto/UMMM/commits/master . 잘 작동하며 일상적으로 사용합니다.
UuDdLrLrSs

0

mt.exe에 포함되지 않은 ProgID를 입력 ProgIDFromCLSID하려면 레지스트리에서 조회하도록 호출 할 수 있습니다. 이를 위해서는 매니페스트 파일을 완료하기 전에 기존의 COM 등록이 필요하지만 이후 매니페스트 파일은 자급 자족 할 수 있습니다.

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

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;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.