Vista 之後修改登錄表需管理員權限,直接寫入極其麻煩。採用「產生 .reg 檔案 + ShellExecute 執行」策略,利用系統註冊編輯器自動提權完成操作。
uses System.IOUtils, Winapi.ShellAPI, Winapi.ShlObj;
{ 關聯副檔名到指定應用程式並設定圖示 }
procedure RegApp(const aExt, aAppName, aAppPath: string);
const
nRegFmt =
'Windows Registry Editor Version 5.00' + sLineBreak +
'[HKEY_CLASSES_ROOT\%0:s]' + sLineBreak +
'@="%1:s"' + sLineBreak +
'[HKEY_CLASSES_ROOT\%1:s\DefaultIcon]' + sLineBreak +
'@="%2:s,0"' + sLineBreak +
'[HKEY_CLASSES_ROOT\%1:s\shell]' + sLineBreak +
'[HKEY_CLASSES_ROOT\%1:s\shell\open]' + sLineBreak +
'[HKEY_CLASSES_ROOT\%1:s\shell\open\command]' + sLineBreak +
'@="%3:s"';
var
RegStr: string;
str3, str4: string;
RegTmpFile: string;
begin
{ 路徑轉義處理 }
str3 := aAppPath.Replace('\', '\\');
str4 := Format('"%s" "%%1"', [str3]).Replace('"', '\"');
RegStr := Format(nRegFmt, [aExt, aAppName, str3, str4]);
{ 寫入暫存 .reg 檔案 }
RegTmpFile := TPath.GetTempPath + 'RegTmp.reg';
with TStringList.Create do
begin
Text := RegStr;
SaveToFile(RegTmpFile);
Free;
end;
{ 呼叫系統註冊編輯器執行 (自動觸發 UAC 提權) }
ShellExecute(0, nil, PChar(RegTmpFile), nil, nil, SW_SHOWNORMAL);
{ 通知 Shell 重新整理圖示快取 }
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
{ 註冊 .tst 副檔名關聯到當前程式 }
RegApp('.tst', 'MyApp1', Application.ExeName);
end;
\""%1" 代表被雙擊的檔案完整路徑regedit.exe,自動彈出 UAC 對話框| 優點 | 缺點 |
|---|---|
| 無需程式本身以管理員執行 | 彈出 UAC 對話框需使用者確認 |
| 程式碼簡潔,利用系統元件 | 依賴 regedit.exe 關聯正常 |
| 自動處理複雜的權限提升流程 | 非即時生效,需等待使用者回應 |
此方案為「不以管理員身分執行主程式」情境下的最佳折衷方案,廣泛適用於檔案關聯、自啟動註冊等需寫入 HKLM 或 HKCR 的場景。