使用包支持框架运行脚本

脚本使 IT 专业人员能够在使用 MSIX 打包应用程序后动态地将应用程序自定义到用户环境。 例如,可以使用脚本来配置数据库、设置 VPN、装载共享驱动器或动态执行许可证检查。 脚本提供了很大的灵活性。 它们可能会更改注册表项,或者根据计算机或服务器配置执行文件修改。

可以使用包支持框架 (PSF) 在打包的应用程序可执行文件运行之前运行一个 PowerShell 脚本,并在应用程序可执行文件运行后运行一个 PowerShell 脚本来清理。 应用程序清单中定义的每个应用程序可执行文件都可以有自己的脚本。 可以将脚本配置为仅在第一个应用启动时运行一次,而不显示 PowerShell 窗口,以便用户不会错误地提前结束脚本。 还有其他选项可用于配置脚本可以运行的方式,如下所示。

先决条件

若要使脚本能够运行,需要将 PowerShell 执行策略设置为 RemoteSigned。 可以通过运行以下命令来执行此操作:

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned

需要为 64 位 PowerShell 可执行文件和 32 位 PowerShell 可执行文件设置执行策略。 请确保打开每个版本的 PowerShell 并运行上面所示的命令之一。

下面是每个可执行文件的位置。

  • 64 位计算机:
    • 64 位可执行文件:%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe
    • 32 位可执行文件:%SystemRoot%\SysWOW64\WindowsPowerShell\v1.0\powershell.exe
  • 32 位计算机:
    • 32 位可执行文件:%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe

有关 PowerShell 执行策略的详细信息,请参阅 本文

🚩 请确保还包括包中的 StartingScriptWrapper.ps1 文件,并将其放置在可执行文件所在的同一文件夹中。 可以从 PSF NuGet 包PSF Github 存储库复制此文件。

启用脚本

若要指定将针对每个打包的应用程序可执行文件运行的脚本,需要修改 config.json 文件。 若要告诉 PSF 在执行打包的应用程序之前运行脚本,请添加一个名为的配置 startScript项。 若要告诉 PSF 在打包的应用程序完成后运行脚本,请添加一个名为的配置 endScript项。

脚本配置项目

下面是可用于脚本的配置项。 结束脚本将 waitForScriptToFinish 忽略和 stopOnScriptError 配置项。

项名称 值类型 必需? 默认 说明
scriptPath 字符串 不适用 脚本的路径,包括名称和扩展。 如果指定,则路径相对于应用程序的工作目录,否则它将从包的根目录开始。
scriptArguments 字符串 empty 空格分隔参数列表。 PowerShell 脚本调用的格式相同。 此字符串将追加到 scriptPath 进行有效的PowerShell.exe调用。
runInVirtualEnvironment boolean 指定脚本是否应在打包应用程序所在的同一虚拟环境中运行。
runOnce boolean 指定脚本是否应按每个版本每个用户运行一次。
showWindow boolean false 指定是否显示 PowerShell 窗口。
stopOnScriptError boolean false 指定在启动脚本失败时是否退出应用程序。
waitForScriptToFinish boolean 指定打包的应用程序是否应等待启动脚本在开始之前完成。
timeout DWORD INFINITE 允许脚本执行多长时间。 时间过后,脚本将停止。

注意

不支持设置 stopOnScriptError: truewaitForScriptToFinish: false 示例应用程序。 如果同时设置这两个配置项,PSF 将返回错误ERROR_BAD_CONFIGURATION。

示例配置

下面是使用两个不同的应用程序可执行文件的示例配置。

{
  "applications": [
    {
      "id": "Sample",
      "executable": "Sample.exe",
      "workingDirectory": "",
      "stopOnScriptError": false,
      "startScript":
      {
        "scriptPath": "RunMePlease.ps1",
        "scriptArguments": "\\\"First argument\\\" secondArgument",
        "runInVirtualEnvironment": true,
        "showWindow": true,
        "waitForScriptToFinish": false
      },
      "endScript":
      {
        "scriptPath": "RunMeAfter.ps1",
        "scriptArguments": "ThisIsMe.txt"
      }
    },
    {
      "id": "CPPSample",
      "executable": "CPPSample.exe",
      "workingDirectory": "",
      "startScript":
      {
        "scriptPath": "CPPStart.ps1",
        "scriptArguments": "ThisIsMe.txt",
        "runInVirtualEnvironment": true
      },
      "endScript":
      {
        "scriptPath": "CPPEnd.ps1",
        "scriptArguments": "ThisIsMe.txt",
        "runOnce": false
      }
    }
  ],
  "processes": [
    ...(taken out for brevity)
  ]
}