COM Interops InvalidCastException with IGroupPolicyObject

时间:2012-06-14 22:34:06

标签: c# .net windows com group-policy

我使用COM定义了以下类,使用C#.NET来使用IGroupPolicyObject:

 [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调用由于以下错误而失败:不支持此类接口(HRESULT异常:0x80004002(E_NOINTERFACE))

关于如何解决这个问题的任何想法? 感谢

2 个答案:

答案 0 :(得分:2)

您可以使用Regedit.exe,HKCR \ CLSID \ {EA502722-A23D-11D1-A7D3-0000F87571E3} \ InProcServer32密钥找回它。其中包含ThreadModel值,它设置为“Apartment”。这意味着coclass不是线程安全的,必须从单线程公寓调用。你会认识到首字母缩略词,这就是STA在[STAThread]中的含义。

HKCR \ Interface中通常还有一个密钥,用于声明代理/存根DLL,它可以跨公寓封送接口调用。但那已经不见了。这就是错误消息的真正含义,COM创建了一个单独的线程,为组件提供了一个安全的家,但是却无法找到一种方法来编组调用。微软只是没有打扰,这个coclass通常是通过运行组策略编辑器gpedit.msc从MMC使用的。您必须为此非线程安全组件提供类似的安全主页,这是一个泵送消息循环的STA线程。 GUI程序的UI线程。您使用属性处理STA,可能不是消息循环。你可能会侥幸成功,如果你注意到死锁,那么你就没有。

答案 1 :(得分:1)

看来这篇文章有些干净但我无法让它工作。我通过向main方法添加[STAThread]来解决问题。 (using System.Threading;