2017-09-26 74 views
0

VS 2017年定義Microsoft.VisualStudio.Shell.Interop.15.0.DesignTime.dll這個接口:在C#中定義Visual Studio COM接口時,應該使用哪個類/方法/參數屬性?

[Guid("A459C228-5617-4136-BCBE-C282DF6D9A62")] 
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface IVsSolutionEvents7 
{ 
    void OnAfterCloseFolder(string folderPath); 
    void OnAfterLoadAllDeferredProjects(); 
    void OnAfterOpenFolder(string folderPath); 
    void OnBeforeCloseFolder(string folderPath); 
    void OnQueryCloseFolder(string folderPath, ref int pfCancel); 
} 

我想實現這個接口在我的擴展,使我可以對這些事件作出迴應,但我想相同的擴展程序集與Visual Studio 2015兼容,所以我不希望依賴於該VS 2016 DLL。因此,我將該定義複製粘貼到我的代碼中。

我可以從文檔或從Visual Studio本身通過F12獲得該定義,當我添加對該DLL的引用時,或從JustDecompile。它們都給出了大致相同的界面定義。

但是,接口定義不工作:

  • 的方法是在錯誤的順序,所以那些錯誤的被調用。
  • 字符串沒有正確傳入 - 我的猜測是它們被認爲是Bstrs,但是這些是LPWStrs。
  • 我經常在通話後遇到訪問衝突 - 我的猜測是不正確的調用約定。

如果我申請了一堆屬性的接口,因此它成爲這樣的:

[ComVisible(true)] 
[ComImport] 
[Guid("A459C228-5617-4136-BCBE-C282DF6D9A62")] 
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface IVsSolutionEvents7 
{ 
    [PreserveSig, MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] 
    int OnAfterOpenFolder([In, MarshalAs(UnmanagedType.LPWStr)] string folderPath); 
    ... 

,並把這些方法在正確的順序,那麼它的工作原理。

你怎麼會知道要使用的這些屬性,或者把它才能在方法呢?文檔不一定有用 - 例如,documentation for that interface對上面的簡單破碎定義沒有任何意義。

即使我有權訪問定義接口的組合件(本例中爲Microsoft.VisualStudio.Shell.Interop.15.0.DesignTime.dll),這些屬性的位置在哪裏?當我在Visual Studio或JustDecompile中查看該DLL中的定義時,我只能看到那個簡單的定義,但如果通過對該DLL的引用使用該接口,則可以工作。這些屬性在某種程度上存在但不可見,或者與我自己定義接口時的默認屬性不同。

我拼湊起了我從貨物崇拜覆制,檢查IDL和盲目試驗和錯誤中使用的屬性,因此我並不真正相信它們。 我該怎麼做呢?

回答

2

這只是JustDecompile這裏做不好工作。其他工具,如DotPeek,DnSpy和反射(商業)似乎都工作正常。 Visual Studio F12只是有用的,因爲它是集成的,但對interop無用。

另一種選擇是在可用時使用C/C++/H/IDL文件。該IDL可以在這裏<programfiles>Microsoft Visual Studio\2017\<sku>\VSSDK\VisualStudioIntegration\Common\IDL\vsshell150.idl這裏產生的.H頭文件<programfiles>Microsoft Visual Studio\2017\<sku>\VSSDK\VisualStudioIntegration\Common\inc\vsshell150.h

他們的法律。如有疑問,請參閱其中之一(我更喜歡。h,最低的二進制級別)。

這是怎麼IVsSolutionEvents7在.h文件中定義:

MIDL_INTERFACE("A459C228-5617-4136-BCBE-C282DF6D9A62") 
IVsSolutionEvents7 : public IUnknown 
{ 
public: 
    virtual HRESULT STDMETHODCALLTYPE OnAfterOpenFolder( 
     /* [in] */ __RPC__in LPCOLESTR folderPath) = 0; 

    virtual HRESULT STDMETHODCALLTYPE OnBeforeCloseFolder( 
     /* [in] */ __RPC__in LPCOLESTR folderPath) = 0; 

    virtual HRESULT STDMETHODCALLTYPE OnQueryCloseFolder( 
     /* [in] */ __RPC__in LPCOLESTR folderPath, 
     /* [out][in] */ __RPC__inout BOOL *pfCancel) = 0; 

    virtual HRESULT STDMETHODCALLTYPE OnAfterCloseFolder( 
     /* [in] */ __RPC__in LPCOLESTR folderPath) = 0; 

    virtual HRESULT STDMETHODCALLTYPE OnAfterLoadAllDeferredProjects(void) = 0; 

}; 
+0

謝謝,是的,我使用IDL作爲我的來源之一。但是,例如,MethodImplOptions.InternalCall與IDL有什麼關係? (如果它不在IDL中,但作爲STDMETHODCALLTYPE存在於.h中,則同樣的問題適用 - 你如何將它與另一個相關聯?) – RichieHindle

+0

感謝指向dotPeek的指針 - 它已立即替換了我的工具箱中的JustDecompile!我不知道JustDecompile會悄悄丟棄這樣的屬性。 – RichieHindle

+0

STDMETHODCALLTYPE是一個基本上在方法上應用'__stdcall'調用約定的Windows C宏。它在平臺調用方法的.NET方面是隱含的,所以你不需要添加它。 InternalCall不一樣,它與CLR如何實現所有這些有關,但是你可以忘記這個屬性。 –

1

只需使用Microsoft.VisualStudio.Shell.Interop.14.0.DesignTime.dll,所有新版本的VS有綁定重定向

+0

但是當我添加引用Microsoft.VisualStudio.Shell.Interop.14.0.DesignTime.dll而不是0.15,我可以。沒有看到IVsSolutionEvents7(「無法找到類型或名稱空間名稱」)。 – RichieHindle

+0

這些事件支持僅在VS 2017中可用的功能! https://docs.microsoft.com/en-us/visualstudio/extensibility/lightweight-solution-load-extension-impact – ErikEJ

+0

「我想在我的擴展中實現該接口,以便我可以響應這些事件,但我想相同的擴展程序集與Visual Studio 2015兼容「 – RichieHindle

相關問題