문제

I have defined the following class using COM to use the IGroupPolicyObject using C#.NET:

 [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);  
    }

The problem is when I try to use the IGroupPolicyObject as follows I get an InvalidCastException:

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

Exception I get is: Unable to cast COM object of type 'ConfigureRemoteSources.GPClass' to interface type 'ConfigureRemoteSources.IGroupPolicyObject'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{EA502722-A23D-11D1-A7D3-0000F87571E3}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).

Any ideas on how to solve this? Thanks

도움이 되었습니까?

해결책

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.

다른 팁

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;)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top