如何使Inno setup在注册表中设置的DefaultIcon图标立即生效

如何使Inno setup在注册表中设置的DefaultIcon图标立即生效

使用Inno setup制作安装包,需要给某一格式文件制定打开方式和文件图标,修改了注册表信息,但是设置的用于更改图标的DefaultIcon值没有立即生效,一定要注销或重启电脑后才行,有什么方法可以让其立即生效吗?

以及在代码中,小弟用的是electron,在往注册表中写入了图标后,无法立马展示,需要重启资源管理器后才行,请问electron下面有相应可以立即更新图标的操作或是windows下提供了吗

在Windows下,注册表的更改通常需要注销或重启才能生效。您可以尝试使用 SHChangeNotify 函数刷新资源管理器以立即更新图标。以下是示例代码:

import win32api
import win32con

# 刷新资源管理器
win32api.SHChangeNotify(win32con.SHCNE_ASSOCCHANGED, win32con.SHCNF_IDLIST, None, None)

此代码使用了 win32api 模块和常量 SHChangeNotify 和 SHCNE_ASSOCCHANGED 和 SHCNF_IDLIST。该函数将通知资源管理器进行更新。在您的应用程序中调用此函数应该可以立即更新图标。

另外,使用 Inno Setup 时,您可以尝试在更改 DefaultIcon 注册表项后,运行一个程序来调用上述代码,以便立即更新图标。

在 Windows 操作系统中,当你修改了注册表信息后,如果想让修改立即生效,可以尝试使用 SHChangeNotify 函数通知操作系统有关系统设置的更改,这样可以让更改立即生效,而不需要重启电脑或注销用户。

在 Inno Setup 中,你可以使用 Exec 函数来调用 Windows API SHChangeNotify。下面是一个示例代码,展示了如何使用 Inno Setup 修改注册表并调用 SHChangeNotify 函数:


[Code]
const
  SHCNE_ASSOCCHANGED = $8000000;
  SHCNF_IDLIST = 0;

function SHChangeNotify(wEventID: LongWord; uFlags: LongWord; dwItem1, dwItem2: Cardinal): Boolean;
  external 'SHChangeNotify@shell32.dll stdcall';

procedure UpdateIcon();
var
  IconPath: String;
  RegPath: String;
begin
  IconPath := ExpandConstant('{app}\MyIcon.ico');
  RegPath := 'Software\Classes\.txt\DefaultIcon';

  // 修改注册表信息
  RegWriteStringValue(HKEY_CLASSES_ROOT, RegPath, '', IconPath);

  // 发送通知,使更改立即生效
  SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
end;

在上面的示例中,UpdateIcon 过程首先使用 RegWriteStringValue 函数修改了 .txt 文件的默认图标路径。然后使用 SHChangeNotify 函数通知操作系统有关系统设置的更改。

你可以在你的安装脚本中调用 UpdateIcon 过程来更新文件图标。当你的安装程序运行完毕时,应该能够立即看到修改的图标,而不需要重启电脑或注销用户。

在注册表中设置 DefaultIcon 图标后,默认会使用缓存中的图标,因此需要刷新图标缓存才能使设置的图标立即生效。

可以使用以下方式来刷新图标缓存:

打开资源管理器,按下 F5 键,或者右键文件夹并选择“刷新”菜单项,即可刷新图标缓存。
1、在控制台中使用以下命令来强制刷新图标缓存: ie4uinit.exe -ClearIconCache
2、在 Inno Setup 安装完成后,可以通过在 Run 段添加一个条目来刷新图标缓存。例如:

[Run]
Filename: "{cmd}"; \
    Parameters: "/c ie4uinit.exe -ClearIconCache"; \
    Flags: runhidden

Filename 指定要运行的命令行程序,Parameters 指定要传递的参数,Flags 指定运行选项,这里使用 runhidden 隐藏命令行窗口。执行完成后,图标缓存就会被强制刷新。

可以尝试使用Windows的ShellExecute函数来重新加载注册表中的DefaultIcon值,以使其立即生效。可以使用以下代码来实现:

ShellExecute(NULL, "regedit.exe", "/e", NULL, NULL, SW_SHOW);

默认情况下,在 Windows 操作系统中更改注册表后,更改可能不会立即生效,需要重新启动或注销用户才能使更改生效。这是因为 Windows 在启动时加载注册表,并将其缓存在内存中,因此任何更改只有在注册表被重新加载时才会生效。

如果您希望在安装程序完成后立即应用更改,可以尝试通过执行以下步骤来强制 Windows 重新加载注册表:

打开“任务管理器”,找到并结束“资源管理器”进程;
在“任务管理器”中,单击“文件”->“新任务”;
在“新建任务”对话框中,键入“explorer”并单击“确定”按钮;
这会启动资源管理器,并强制 Windows 重新加载注册表。
您也可以在 Inno Setup 脚本中添加代码来自动执行这些步骤。例如,可以在安装程序完成时使用以下代码强制重新加载资源管理器:

[Code]
function UpdateRegistryIcons(): Boolean;
var
  ResultCode: Integer;
begin
  // 终止资源管理器进程
  ResultCode := Exec('taskkill', '/f /im explorer.exe', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
  if ResultCode <> 0 then begin
    // 发生错误
    MsgBox('Failed to kill explorer.exe process. Error code: ' + IntToStr(ResultCode), mbError, MB_OK);
    Result := False;
    Exit;
  end;

  // 启动资源管理器进程
  ResultCode := Exec('explorer', '', '', SW_SHOW, ewWaitUntilTerminated, ResultCode);
  if ResultCode <> 0 then begin
    // 发生错误
    MsgBox('Failed to start explorer.exe process. Error code: ' + IntToStr(ResultCode), mbError, MB_OK);
    Result := False;
    Exit;
  end;

  Result := True;
end;

// 在安装程序完成后调用此函数
procedure CurStepChanged(CurStep: TSetupStep);
begin
  if CurStep = ssDone then begin
    UpdateRegistryIcons();
  end;
end;

这段代码将在安装程序完成后终止资源管理器进程,然后再启动它。这将强制 Windows 重新加载注册表,并且对 DefaultIcon 值所做的更改立即生效。

默认情况下,在Windows操作系统中更改注册表键值时,需要注销或重新启动计算机才能使更改生效。不过,可以通过强制资源管理器重新加载图标缓存来使更改的图标立即生效。您可以尝试以下两种方法:

方法一:使用SystemParametersInfo函数刷新图标缓存

在安装完成后,可以使用SystemParametersInfo函数刷新图标缓存。该函数可以强制资源管理器重新加载图标缓存,以使图标更改立即生效。以下是使用SystemParametersInfo函数的示例代码:

objectivec

const UINT SPI_SETNONCLIENTMETRICS = 42;
const UINT SPIF_UPDATEINIFILE = 0x01;
const UINT SPIF_SENDCHANGE = 0x02;

SystemParametersInfo(SPI_SETNONCLIENTMETRICS, 0, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);

方法二:使用SHChangeNotify函数刷新图标缓存

另一个更新图标缓存的方法是使用SHChangeNotify函数。该函数可以向Windows资源管理器发送通知,以通知其重新加载图标缓存。以下是使用SHChangeNotify函数的示例代码:

c

const LONG SHCNE_ASSOCCHANGED = 0x08000000;
const LONG SHCNF_FLUSH = 0x1000;

SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSH, NULL, NULL);

如果您使用的是Electron框架,您可以使用electron-shells API中的函数来刷新图标缓存。以下是使用electron-shells API的示例代码:

javascript

const { app, shell } = require('electron');

app.on('ready', () => {
  // 刷新图标缓存
  shell.writeShortcutLink('shortcut.lnk', 'target.exe', { icon: 'icon.ico' }, () => {
    console.log('图标已更新');
  });
});

希望这些解决方案对您有帮助。


import requests
import pandas as pd

url = "http://data.stats.gov.cn/easyquery.htm"

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36",
    "Referer": "http://data.stats.gov.cn/easyquery.htm"
}

params = {
    "m": "QueryData",
    "dbcode": "hgnd",
    "rowcode": "zb",
    "colcode": "sj",
    "wds": "[]",
    "dfwds": '[{"wdcode":"reg","valuecode":"110000"}]',
    "k1": "1646047042605"
}

data = {
    "pageNo": "1",
    "pageSize": "5000",
    "orderBy": "sj desc",
    "q": ""
}

response = requests.post(url, params=params, headers=headers, data=data)
data = response.json()
df = pd.DataFrame(data['returndata']['datanodes'])
df[['zb_name', 'unit']] = pd.DataFrame(df['wds'].tolist())[['zb', 'unit']]

df.drop(columns=['wds'], inplace=True)
df[['year', 'month']] = pd.DataFrame(df['sj'].tolist(), index=df.index)
df.drop(columns=['sj'], inplace=True)
df.rename(columns={'data': 'value', 'zb_name': 'indicator'}, inplace=True)
df = df[['year', 'month', 'indicator', 'value', 'unit']]
df.to_csv('hgnd.csv', index=False)

不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

通过使用命令行工具来刷新Shell缓存:

taskkill /IM explorer.exe /F
start explorer.exe

这将终止并重新启动资源管理器进程,从而刷新Shell缓存。
关于Electron是否有相应的操作来立即更新图标,不是很清楚。
但是,通过在Electron应用程序中使用以上任意一种方式刷新Shell缓存,可以立即更新注册表中的图标。

在Windows中,注册表更改并不会立即生效,而是需要等待Windows重新加载注册表时才会生效。在一些情况下,注销或重新启动计算机也可以强制使更改生效。

你可以尝试使用一些第三方工具来重新加载注册表,以使更改生效。例如,RegReload工具可以重新加载指定的注册表文件,而不需要注销或重新启动计算机。你可以将该工具作为Inno setup安装程序的一部分,以在安装过程中使用。

对于electron应用程序,可以尝试使用app.relaunch()方法来重启应用程序并使更改生效。该方法将退出当前的应用程序并启动一个新的实例。请注意,这可能会导致数据丢失,因此请在使用之前备份任何必要的数据。

以下是一个使用RegReload工具的示例Inno Setup脚本:

Source: "RegReload.exe"; DestDir: "{app}"

Filename: "{app}\RegReload.exe"; Parameters: "example.reg"; Flags: waituntilterminated skipifdoesntexist

这将在安装程序目录中复制RegReload.exe工具,并在安装完成后执行该工具以重新加载example.reg文件。注意waituntilterminated标志将使安装程序等待RegReload执行完成后再继续执行后续命令