Question

I would like to add a registry key to GPO registry entry? Standard .NET registry classes doesn't handle this scenario.

Was it helpful?

Solution

The working solution I found was to use Group Policy Object COM+ API Interface.

Remarks:

  • thread marked as STA must be used. It can be applied to whole application or just one thread;

  • COM+ IGroupPolicyObject must be used via ComInterop;

  • MS encourages using "GPMC Class Library" in the .NET, but this library is not working properly;

  • the IGroupPolicyObject proxy on .NET side must contain definitions for ALL methods from the COM object (or else an exception would be thrown "Attempted to read or write protected memory. This is often an indication that other memory is corrupt." by a one of the methods);

Following code enables management (adding, removing, etc) of registry entries under GPO:

static void Main(string[] args)
{
    Thread t = new Thread(new ThreadStart(StartNewStaThread));
    t.SetApartmentState(ApartmentState.STA);
    t.Start();
}

private static void StartNewStaThread()
{
    GPClass gpClass = new GPClass();
    IGroupPolicyObject gpo = (IGroupPolicyObject)gpClass;

    uint hr = gpo.OpenLocalMachineGpo(1); // GPO_OPEN_LOAD_REGISTRY=0x00000001

    if (hr == 0) //S_OK == 0
    {
        StringBuilder sb = new StringBuilder();
        hr = gpo.GetDisplayName(sb, 50);
    }
}

[ComImport, Guid("EA502722-A23D-11d1-A7D3-0000F87571E3")]
public class GPClass
{
}

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

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

    uint OpenLocalMachineGPO(
        uint flags);

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

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

    uint Delete();

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

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

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

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

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

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

    uint GetRegistryKey(
        uint section,
        out IntPtr key);

    uint GetOptions();

    uint SetOptions(
        uint options,
        uint mask);

    uint GetType(
        out IntPtr gpoType
    );

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

    uint GetPropertySheetPages(
        out IntPtr pages);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top