استخدام DLL لـ .NET 8 من VBA بأنواع صريحة: نشر COM وTLB بـ dscom

· آخر تحديث: · · C#, .NET 8, VBA, COM, Office, dscom

سجل التعديلات (2 تحديثات، آخر تحديث 2 Sep، 2026)

سجل بالتغييرات التي أُجريت على هذا المقال. وحيثما حُفظت نسخة سابقة، تبقى متاحة للقراءة عبر رابط دائم يحمل معرّف DOI.

أُعيدَت الترجمة العربية كترجمة كاملة عن النص الياباني الأصلي، وأُضيفَت خريطة المعرفة.
أعيدت الترجمة كترجمة كاملة عن النص الياباني الأصلي. كانت النسخة العربية السابقة مختصراً يسقط أبواباً وجداول ورسوم Mermaid وتعليقات الأشكال وFAQ. أُعيدت هذه العناصر وفق الأصل الياباني، والادّعاءات التقنية مطابقة للنسخة اليابانية.
النشر الأول
الاستشهاد بهذا المقال(DOI: 10.5281/zenodo.21621394)

هذا المقال محفوظ على Zenodo. يرد أدناه معرّف DOI الذي يشير دائمًا إلى أحدث نسخة، ومعرّف DOI المثبَّت على النسخة التي تقرؤها.

小村 豪 (2026). استخدام DLL لـ .NET 8 من VBA بأنواع صريحة: نشر COM وTLB بـ dscom. شركة كومورا سوفت ذ.م.م.. https://doi.org/10.5281/zenodo.21621394 https://comcomponent.com/ar/blog/2026/03/16/007-dotnet8-dll-typed-vba-com-dscom-tlb/

DOI (أحدث نسخة)
10.5281/zenodo.21621394
DOI (هذه النسخة)
10.5281/zenodo.22240850

ما زالت مشاهد استدعاء معالجة .NET 8 من VBA شائعة. خصوصاً عندما تُبقى أصول Excel أو Access كما هي، ويُراد إخراج الجزء الثقيل فقط إلى C#: معالجة ثقيلة، معالجة نصوص، HTTP، تشفير، منطق عمل.

غير أن الميل إلى الربط المتأخّر بـ CreateObject يملأ جانب VBA بـ Object. تضعف IntelliSense، وخطأ اسم المنهج لا يُكتشف حتى التنفيذ، وينزلق الأمر تدريجياً إلى وحل الاعتماد على النصوص.

وحل الربط المتأخّرمخطّط يبيّن أن الميل إلى الربط المتأخّر بـ CreateObject يملأ جانب VBA بـ Object، فتضعف IntelliSense، ولا يُكتشف خطأ اسم المنهج حتى التنفيذ.ربط متأخّر بـ CreateObjectجانب VBA ممتلئ بـ Objectتضعف IntelliSenseخطأ الكتابة لا يُكتشف حتى التنفيذ

الشكل 1: كلّما ملت إلى الربط المتأخّر، غصت في وحل الاعتماد على النصوص.

لذلك هذه المرّة نحصر الترتيب في نشر DLL لـ .NET 8 عبر COM، وتوليد مكتبة أنواع (TLB) بـ dscom، واستخدامها من VBA بربط مبكّر وأنواع صريحة.

حديث .NET Framework + RegAsm القديم، وكتابة IDL يدوياً وتثبيتها بـ MIDL، وReg-Free COM، نضعها جانباً هذه المرّة. هنا مسار واحد فقط: .NET 8 / COM host / dscom / VBA early binding.

الكود الوارد في المقالة منشور على GitHub كعيّنة كاملة قابلة للبناء والتحقق (مكتبة نشر COM، سكربتات توليد TLB والتسجيل، وحدة VBA، اختبارات وحدة).

dotnet8-dll-typed-vba-com-dscom-tlb - komurasoft-blog-samples (GitHub)

البيئة المطلوبة

البند المطلوب
نظام التشغيل Windows. ستُجري تسجيل COM، فيلزم تشغيل regsvr32 بامتياز مدير
.NET SDK .NET 8 SDK. EnableComHosting ميزة من .NET 5 فما بعده
Office Excel أو Access. تحقّق أولاً أهو إصدار 32 بت أم 64 بت (الفصل 3)
أداة توليد TLB dscom. طريق الحصول يختلف بين 64 بت و32 بت (الفصل 6)
جهاز العميل زمن تشغيل .NET 8 بنفس bitness مكتب Office (الفصل 9)

قبل الدخول في الخطوات، يُنصح بقوّة بتسجيل إصدارات بيئتك. عندما يصير «نفس الخطوات لا تعمل»، لا يبقى ما تقارن به إلا هذه المعلومات.

# .NET SDK とランタイムの一覧(x64 / x86 のどちらが入っているかも分かります)
dotnet --info

# Windows のビルド番号
winver

إصدار Office وبتّاته يُؤكَّدان من Excel: ملف > حساب > معلومات عن Excel. في نهاية سطر عنوان الحوار يظهر 32 بت أو 64 بت.

1. الخلاصة أوّلاً

إن رُتّبت الخلاصة فقط، فالمسار كالتالي.

  • ابنِ مكتبة أصناف .NET 8 بـ EnableComHosting=true
  • اصنع واجهة صريحة وصنفاً يُعرضان لـ COM
  • اجعل الصنف ClassInterfaceType.None ولا تهرب إلى AutoDual
  • اجعل الواجهة التي يستخدمها VBA هي InterfaceIsDual
  • من *.dll الناتجة بعد البناء ولّد *.tlb بـ dscom tlbexport
  • سجّل *.comhost.dll بـ regsvr32
  • سجّل *.tlb بـ dscom tlbregister
  • أضف مرجعاً في VBA واستخدم بأنواع صريحة مثل Dim x As اسم المكتبة.IYourInterface

باختصار: مدخل COM هو *.comhost.dll الذي يصنعه .NET SDK، ومعلومات النوع هي *.tlb التي يصنعها dscom، وVBA يرى تلك TLB ويربط ربطاً مبكّراً.

المسار الواحد حتى الاستخدام بأنواع صريحةمخطّط يبيّن المسار: البناء بـ EnableComHosting، وتوليد TLB بـ dscom tlbexport، وتسجيل comhost بـ regsvr32، وتسجيل TLB بـ dscom tlbregister، ثم الاستخدام بأنواع صريحة من مراجع VBA.ابنِ بـ EnableComHostingولّد TLB بـ dscom tlbexportسجّل comhost بـ regsvr32سجّل TLB بـ dscom tlbregisterأضف مرجعاً في VBA واستخدم بأنواع صريحة

الشكل 2: إن سرت بالترتيب: بناء، توليد TLB، تسجيلان، مرجع، استطعت الاستدعاء بأنواع صريحة.

خريطة المعرفة لهذه المقالة

استخدام مكتبة أصناف .NET 8 من VBA بأنواع صريحة يتطلّب مكتبة أنواع، أي معلومات نوع COM، وأداة اسمها dscom تولّدها وتسجّلها خلفاً لـ tlbexp.exe وRegAsm.exe اللذين أُلغيا مع .NET Framework. في جانب .NET، ضيف COM مبني بـ EnableComHosting مدخل تشغيل COM، وتسجيل regsvr32 وتطابق bitness مع Office شرطان مسبقان. في جانب VBA، تحميل مكتبة الأنواع عبر مرجع يتيح الربط المبكّر، وهو أأمن أنواع من الربط المتأخّر بـ CreateObject. التوافق بعد النشر يعتمد على معاملة IID وCLSID وعلى اختيار ClassInterfaceType، وتوليفة ClassInterfaceType.None وInterfaceIsDual وDispId هي الطريقة المعيارية لتفادي كسر مراجع VBA.

خريطة معرفة استخدام DLL لـ .NET 8 من VBA بأنواع صريحةمخطّط يبيّن أن VBA يحتاج مكتبة أنواع ليستخدم COM بأنواع صريحة عبر الربط المبكّر، وأن dscom يولّد تلك TLB ويسجّلها، وأن جانب .NET 8 يُكشَف كضيف COM، وكيف يؤثّر ClassInterfaceType ومعاملة IID وCLSID في توافق مراجع VBAيشترطيشترطيستخدميستخدمغير موصى به لـينفّذيخلفيُكوَّن بـيُكوَّن بـيشترطينفّذيستخدميشترطيشترطقد يسبّبقد يسبّبقد يسبّبغير موصى به لـموصى به لـيخفّفموصى به لـيستخدميُتحقّق بـيُكوَّن بـيشترطيشترطيشترطVBA (Visual Basic for Applications)dscomمكتبة الأنواع (TLB)ربط مبكّر (VBA)ربط متأخّر (CreateObject)tlbexp.exe / RegAsm.exeCOM host (*.comhost.dll)regsvr32.NET (Core وما بعده)COM (Component Object Model)IID (معرّف الواجهة)CLSID (Class ID)كسر مرجع VBA أو التسجيلClassInterfaceType.AutoDualClassInterfaceType.NoneDispIdAttributeInterfaceIsDual (واجهة مزدوجة)HRESULTاستثناء .NETComVisibleAttributeمتطلّب تطابق bitness

في المخطّط، يشير الخطّ المتّصل إلى علاقة قائمة دائماً، ويشير الخطّ المتقطّع إلى علاقة مشروطة (شروط قيامها مذكورة في شرح كلّ علاقة في الصفحة التفصيليّة). القائمة الكاملة للعلاقات (المجموع 27، مع الأدلّة ودرجة اليقين) وتعريفات المفاهيم الرئيسة مجمّعة في صفحة تفاصيل خريطة المعرفة (باليابانية). البيانات: JSON-LD / Turtle

2. الصورة الكلّية لهذا التكوين

أولاً، دور كل جزء في ورقة واحدة.

الحصول على معلومات النوع من TLB المضافة مرجعاًاستدعاء COMVBA / Excel / AccessVbaTypedComSample.tlbVbaTypedComSample.comhost.dllVbaTypedComSample.dll (.NET 8).NET 8 Runtime

الشكل 3: يحصل VBA على معلومات النوع من TLB، ويستدعي جسم تنفيذ .NET 8 عبر comhost.

أدوار كل ملف كالتالي.

الملف الدور
VbaTypedComSample.dll جسم تنفيذ .NET 8
VbaTypedComSample.comhost.dll المدخل الذي يُستدعى من COM
VbaTypedComSample.tlb معلومات النوع التي يراها VBA
VbaTypedComSample.deps.json معلومات حل الاعتمادات
VbaTypedComSample.runtimeconfig.json معلومات إقلاع زمن تشغيل .NET

المهم هنا: ما يحتاجه VBA لمعرفة الأنواع هو TLB، وما يحتاجه مدخل تشغيل COM هو comhost.

تمرير *.dll وحدها لا يكفي: هذا الجانب غير المستقيم في عالم COM.

3. ما يُقرَّر أولاً: مواءمة 32 بت / 64 بت

إن أسقطت هذا، فباحتمال عالٍ تتدحرج نحو «لا يمكن إنشاء كائن لمكوّن ActiveX».

واءم bitness بين Office / VBA وخادم COM.

جانب الاستخدام مؤشر جانب .NET توليد TLB أمر التسجيل
Office 64 بت x64 / win-x64 dscom C:\Windows\System32\regsvr32.exe
Office 32 بت (على Windows 64 بت) x86 / win-x86 dscom32.exe C:\Windows\SysWOW64\regsvr32.exe

في COM host من .NET 5+ فما بعده، إبقاء AnyCPU يميل *.comhost.dll إلى جانب 64 بت فيصطدم بـ Office 32 بت أحياناً. لذلك الأأمن التصريح بـ x86 / x64 وفق Office.

عدم التطابق الذي يجلبه ترك AnyCPUمخطّط يبيّن أن إبقاء AnyCPU يميل comhost إلى جانب 64 بت فيصطدم بـ Office 32 بت أحياناً، لذلك الأمان التصريح بـ x86 أو x64 وفق Office.إبقاء AnyCPUيميل comhost إلى جانب 64 بتيصطدم بـ Office 32 بتصرّح بالبتّات وفق Office

الشكل 4: انحراف bitness طريق مختصر إلى «لا يمكن إنشاء الكائن».

كود هذه المقالة مثال موجّه إلى Office 64 بت. لـ Office 32 بت اقرأ x64 لاحقاً على أنه x86، و win-x64 على أنه win-x86.

4. اصنع جانب .NET 8

هنا عيّنة دنيا يمكن استدعاء Add و Divide و Hello منها من VBA.

4.1 .csproj

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <EnableComHosting>true</EnableComHosting>
    <PlatformTarget>x64</PlatformTarget>
    <NETCoreSdkRuntimeIdentifier>win-x64</NETCoreSdkRuntimeIdentifier>
  </PropertyGroup>
</Project>

الجوهر EnableComHosting. إن أضفته وُلد VbaTypedComSample.comhost.dll عند البناء.

4.2 اجعل التجميعة كلّها غير ظاهرة لـ COM افتراضياً

تريد ComVisible(true) للأنواع المعروضة لـ COM فقط، فالأسهل جعل التجميعة كلّها false.

using System.Runtime.InteropServices;

[assembly: ComVisible(false)]

4.3 اكتب الواجهة والصنف المنشورين

using System.Runtime.InteropServices;

namespace VbaTypedComSample;

[ComVisible(true)]
[Guid("2A1BBEDE-DE6E-4C34-AD60-2E9E0E33E999")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface ICalculator
{
    [DispId(1)]
    int Add(int x, int y);

    [DispId(2)]
    double Divide(double x, double y);

    [DispId(3)]
    string Hello(string name);
}

[ComVisible(true)]
[Guid("FAD1C752-0BB6-4DDD-889F-FE446350847A")]
[ClassInterface(ClassInterfaceType.None)]
[ComDefaultInterface(typeof(ICalculator))]
public class Calculator : ICalculator
{
    public Calculator()
    {
    }

    public int Add(int x, int y) => checked(x + y);

    public double Divide(double x, double y)
    {
        if (y == 0)
        {
            throw new ArgumentOutOfRangeException(nameof(y), "لا يمكن القسمة على 0.");
        }

        return x / y;
    }

    public string Hello(string name)
    {
        if (string.IsNullOrWhiteSpace(name))
        {
            return "Hello";
        }

        return $"Hello, {name}";
    }
}

ما ينبغي تثبيته في هذا الكود:

  • اجعل Guid للواجهة وللصنف منفصلين
  • اجعل ClassInterfaceType.None ولا تعتمد على واجهة صنف مولَّدة تلقائياً
  • اجعل InterfaceIsDual ليسهل التعامل من VBA
  • تعيين DispId يقلّل حوادث العبث بترتيب المناهج بعد النشر
  • يُنشأ من COM بـ New، فجهّز منشئ public بلا وسائط
تركيب النوع المنشورمخطّط يبيّن تركيباً يضع InterfaceIsDual وDispId على الواجهة الصريحة ICalculator، وينفّذ الصنف Calculator بـ ClassInterfaceType.None، ويفرّق Guid بين الواجهة والصنف.ينفّذICalculator (واجهة صريحة)InterfaceIsDual وDispIdCalculator (صنف)ClassInterfaceType.NoneGuid منفصل لكل منهما

الشكل 5: جوهر النشر بأنواع صريحة توليفة واجهة صريحة وصنف معيَّن None.

5. ابنِ

ابنِ بإصدار Release.

dotnet build -c Release

بعد البناء تصطف في مجلد الإخراج على الأقل ملفات كهذه.

bin/
  Release/
    net8.0-windows/
      VbaTypedComSample.dll
      VbaTypedComSample.comhost.dll
      VbaTypedComSample.deps.json
      VbaTypedComSample.runtimeconfig.json

هذا المجلد هو ما يُستخدم في التوزيع والتسجيل. إن غيّرت موضع النشر لاحقاً، لزم إعادة التسجيل أيضاً.

6. ولّد TLB بـ dscom

6.1 ما هو dscom

dscom أداة سطر أوامر مفتوحة المصدر لتوليد مكتبة أنواع COM (TLB) من تجميعة .NET وتسجيلها. تنشرها شركة dSPACE، والرخصة Apache-2.0.

لماذا تلزم: لأن tlbexp.exe و RegAsm.exe أُلغيا من .NET 5 فما بعده. في عصر .NET Framework كان الاثنان يولّدان TLB ويسجّلان التجميعة، أما .NET 5+ فلا يحمل خلفاً قياسياً. dscom أداة سُدّ بها ذلك الفراغ.

الفراغ الذي يسدّه dscomمخطّط يبيّن أنه في عصر .NET Framework كان tlbexp.exe وRegAsm.exe يولّدان TLB ويسجّلان التجميعة، وأن كليهما أُلغي بلا خلف قياسي من .NET 5 فما بعده، فيسدّ dscom ذلك الفراغ.عصر .NET Frameworktlbexp.exe وRegAsm.exeمن .NET 5 فما بعدهكلاهما أُلغي بلا خلفdscom يسدّ الفراغ

الشكل 6: أداة توليد TLB من .NET 5 فما بعده صارت dscom.

يكفي حفظ الأوامر الفرعية التالية.

الأمر الفرعي الدور
tlbexport كتابة TLB من التجميعة
tlbregister تسجيل TLB في النظام
tlbunregister إلغاء تسجيل TLB
tlbdump إخراج محتوى TLB للفحص
tlbembed تضمين TLB في ملف

tlbdump مفيد للتأكد قبل فتح VBA من أن الأنواع المقصودة دخلت TLB المولَّدة.

6.2 حالة 64 بت

إن أردت صنع TLB 64 بت فقط، تدخل بـ dotnet tool.

dotnet tool install --global dscom

ثم ولّد TLB من التجميعة المبنية.

dscom tlbexport .\bin\Release\net8.0-windows\VbaTypedComSample.dll --out .\bin\Release\net8.0-windows\VbaTypedComSample.tlb

6.3 حالة Office 32 بت: من أين تحصل على dscom32.exe

هنا أكثر موضع يُحتبَس فيه دعم Office 32 بت.

dscom الداخل بـ dotnet tool install يعالج تجميعات AnyCPU أو 64 بت فقط، ولا يولّد إلا TLB 64 بت. لصنع TLB 32 بت تحتاج ملف تنفيذ آخر هو dscom32.exe، وهذا يُنزَّل من صفحة إصدارات GitHub لا من NuGet.

في مثال هذه المقالة يُوضع dscom32.exe المنزَّل في مجلد tools تحت المشروع. موضع الوضع حر، لكن لا توزّعه مع مخرجات البناء. أداة وقت تطوير، ولا تلزم وقت التشغيل.

شرط يسهل إسقاطه أيضاً: لتشغيل dscom32.exe يلزم زمن تشغيل .NET بإصدار x86. بسبب تحميل dscom لـ hostfxr.dll، لا يعمل في بيئة فيها إصدار x64 فقط. في قائمة خرج dotnet --info تحقّق من وجود زمن تشغيل x86.

إعداد صنع TLB 32 بتمخطّط يبيّن أن dscom الداخل بـ dotnet tool لا يصنع إلا TLB 64 بت، لذلك تُصنع TLB 32 بت بـ dscom32.exe من صفحة إصدارات GitHub، وتشغيله يحتاج زمن تشغيل .NET بإصدار x86.تلزم TLB 32 بتاحصل على dscom32.exe من صفحة الإصداراتتحقّق من وجود زمن تشغيل x86tlbexport بـ dscom32.exeإصدار dotnet tool لـ TLB 64 بت فقط

الشكل 7: دعم 32 بت يختلف من مسار الحصول على الأداة، لذلك يسهل الاحتباس هنا.

.\tools\dscom32.exe tlbexport .\bin\Release\net8.0-windows\VbaTypedComSample.dll --out .\bin\Release\net8.0-windows\VbaTypedComSample.tlb

وثائق dscom نفسها أيضاً توصي، إن استخدمت 32 بت، بتجميع التجميعة نفسها 32 بت، لأن إبقاء AnyCPU يولّد *.comhost.dll على أنه 64 بت. نفس خلاصة الفصل 3.

إن سئمت الطرق اليدوي عند كل بناء، حزمة dSPACE.Runtime.InteropServices.BuildTasks تولّد TLB تلقائياً عند التجميع.

7. سجّل COM host وTLB

نفّذ هنا من موجّه أوامر / PowerShell بامتياز مدير.

7.1 حالة Office 64 بت / COM 64 بت

$out = Resolve-Path .\bin\Release\net8.0-windows

C:\Windows\System32\regsvr32.exe "$out\VbaTypedComSample.comhost.dll"
dscom tlbregister "$out\VbaTypedComSample.tlb"

7.2 حالة Office 32 بت (على Windows 64 بت)

$out = Resolve-Path .\bin\Release\net8.0-windows

C:\Windows\SysWOW64\regsvr32.exe "$out\VbaTypedComSample.comhost.dll"
.\tools\dscom32.exe tlbregister "$out\VbaTypedComSample.tlb"

ما يُفعل هنا أمران.

  • تسجيل *.comhost.dll كخادم COM بـ regsvr32
  • تسجيل *.tlb كمكتبة أنواع بـ tlbregister
التسجيل مسارانمخطّط يبيّن تسجيلين بامتياز مدير: regsvr32 يسجّل comhost كخادم COM، وdscom tlbregister يسجّل TLB كمكتبة أنواع.تشغيل بامتياز مديرسجّل comhost بـ regsvr32سجّل TLB بـ tlbregisterتسجيل مدخل تشغيل COMتسجيل معلومات النوع التي يراها VBA

الشكل 8: مدخل التشغيل ومعلومات النوع شيئان مختلفان، لذلك التسجيل زوج.

8. أضف مرجعاً في VBA واستخدم بأنواع صريحة

  1. افتح Excel أو Access
  2. افتح محرّر VBA (VBE) بـ Alt + F11. من الشريط: تبويب مطور > Visual Basic. إن لم يظهر تبويب مطور، ضع علامة على مطور في ملف > خيارات > تخصيص الشريط
  3. في قائمة VBE: أدوات > مراجع
  4. قائمة ملفات المكتبات المتاحة مرتّبة أبجدياً. إن نجح التسجيل ظهر فيها اسم المكتبة (افتراضياً اسم التجميعة نفسه VbaTypedComSample)، فضع علامة في خانة الاختيار يساراً ثم موافق
  5. إن لم تظهر في القائمة، اختر VbaTypedComSample.tlb مباشرة من زر استعراض...

إن لم تظهر في القائمة، السبب غالباً أحد اثنين: عدم تطابق bitness في الفصل 3، أو عدم مرور tlbregister في الفصل 7. Office 32 بت لا يرى TLB المسجّلة 64 بت.

عزل سبب غياب المكتبة عن المراجعمخطّط يبيّن أن سبب غياب المكتبة عن قائمة المراجع غالباً عدم تطابق bitness أو عدم مرور tlbregister، وأن Office 32 بت لا يرى TLB المسجّلة 64 بت.المكتبة لا تظهر في القائمةشكّ في عدم تطابق bitness في الفصل 3شكّ في فشل tlbregister في الفصل 7Office 32 بت لا يرى TLB 64 بت

الشكل 9: سبب الغياب عن القائمة ينحصر تقريباً في bitness أو التسجيل.

هل دخل المرجع يُؤكَّد بفتح عرض > مستعرض الكائنات (F2) واختيار VbaTypedComSample في منتقي المكتبة أعلى اليسار. إن ظهرت ICalculator و Calculator و Add / Divide / Hello، فقد وُلدت TLB صحيحاً.

Option Explicit

Public Sub UseCalculator()
    Dim calc As VbaTypedComSample.ICalculator
    Set calc = New VbaTypedComSample.Calculator

    Debug.Print calc.Add(10, 20)
    Debug.Print calc.Divide(10, 4)
    Debug.Print calc.Hello("VBA")
End Sub

ضع المؤشّر على هذا الإجراء ونفّذه بـ F5، وافتح النافذة الفورية بـ Ctrl + G، فتظهر ثلاثة أسطر وفق تنفيذ الفصل 4.

30
2.5
Hello, VBA

إن طابق هذا التوقّع، فقد مرّ المرجع وتسجيل COM وإقلاع زمن التشغيل وتمرير الوسائط والقيم الراجعة جميعاً. بالمقابل، إن لم تطابق القيم فشكّ في تنفيذ جانب .NET، وإن تعذّر التشغيل أصلاً فشكّ في الفصلين 3 و7.

العزل بنتيجة التشغيلمخطّط يبيّن أنه إن طابقت نتيجة العيّنة التوقّع فقد مرّ المسار من المرجع حتى التمرير، وإن لم تطابق القيم فشكّ في تنفيذ جانب .NET، وإن تعذّر التشغيل فشكّ في bitness الفصل 3 وتسجيل الفصل 7.وفق التوقّعالقيم لا تطابقلا يعملشغّل عيّنة VBAما النتيجةالمسار كلّه نافذشكّ في تنفيذ جانب .NETشكّ في bitness والتسجيل

الشكل 10: ثلاثة أسطر خرج وحدها تقرّر أي طبقة تشكّ فيها.

عندها ينال جانب VBA هذه الفوائد.

  • تعمل IntelliSense
  • يسهل اكتشاف خطأ اسم المنهج قبل التنفيذ
  • يمكن فحص واجهة برمجيّة منشورة في Object Browser
  • أوضح قراءة من كتابة Object صريحة

8.1 الاستثناء يصير خطأ COM في جانب VBA

مثلاً إن أُلقي استثناء في جانب .NET مثل Divide(10, 0)، يراه جانب VBA خطأ COM.

Option Explicit

Public Sub UseCalculatorWithErrorHandling()
    On Error GoTo EH

    Dim calc As VbaTypedComSample.ICalculator
    Set calc = New VbaTypedComSample.Calculator

    Debug.Print calc.Divide(10, 0)
    Exit Sub

EH:
    Debug.Print Err.Number
    Debug.Print Hex$(Err.Number)
    Debug.Print Err.Description
End Sub

إن ثبتت قراءة القيم الظاهرة هنا، سرع العزل.

البند ما يدخل
Err.Number HRESULT الموافق لاستثناء .NET، كـ Long موقّع. العشري صعب القراءة فحوّله إلى ست عشري بـ Hex$(Err.Number)
Err.Description عبر IErrorInfo لـ COM تدخل رسالة استثناء .NET كما هي. في الكود أعلاه سلسلة تتضمّن لا يمكن القسمة على 0.

قيمة HRESULT ثابتة لكل نوع استثناء. الموافق لـ ArgumentOutOfRangeException هو COR_E_ARGUMENTOUTOFRANGE، والقيمة 0x80131502. أي إن صار Hex$(Err.Number) هو 80131502، فقد وصل ArgumentOutOfRangeException من جانب .NET كما هو متوقّع.

الأبرز كالتالي.

استثناء .NET ثابت HRESULT القيمة
ArgumentException COR_E_ARGUMENT 0x80070057
ArgumentOutOfRangeException COR_E_ARGUMENTOUTOFRANGE 0x80131502
InvalidOperationException COR_E_INVALIDOPERATION 0x80131509
NotSupportedException COR_E_NOTSUPPORTED 0x80131515
استثناء عام غير ما سبق COR_E_EXCEPTION 0x80131500

إن أردت فصل المعالجة حسب نوع الاستثناء في جانب VBA، فستتفرّع بهذا HRESULT. غير أن تصميماً يتفرّع بـ HRESULT ضعيف أمام تغيير نوع الاستثناء في جانب .NET، لذلك الفشل العملي أستقر على الحدود إن أُرجع بقيمة راجعة أو رمز خطأ لا باستثناء.

حتى يصل استثناء .NET إلى VBAمخطّط يبيّن أن الاستثناء المُلقى في جانب .NET يُحوَّل إلى HRESULT عند حدود COM، فيدخل ذلك HRESULT في Err.Number كـ Long موقّع، ورسالة الاستثناء عبر IErrorInfo في Err.Description.يُلقى استثناء في جانب .NETيُحوَّل إلى HRESULT عند حدود COMيدخل موقّعاً في Err.Numberالرسالة في Err.Descriptionيُقرأ ست عشرياً بـ Hex$

الشكل 11: الاستثناء يتغيّر هيئة إلى HRESULT عند حدود COM ويصل إلى Err في VBA.

9. النظرة عند التوزيع

المهم عند التوزيع وضع مجموعة الإخراج لا توزيع DLL وحدها.

VbaTypedComSample.dll
VbaTypedComSample.comhost.dll
VbaTypedComSample.deps.json
VbaTypedComSample.runtimeconfig.json
VbaTypedComSample.tlb
(مجموعة DLL الاعتماد إن لزم)

ثم يلزم جهاز العميل زمن تشغيل .NET 8 الموافق. تشغيل COM host ليس توزيعاً self-contained، بل framework-dependent أساساً.

ما يُثبَّت تحديداً كالتالي.

  • صفحة التوزيع تنزيلات .NET 8
  • المطلوب زمن تشغيل لا SDK. عيّنة هذه المقالة مكتبة أصناف بلا شاشة، فيكفي .NET Runtime. إن استخدمت أنواعاً من WPF أو Windows Forms لزم .NET Desktop Runtime
  • bitness يُواءم مع Office. Office 64 بت فزمن تشغيل x64، وOffice 32 بت فـ x86. لنفس سبب التصريح بـ x64 / x86 في الفصل 3، إن لم يتطابق هنا لا يقلع
  • هل ثُبّت يُعرف بتشغيل dotnet --list-runtimes على جهاز العميل والنظر إلى سطر Microsoft.NETCore.App 8.x

في مواد التوزيع اكتب حتماً «نوع زمن التشغيل المطلوب وإصداره وbitness». إن سقط من خطوات التثبيت، رأيت في الميدان «لا يمكن إنشاء كائن لمكوّن ActiveX» وشككت في bitness وأضعت وقتاً.

ما يُكمَل عند التوزيعمخطّط يبيّن أن التوزيع يضع مجموعة الإخراج لا DLL وحدها، ويثبّت على جهاز العميل زمن تشغيل .NET 8 بنفس bitness مكتب Office، ويكتب نوع زمن التشغيل وإصداره وbitness في مواد التوزيع.ضع مجموعة الإخراجيعمل على العميلزمن تشغيل .NET 8 بنفس bitnessاكتب معلومات زمن التشغيل في المواد

الشكل 12: DLL وحدها لا تعمل، ولا تعمل إلا باكتمال المجموعة وزمن التشغيل.

10. مواضع الاحتباس

10.1 لا تترك AnyCPU كما هو

إن انحرف bitness VBA / Office عن bitness COM host، جاء الفشل بشكل مزعج جدّاً.

  • Office 64 بت فـ x64 / win-x64
  • Office 32 بت فـ x86 / win-x86

10.2 لا تستخدم ClassInterfaceType.AutoDual

يبدو سهلاً، لكنه ينكسر بسهولة إن لمست ترتيب الأعضاء أو التركيب بعد النشر.

إن أردت استخداماً مستقرّاً بأنواع صريحة من VBA، فالقاعدة تعريف واجهة صريحة، والصنف ClassInterfaceType.None.

10.3 لا تولّد GUID بلا رويّة من جديد

في COM المعرّف GUID هو العقد نفسه. استبدال IID أو CLSID بلا رويّة بعد النشر يكسر مراجع VBA أو التسجيل القائمة.

10.4 لا تكسر واجهة منشورة

COM قد لا يمرّ بسلام حتى مع «منهج واحد أُضيف لاحقاً فقط».

  • أبقِ ICalculator
  • إن كبر التغيير فأنشئ ICalculator2
  • يجوز للصنف تنفيذ الاثنين
طريقة حفظ واجهة منشورةمخطّط يبيّن حفظ التوافق بإبقاء ICalculator المنشور كما هو، وإنشاء ICalculator2 إن كبر التغيير، وجواز تنفيذ الصنف للاثنين.ICalculator المنشورأبقه كما هوتريد تغييراً كبيراًأنشئ ICalculator2يجوز للصنف تنفيذ الاثنين

الشكل 13: أسلوب COM إبقاء العقد القائم وإضافة عقد جديد إلى جانبه.

10.5 قرّب الأنواع بتواضع

عند الحدود المعروضة لـ VBA، عدم التأنّق أأمن.

ما يتوافق جيّداً أولاً من هذا القبيل.

  • int
  • double
  • bool
  • string
  • DateTime
  • decimal
  • enum

10.6 لا تحدّث وOffice مفتوح

قد يمسك Excel أو Access بـ DLL، فيصير البناء أو إعادة التسجيل مزعجاً.

  • أغلق Office
  • ألغِ التسجيل إن لزم
  • أعد البناء
  • سجّل مرّة أخرى

إلغاء التسجيل يتم بالترتيب العكسي لتسجيل، وبنفس أوامر bitness التي استُخدمت عند التسجيل. امتياز المدير لازم كما عند التسجيل.

# 64bit Office / 64bit COM の場合
$out = Resolve-Path .\bin\Release\net8.0-windows

dscom tlbunregister "$out\VbaTypedComSample.tlb"
C:\Windows\System32\regsvr32.exe /u "$out\VbaTypedComSample.comhost.dll"
# 32bit Office(64bit Windows 上)の場合
$out = Resolve-Path .\bin\Release\net8.0-windows

.\tools\dscom32.exe tlbunregister "$out\VbaTypedComSample.tlb"
C:\Windows\SysWOW64\regsvr32.exe /u "$out\VbaTypedComSample.comhost.dll"

/u في regsvr32 خيار إلغاء التسجيل. إن استخدمت regsvr32 مختلفاً عن التسجيل لم يُلغَ (ما سُجّل 64 بت لا يُزال بـ regsvr32 في SysWOW64). إن نقلت المجلد أو حذفته قبل الإلغاء، بقي في السجل تسجيل لمسار غير موجود.

طي التسجيل قبل التحديث وبعدهمخطّط يبيّن مسار التحديث: إغلاق Office، ثم إلغاء التسجيل إن لزم بالترتيب العكسي ونفس أوامر bitness المستخدمة عند التسجيل، ثم إعادة البناء، ثم التسجيل مرّة أخرى.أغلق Officeألغِ بالعكس إن لزمأعد البناءسجّل مرّة أخرىبنفس أوامر bitness المستخدمة عند التسجيل

الشكل 14: تجنّباً لـ DLL الممسوكة والتسجيل المتبقي، اجعل الإلغاء وإعادة التسجيل زوجاً.

11. الخلاصة

حديث استخدام DLL لـ .NET 8 بأنواع صريحة من VBA، إن حُصر في نشر COM + توليد TLB بـ dscom، ليس خطوات مخيفة إلى ذلك الحد. في جانب .NET 8 اجعل EnableComHosting=true وجهّز واجهة صريحة (الصنف ClassInterfaceType.None، ولـ VBA InterfaceIsDual)، وصنع TLB بـ dscom tlbexport، وسجّل *.comhost.dll بـ regsvr32 و *.tlb بـ dscom tlbregister. بعدها يكفي إضافة مرجع في VBA والربط المبكّر.

عند الحيرة، الحيلة فصل التفكير في COM host عن TLB.

  • مدخل التشغيل *.comhost.dll
  • معلومات النوع *.tlb
  • جسم التنفيذ *.dll

روابط مرجعية

أحدث المقالات التي تشترك في نفس الوسوم. عمّق فهمك بمواضيع مرتبطة.

ترتبط هذه المقالة بشكل طبيعي بصفحات الخدمات التالية.

الأسئلة الشائعة

أسئلة شائعة حول موضوع هذه المقالة.

ما المطلوب لاستخدام DLL لـ .NET 8 من VBA بأنواع صريحة (ربط مبكّر)؟
ابنِ مكتبة أصناف .NET 8 بـ EnableComHosting=true لتوليد *.comhost.dll، ثم ولّد *.tlb بـ dscom tlbexport. بعدها سجّل *.comhost.dll بـ regsvr32 و*.tlb بـ dscom tlbregister، وأضف تلك TLB في مراجع VBA، فتستخدم Dim x As اسم المكتبة.IYourInterface بأنواع صريحة. توزيع الأدوار: مدخل تشغيل COM هو *.comhost.dll، ومعلومات النوع التي يراها VBA هي *.tlb، وجسم التنفيذ هو *.dll.
ما سبب ظهور «لا يمكن إنشاء كائن لمكوّن ActiveX»؟
السبب النموذجي عدم تطابق bitness بين Office/VBA وخادم COM. لـ Office 64 بت ابنِ بـ x64/win-x64 وسجّل بـ regsvr32 في System32. لـ Office 32 بت (على Windows 64 بت) ابنِ بـ x86/win-x86 وسجّل بـ regsvr32 في SysWOW64، ولتوليد TLB استخدم dscom32.exe. في COM host لـ .NET 5 فما بعده، إبقاء AnyCPU يميل *.comhost.dll إلى جانب 64 بت فيصطدم بـ Office 32 بت، لذلك الأمان التصريح بـ x86/x64 وفق Office.
هل يُمنع استخدام ClassInterfaceType.AutoDual؟
يبدو سهلاً، لكنه ينكسر بسهولة إن لمست ترتيب الأعضاء أو التركيب بعد النشر، فينبغي تجنّبه. إن أردت استخداماً مستقرّاً بأنواع صريحة من VBA، عرّف واجهة صريحة واجعل الصنف ClassInterfaceType.None، واجعل الواجهة التي يستخدمها VBA هي InterfaceIsDual. تعيين DispId يقلّل حوادث تغيير ترتيب المناهج. في COM المعرّف GUID هو العقد نفسه، فتوليد IID أو CLSID بلا رويّة بعد النشر يكسر مراجع VBA أو التسجيل القائمة.
عند التوزيع، هل يكفي تمرير DLL وحدها؟
DLL وحدها لا تعمل. ضع معاً جسم التنفيذ *.dll و*.comhost.dll و*.deps.json و*.runtimeconfig.json و*.tlb ومجموعة DLL الاعتماد إن لزم. وعلى جهاز العميل زمن تشغيل .NET 8 الموافق، وتشغيل COM host ليس توزيعاً self-contained بل framework-dependent أساساً. إن غيّرت موضع النشر لاحقاً لزم إعادة التسجيل أيضاً.

الملف الشخصي للمؤلف

صفحة الملف الشخصي لمؤلف المقالة.

غو كومورا

مؤسّس شركة كومورا سوفت ذ.م.م.

يركّز على تطوير برامج ويندوز، والاستشارات التقنية، والتحقيق في الأخطاء، ويتميّز في المشاريع التي تبقى فيها الأصول القديمة ناشطة، وفي تشخيص الأعطال التي يصعب تحديد سببها.

العودة إلى المدونة