首页 > 解决方案 > 如何为我的应用程序取消注册文件格式?

问题描述

在 Windows 10 的 Delphi 10.4.2 win-32 VCL 应用程序中,我.ICO使用DSiWin32.DSiRegisterUserFileAssoc为我的图形应用程序注册文件格式:

DSiRegisterUserFileAssoc(
    '.ico',                                              // extension: .ico
    'UGAICOFile',                                        // progID: UGAICOFile
    'ICO File',                                          // description: ICO File
    'C:\DELPHI\MyApp\MyApp.ico',                         // Icon File
    '"C:\DELPHI\MyApp\Win32\Debug\MyApp.exe" "%1"'       // openCommand
    );

SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);

这可以正常工作,并且在 Windows 文件资源管理器中双击 .ICO 文件时,我的应用程序会加载 .ICO 文件。这些注册表项已使用正确的值创建:

在此处输入图像描述

在此处输入图像描述

但是,当我尝试使用 取消注册.ICO图形应用程序的文件格式时DSiWin32.DSiUnregisterUserFileAssoc,它不起作用:

procedure TForm1.btnUnregisterClick(Sender: TObject);
begin
  DSiUnregisterUserFileAssoc('UGAICOFile');
  SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);
end;

UGAICOFileprogID 键没有从注册表中删除!在文件资源管理器中双击 .ICO 文件仍会加载我的应用程序!

即使我在提升模式下尝试它(通过以管理员身份启动程序)它也不起作用!难道是注册的微软应用程序.ico\OpenWithProgrids可以阻止密钥被删除?

那么如何取消注册.ICO我的应用程序的注册文件格式?

标签: delphiregistryfile-formatdelphi-10.4-sydney

解决方案


问题似乎是DSiUnregisterUserFileAssoc函数没有获得所需的注册表访问级别。

编程时我的经验法则之一是除非绝对必要,否则永远不要使用第三方库,部分原因是您不了解它们的所有细节。在这种情况下,我不太明白添加一个相当大的库只是为了做一些简单的注册表更改的意义!

手动建立关联很简单:

var Reg := TRegistry.Create;
try
  Reg.RootKey := HKEY_CURRENT_USER;
  if Reg.OpenKey('\Software\Classes\.myfile', True) then
    Reg.WriteString('', 'MyAppDataFile');
  if Reg.OpenKey('\Software\Classes\MyAppDataFile', True) then
    Reg.WriteString('', 'My Very Own Text File Type');
  if Reg.OpenKey('\Software\Classes\MyAppDataFile\DefaultIcon', True) then
    Reg.WriteString('', 'C:\WINDOWS\notepad.exe');
  if Reg.OpenKey('\Software\Classes\MyAppDataFile\shell\open\command', True) then
    Reg.WriteString('', 'C:\WINDOWS\notepad.exe "%1"');
finally
  Reg.Free;
end;
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);

删除它也是如此:

var Reg := TRegistry.Create;
try
  Reg.RootKey := HKEY_CURRENT_USER;
  Reg.DeleteKey('\Software\Classes\MyAppDataFile');
finally
  Reg.Free;
end;
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);

这很有效,它不需要额外的库(有很多你不需要的东西、潜在的安全问题、潜在的错误等),并且你确切地知道代码的作用。你对它有100%的理解。


我可以通过将 DSi 功能更改为以下内容来使其工作:

DSiKillRegistry('\Software\Classes\' + progID, HKEY_CURRENT_USER, KEY_ALL_ACCESS);

推荐阅读