注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

珠海渔郎之电子网档

项目管理 + 程序开发 + Delphi + 电脑应用 + 数码 + 进化感悟

 
 
 

日志

 
 

Windows组策略的刷新和修改  

2009-08-22 18:13:07|  分类: Delphi |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

Windows组策略的刷新和修改

By Kingron, 版权所有,2006-6-20

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

网友kaso_tian的补充:

经过Kingron的指点,我也搞定的组策略,而且证明K兄的思路非常正确.下边把我的vc++.net代码发上来共享.PS:因为是公司的项目,所以只发个我写的修改组策略的函数,别的有什么问题E-MAIL我

/*
更改组策略设置方法
参数:
 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;
   }

  评论这张
 
阅读(3830)| 评论(1)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017