0

我使用 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)) .

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

4

2 回答 2

2

You can find it back with Regedit.exe, HKCR\CLSID\{EA502722-A23D-11D1-A7D3-0000F87571E3}\InProcServer32 key. Which contains the ThreadModel value, it is set to "Apartment". That means that the coclass is not thread-safe, it must be called from a Single-Threaded Apartment. You'll recognize the acronym, that's what STA means in [STAThread].

There's commonly also a key in HKCR\Interface that declares the proxy/stub DLL that marshals an interface call across apartments. But that's missing. Which is what the error message really means, COM created a separate thread to give the component a safe home but then it couldn't find a way to marshal the call. Microsoft just didn't bother, this coclass is normally used from MMC by running the group policy editor, gpedit.msc. You must provide a similar safe home for this non-threadsafe component, an STA thread that pumps a message loop. The UI thread of a GUI program. You took care of STA with the attribute, probably not of the message loop. You might get away with it, if you notice deadlock then you didn't.

于 2012-06-14T23:57:44.673 回答
1

It seems that this article has something clean but I wasn't able to get that working though. I got the issue solved by adding [STAThread] to the main method. (using System.Threading;)

于 2012-06-14T23:22:26.453 回答