สร้างไฟล์รายการสำหรับ COM ที่ไม่ต้องลงทะเบียน


87

ฉันมีแอปพลิเคชันบางตัว (เนทีฟบางตัวบางตัว. NET) ที่ใช้ไฟล์รายการเพื่อให้สามารถใช้งานได้โดยแยกออกจากกันโดยไม่ต้องลงทะเบียน COM ส่วนกลางใด ๆ ตัวอย่างเช่นการอ้างอิงบนเซิร์ฟเวอร์ dbgrid32.ocx com จะถูกประกาศดังต่อไปนี้ในไฟล์ myapp.exe.manifest ซึ่งอยู่ในโฟลเดอร์เดียวกับ 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 ถูกปรับใช้กับโฟลเดอร์เดียวกันพร้อมกับไฟล์ 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>

ทั้งหมดนี้ใช้งานได้ดี แต่การดูแลรักษาไฟล์ manifest เหล่านี้ด้วยตนเองนั้นค่อนข้างลำบาก มีวิธีสร้างไฟล์เหล่านี้โดยอัตโนมัติหรือไม่? ตามหลักการแล้วฉันต้องการประกาศการอ้างอิงของแอปพลิเคชันในรายการเซิร์ฟเวอร์ COM (ทั้งเนทีฟและ. NET) จากนั้นปล่อยให้ส่วนที่เหลือถูกสร้างขึ้นโดยอัตโนมัติ เป็นไปได้ไหม?


+1 ด้วย: Retagged regfreecom เนื่องจากแท็กนั้นเป็นเรื่องธรรมดาสำหรับ COM ที่ไม่มีรีจิสทรี
MarkJ

ฉันสามารถใช้ mstscax.dll เวอร์ชันที่สูงกว่าในโฟลเดอร์การติดตั้งของฉันเองโดยใช้ไฟล์ manifest ได้หรือไม่
Acewind

@acewind ใช่ (คุณอาจต้องการโพสต์คำถามใหม่พร้อมรายละเอียดเพิ่มเติม)
UuDdLrLrSs

@UuDdLrLrSs ข่าวดี! ฉันตั้งคำถามใหม่ที่นี่: stackoverflow.com/questions/63575746/…
Acewind

คำตอบ:


64

ดูเหมือนว่ายังไม่มีโซลูชันที่สมบูรณ์แบบ สรุปงานวิจัยบางส่วน:

สร้างไฟล์ Manifest ของฉัน ( ลิงค์ )

เครื่องมือนี้จะสแกนโปรเจ็กต์ VB6 เพื่อค้นหาการอ้างอิง COM แต่ยังรองรับการประกาศด้วยตนเองของการอ้างอิง COM แบบผูกปลายด้วย (เช่นที่ใช้ผ่าน CreateObject)

น่าสนใจพอเครื่องมือนี้ใส่ข้อมูลทั้งหมดเกี่ยวกับการอ้างอิงไว้ในรายการแอปพลิเคชัน แอ็พพลิเคชัน exe และการอ้างอิงถูกอธิบายว่าเป็นแอสเซมบลีเดียวที่ประกอบด้วยไฟล์หลายไฟล์ ฉันไม่เคยรู้มาก่อนเลยว่ามันเป็นไปได้

ดูเหมือนเครื่องมือที่ดีมาก แต่ในเวอร์ชัน 0.6.6 มีข้อ จำกัด ดังต่อไปนี้:

  • สำหรับแอปพลิเคชัน VB6 เท่านั้นเริ่มจากไฟล์โครงการ VB6 ความอัปยศเพราะหลาย ๆ สิ่งที่มันไม่เกี่ยวข้องกับ VB6
  • แอปพลิเคชันสไตล์ตัวช่วยสร้างไม่เหมาะที่จะรวมเข้ากับกระบวนการสร้าง นี่ไม่ใช่ปัญหาใหญ่หากการอ้างอิงของคุณไม่เปลี่ยนแปลงมากนัก
  • ฟรีแวร์ที่ไม่มีแหล่งที่มามีความเสี่ยงที่จะพึ่งพาเนื่องจากอาจกลายเป็นซอฟต์แวร์ละทิ้งได้ตลอดเวลา

ฉันไม่ได้ทดสอบว่ารองรับไลบรารี. NET com หรือไม่

regsvr42 ( ลิงค์ codeproject )

เครื่องมือบรรทัดคำสั่งนี้สร้างไฟล์รายการสำหรับไลบรารี COM ดั้งเดิม เรียกใช้ DllRegisterServer จากนั้นสอดแนมการลงทะเบียนด้วยตนเองเมื่อเพิ่มข้อมูลลงในรีจิสทรี นอกจากนี้ยังสามารถสร้างรายการไคลเอ็นต์สำหรับแอปพลิเคชัน

ยูทิลิตี้นี้ไม่รองรับไลบรารี. NET COM เนื่องจากสิ่งเหล่านี้ไม่เปิดเผยรูทีน DllRegisterServer

ยูทิลิตี้นี้เขียนด้วยภาษา C ++ มีซอร์สโค้ด

mt.exe

ส่วนหนึ่งของ windows SDK (สามารถดาวน์โหลดได้จากMSDN ) ซึ่งคุณมีอยู่แล้วหากคุณติดตั้ง Visual Studio มันเป็นเอกสารที่นี่ คุณสามารถสร้างไฟล์ manifest สำหรับไลบรารี COM ดั้งเดิมได้ดังนี้:

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

คุณสามารถสร้างไฟล์ manifest สำหรับไลบรารี. NET COM ได้ดังนี้:

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

อย่างไรก็ตามมีปัญหาบางอย่างกับเครื่องมือนี้:

  • ตัวอย่างแรกจะไม่สร้างแอตทริบิวต์ progid ทำลายไคลเอนต์ที่ใช้ CreateObject กับ progids
  • ตัวอย่างข้อมูลที่สองจะสร้าง <runtime>และ<mvid>องค์ประกอบที่จำเป็นต้องถอดออกก่อนที่รายการจะทำงานจริง
  • ไม่สนับสนุนการสร้างรายการไคลเอ็นต์สำหรับแอปพลิเคชัน

บางทีการเผยแพร่ SDK ในอนาคตจะช่วยปรับปรุงเครื่องมือนี้ฉันได้ทดสอบใน Windows SDK 6.0a (vista)


1
ฉันคิดว่าคุณพลาดทางเลือกหนึ่ง: mazecomputer.comแต่ฉันไม่รู้อะไรเลยเกี่ยวกับเรื่องนี้เว็บไซต์ไม่ได้อธิบายไว้
Bob

MMM จะเปลี่ยนเส้นทาง DLL ที่ไม่ใช่ COM (มาตรฐาน) ด้วย ฉันไม่แน่ใจว่าเครื่องมืออื่นทำเช่นนี้
Bob

หมายเหตุสำหรับคนกังวล: แหล่งที่มาของ MMM ได้รับการเผยแพร่แล้ว ในทางกลับกันสิ่งนี้ดูเหมือนจะเป็นเพราะผู้เขียนได้ตัดสินใจที่จะหยุดทำงานกับมัน ยังคงเป็นสัญญาณเชิงบวก
Gavin

2
เว็บไซต์สำหรับ MMM เป็น nolonger แต่สถานที่ที่รหัสที่มาถูกนำยังคงมีอยู่สำหรับV0.9และv0.12
Scott Chamberlain

1
เพิ่งลอง mt.exe สำหรับไลบรารี. NET COM ตามที่อธิบายไว้ข้างต้นและใช้งานได้โดยไม่มีการปรับเปลี่ยนไฟล์ Manifest โดยใช้ v7.1A นอกจากนี้ลิงก์สำหรับ MMM ใช้งานไม่ได้ แต่Unattented Make My Manifestดูเหมือนจะทำงานได้ดี
bzuillsmith

29

ด้วยภารกิจ MSBuild GenerateApplicationManifestฉันสร้างรายการที่บรรทัดคำสั่งเหมือนกับที่ Visual Studio สร้างขึ้น ฉันสงสัยว่า Visual Studio ใช้GenerateApplicationManifestระหว่างการสร้าง ด้านล่างนี้คือสคริปต์การสร้างของฉันซึ่งสามารถเรียกใช้จากบรรทัดคำสั่งโดยใช้ msbuild "msbuild build.xml"

ขอขอบคุณที่เดฟ 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>

1
ฉันคิดว่านี่ควรถูกทำเครื่องหมายว่าเป็นคำตอบสำหรับคำถามนี้จริงๆ ตอนนี้ฉันกำลังใช้สิ่งนี้เพื่อทำให้การสร้างรายการทั้งหมดของเราเป็นไปโดยอัตโนมัติ ขอบคุณ @mcdon คุณช่วยฉันได้มาก
Pete Magsig

ฉันยอมรับว่านี่เป็นทางออกที่ดีที่สุดเมื่อสร้างด้วย Visual Studio อาจไม่ได้รับการจัดอันดับที่สูงขึ้นเพียงเพราะโพสต์ช้ากว่าคำตอบอื่น ๆ มาก
dschaeffer

จะเพิ่มสิ่งนี้ลงใน csproj ได้อย่างไร?
jle

@jle ฉันคิดว่าคุณสามารถเพิ่มลงใน csproj ของคุณในเป้าหมาย AfterBuild นี่คือลิงค์จาก msdnและอีกโพสต์ในหัวข้อของเหตุการณ์ prebuild และ postbuild หมายเหตุฉันยังไม่ได้ทดสอบรวมสิ่งนี้ใน csproj แต่ฉันสงสัยว่ามันจะใช้ได้
mcdon

1
11 ปีที่ไปงานปาร์ตี้ แต่ขอบคุณสำหรับการกล่าวถึง!
Dave Templin

9

Make My Manifest (MMM)เป็นเครื่องมือที่ดีสำหรับการทำสิ่งนี้ นอกจากนี้ยังสามารถเขียนสคริปต์เพื่อประมวลผลไฟล์ DLL / OCX ทั้งหมดของคุณโดยใช้mt.exeเพื่อสร้างรายการสำหรับแต่ละไฟล์จากนั้นรวมเข้าด้วยกัน MMM มักจะดีกว่า / ง่ายกว่าเพราะจัดการกรณีพิเศษ / แปลก ๆ มากมาย


3
ฉันค่อนข้างกังวลเกี่ยวกับสิ่งที่ MMM นี้ มันเป็นแค่บล็อกฟรีแวร์ แต่ไม่มีซอร์สโค้ดมีเพียงลิงค์ไปยัง "exe ที่แตกตัวเอง" และฉันเห็นความคิดเห็นเกี่ยวกับยูทิลิตี้ที่ทำให้ XP ขัดข้อง mmm ...
Wim Coenen

"ข้อขัดข้อง" เหล่านั้นคือยูทิลิตี้ MMM ที่กำลังจะตาย สิ่งนี้ได้รับการแก้ไขแล้วในเวอร์ชัน 0.6.5 แต่คุณจะต้องใช้ 0.6.6 อยู่ดีเนื่องจากในขณะที่ยังเป็นเบต้าจะไม่หมดอายุอีกต่อไป คุณสามารถใช้ MT.EXE แทนได้ตลอดเวลาแม้ว่าจะแนะนำไปแล้วก็ตาม
Bob

mt.exe ไม่ได้สร้าง progid เมื่อฉันใช้บนเซิร์ฟเวอร์ com ดั้งเดิมเช่น dbgrid32.ocx
Wim Coenen

การใช้ COM ฟรี reg กับคอมโพเนนต์ที่เขียนขึ้น. NET สามารถทำให้ XP ขัดข้องได้ - ดูที่stackoverflow.com/questions/617253/…
MarkJ

8

คุณสามารถใช้Unattended 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
#

จะทำงานบน Windows 32 หรือ 64 บิต


+1 น่าสนใจโดยเฉพาะอย่างยิ่งเนื่องจากมีซอร์สโค้ด ฉันสับสนเล็กน้อยกับความคล้ายคลึงกันของชื่อดูเหมือนว่า "make my manifest" และ "unattended make my manifest" เป็นเครื่องมือที่แตกต่างกันโดยผู้เขียนคนละคนกัน
Wim Coenen

2
หมายเหตุ - ณ ปี 2017 (8 ปีในวันที่ ... ) โครงการนี้ยังคงทำงานอยู่โดยมีการอัปเดตการบำรุงรักษาเป็นครั้งคราว github.com/wqweto/UMMM/commits/master ทำงานได้ดีและฉันใช้เป็นประจำ
UuDdLrLrSs

0

ในการกรอก ProgIDs ที่ mt.exe ไม่มีให้คุณสามารถเรียกProgIDFromCLSIDค้นหาได้จากรีจิสทรี สิ่งนี้ต้องมีการลงทะเบียน COM แบบดั้งเดิมก่อนที่จะเสร็จสิ้นไฟล์รายการ แต่ในภายหลังไฟล์ Manifest จะเป็นแบบพอเพียง

รหัส C # นี้เพิ่ม ProgIDs ให้กับคลาส COM ทั้งหมดในรายการ:

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

รหัสอาศัยนิยามการทำงานร่วมกันเหล่านี้:

[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.