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

WiX自定义动作无法同步路径值至文本框及DISM调用问题

我来帮你搞定这两个WiX自定义动作的问题,都是实际开发中很容易踩的坑:


问题1:BrowseForFolder返回值无法同步到SXS_PATH属性和文本框

原因分析

你的代码没法同步路径,主要是两个关键问题:

  1. 未处理用户取消浏览的场景:当用户点击BrowseForFolder对话框的「取消」按钮时,objFolder会变成空值(Nothing),这时候执行Set objFolderItem = objFolder.Self会直接抛出错误,导致Err.Number不为0,跳过了设置Session.Property("SXS_PATH")的逻辑。
  2. SXS_PATH属性未标记为Secure:在UAC启用的Windows环境下,immediate模式的自定义动作要把属性传递给后续UI或动作,必须给属性加上Secure="yes",否则属性值会被UAC机制过滤,无法正常传递。

修复方案

1. 修改VBScript代码,增加空值判断

给脚本加上错误捕获,并且只在用户确实选择了文件夹时才设置属性:

Option Explicit
Public Sub GetSxsPath()
    Dim objShell, objFolder, objFolderItem, strPath
    Const WINDOW_HANDLE = 0
    Const NO_OPTIONS = 0
    
    On Error Resume Next ' 开启错误捕获,避免取消时直接崩溃
    Set objShell = CreateObject("Shell.Application")
    Set objFolder = objShell.BrowseForFolder _
        (WINDOW_HANDLE, "Choose SxS Folder for IIS role and .NET features", NO_OPTIONS)
    
    If Not objFolder Is Nothing Then ' 仅当用户选择了文件夹才继续
        Set objFolderItem = objFolder.Self
        strPath = objFolderItem.Path
        Session.Property("SXS_PATH") = strPath
    End If
    
    ' 清理对象,避免内存泄漏
    Set objFolderItem = Nothing
    Set objFolder = Nothing
    Set objShell = Nothing
    On Error GoTo 0 ' 关闭错误捕获
End Sub

2. 修改WiX中的SXS_PATH属性,添加Secure标记

<Property Id="SXS_PATH" Value="C:\" Secure="yes" />

这样修改后,用户选择文件夹时会正确同步路径到SXS_PATH,取消操作也不会报错,属性值也能在UAC环境下正常传递。


问题2:调用DISM命令并传入SXS_PATH的值

DISM是修改系统组件的命令,需要管理员权限,所以不能用普通的immediate自定义动作,得用**延迟执行(deferred)**的模式,并且禁用用户模拟(Impersonate="no"),同时要把SXS_PATH属性传递到延迟上下文里,具体实现方案如下:

方案1:用WiX自带的CAQuietExec执行命令(推荐)

这种方式不用额外写脚本,直接用WiX内置的静默执行组件:

  1. 定义传递属性的CustomAction:把SXS_PATH打包成CustomActionData,传递给延迟动作
<CustomAction Id="SetDismActionData" Property="RunDismCommand" Value="SXS_PATH=[SXS_PATH]" Execute="immediate" />
  1. 定义执行DISM的CustomAction:配置延迟执行和权限
<CustomAction Id="RunDismCommand" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Impersonate="no" Return="check" />
  1. 配置DISM命令参数:用转义后的引号和连接符整合命令,通过[SXS_PATH]引用传递的路径
<Property Id="RunDismCommand" Value="&quot;C:\Windows\System32\DISM.exe&quot; /Online /Enable-Feature /FeatureName:NetFx3 /All /Source:[SXS_PATH] &amp;&amp; &quot;C:\Windows\System32\DISM.exe&quot; /Online /Enable-Feature /FeatureName:IIS-WebServerRole /FeatureName:IIS-RequestFiltering /FeatureName:IIS-Security /FeatureName:IIS-HttpLogging /FeatureName:IIS-HealthAndDiagnostics /FeatureName:IIS-WebServerManagementTools /FeatureName:IIS-ManagementConsole /FeatureName:IIS-IIS6ManagementCompatibility /FeatureName:IIS-Metabase /FeatureName:IIS-WebServer /FeatureName:IIS-Performance /FeatureName:IIS-HttpCompressionStatic /FeatureName:IIS-CommonHttpFeatures /FeatureName:IIS-StaticContent /FeatureName:IIS-DefaultDocument /FeatureName:IIS-DirectoryBrowsing /FeatureName:IIS-HttpErrors /FeatureName:IIS-ApplicationDevelopment /FeatureName:IIS-ASPNET /FeatureName:IIS-NetFxExtensibility /FeatureName:IIS-ISAPIExtensions /FeatureName:IIS-ISAPIFilter /all /Source:[SXS_PATH]" />

注意:XML里引号要用&quot;转义,多个命令用&amp;&amp;连接

  1. 添加到安装序列:确保动作在正确的时机执行,且只在用户选择离线安装时触发
<InstallExecuteSequence>
    <Custom Action="SetDismActionData" Before="RunDismCommand">ONOFF_PROPERTY = "1" AND NOT Installed</Custom>
    <Custom Action="RunDismCommand" Before="InstallFinalize">ONOFF_PROPERTY = "1" AND NOT Installed</Custom>
</InstallExecuteSequence>

方案2:用VBScript执行DISM(适合需要更多自定义逻辑的场景)

如果你更习惯用VBScript,也可以写一个延迟执行的脚本:

  1. VBScript代码:通过Session.CustomActionData获取传递的路径
Option Explicit
Public Sub RunDism()
    Dim strSxsPath, objShell, strCmd
    strSxsPath = Session.CustomActionData("SXS_PATH")
    
    ' 拼接DISM命令,用Chr(34)表示引号
    strCmd = """C:\Windows\System32\DISM.exe"" /Online /Enable-Feature /FeatureName:NetFx3 /All /Source:" & Chr(34) & strSxsPath & Chr(34)
    strCmd = strCmd & " && ""C:\Windows\System32\DISM.exe"" /Online /Enable-Feature /FeatureName:IIS-WebServerRole /FeatureName:IIS-RequestFiltering /FeatureName:IIS-Security /FeatureName:IIS-HttpLogging /FeatureName:IIS-HealthAndDiagnostics /FeatureName:IIS-WebServerManagementTools /FeatureName:IIS-ManagementConsole /FeatureName:IIS-IIS6ManagementCompatibility /FeatureName:IIS-Metabase /FeatureName:IIS-WebServer /FeatureName:IIS-Performance /FeatureName:IIS-HttpCompressionStatic /FeatureName:IIS-CommonHttpFeatures /FeatureName:IIS-StaticContent /FeatureName:IIS-DefaultDocument /FeatureName:IIS-DirectoryBrowsing /FeatureName:IIS-HttpErrors /FeatureName:IIS-ApplicationDevelopment /FeatureName:IIS-ASPNET /FeatureName:IIS-NetFxExtensibility /FeatureName:IIS-ISAPIExtensions /FeatureName:IIS-ISAPIFilter /all /Source:" & Chr(34) & strSxsPath & Chr(34)
    
    Set objShell = CreateObject("WScript.Shell")
    objShell.Run strCmd, 0, True ' 0表示隐藏命令窗口,True表示等待命令执行完成
    Set objShell = Nothing
End Sub
  1. WiX配置:定义脚本二进制文件和对应的CustomAction
<CustomAction Id="SetDismVbsActionData" Property="RunDismVbs" Value="SXS_PATH=[SXS_PATH]" Execute="immediate" />
<CustomAction Id="RunDismVbs" BinaryKey="DismScript.vb" Impersonate="no" Return="check" Execute="deferred" VBScriptCall="RunDism" />
<Binary Id="DismScript.vb" SourceFile="RunDism.vbs"/>
<InstallExecuteSequence>
    <Custom Action="SetDismVbsActionData" Before="RunDismVbs">ONOFF_PROPERTY = "1" AND NOT Installed</Custom>
    <Custom Action="RunDismVbs" Before="InstallFinalize">ONOFF_PROPERTY = "1" AND NOT Installed</Custom>
</InstallExecuteSequence>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:34:51