2011-04-01 18 views
3

我正在使用IRunningObjectTable.RegisterIRunningObjectTable.Revoke,如this教程中所示。我的VBScript客戶端最初調用方法沒有問題,但是當C#COM服務器處置時,我總是收到「值不在預期範圍內」異常。這是由於下面的註釋行:IRunningObjectTable.Register始終將pdwRegister設置爲65536,無效值

private const int ACTIVEOBJECT_STRONG = 0x0; 

[DllImport("ole32.dll")] 
private static extern int CreateBindCtx(int reserved, 
    out IBindCtx bindCtx); 

[DllImport("oleaut32.dll")] 
private static extern int RegisterActiveObject 
    ([MarshalAs(UnmanagedType.IUnknown)] object punk, 
    ref Guid rclsid, 
    uint dwFlags, 
    out int pdwRegister); 

// register instance so it appears in ROT 
private static int Register<T>(T classToRegister) 
{ 
    int pdwRegister; 
    Guid guid = Marshal.GenerateGuidForType(typeof(T)); 

    RegisterActiveObject(classToRegister, 
     ref guid, 
     ACTIVEOBJECT_STRONG, 
     out pdwRegister); 

    return pdwRegister; 
} 

// do stuff in VBScript before disposal calls Revoke with the stored 
// pdwRegister value from the method above 

// revoke instance so it's removed from ROT 
private static void Revoke(int pdwRegister) 
{ 
    IBindCtx bc; 
    CreateBindCtx(0, out bc); 

    IRunningObjectTable rot; 
    bc.GetRunningObjectTable(out rot); 
    // EXCEPTION: pdwRegister is *always* 65536, an invalid value! 
    rot.Revoke(pdwRegister);  
} 

如果我終止程序,並忽略了的異常,實例通常是從ROT刪除自身。但是,經過一段時間後,我發現ROT中有多個應用程序的GUID實例,而我的VBScript客戶端在GetObject(,「my.id」)上啓動失敗。有什麼想法嗎?

+1

的代碼片段是無望的,沒有註冊電話的標誌。郵政編碼,可以重現該問題。 – 2011-04-01 15:05:28

+0

固定 - 更多詳細信息可以在鏈接的文章 – Pakman 2011-04-01 15:40:51

+0

中找到呃,調試這個。在RegisterActiveObject調用之後,pdwRegister的值是多少?該值是否存儲在VBScript變量中?這樣做會被破壞嗎?不檢查RegisterActiveObject的返回值是不明智的。 – 2011-04-01 15:54:45

回答

1

我懷疑你沒有正確維護對象的生命週期。我已經做了同樣的事情,但使用了兩個不同的類型,將它們放在運行對象表中。

與你一樣,我放置在表格中的第一個對象是,我收到一個句柄值65536.但是,對於第二個項目,我收到了一個不同的句柄。

但是,當調用RevokeActiveObject時,兩個調用都返回了S_OK的HRESULT。

東西告訴我你的對象在撤銷它們的調用被處理之前被處置掉了。

要麼是這樣,要麼是不增加/減少ROT上項目的引用計數。

+0

不幸的是,我沒有了麻煩的代碼,一個簡單的測試不會引發異常。也許它確實與對象的生命週期有關...... – Pakman 2012-03-15 15:00:49

2

註冊的第一個始終是65536,這是正確的。

使用

[DllImport("oleaut32.dll", PreserveSig = false)] 
     public static extern void RevokeActiveObject(
      uint handle, 
      IntPtr reserved); 

而不是:

IBindCtx bc; 
    CreateBindCtx(0, out bc); 


IRunningObjectTable rot; 
bc.GetRunningObjectTable(out rot); 
// EXCEPTION: pdwRegister is *always* 65536, an invalid value! 
rot.Revoke(pdwRegister);  

而且RevokeActiveObject需要在同一個線程和進程內調用,因爲它是在註冊

+0

對於第一個對象始終是65536,你必須是正確的,因爲這總是我看到的值。你知道這兩種方法有什麼區別嗎?你爲什麼建議pinvoke方法? – Pakman 2012-03-15 15:02:24

相關問題