سؤال

لدي بعض التطبيقات (بعضها أصلي وبعضها .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>

كل هذا يعمل بشكل جيد ولكن الحفاظ على ملفات البيان هذه يدويًا يعد أمرًا مؤلمًا بعض الشيء.هل هناك طريقة لتوليد هذه الملفات تلقائيا؟من الناحية المثالية، أود فقط الإعلان عن تبعية التطبيق على قائمة خوادم COM (سواء الأصلية أو .NET) ثم السماح بإنشاء الباقي تلقائيًا.هل هو ممكن؟

هل كانت مفيدة؟

المحلول

ويبدو أن الحل الأمثل غير موجود بعد.تلخيص بعض الأبحاث:

جعل بياني (وصلة)

تقوم هذه الأداة بفحص مشروع VB6 للبحث عن تبعيات COM، ولكنها تدعم أيضًا الإعلان اليدوي لتبعيات COM المرتبطة متأخرًا (أي.تلك المستخدمة عبر CreateObject).

ومن المثير للاهتمام أن هذه الأداة تضع جميع المعلومات حول التبعيات داخل بيان التطبيق.يتم وصف تطبيق exe وتبعياته على أنه تجميع واحد يتكون من ملفات متعددة.لم أكن أدرك من قبل أن هذا ممكن.

تبدو أداة جيدة جدًا ولكن اعتبارًا من الإصدار 0.6.6 فهي تحتوي على القيود التالية:

  • فقط لتطبيقات VB6 ، يبدأ من ملف مشروع VB6.عار ، لأن الكثير مما يفعله لا علاقة له بـ VB6.
  • تطبيق نمط المعالج ، غير مناسب للاندماج في عملية البناء.هذه ليست مشكلة كبيرة إذا لم تتغير تبعياتك كثيرًا.
  • برنامج مجاني بدون مصدر، ومن الخطورة الاعتماد عليه لأنه قد يصبح برنامجًا مهجورًا في أي لحظة.

لم أختبر ما إذا كان يدعم مكتبات .NET com.

regsvr42 (رابط مشروع الكود)

تقوم أداة سطر الأوامر هذه بإنشاء ملفات بيان لمكتبات COM الأصلية.فهو يستدعي DllRegisterServer ثم يتجسس على التسجيل الذاتي لأنه يضيف معلومات إلى السجل.ويمكنه أيضًا إنشاء بيان عميل للتطبيقات.

لا تدعم هذه الأداة المساعدة مكتبات .NET COM، نظرًا لأنها لا تكشف عن روتين DllRegisterServer.

الأداة مكتوبة بلغة C++.يتوفر شفرة المصدر.

mt.exe

جزء من 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 ، مما يؤدي إلى كسر العملاء الذين يستخدمون CreateObject مع البروجيدات.
  • سيتم إنشاء المقتطف الثاني<runtime> و <mvid> العناصر التي تحتاج إلى تجريدها قبل أن تعمل البيان بالفعل.
  • لا يتم دعم توليد إظهار العميل للتطبيقات.

ربما تعمل إصدارات SDK المستقبلية على تحسين هذه الأداة، لقد اختبرت الإصدار الموجود في Windows SDK 6.0a (vista).

نصائح أخرى

ومع مهمة GenerateApplicationManifest أنا ولدت واضح في الأمر خط مطابقة للالبصرية ستوديو اضح يولد. وأظن البصرية ستوديو يستخدم GenerateApplicationManifest أثناء الإنشاء. أقل من بلدي النصي بناء والتي يمكن تشغيلها من سطر الأوامر باستخدام msbuild "msbuild build.xml"

وبفضل ديف تيمبلين وله آخر أن أشار لي في GenerateApplicationManifest مهمة ، وفي MSDN < وأ href = "http://msdn.microsoft.com/en-us/library/6wc2ccdc.aspx" يختلط = "noreferrer"> المزيد من الوثائق المهمة في .

و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 بت ويندوز.

لملء ProgIDs أن mt.exe لا تشمل، يمكنك الاتصال ProgIDFromCLSID للبحث عنها من التسجيل. وهذا يتطلب تسجيل COM التقليدي قبل الانتهاء من ملف واضح، ولكن في وقت لاحق، فإن ملف البيان الاكتفاء الذاتي.

وهذا 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;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top