簡體   English   中英

沒有表單的ActiveX控件

[英]ActiveX control without a form

我們需要使用第三方ActiveX控件。

唯一的問題是,我們軟件中的圖層是業務層,無法訪問窗口或表單。 它還運行在不是STA的單獨線程上(並且應該在任何線程中工作)。

我們使用此解決方法使其工作,而不是將UI與業務邏輯分開。

Thread thread = new Thread((ThreadStart)
delegate
{
_myActiveX = new MyActiveXType();
_myActiveX.CreateControl();

//more initialize work

Application.Run();
});
thread.SetApartmentState(ApartmentState.STA);
thread.IsBackground = true;
thread.Start();

然后,只要我們需要引用控件,我們就會調用_myActiveX.BeginInvoke()Invoke()

在處理這個類(退出我們的應用程序)時,我們處理控件並中止線程。

我的問題是,這有什么問題嗎? 有沒有更好的方法來處理這個?

在未知的多線程環境中有沒有更好的內置方法來使用ActiveX控件? 我們試圖以包裝控件的方式編寫我們的類,但是可以在任何線程中工作。

更新:作為一個答案建議,我們真的寧願使用標准COM對象,而根本不使用控件。 我們的問題是我們會在我們調用COM對象的第一個方法或屬性上得到錯誤“(來自HRESULT的異常:0x8000FFFF(E_UNEXPECTED)”。這是一個非常一般的錯誤,我們在使用ActiveX時沒有得到這個錯誤, 有任何想法嗎?

更新:我們的ocx是“CX25.ocx”,使用tlbimp.exe我們得到CX25Lib.dll。 使用aximp.exe,我們得到AxCX25Lib.dll和CX25Lib.dll。 在任何一種情況下CX25Lib.dll都不起作用。 AxCX25Lib.dll可以使用。

我認為這是解決這個問題的正確方法。

過去幾周我們一直在測試環境中使用我的代碼而沒有任何問題。

如果有人必須使用沒有表單的ActiveX,我認為這是一種方法。

只需確保在ActiveX對象的構造函數后直接調用_yourActiveXControl.CreateControl()。 這簡化了我們最初的許多問題。

如果從業務層調用ActiveX控件,這意味着它必須能夠在沒有UI的情況下使用,例如只需調用其公共方法即可。 為什么不直接為ActiveX控件類創建一個interop RCW並直接調用它的方法?

我的解決方案是創建一個托管activex控件的隱藏winform

我知道這是一個老帖子,但我建議在現代時代使用TPL。

由於異常處理,取消,延續和返回結果的特性,最好使用任務並行庫而不是舊的線程API。

這是一個例子:

using (var sta = new StaTaskScheduler(1))
{    
    var taskResult = await Task.Factory.StartNew(() =>
    {
        var results = new List<ResultType>();

        using (var ax = new MyActiveXType())
        {
            // important to call this just after constructing ActiveX type
            ax.CreateControl();

            ax.SomeIterativeEvent += (s, e) => results.Add(e.SomeThing);

            // if applicable, you can tear down the message pump
            ax.SomeFinalEvent += (s, e) => Application.ExitThread();

            //more initialize work

            // start message pump
            Application.Run();

            return results;
        }
    }, CancellationToken.None, TaskCreationOptions.None, sta);

    return taskResult;
}

一些要點:

  1. StaTaskScheduler是在ParallelExtensionsExtras nuget包中找到的類型。 您需要這個來安排在單線程公寓中執行的任務。

  2. 我將1傳遞給StaTaskScheduler的構造函數,以便它只為我創建一個單獨的線程。

  3. 調用Application.ExitThread()來停止消息泵,這反過來允許執行由Application.Run()傳遞,以便可以將某些結果返回給調用者。

CreateControl()方法來自AxHost,需要System.Windows.Forms作為依賴項。 如果要在不使用UI的情況下使用ActiveX,可以使用本機調用直接創建ocx的COM對象。

   [DllImport("ole32.dll", PreserveSig = false)]
    [return: MarshalAs(UnmanagedType.Interface)]
    public static extern object CoCreateInstance([In] ref Guid clsid,[MarshalAs(UnmanagedType.Interface)] object punkOuter,int context, [In] ref Guid iid);


public object createComObject(){ 
    Guid IID_IUnknown = new Guid("{00000000-0000-0000-C000-000000000046}");

    var gid = "{6bf52a52-394a-11d3-b153-00c04f79faa6}"; //your ocx guid
    var clsid = new Guid(gid);

    object yourOCX = CoCreateInstance(ref clsid, (object)null, 1, ref IID_IUnknown);
  return yourOCX ;
}

您可以稍后將COM對象強制轉換為所需的接口

IOleObject iole = yourOCX as IOleObject;

IWMPCore iwmp =  yourOCX as IWMPCore;

我通過此鏈接在C#中創建了沒有UI或AxHost的Windows Media Player ActiveX。 它可能會幫助有人嘗試在沒有UI的情況下運行ActiveX。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM