Run scripts with the Package Support Framework
Scripts enable IT Pros to customize an application dynamically to the user's environment after it is packaged using MSIX. For example, you can use scripts to configure your database, set up a VPN, mount a shared drive, or perform a license check dynamically. Scripts provide a lot of flexibility. They may change registry keys or perform file modifications based on the machine or server configuration.
You can use the Package Support Framework (PSF) to run one PowerShell script before a packaged application executable runs and one PowerShell script after the application executable runs to clean up. Each application executable defined in the application manifest can have its own scripts. You can configure the script to run once only on the first app launch and without showing the PowerShell window so users won't end the script prematurely by mistake. There are other options to configure the way scripts can run, shown below.
Prerequisites
To enable scripts to run, you need to set the PowerShell execution policy to RemoteSigned
. You can do this by running this command:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
The execution policy needs to be set for both the 64-bit PowerShell executable and the 32-bit PowerShell executable. Make sure to open each version of PowerShell and run one of the commands shown above.
Here are the locations of each executable.
- 64-bit computer:
- 64-bit executable: %SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe
- 32-bit executable: %SystemRoot%\SysWOW64\WindowsPowerShell\v1.0\powershell.exe
- 32-bit computer:
- 32-bit executable: %SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe
For more information about PowerShell execution policies, see this article.
🚩 Make sure to also include the StartingScriptWrapper.ps1 file in your package and place it in the same folder as your executable. You can copy this file from the PSF NuGet package or from the PSF Github repo.
Enable scripts
To specify what scripts will run for each packaged application executable, you need to modify the config.json file. To tell PSF to run a script before the execution of the packaged application, add a configuration item called startScript
. To tell PSF to run a script after the packaged application finishes add a configuration item called endScript
.
Script configuration items
The following are the configuration items available for the scripts. The ending script ignores the waitForScriptToFinish
and stopOnScriptError
configuration items.
Key name | Value type | Required? | Default | Description |
---|---|---|---|---|
scriptPath |
string | Yes | N/A | The path to the script including the name and extension. The path is relative to the application's working directory if specified, otherwise, it starts at the root directory of the package. |
scriptArguments |
string | No | empty | Space delimited argument list. The format is the same for a PowerShell script call. This string gets appended to scriptPath to make a valid PowerShell.exe call. |
runInVirtualEnvironment |
boolean | No | true | Specifies whether the script should run in the same virtual environment that the packaged application runs in. |
runOnce |
boolean | No | true | Specifies whether the script should run once per user, per version. |
showWindow |
boolean | No | false | Specifies whether the PowerShell window is shown. |
stopOnScriptError |
boolean | No | false | Specifies whether to exit the application if the starting script fails. |
waitForScriptToFinish |
boolean | No | true | Specifies whether the packaged application should wait for the starting script to finish before starting. |
timeout |
DWORD | No | INFINITE | How long the script will be allowed to execute. When the time elapses, the script will be stopped. |
Note
Setting stopOnScriptError: true
and waitForScriptToFinish: false
for the sample application is not supported. If you set both of these configuration items, PSF will return the error ERROR_BAD_CONFIGURATION.
Sample configuration
Here is a sample configuration using two different application executables.
{
"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)
]
}