.NET2.0 C# التشغيل المتداخل:كيفية الاتصال برمز COM من C#؟

StackOverflow https://stackoverflow.com/questions/469802

سؤال

في بيئة التطوير الأخيرة الخاصة بي، تمكنت من التفاعل بسهولة مع COM، واستدعاء الأساليب على كائنات COM.إليك الكود الأصلي، مترجمًا إلى كود نمط C# (لإخفاء اللغة الأصلية):

public static void SpawnIEWithSource(String szSourceHTML)
{
    OleVariant ie; //IWebBrowser2
    OleVariant ie = new InternetExplorer();
    ie.Navigate2("about:blank");

    OleVariant webDocument = ie.Document;
    webDocument.Write(szSourceHTML);
    webDocument.close;

    ie.Visible = True;
}

تبدأ الآن العملية الشاقة والمؤلمة لمحاولة التفاعل مع COM من التعليمات البرمجية المُدارة.

يحتوي PInvoc.net بالفعل على ملف ترجمة IWebBrower2, ، والنسبة النسبية منها هي:

[ComImport, 
   DefaultMember("Name"), 
   Guid("D30C1661-CDAF-11D0-8A3E-00C04FC9E26E"), 
   InterfaceType(ComInterfaceType.InterfaceIsIDispatch), 
   SuppressUnmanagedCodeSecurity]
public interface IWebBrowser2
{
    [DispId(500)]
    void Navigate2([In] ref object URL, [In] ref object Flags, [In] ref object TargetFrameName, [In] ref object PostData, [In] ref object Headers);

    object Document { [return: MarshalAs(UnmanagedType.IDispatch)] [DispId(0xcb)] get; }
}

لقد قمت بإنشاء فئة COM:

[ComImport]
[Guid("0002DF01-0000-0000-C000-000000000046")]
public class InternetExplorer
{
}

والآن حان الوقت لمعاملة C# الفعلية:

public static void SpawnIEWithSource(String szHtml)
{
    PInvoke.ShellDocView.IWebBrowser2 ie;
    ie = (PInvoke.ShellDocView.IWebBrowser2)new PInvoke.ShellDocView.InternetExplorer();

    //Navigate to about:blank to initialize the browser
    object o = System.Reflection.Missing.Value;
    String url = @"about:blank";
    ie.Navigate2(ref url, ref o, ref o, ref o, ref o);

    //stuff contents into the document
    object webDocument = ie.Document;
    //webDocument.Write(szHtml);
    //webDocument.Close();

    ie.Visible = true;
}

لاحظ القراء الحذرين أن IWebBrowser2.Document هو IDispatch المنضم متأخرًا.نحن نستخدم Visual Studio 2005، مع .NET 2.0 على أجهزتنا وأجهزتنا الخاصة بعملائنا.

إذًا ما هي طريقة .NET 2.0 لاستدعاء الأساليب على كائن يدعم فقط IDispatch المتأخر الارتباط، على مستوى ما؟

يظهر بحث سريع في Stack Overflow لاستخدام IDispatch من C# هذا المشنور قول ما أريد غير ممكن في .NET.

فهل من الممكن استخدام COM من C# .NET 2.0؟


السؤال هو أن هناك نمط تصميم مقبول أريد استخدامه في C#/.NET.فهو يتضمن إطلاق برنامج Internet Explorer خارج العملية، وتزويده بمحتوى HTML، مع عدم استخدام الملفات المؤقتة.

فكرة التصميم المرفوضة هي استضافة Internet Explorer على WinForm.

البديل المقبول هو تشغيل متصفح الويب المسجل في النظام، وإعطائه HTML للعرض، دون استخدام ملف مؤقت.

العائق الوحيد هو الاستمرار في استخدام كائنات COM في عالم .NET.تتضمن المشكلة المحددة إجراء مكالمات ربط متأخرة إلى IDispatch دون الحاجة إلى C# 4.0.(أي.أثناء استخدام .NET 2.0)

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

المحلول 2

وIDispatch وملزمة في وقت متأخر دعا من السهل relativly في .NET، على الرغم من أن شخ الفقراء:

public static void SpawnIEWithSource(String szHtml)
{
    // Get the class type and instantiate Internet Explorer.
    Type ieType = Type.GetTypeFromProgID("InternetExplorer.Application");
    object ie = Activator.CreateInstance(ieType);

    //Navigate to the blank page in order to make sure the Document exists
    //ie.Navigate2("about:blank");
    Object[] parameters = new Object[1];
    parameters[0] = @"about:blank";
    ie.GetType().InvokeMember("Navigate2", BindingFlags.InvokeMethod | BindingFlags.IgnoreCase, null, ie, parameters);

    //Get the Document object now that it exists
    //Object document = ie.Document;
    object document = ie.GetType().InvokeMember("Document", BindingFlags.GetProperty | BindingFlags.IgnoreCase, null, ie, null);

    //document.Write(szSourceHTML);
    parameters = new Object[1];
    parameters[0] = szHtml;
    document.GetType().InvokeMember("Write", BindingFlags.InvokeMethod | BindingFlags.IgnoreCase, null, document, parameters);

    //document.Close()
    document.GetType().InvokeMember("Close", BindingFlags.InvokeMethod | BindingFlags.IgnoreCase, null, document, null);

    //ie.Visible = true;
    parameters = new Object[1];
    parameters[0] = true;
    ie.GetType().InvokeMember("Visible", BindingFlags.SetProperty | BindingFlags.IgnoreCase, null, ie, parameters);
}

ووالمشار السؤال SO أن قال في الأصل "لم يكن ممكنا حتى C # 4.0" تم تعديله لاظهار كيف أنه من الممكن في Framework 2.0.

هل C # .NET دعم IDispatch والربط المتأخر؟

نصائح أخرى

تحديث: بناءً على تحديثات الأسئلة، قمت بإزالة أجزاء إجابتي التي لم تعد ذات صلة بالسؤال.ومع ذلك، في حالة بحث القراء الآخرين عن طريقة سريعة وقذرة لإنشاء HTML في تطبيق winforms ولا يحتاجون إلى برنامج IE قيد التشغيل، فسوف أترك ما يلي:

السيناريو المحتمل 1:الهدف النهائي هو ببساطة عرض HTML للمستخدم النهائي واستخدام نماذج Windows

System.Windows.Forms.WebBrowser هو برنامج تضمين .NET السهل للغاية للواجهة التي تحاول تنفيذها يدويًا.للحصول عليه، قم بسحب وإسقاط مثيل لهذا الكائن من شريط الأدوات الخاص بك (المدرج باسم "متصفح الويب" ضمن قسم "جميع نماذج Windows") في النموذج الخاص بك.ثم، على بعض معالج الأحداث المناسب:

webBrowser1.Navigate("about:blank");
webBrowser1.Document.Write("<html><body>Hello World</body></html>");

في تطبيق الاختبار الخاص بي، أظهر هذا بشكل صحيح الرسالة المؤرقة التي تعلمنا جميعًا أن نخافها ونكرهها.

والأجوبة في ما بعد أن كنت على صلة غير صحيحة في الواقع. ومن المسلم به عموما من السهل جدا للتعامل مع الأشياء IDispatch ومقرها في صافي. في الأساس تذهب من خلال ثلاث خطوات:

ومعظم كائنات أتمتة (وربما أيضا أكثر من 90٪) التي يتعرض لها واجهات IDispatch وواجهات الأخرى التي يمكن استخدامها من قبل عملاء نوع COM غير البرمجة (إما واجهة IDispatch هو في الواقع واجهة COM الكاملة المستمدة من IDispatch وأو الكائن تدعم واحد أو أكثر الأخرى واجهات IUnknown المشتقة). في هذه الحالة، يمكنك ببساطة استيراد تعريف مناسب اجهة COM ثم يلقي الكائن إلى واجهة المناسبة. ويدعو يلقي QueryInterface تحت الأغطية وإرجاع إشارة ملفوفة إلى الواجهة التي تريد.

وهذا هو الأسلوب الذي سيستخدم في السيناريو الذي عرضت أعلاه. الكائن الوثيقة التي تم إرجاعها من الكائن أتمتة IE يدعم واجهات IHTMLDocument، IHTMLDocument2، IHTMLDocument3، IHTMLDocument4 وIHTMLDocument5 (اعتمادا على إصدار IE الذي تستخدمه). يجب أن يلقي إلى واجهة المناسبة ومن ثم استدعاء الأسلوب المناسب. على سبيل المثال:

IHTMLDocument2 htmlDoc = (IHTMLDocument2)webDocument;
htmlDoc.Write(htmlString);
htmlDoc.Close();

في حالة نادرة حيث لا الكائن أتمتة تدعم واجهة بديلة. ثم يجب عليك استخدام VB.Net التفاف تلك الواجهة. مع الخيار مجموعة الصارم قبالة (للفئة المجمع فقط) يمكنك استخدام VB الذي بني في دعم للمكالمات ملزمة في وقت متأخر لدعوة ببساطة الأساليب IDispatch والمناسبة تحت الأغطية. في حالات نادرة مع أنواع حجة غير عادية قد تحتاج إلى عزف قليلا مع الدعوة ولكن، بشكل عام، في VB يمكنك أن تفعل ذلك فقط! حتى مع إضافات ديناميكية لVB C # V4 سيبقى على الارجح دعم أفضل بكثير للمكالمات المتأخر COM.

وإذا كان لسبب لا يمكنك استخدام VB إلى التفاف اجهة أتمتة ثم لا يزال بإمكانك إجراء أي مكالمات اللازمة من C # باستخدام الانعكاس. ولن أخوض في أي تفاصيل لأن هذا الخيار يجب في الأساس ألا تستخدم أبدا ولكن هنا هو التي تنطوي على مكتب أتمتة .

وانظر هذا المقال: http://www.codeproject.com/KB/cs/IELateBindingAutowod.aspx

وإنترنت إكسبلورر الربط المتأخر أتمتة بواسطة yincekara

وأتمتة إنترنت إكسبلورر نموذج التعليمات البرمجية باستخدام الربط المتأخر، دون Microsoft.mshtml والاعتماد SHDOCVW.

ولhtmlDoc.write (htmlString)؛ تعديل

   [Guid("332C4425-26CB-11D0-B483-00C04FD90119")]
    [ComImport]
    [TypeLibType((short)4160)]
    [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
    internal interface IHTMLDocument2
    {
        [DispId(1054)]
        void write([MarshalAs(UnmanagedType.BStr)] string psArray);
        //void write([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] object[] psarray);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top