IOfficeAntiVirus COM インターフェイスを使用して、Microsoft Security Essentials ウイルス スキャナーを使用したスキャンを実行しようとしています。
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
{
}
scan メソッドのパラメーターは、この例に由来する型です。この例は、scan メソッドを呼び出すのではなく、.NET クラスを使用して IOfficeAntiVirus インターフェイスを実装しているため、私が望んでいたこととは反対のことをしています。この例のマーシャリングと型は、私が知る限り、ドキュメントと一致しているようです。
[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 ドキュメントのヘッダー ファイルと同じ名前です。その dll を ole-com オブジェクト ビューアで開いて中身を確認することができません。次のようなメッセージが表示されます。
IMoniker::BindToObject から作成されたファイル モニカー ( "C:\Program Files\Microsoft Security Client\MpOAv.dll" ) で失敗しました。ファイルの拡張子が正しくありません
MK_E_INVALIDEXTENSION ($800401E6)
また、構造体を Scan メソッドに正しく渡していない可能性もあります。AllocCoTaskMem() を使用したり、構造体を参照渡ししたりするなど、約 100 のバリエーションを試してみました。
私は実際に相互運用の経験があまりないので (今日、これを理解しようとしてヒープを学びました!)、正しい方向へのプッシュに本当に感謝しています。:)