如何在不重启的情况下刷新注册表项?
How to refresh registry keys without reboot?
我使用以下代码更改注册表中的区域数据。
procedure TForm1.Button1Click(Sender: TObject);
var
reg: TRegistry;
begin
reg:=TRegistry.Create;
try
reg.RootKey:=HKEY_CURRENT_USER;
reg.OpenKey('\Control Panel\International\',true);
reg.WriteString('iCountry','1');
reg.WriteString('iCurrDigits','2');
reg.WriteString('iCurrency','0');
reg.WriteString('iDate','1');
reg.WriteString('iDigits','2');
reg.WriteString('iLZero','0');
reg.WriteString('iMeasure','1');
reg.WriteString('iNegCurr','0');
reg.WriteString('iNegNumber','1');
reg.WriteString('iTimePrefix','0');
reg.WriteString('iTLZero','1');
reg.WriteString('Locale','00000409');
reg.WriteString('LocaleName','en-US');
reg.WriteString('sCountry','United States');
reg.WriteString('sDate','/');
reg.WriteString('sDecimal','.');
reg.WriteString('iNegCurr','0');
reg.WriteString('sShortDate','dd/MM/yyyy'); reg.CloseKey;
finally
reg.free;
end;
end;
但这需要在更改生效之前重新启动机器。不重启也可以吗?
更改注册表后,广播系统范围的 WM_SETTINGCHANGE
message by calling SendMessageTimeout()
,其 hWnd
设置为 HWND_BROADCAST
:
Applications should send WM_SETTINGCHANGE to all top-level windows when they make changes to system parameters.
...
wParam
... When the system sends this message as a result of a change in locale settings, this parameter is zero.
When an application sends this message, this parameter must be NULL.
...
lParam
... When the system sends this message as a result of a change in locale settings, this parameter points to the string "intl".
例如:
procedure TForm1.Button1Click(Sender: TObject);
var
reg: TRegistry;
begin
reg := TRegistry.Create;
try
reg.RootKey := HKEY_CURRENT_USER;
reg.Access := KEY_SET_VALUE;
if reg.OpenKey('\Control Panel\International\', true) then
try
reg.WriteString('iCountry','1');
reg.WriteString('iCurrDigits','2');
reg.WriteString('iCurrency','0');
reg.WriteString('iDate','1');
reg.WriteString('iDigits','2');
reg.WriteString('iLZero','0');
reg.WriteString('iMeasure','1');
reg.WriteString('iNegCurr','0');
reg.WriteString('iNegNumber','1');
reg.WriteString('iTimePrefix','0');
reg.WriteString('iTLZero','1');
reg.WriteString('Locale','00000409');
reg.WriteString('LocaleName','en-US');
reg.WriteString('sCountry','United States');
reg.WriteString('sDate','/');
reg.WriteString('sDecimal','.');
reg.WriteString('iNegCurr','0');
reg.WriteString('sShortDate','dd/MM/yyyy');
finally
reg.CloseKey;
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, LPARAM(PChar('intl')), SMTO_NORMAL, 100, PDWORD(nil)^);
end;
finally
reg.free;
end;
end;
在你问之前,是的,以这种方式在最后一个参数中使用 nil
是安全的:
Passing nil to a variable parameter
在 XE2 之前,Delphi 的 Windows
单元将 SendMessageTimeout()
的最后一个参数声明为:
var lpdwResult: DWORD
但 Win32 API 将参数定义为:
_Out_opt_ PDWORD_PTR lpdwResult
允许传入 NULL 指针。上述 nil
技巧是 Delphi 代码将 NULL 值传递给 var
参数的唯一方法。编译器生成的机器代码是正确的——它只是简单地将值 0 传递给参数,它实际上不会尝试访问内存地址 $00000000.
在 XE2 中,Windows
单元被更改为将最后一个参数声明为:
lpdwResult: PDWORD_PTR
匹配 Win32 API 定义。
因此,如果您将代码升级到 XE2 或更高版本,只需将 PDWORD(nil)^
替换为 nil
。或者,您可以现在考虑,以后不用担心:
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, LPARAM(PChar('intl')), SMTO_NORMAL, 100, {$IF RTLVersion >= 23}nil{$ELSE}PDWORD(nil)^{$IFEND});
我使用以下代码更改注册表中的区域数据。
procedure TForm1.Button1Click(Sender: TObject);
var
reg: TRegistry;
begin
reg:=TRegistry.Create;
try
reg.RootKey:=HKEY_CURRENT_USER;
reg.OpenKey('\Control Panel\International\',true);
reg.WriteString('iCountry','1');
reg.WriteString('iCurrDigits','2');
reg.WriteString('iCurrency','0');
reg.WriteString('iDate','1');
reg.WriteString('iDigits','2');
reg.WriteString('iLZero','0');
reg.WriteString('iMeasure','1');
reg.WriteString('iNegCurr','0');
reg.WriteString('iNegNumber','1');
reg.WriteString('iTimePrefix','0');
reg.WriteString('iTLZero','1');
reg.WriteString('Locale','00000409');
reg.WriteString('LocaleName','en-US');
reg.WriteString('sCountry','United States');
reg.WriteString('sDate','/');
reg.WriteString('sDecimal','.');
reg.WriteString('iNegCurr','0');
reg.WriteString('sShortDate','dd/MM/yyyy'); reg.CloseKey;
finally
reg.free;
end;
end;
但这需要在更改生效之前重新启动机器。不重启也可以吗?
更改注册表后,广播系统范围的 WM_SETTINGCHANGE
message by calling SendMessageTimeout()
,其 hWnd
设置为 HWND_BROADCAST
:
Applications should send WM_SETTINGCHANGE to all top-level windows when they make changes to system parameters.
...
wParam
... When the system sends this message as a result of a change in locale settings, this parameter is zero.When an application sends this message, this parameter must be NULL.
...
lParam
... When the system sends this message as a result of a change in locale settings, this parameter points to the string "intl".
例如:
procedure TForm1.Button1Click(Sender: TObject);
var
reg: TRegistry;
begin
reg := TRegistry.Create;
try
reg.RootKey := HKEY_CURRENT_USER;
reg.Access := KEY_SET_VALUE;
if reg.OpenKey('\Control Panel\International\', true) then
try
reg.WriteString('iCountry','1');
reg.WriteString('iCurrDigits','2');
reg.WriteString('iCurrency','0');
reg.WriteString('iDate','1');
reg.WriteString('iDigits','2');
reg.WriteString('iLZero','0');
reg.WriteString('iMeasure','1');
reg.WriteString('iNegCurr','0');
reg.WriteString('iNegNumber','1');
reg.WriteString('iTimePrefix','0');
reg.WriteString('iTLZero','1');
reg.WriteString('Locale','00000409');
reg.WriteString('LocaleName','en-US');
reg.WriteString('sCountry','United States');
reg.WriteString('sDate','/');
reg.WriteString('sDecimal','.');
reg.WriteString('iNegCurr','0');
reg.WriteString('sShortDate','dd/MM/yyyy');
finally
reg.CloseKey;
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, LPARAM(PChar('intl')), SMTO_NORMAL, 100, PDWORD(nil)^);
end;
finally
reg.free;
end;
end;
在你问之前,是的,以这种方式在最后一个参数中使用 nil
是安全的:
Passing nil to a variable parameter
在 XE2 之前,Delphi 的 Windows
单元将 SendMessageTimeout()
的最后一个参数声明为:
var lpdwResult: DWORD
但 Win32 API 将参数定义为:
_Out_opt_ PDWORD_PTR lpdwResult
允许传入 NULL 指针。上述 nil
技巧是 Delphi 代码将 NULL 值传递给 var
参数的唯一方法。编译器生成的机器代码是正确的——它只是简单地将值 0 传递给参数,它实际上不会尝试访问内存地址 $00000000.
在 XE2 中,Windows
单元被更改为将最后一个参数声明为:
lpdwResult: PDWORD_PTR
匹配 Win32 API 定义。
因此,如果您将代码升级到 XE2 或更高版本,只需将 PDWORD(nil)^
替换为 nil
。或者,您可以现在考虑,以后不用担心:
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, LPARAM(PChar('intl')), SMTO_NORMAL, 100, {$IF RTLVersion >= 23}nil{$ELSE}PDWORD(nil)^{$IFEND});