通过.NET COM互操作调用方法时出错

时间:2012-08-15 16:44:53

标签: c# com-interop

我正在尝试使用IOfficeAntiVirus COM interface使用Microsoft安全性要点病毒扫描程序来调用扫描。

我正在进行早期绑定,因为文档说IOfficeAntiVirus接口继承自IUknown并且不支持IDispatch。

[Guid("56FFCC30-D398-11d0-B2AE-00A0C908FA49"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
]
public interface IOfficeAntiVirus
{
    void Scan(IntPtr info);
}

[ComImport, Guid("2781761E-28E1-4109-99FE-B9D127C57AFE")]
class SecurityEssentialsAntiVirus
{
}

扫描方法的参数是来自this example的类型。该示例与我想要的相反,因为它使用.NET类实现IOfficeAntiVirus接口,而不是调用scan方法。据我所知,示例中的编组和类型似乎match the documentation

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct MSOAVINFO
{
public int cbsize;

[MarshalAs(UnmanagedType.U4)]
public uint uFlags;
public IntPtr hwnd;

[MarshalAs(UnmanagedType.LPWStr)]
public string pwzFullPath;

[MarshalAs(UnmanagedType.LPWStr)]
public string pwzHostname;

[MarshalAs(UnmanagedType.LPWStr)]
public string pwzOrigURL;
}

这是我试图用来调用扫描方法的代码:

var antivirus = (IOfficeAntiVirus)new SecurityEssentialsAntiVirus();
var file = new MSOAVINFO();
file.pwzFullPath = @"test.txt";
IntPtr lParam = Marshal.AllocHGlobal(Marshal.SizeOf(file));
Marshal.StructureToPtr(file, lParam, false);
antivirus.Scan(lParam);

调用scan方法失败。我得到一个例外:

  

“尝试读取或写入受保护的内存。这通常是一个   表明其他内存已损坏。“

我是从64位系统上的32位命令行应用程序运行的。我已尝试在32位和64位运行命令行程序但没有成功。

我确信IOfficeAntiVirus guid是正确的,因为我从文档中得到了它。当我尝试将对象强制转换为接口时,尝试不是COM接口的随机GUID会导致错误。

我确信SecurityEssentialsAntiVirus guid实现了IOfficeAntiVirus,因为当我尝试将不同类型的COM对象转换为该接口时,我收到了一个错误。

我认为问题可能是接口上的Scan方法没有被正确声明(在接口上声明一个随机方法会产生同样的错误)。我没有使用安全要素程序集的文档,因此它可能无法以我想象的方式实现接口(或根本不是)。有谁知道如何检查?

我可以在其目录中看到一个MpOAv.dll文件,该文件与IOfficeAntiVirus文档中的头文件名称相同,我知道这不是很多。我无法在ole-com对象查看器中打开该DLL以查看其中的内容。我收到一条消息说:

  

IMoniker :: BindToObject在创建的文件名字对象上失败(   “C:\ Program Files \ Microsoft Security Client \ MpOAv.dll”)。坏   文件扩展名

     

MK_E_INVALIDEXTENSION($ 800401E6)

也可能是我没有正确地将结构传递给Scan方法。我已经尝试了大约一百个变种而没有任何运气,包括使用AllocCoTaskMem()并通过引用传递结构。

我真的没有太多使用互操作的经验(今天学会了一堆试图解决这个问题!)所以我真的很感激推进正确的方向。 :)

2 个答案:

答案 0 :(得分:0)

我注意到的一件事是你没有设置cbsize。 file.cbsize = Marshal.SizeOf(文件);

答案 1 :(得分:0)

我也在同一个问题上度过了几天但没有任何结果。我能够做到的最大值是运行检查没有任何错误,但即使对于恶意软件,它也会返回OK状态,在我的情况下

所以,我继续研究,发现Mozilla使用IAttachmentExecute防病毒API进行检查。和Save方法一样,做同样的工作 扫描IOfficeAntiVirus

  

IAttachmentExecute :: Save可能会运行病毒扫描程序或其他信任   在保存文件之前验证文件的服务。请注意这些   服务可以删除或更改文件。

并在代码http://antivirusscanner.codeplex.com/

上实现它