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

use*_*348 2 delphi registry file-format delphi-10.4-sydney

在 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);
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

在此输入图像描述

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

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

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

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

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

And*_*and 6

问题似乎是该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);
Run Code Online (Sandbox Code Playgroud)

删除它也是如此:

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);
Run Code Online (Sandbox Code Playgroud)

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


我可以通过将 DSi 函数更改为以下方式来使其工作:

DSiKillRegistry('\Software\Classes\' + progID, HKEY_CURRENT_USER, KEY_ALL_ACCESS);
Run Code Online (Sandbox Code Playgroud)