You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改Wix代码使安装结束时以管理员权限启动自定义Run.exe?

问题描述

我制作了一款Wix安装程序,期望实现以下功能:在安装即将结束(点击「完成」按钮前),启动自定义的Run.exe,完成VS Redistributable的安装并启动主应用Converter。

目前遇到的问题:代码无法启动Converter,会收到来自Converter的错误提示「Failed to launch Converter for Windows.」,但以管理员身份打开命令行窗口执行以下命令时,Converter可以正常启动:

msiexec.exe /i C:\ConverterWixSetup64.msi /L*vx c:\Log.txt

请问需要修改哪些代码,才能让Run.exe以管理员权限启动,从而无需以管理员身份运行命令行即可正常启动Converter?

现有代码

Wix代码

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
     xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
    <?include "..\include\Variables.wxi" ?>
    <Fragment>
      <CustomAction Id='LaunchApplication' Directory="INSTALLFOLDER" ExeCommand='cmd.exe /c Run.exe' Execute='deferred' Impersonate='no' Return='asyncNoWait' />
    </Fragment>
</Wix>


<InstallExecuteSequence>
    <Custom Action="LaunchApplication" Before="InstallFinalize"></Custom>
</InstallExecuteSequence>

Run.exe启动Converter的代码

//_tprintf(_T("\nLaunching %s..."), appDisplayName);
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(STARTUPINFO));
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
si.cb = sizeof(STARTUPINFO);
//start Converter application
if (!CreateProcess(appName, NULL, NULL, NULL, false, CREATE_NEW_PROCESS_GROUP, NULL, NULL, &si, &pi))
{
    //if failed to open, give user feed back
    /*_tprintf(_T("\n>  %s failed to launch."), appDisplayName);
    _tprintf(_T("\n%s"), closingApp);*/
    MessageBox(NULL, appFailedString.c_str(), failedToOpenConverterForWindows, MB_OK);
    return 3;
}
HWND hWnd = GetConsoleWindow();
ShowWindow(hWnd, SW_HIDE);
//WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
解决方案

针对你的问题,需要从Wix配置和Run.exe代码两方面修改,确保Run.exe以管理员权限启动,同时解决路径/工作目录问题:

1. 优化Wix自定义动作配置

当前通过cmd.exe /c调用Run.exe会额外创建cmd进程,可能导致权限传递或工作目录异常,建议直接调用Run.exe:

<CustomAction Id='LaunchApplication' 
              Directory="INSTALLFOLDER" 
              ExeCommand='Run.exe' 
              Execute='deferred' 
              Impersonate='no' 
              Return='asyncNoWait' />
  • 移除cmd.exe /c,直接执行Run.exe,避免额外进程带来的干扰
  • 保留Execute='deferred'和Impersonate='no',确保自定义动作以系统管理员权限运行

2. 修复Run.exe的CreateProcess调用

Converter启动失败核心原因大概率是路径错误或工作目录不正确,需要做以下调整:

(1)使用Converter的绝对路径

确保appName是Converter.exe的完整绝对路径,可以通过Run.exe自身路径拼接获取:

TCHAR runPath[MAX_PATH];
GetModuleFileName(NULL, runPath, MAX_PATH);
PathRemoveFileSpec(runPath); // 获取Run.exe所在目录
TCHAR appPath[MAX_PATH];
PathCombine(appPath, runPath, _T("Converter.exe")); // 拼接Converter的绝对路径

之后用appPath替代原代码中的appName传入CreateProcess。

(2)指定正确的工作目录

在CreateProcess的第8个参数(lpCurrentDirectory)传入Run.exe所在目录,确保Converter启动时工作目录正确:

if (!CreateProcess(appPath, NULL, NULL, NULL, false, CREATE_NEW_PROCESS_GROUP, NULL, runPath, &si, &pi))

(3)简化窗口隐藏逻辑(可选)

替换手动隐藏控制台窗口的代码,在CreateProcess中添加CREATE_NO_WINDOW标志直接隐藏窗口:

if (!CreateProcess(appPath, NULL, NULL, NULL, false, CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW, NULL, runPath, &si, &pi))

这样可以省去GetConsoleWindow()和ShowWindow()的代码。

3. 确认安装序列时机

当前Before="InstallFinalize"的配置是正确的,此时所有安装文件已复制到目标目录,Run.exe和Converter都已存在,无需调整。

内容的提问来源于stack exchange,提问作者Ming

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 04:45:34