2016-05-06 34 views
0

私は、彼らがされるべきだと思うと、このタスクのために、私はその後、私は手動でインターフェイスを取得しようとした、最初から定義を建てて、pinvoke.netのようなサイトに記載されていないIOpenControlPanelインターフェイスを実装しようとしていますレジストリからのCLSIDはD11AD862-66DE-4DF4-BF6C-1F5621996AF1と思われ、そのインフェフェースを実装するクラスは06622D85-6856-4460-8DE1-A81921B41C4Bと思われます。マネージコードからwin32 'IOpenControlPanel'インターフェイスを使用するには?

問題がthis MSDN articleで説明したように、次のコードで(私はMicrosoft.DefaultProgramsのような適切な正規名を使用しています、私は期待値を得ることはありませんGetCurrentView関数を呼び出すと、Open関数の呼び出しは、何もしない場合ということですthis list of canonical namesから。)

Dim cp As New COpenControlPanel 
Dim view As ControlPanelView 
DirectCast(cp, IOpenControlPanel).GetCurrentView(view) 
DirectCast(cp, IOpenControlPanel).Open("Microsoft.DefaultPrograms", "", Nothing) 

だから、私は私の定義はいくつかの方法で間違っている、私はそれを修正するための助けが必要だと思います。


これらの定義は以下のとおりです。

VB.Net:

Friend NotInheritable Class NativeMethods 

    Enum ControlPanelView As Integer 
     Classic = 0 
     Category = 1 
    End Enum 

    <ComImport()> 
    <Guid("06622D85-6856-4460-8DE1-A81921B41C4B")> 
    Class COpenControlPanel 
    End Class 

    <ComImport()> 
    <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> 
    <Guid("D11AD862-66DE-4DF4-BF6C-1F5621996AF1")> 
    Interface IOpenControlPanel 

     <PreserveSig()> 
     Function GetCurrentView(ByRef refView As ControlPanelView 
     ) As Integer 

     <PreserveSig()> 
     Function GetPath(<MarshalAs(UnmanagedType.LPWStr)> ByVal name As String, 
         <MarshalAs(UnmanagedType.LPWStr)> ByRef refPath As StringBuilder, 
                  ByVal bufferSize As Integer 
     ) As Integer 

     <PreserveSig()> 
     Function Open(<MarshalAs(UnmanagedType.LPWStr)> ByVal name As String, 
         <MarshalAs(UnmanagedType.LPWStr)> ByVal page As String, 
                 ByVal punkSite As IntPtr 
     ) As Integer 

    End Interface 

End Class 

C#(オンライン翻訳):あなたがいなかったので

internal sealed class NativeMethods { 

    public enum ControlPanelView : int { 
     Classic = 0, 
     Category = 1 
    } 

    [ComImport()] 
    [Guid("06622D85-6856-4460-8DE1-A81921B41C4B")] 
    class COpenControlPanel {} 

    [ComImport()] 
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
    [GuidAttribute("D11AD862-66DE-4DF4-BF6C-1F5621996AF1")] 
    public interface IOpenControlPanel { 

     [PreserveSig()] 
     int GetCurrentView(ref ControlPanelView refView); 

     [PreserveSig()] 
     int GetPath([MarshalAs(UnmanagedType.LPWStr)] string name, 
        [MarshalAs(UnmanagedType.LPWStr)] ref StringBuilder refPath, 
                 int bufferSize); 

     [PreserveSig()] 
     int Open([MarshalAs(UnmanagedType.LPWStr)] string name, 
       [MarshalAs(UnmanagedType.LPWStr)] string page, 
                IntPtr punkSite); 
    } 
} 
+0

あなたがインターフェイスを作成することはできません。インターフェイスを提供(実装)するオブジェクトを作成する必要があります。 – GSerg

+0

@GSerg、私は参照するために、** IShellLink **インターフェイスを使って次の例を取り上げました。これはインターフェイスだけを定義し、私が適用しようとしているのと同じテクニックを使用して成功裏にインスタンシエートしました:http://www.pinvoke.net /default.aspx/Interfaces/IShellLinkW.html – ElektroStudios

+0

'IShellLink'を実装し、独自の' CLSID_ShellLink'を持つクラスである[ShellLink'を定義しました](http://stackoverflow.com/q/18885865/11683)あなたはそのクラスをインスタンス化しました。こっちも一緒。 – GSerg

答えて

4

あなたのインタフェース定義が間違っていますMSDNと同じ順序で定義されたメソッドを使用します(実際には名前は重要ではなく、重要なのはインターフェイスメソッドですout:正しい順序でバイナリ署名にマッチする)。 の順番はでなければなりません。MS SDKが表示するのではなく、Windows SDKで利用可能な.hファイルで定義されているものと正確に一致する必要があります。これは実際に誤解を招くものです。この場合、ヘッダーファイルはShobjidl.hです。これは、それはC/C++で定義されています方法です:

MIDL_INTERFACE("D11AD862-66DE-4DF4-BF6C-1F5621996AF1") 
IOpenControlPanel : public IUnknown 
{ 
public: 
    virtual HRESULT STDMETHODCALLTYPE Open( 
     /* [string][unique][in] */ __RPC__in_opt_string LPCWSTR pszName, 
     /* [string][unique][in] */ __RPC__in_opt_string LPCWSTR pszPage, 
     /* [unique][in] */ __RPC__in_opt IUnknown *punkSite) = 0; 

    virtual HRESULT STDMETHODCALLTYPE GetPath( 
     /* [string][unique][in] */ __RPC__in_opt_string LPCWSTR pszName, 
     /* [size_is][string][out] */ __RPC__out_ecount_full_string(cchPath) LPWSTR pszPath, 
     /* [in] */ UINT cchPath) = 0; 

    virtual HRESULT STDMETHODCALLTYPE GetCurrentView( 
     /* [out] */ __RPC__out CPVIEW *pView) = 0; 

}; 

あり、複数の同等の定義は、.NET、C#であるが、ここでは動作するはずです:

[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
    [Guid("D11AD862-66DE-4DF4-BF6C-1F5621996AF1")] 
    public interface IOpenControlPanel 
    { 
     [PreserveSig] 
     int Open([MarshalAs(UnmanagedType.LPWStr)] string name, 
       [MarshalAs(UnmanagedType.LPWStr)] string page, 
                IntPtr punkSite); 
     [PreserveSig] 
     int GetPath([MarshalAs(UnmanagedType.LPWStr)] string name, 
        [MarshalAs(UnmanagedType.LPWStr)] StringBuilder refPath, 
                 int bufferSize); 

     // if you remove PreserveSig, you can return the [out] param directly 
     // note in this case, the function could throw instead of returning an error int like with PreserveSig 
     ControlPanelView GetCurrentView(); 
    } 
+0

答えをありがとう、私は** GetPath **の実際の定義は、マーシャリングに関連したメモリへの無効なアクセスの例外をスローし、なぜ私がした修正をロールバックするのかをコメントしたいだけです。 – ElektroStudios

+0

あなたの最初の文章に誤字があるとします。 "あなたはMSDNと同じ順序でメソッドを定義していませんでした"と言いたいですか? – Elmue

+0

@Elmue - 絶対に:-)それを指摘してくれてありがとう。 –

関連する問題