0

C#.NET を使用して IGroupPolicyObject を使用するために、COM を使用して次のクラスを定義しました。

 [ComImport, Guid("EA502722-A23D-11d1-A7D3-0000F87571E3")]
    public class GPClass
    {
        // The C# compiler will add a parameterless constructor that we will call          // to create an instance of the COM coclass.
    }


   [ComImport, Guid("EA502723-A23D-11d1-A7D3-0000F87571E3"),  
    InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]  
    public interface IGroupPolicyObject  
    {  
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords")]  
        void New(  
            [MarshalAs(UnmanagedType.LPWStr)] string domainName,  
            [MarshalAs(UnmanagedType.LPWStr)] string displayName,  
            uint flags);  

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]  
        void OpenDsgpo(  
            [MarshalAs(UnmanagedType.LPWStr)] string path,  
            uint flags);  

        void OpenLocalMachineGpo(  
            uint flags);  

        void OpenRemoteMachineGpo(  
            [MarshalAs(UnmanagedType.LPWStr)] string computerName,  
            uint flags);  

        void Save(  
            [MarshalAs(UnmanagedType.Bool)] bool machine,  
            [MarshalAs(UnmanagedType.Bool)] bool add,  
            [MarshalAs(UnmanagedType.LPStruct)] Guid extension,  
            [MarshalAs(UnmanagedType.LPStruct)] Guid app);  

        void Delete();  

        void GetName(  
            [MarshalAs(UnmanagedType.LPWStr)] StringBuilder name,  
            int maxLength);  

        void GetDisplayName(  
            [MarshalAs(UnmanagedType.LPWStr)] StringBuilder name,  
            int maxLength);  

        void SetDisplayName(  
            [MarshalAs(UnmanagedType.LPWStr)] string name);  

        void GetPath(  
            [MarshalAs(UnmanagedType.LPWStr)] StringBuilder path,  
            int maxPath);  

        void GetDSPath(  
            uint section,  
            [MarshalAs(UnmanagedType.LPWStr)] StringBuilder path,  
            int maxPath);  

        void GetFileSysPath(  
            uint section,  
            [MarshalAs(UnmanagedType.LPWStr)] StringBuilder path,  
            int maxPath);  

        IntPtr GetRegistryKey(uint section);  

        uint GetOptions();  

        void SetOptions(  
            uint options,  
            uint mask);  

        void GetMachineName(  
            [MarshalAs(UnmanagedType.LPWStr)] StringBuilder name,  
            int maxLength);  

        uint GetPropertySheetPages(  
            out IntPtr pages);  
    }

問題は、次のように IGroupPolicyObject を使用しようとすると、InvalidCastException が発生することです。

GPClass gpClass = new GPClass();
IGroupPolicyObject comGroupPolicyObject = (IGroupPolicyObject)gpClass;

私が得る例外は次 のとおりです。タイプ「ConfigureRemoteSources.GPClass」のCOMオブジェクトをインターフェースタイプ「ConfigureRemoteSources.IGroupPolicyObject」にキャストできません。IID '{EA502722-A23D-11D1-A7D3-0000F87571E3}' を持つインターフェイスの COM コンポーネントでの QueryInterface 呼び出しが次のエラーにより失敗したため、この操作は失敗しました: No such interface supported (HRESULT からの例外: 0x80004002 (E_NOINTERFACE)) .

これを解決する方法についてのアイデアはありますか? ありがとう

4

2 に答える 2

2

Regedit.exe、HKCR \ CLSID \ {EA502722-A23D-11D1-A7D3-0000F87571E3}\InProcServer32キーで元に戻すことができます。ThreadModel値が含まれているため、「Apartment」に設定されます。つまり、コクラスはスレッドセーフではなく、シングルスレッドアパートメントから呼び出す必要があります。あなたは頭字語を認識するでしょう、それはSTAが[STAThread]で意味するものです。

通常、HKCR \ Interfaceには、アパートメント間でインターフェイス呼び出しをマーシャリングするプロキシ/スタブDLLを宣言するキーもあります。しかし、それは欠けています。これがエラーメッセージの本当の意味です。COMはコンポーネントに安全なホームを提供するためにのスレッドを作成しましたが、呼び出しをマーシャリングする方法を見つけることができませんでした。Microsoftは気にしませんでした。このコクラスは通常、グループポリシーエディターgpedit.mscを実行することによってMMCから使用されます。この非スレッドセーフコンポーネント、メッセージループをポンピングするSTAスレッドにも同様の安全なホームを提供する必要があります。GUIプログラムのUIスレッド。おそらくメッセージループではなく、属性を使用してSTAを処理しました。あなたはそれで逃げるかもしれません、あなたがデッドロックに気づいたなら、あなたはそうしませんでした。

于 2012-06-14T23:57:44.673 に答える