如何从托管代码使用 win32 'IOpenControlPanel' 接口?
How to use win32 'IOpenControlPanel' interface from managed code?
我正在尝试实现 IOpenControlPanel interface, which is not documented in sites like pinvoke.net,因此对于此任务,我按照我认为应该的方式从头开始构建定义,然后我尝试手动从注册表中检索接口 CLSID,它似乎是 D11AD862-66DE-4DF4-BF6C-1F5621996AF1
,以及实现该接口的 Class,它似乎是 06622D85-6856-4460-8DE1-A81921B41C4B
.
问题是在下面的代码中如果我调用 GetCurrentView
函数我没有得到预期的值,并且对 Open
函数的调用什么也不做(我使用的是适当的规范名称,如 Microsoft.DefaultPrograms
,如 this MSDN article from 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")>
Public Interface IOpenControlPanel
<PreserveSig()>
Function Open(<MarshalAs(UnmanagedType.BStr)> ByVal name As String,
<MarshalAs(UnmanagedType.BStr)> ByVal page As String,
ByVal punkSite As IntPtr
) As Integer ' HResult
<PreserveSig()>
Function GetPath(<MarshalAs(UnmanagedType.BStr)> ByVal name As String,
<MarshalAs(UnmanagedType.LPWStr)> ByVal path As StringBuilder,
ByVal bufferSize As Integer
) As Integer ' HResult
<PreserveSig()>
Function GetCurrentView(ByRef refView As ControlPanelView
) As Integer ' HResult
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)]
[Guid("D11AD862-66DE-4DF4-BF6C-1F5621996AF1")]
public interface IOpenControlPanel
{
[PreserveSig()]
int Open([MarshalAs(UnmanagedType.BStr)] string name,
[MarshalAs(UnmanagedType.BStr)] string page,
IntPtr punkSite);
[PreserveSig()]
int GetPath([MarshalAs(UnmanagedType.BStr)] string name,
[MarshalAs(UnmanagedType.LPWStr)] StringBuilder path,
int bufferSize);
[PreserveSig()]
int GetCurrentView(ref ControlPanelView refView);
}
}
你的接口定义是错误的,因为你没有按照MSDN定义的顺序定义方法(事实上,名称并不重要,重要的是接口方法布局:以正确的顺序匹配二进制签名)。 必须 的顺序与 Windows SDK 提供的 .h 文件中定义的完全相同,而不是 MSDN 显示的顺序 - 这实际上是误导 :-)。在这种情况下,头文件是 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();
}
我正在尝试实现 IOpenControlPanel interface, which is not documented in sites like pinvoke.net,因此对于此任务,我按照我认为应该的方式从头开始构建定义,然后我尝试手动从注册表中检索接口 CLSID,它似乎是 D11AD862-66DE-4DF4-BF6C-1F5621996AF1
,以及实现该接口的 Class,它似乎是 06622D85-6856-4460-8DE1-A81921B41C4B
.
问题是在下面的代码中如果我调用 GetCurrentView
函数我没有得到预期的值,并且对 Open
函数的调用什么也不做(我使用的是适当的规范名称,如 Microsoft.DefaultPrograms
,如 this MSDN article from 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")>
Public Interface IOpenControlPanel
<PreserveSig()>
Function Open(<MarshalAs(UnmanagedType.BStr)> ByVal name As String,
<MarshalAs(UnmanagedType.BStr)> ByVal page As String,
ByVal punkSite As IntPtr
) As Integer ' HResult
<PreserveSig()>
Function GetPath(<MarshalAs(UnmanagedType.BStr)> ByVal name As String,
<MarshalAs(UnmanagedType.LPWStr)> ByVal path As StringBuilder,
ByVal bufferSize As Integer
) As Integer ' HResult
<PreserveSig()>
Function GetCurrentView(ByRef refView As ControlPanelView
) As Integer ' HResult
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)]
[Guid("D11AD862-66DE-4DF4-BF6C-1F5621996AF1")]
public interface IOpenControlPanel
{
[PreserveSig()]
int Open([MarshalAs(UnmanagedType.BStr)] string name,
[MarshalAs(UnmanagedType.BStr)] string page,
IntPtr punkSite);
[PreserveSig()]
int GetPath([MarshalAs(UnmanagedType.BStr)] string name,
[MarshalAs(UnmanagedType.LPWStr)] StringBuilder path,
int bufferSize);
[PreserveSig()]
int GetCurrentView(ref ControlPanelView refView);
}
}
你的接口定义是错误的,因为你没有按照MSDN定义的顺序定义方法(事实上,名称并不重要,重要的是接口方法布局:以正确的顺序匹配二进制签名)。 必须 的顺序与 Windows SDK 提供的 .h 文件中定义的完全相同,而不是 MSDN 显示的顺序 - 这实际上是误导 :-)。在这种情况下,头文件是 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();
}