我正在尝试实施 IOpenControlPanel 界面,该界面没有在 pinvoke.net 这样的网站中记录,所以对于这个任务,我建立了我认为它们应该是从头开始的定义,然后我尝试从注册表中手动检索接口CLSID(似乎是D11AD862-66DE-4DF4-BF6C-1F5621996AF1
),以及一个实现该接口的类,它似乎是06622D85-6856-4460-8DE1-A81921B41C4B
问题是在下面的代码中如果我调用GetCurrentView
函数我没有得到预期的值,并且对Open
函数的调用什么都不做(我使用的是正确的规范名称与 this MSDN article 中 this list of canonical names 中解释的Microsoft.DefaultPrograms
类似。)
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);
}
}
答案 0 :(得分:4)
您的接口定义错误,因为您没有按照与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();
}