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

写入注册表后刷新系统或者重新启动服务器,是可以起作用的,但是组策略不认,因此在下一次组策略刷新后可能会导致配置失效,因此还是必须让组策略接纳我们的修改,组策略的缓冲存储在注册表 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,决定于策略的有效范围!并写入你的数据,最后刷新系统即可。

因此完整的代码如下:

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 // Root

{$EXTERNALSYM GPO_SECTION_ROOT}

GPO_SECTION_USER // User

{$EXTERNALSYM GPO_SECTION_USER}

GPO_SECTION_MACHINE // Machine

const

IID_GPO TGUID '{EA502722-A23D-11d1-A7D3-0000F87571E3}' 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 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 bMachine 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 HRESULT stdcall function GetOptions dwOptions DWORD HRESULT stdcall function SetOptions dwOptions dwMask DWORD HRESULT stdcall function GetType gpoType GROUP_POLICY_OBJECT_TYPE HRESULT stdcall function GetMachineName pszName LPOLESTR cchMaxLength Integer HRESULT stdcall function GetPropertySheetPages hPages PHPROPSHEETPAGE uPageCount HRESULT stdcall const

REGISTRY_EXTENSION_GUID TGUID $35378EAC $683F $11D2 CLSID_GPESnapIn TGUID $8fc0b734 $a0e1 $11d1 procedure TForm1 Button1Click Sender TObject IGroupPolicyObject begin

CreateComObject IID_GPO IGroupPolicyObject OpenLocalMachineGPO GPO_OPEN_LOAD_REGISTRY begin

GetRegistryKey GPO_SECTION_USER TRegistry Create RootKey HKEY_CURRENT_USER OpenKey 'Software\Microsoft\Windows\CurrentVersion\Policies\Explorer' begin

WriteInteger 'StartMenuLogOff' RootKey OpenKey '\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer' begin

WriteInteger 'StartMenuLogOff' RegCloseKey False REGISTRY_EXTENSION_GUID CLSID_GPESnapIn finally

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

,组策略的全部注册表项目,可以在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,

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,

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;