首页  编辑  

组策略的刷新和修改

Tags: /超级猛料/OS.操作系统/   Date Created:

Windows组策略的刷新和修改

By Kingron, 版权所有

组策略的注册表对应项目请参考:

http://msdn2.microsoft.com/en-us/library/ms815238.aspx

Windows有一个gpedit.msc,很好用的一个工具,可以定制Windows很多的配置。但是如果我们需要自己的程序来修改这些配置的话,你会发现Windows的组策略根本不认!但是你修改注册表重新启动机器后,某些配置是起作用的,这个原因在于,我们必须同时刷新系统,而且必须刷新组策略。

Windows组策略会在你的注册表中建立一个组策略的缓冲,必须更新这个缓冲才会同时起作用!

下面以修改Windows XP的开始中的"注销"菜单项配置来说明。

注意:在Windows组策略中,一般地,如果注册表项目不存在,则显示为"未配置",如果数值为0,则显示为已禁用,为1则显示为已启用,其他的值和对应数据相关。

Windows开始菜单的注销配置存储在Software\Microsoft\Windows\CurrentVersion\Policies\Explorer下

数值为: StartMenuLogOff(DWORD) = 0 | 1;

我们正常写注册表代码为:

     RootKey := HKEY_CURRENT_USER;

     if  OpenKey('Software\Microsoft\Windows\CurrentVersion\Policies\Explorer', True) then

     begin

       WriteInteger('StartMenuLogOff', 0);

     end;

写入注册表后刷新系统或者重新启动服务器,是可以起作用的,但是组策略不认,因此在下一次组策略刷新后可能会导致配置失效,因此还是必须让组策略接纳我们的修改,组策略的缓冲存储在注册表 Software\Microsoft\Windows\CurrentVersion\Group Policy Objects\{574DE082-1E91-47C9-95A1-C731CC87F739}Machine\下,其中的GUID为组策略在注册表中映射,组策略实际存储在文件%system%wbem\Repository\FS\OBJECTS.DATA中,该GUID是动态的,每次运行Gpedit.msc或者进行其他组策略操作的时候都不一样。然后必须在这个Key下建立你的除Root外的Key,其中的Machine也可以为User,决定于策略的有效范围!并写入你的数据,最后刷新系统即可。

因此完整的代码如下:

uses ComObj , ActiveX , Registry ;

const

 GPO_OPEN_LOAD_REGISTRY     = $00000001 ;   // Load the registry files

  {$EXTERNALSYM GPO_OPEN_LOAD_REGISTRY}

 GPO_OPEN_READ_ONLY         = $00000002 ;   // Open the GPO as read only

 GPO_SECTION_ROOT                 = 0 ;   // Root

  {$EXTERNALSYM GPO_SECTION_ROOT}

 GPO_SECTION_USER                 = 1 ;   // User

  {$EXTERNALSYM GPO_SECTION_USER}

 GPO_SECTION_MACHINE             = 2 ;   // Machine

const

 IID_GPO : TGUID = '{EA502722-A23D-11d1-A7D3-0000F87571E3}' ;

type

 HPROPSHEETPAGE = Pointer ;

  {$EXTERNALSYM HPROPSHEETPAGE}

 PHPROPSHEETPAGE = ^ HPROPSHEETPAGE ;

 LPOLESTR = POleStr ;

 _GROUP_POLICY_OBJECT_TYPE = (

   GPOTypeLocal ,                         // GPO on the local machine

   GPOTypeRemote ,                         // GPO on a remote machine

   GPOTypeDS );                           // GPO in the Active Directory

  {$EXTERNALSYM _GROUP_POLICY_OBJECT_TYPE}

 GROUP_POLICY_OBJECT_TYPE = _GROUP_POLICY_OBJECT_TYPE ;

 IGroupPolicyObject = interface ( IUnknown )

  [ '{EA502723-A23D-11d1-A7D3-0000F87571E3}' ]

    function New ( pszDomainName , pszDisplayName : LPOLESTR ; dwFlags : DWORD ): HRESULT ; stdcall ;

    function OpenDSGPO ( pszPath : LPOLESTR ; dwFlags : DWORD ): HRESULT ; stdcall ;

    function OpenLocalMachineGPO ( dwFlags : DWORD ): HRESULT ; stdcall ;

    function OpenRemoteMachineGPO ( pszComputerName : LPOLESTR ; dwFlags : DWORD ): HRESULT ; stdcall ;

    function Save ( bMachine , bAdd : BOOL ; const pGuidExtension , pGuid : TGUID ): HRESULT ; stdcall ;

    function Delete : HRESULT ; stdcall ;

    function GetName ( pszName : LPOLESTR ; cchMaxLength : Integer ): HRESULT ; stdcall ;

    function GetDisplayName ( pszName : LPOLESTR ; cchMaxLength : Integer ): HRESULT ; stdcall ;

    function SetDisplayName ( pszName : LPOLESTR ): HRESULT ; stdcall ;

    function GetPath ( pszPath : LPOLESTR ; cchMaxPath : Integer ): HRESULT ; stdcall ;

    function GetDSPath ( dwSection : DWORD ; pszPath : LPOLESTR ; cchMaxPath : Integer ): HRESULT ; stdcall ;

    function GetFileSysPath ( dwSection : DWORD ; pszPath : LPOLESTR ; cchMaxPath : Integer ): HRESULT ; stdcall ;

    //

    // Returns a registry key handle for the requested section.  The returned

    // key is the root of the registry, not the Policies subkey.  To set / read

    // a value in the Policies subkey, you will need to call RegOpenKeyEx to

    // open Software\Policies subkey first.

    //

    // The handle has been opened with ALL ACCESS rights.  Call RegCloseKey

    // on the handle when finished.

    //

    // If the GPO was loaded / created without the registry being loaded

    // this method will return E_FAIL.

    //

    // dwSection is either GPO_SECTION_USER or GPO_SECTION_MACHINE

    // hKey contains the registry key on return

    //

    function GetRegistryKey ( dwSection : DWORD ; var hKey : HKEY ): HRESULT ; stdcall ;

    function GetOptions ( var dwOptions : DWORD ): HRESULT ; stdcall ;

    function SetOptions ( dwOptions , dwMask : DWORD ): HRESULT ; stdcall ;

    function GetType ( var gpoType : GROUP_POLICY_OBJECT_TYPE ): HRESULT ; stdcall ;

    function GetMachineName ( pszName : LPOLESTR ; cchMaxLength : Integer ): HRESULT ; stdcall ;

    function GetPropertySheetPages ( var hPages : PHPROPSHEETPAGE ; var uPageCount : UINT ): HRESULT ; stdcall ;

  end ;

const

 REGISTRY_EXTENSION_GUID : TGUID = (

   D1 : $35378EAC ; D2 : $683F ; D3 : $11D2 ; D4 :( $A8 , $9A , $00 , $C0 , $4F , $BB , $CF , $A2 ));

 CLSID_GPESnapIn : TGUID = (

   D1 : $8fc0b734 ; D2 : $a0e1 ; D3 : $11d1 ; D4 :( $a7 , $d3 , $0 , $0 , $f8 , $75 , $71 , $e3 ));

procedure TForm1 . Button1Click ( Sender : TObject );

var

 GPO : IGroupPolicyObject ;

 Key : HKEY ;

begin

 GPO := CreateComObject ( IID_GPO ) as IGroupPolicyObject ;

  if S_OK = GPO . OpenLocalMachineGPO ( GPO_OPEN_LOAD_REGISTRY ) then

  begin

    if S_OK = GPO . GetRegistryKey ( GPO_SECTION_USER , Key ) then

    with TRegistry . Create do

    try

     RootKey := HKEY_CURRENT_USER ;

      if  OpenKey ( 'Software\Microsoft\Windows\CurrentVersion\Policies\Explorer' , True ) then

      begin

       WriteInteger ( 'StartMenuLogOff' , 0 );

      end ;

     RootKey := Key ;

      if OpenKey ( '\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer' , True ) then

      begin

       WriteInteger ( 'StartMenuLogOff' , 0 );

      end ;

     RegCloseKey ( Key );

     GPO . Save ( False , True , REGISTRY_EXTENSION_GUID , CLSID_GPESnapIn );

    finally

     Free ;

    end ;

   SendMessage ( HWND_BROADCAST , WM_SETTINGCHANGE , Integer ( PChar ( 'Polices' )), 0 );

  end ;

end ;

同时需要注意的是,组策略不支持多线程处理的,总是以最后的一个存储结果为准,因此在测试上面代码的时候,请不要运行gpedit.msc,如果要验证结果是否正确,可以先启动gpedit.msc,记录下配置,然后关闭gpedit.msc,再运行上面的代码,然后启动gpedit.msc查看配置是不是已经改过来了? :-)

BTW ,组策略的全部注册表项目,可以在MSDN中的Group Policy Registry Table目录中找到。

地址: ms-help://MS.MSDNQTR.2004JAN.1033/gp/gpref.htm

下面是一个网友的C#的代码:

/*

更改组策略设置方法

参数:

hKey:注册表根项目

subKey:注册表子项目

valueName:项目名称

dwType:项目类型

szkeyValue:REG_SZ类型的项目值

dwkeyValue:REG_DWORD类型的项目值

*/

private: System::Boolean SetGroupPolicy(HKEY hKey,LPCTSTR subKey,LPCTSTR valueName,DWORD dwType,const BYTE* szkeyValue,DWORD dwkeyValue){

  HKEY ghKey,ghSubKey,hSubKey;

  LPDWORD flag = NULL;

  //初始化GPO接口对象,如果失败,提示错误信息

  HRESULT hr = CoCreateInstance(CLSID_GroupPolicyObject,NULL,CLSCTX_ALL,IID_IGroupPolicyObject,(LPVOID*)&pGPO);

  if(!SUCCEEDED(hr))

   MessageBox::Show(L"GPO接口对象初始化失败",L"",MessageBoxButtons::OK,MessageBoxIcon::Error);

  //修改本地注册表

  if ( RegCreateKeyEx(hKey,

       subKey,

       0,

       NULL,

       REG_OPTION_NON_VOLATILE,

       KEY_WRITE,

       NULL,

       &hSubKey,

       flag) != ERROR_SUCCESS){

   return false;

  }

  if(dwType == REG_SZ){

   if( RegSetValueEx(hSubKey,valueName,0,dwType,szkeyValue,strlen((char*)szkeyValue)+1) != ERROR_SUCCESS){

    RegCloseKey(hSubKey);

    return false;

   }

  }

  else if(dwType == REG_DWORD){

   if( RegSetValueEx(hSubKey,valueName,0,dwType,(BYTE*)&dwkeyValue,sizeof(dwkeyValue)) != ERROR_SUCCESS){

    RegCloseKey(hSubKey);

    return false;

   }

  }

  //修改本地GPO

  if(!SUCCEEDED(hr)){

   MessageBox::Show(L"GPO接口对象初始化失败",L"",MessageBoxButtons::OK,MessageBoxIcon::Error);

   return false;

  }

  if(pGPO->OpenLocalMachineGPO(GPO_OPEN_LOAD_REGISTRY) != S_OK){

   MessageBox::Show(L"获取本地GPO映射失败",L"",MessageBoxButtons::OK,MessageBoxIcon::Error);  

   return false;

  }//OpenLocalMachine

  if(pGPO->GetRegistryKey(GPO_SECTION_USER,&ghKey) != S_OK){

   MessageBox::Show(L"获取本地GPO映射注册表根键失败",L"",MessageBoxButtons::OK,MessageBoxIcon::Error);

   return false;

  }//GetRegistryKey

  if(RegCreateKeyEx(ghKey,

        subKey,

        0,

        NULL,

        REG_OPTION_NON_VOLATILE,

        KEY_WRITE,

        NULL,

        &ghSubKey,

        flag) != ERROR_SUCCESS){

   RegCloseKey(ghKey);

   MessageBox::Show(L"无法创建组策略注册表子项目",L"",MessageBoxButtons::OK,MessageBoxIcon::Error);

   return false;

  }//RegCreateKeyEx

  if(dwType == REG_SZ){

   if(RegSetValueEx(ghSubKey,valueName,0,dwType,szkeyValue,strlen((char*)szkeyValue)+1) != ERROR_SUCCESS){

    RegCloseKey(ghKey);

    RegCloseKey(ghSubKey);

    MessageBox::Show(L"无法创建组策略注册表子项目值",L"",MessageBoxButtons::OK,MessageBoxIcon::Error);

    return false;

   }//RegSetValueEx

  }

  else if(dwType == REG_DWORD){

   if(RegSetValueEx(ghSubKey,valueName,0,dwType,(BYTE*)&dwkeyValue,sizeof(dwkeyValue)) != ERROR_SUCCESS){

    RegCloseKey(ghKey);

    RegCloseKey(ghSubKey);

    MessageBox::Show(L"无法创建组策略注册表子项目值",L"",MessageBoxButtons::OK,MessageBoxIcon::Error);

    return false;

   }//RegSetValueEx

  }

  if(pGPO->Save(false,true,&ng1,&ng2) != S_OK){

   RegCloseKey(ghKey);

   RegCloseKey(ghSubKey);

   MessageBox::Show(L"保存组策略失败",L"",MessageBoxButtons::OK,MessageBoxIcon::Error);

   return false;

  }

  pGPO->Release();

  RegCloseKey(ghKey);

  RegCloseKey(ghSubKey);

  return true;

  }