SOLVED

Powershell script is not working using PSF

Copper Contributor

Hi Everyone,

 

I am trying to run a powershell script using the PSF binaries in a MSIX package. However, it is not working. The powershell script on its own is working as expected. Can someone look into the config.json file I am using.

The content of the config.json file is:

 

{
"applications": [
{
"id": "TRMANIFEST",
"executable": "VFS/ProgramFilesX86/Maersk Denizcilik A.S/TRManifest_Setup/TRManifest2009.exe",
"stopOnScriptError": false,
"startScript":
{
"scriptExecutionMode": "-ExecutionPolicy Unrestricted",
"scriptPath": "MapDrive.ps1",
"showWindow": true,
"runInVirtualEnvironment": false,
"waitForScriptToFinish": true,
"timeout":10
}
}
]
}

Let me know if there is something wrong in this file.

18 Replies
First, it would help to know what version of the PSF (or what version of tooling you used) is involved. We have better support for scripting in the TimMangan branch on GitHub than in the original Microsoft branch.

Second, there are no obvious errors in your json syntax, however, here are some things to consider:
* The runInVirtualEnvironment setting is ignored. Microsoft removed support for this. In my fork, this script will always run inside the container. Out of container powershell is now possible starting in PSF v2022.06.08 but not through this scripting method. But if you are just mapping a drive it shouldn't matter if it runs inside or outside.
* The timeout value is in MS, so if you intended 10 seconds multiply by 1000.
* As specified, your ps1 file would need to be placed at the root folder of the package.
* The PSF StartingScriptWrapper.ps1 file must also be placed there.
Hi

Can you share the package (via messages), the script and manifest file. It will help us debug it deeper.
Thanks

Hi @Aniket_Banerjee @TIMOTHY MANGAN 

 

Application Name : Notepad++

Requirement : copying file config.xml (to suppress auto updates)

File Location: $Env:ProgramFiles\WindowsApps\Notepad_1.0.0.0_x64__vwr83xx145m1c\VFS\ProgramFilesX86\Notepad++\config.xml

File Destination : %localappdata%\Packages\Notepad_vwr83xx145m1c\LocalCache\Roaming\Notepad++

==============================

I am trying to copy config.xml file from MSIX package install directory location to users localappdata. the file contains settings to suppress auto update. I did everything required, but not able to succeed to achieve the output. Could you please suggest where I am missing. I have attached config.json, copyfile.ps1, MSIX PSF files pictures, please review.

 

I followed below link:

https://www.alexandrumarin.com/add-powershell-scripts-in-msix-with-psf/

https://docs.microsoft.com/en-us/windows/msix/psf/run-scripts-with-package-support-framework

https://techcommunity.microsoft.com/t5/msix/notepad-automatic-language-configuration/m-p/3558411

but no luck. please assist.

THANKS in Advance.

I believe that the correct path for the copy would be under the package writable root VFS\AppData\Notepad++ folder. But you might be working too hard on that.

The Alex link is about deploying a file based on a runtime decision and therefore must be done with a script. To package up Notepad++ using a static preconfigured file, I copy the file after package installation and use the FileRedirectionFixup to take care of the rest. See https://github.com/TimMangan/App-Info/tree/main/docs/Windows/Notepad++/MainApp
thanks for the information, I will try to do that, but my main intension here is to copy a file with powershell script, which is not happening even after doing all. please advise, am I missing anythings?
So assuming that you are not using the FileRedirectionFixup, I know that if you copied the file into the users normal AppData/Roaming/Notepad++ folder (after creating that folder), the MSIX runtime would redirect that write to the location you are trying to copy to. Maybe try that.

On the other hand, if you included the FRF, you'd copy to the %MSIXWritablePackageRoot%\VFS\AppData\Notepad++ folder instead.

@SJamal85Aside from folder layout / pathing issues, if you try to run a script hidden in the background (unsigned,) without any user interaction, it will fail unless the execution policy is set to "Bypass." I don't think I've ever run an unsigned script without it being set to "Bypass."

 

"Set-ExecutionPolicy - Parameters" -> https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/set-executionpolicy...

 

"Bypass. Nothing is blocked and there are no warnings or prompts.

 

Unrestricted. ...If you run an unsigned script that was downloaded from the internet, you're prompted for permission before it runs."

 

How to: Sign application and deployment manifests | Methods of signing scripts

 

NOTE: It also depends on what revision of Powershell the host machine has, ( must have WMF 5.1 ) how up-to-date the cmdlets are, whether it has the latest certificates / protocols, etc (even though that's almost outside of the scope of what you're trying to accomplish. I'm more describing roadblocks which would hinder the functionality / usefulness of your script over the long-term. )

# ExecutionPolicy -List
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope CurrentUser -Force
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope LocalMachine -Force;
Set-PSReadLineOption -HistorySaveStyle SaveNothing -MaximumHistoryCount 1;
Write-Output "Remove-Module PSReadline" | Out-File -FilePath $PROFILE -NoNewline -Width 24;
# Set-Content -Value "Remove-Module PSReadline" -NoNewline -Path $PROFILE;
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;
Install-PackageProvider -Name NuGet -Scope AllUsers -Force;
Install-PackageProvider -Name PowerShellGet -Scope AllUsers -Force;
Get-Module -ListAvailable | Update-Module -Scope AllUsers -Force;
Update-Help -Verbose -Force -ErrorAction SilentlyContinue;

Obviously you could also run a batch file instead, that utilizes powershell without a profile. In theory, you could use this if you wanted to to launch another script to get around access restrictions, to chain scripts / batch files in succession, or it's an environment with a mix of batch files, powershell scripts, etc, where you might only want a few cmdlets, and the rest of the focus is on other scripting languages.

powershell -noprofile -Command "& {New-Item -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\temporaryentry'}"
powershell -noprofile -Command "& {Remove-Item -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\temporaryentry'}"

The onus is on the person installing the MSIX package, to verify whether or not it's safe to use. It's not like this is enabling malicious software, and there are plenty of ways to add safeguards. You could find a way to sign all of your scripts and code before distributing them, with public / private key certificates. It seems more like this is just for personal use, so it would be hard to justify that type of workload. You could even use OpenSSL 3.x to generate it, and convert it to a .PFX file afterwards. To distribute it though, you would probably need to leverage either a post-paid or free certificate authority, for code signing or just generating RSA / ECC certs. It really depends on what it is. I mean I compiled OpenSSL on Windows, and then used it to generate a whole bunch of generic certs by hand ( utilizing cryptographically secure seed values on an air-gapped device, with virtual memory disabled, etc. I erased my seed values after with Sdelete. )

@TIMOTHY MANGAN , @Aniket_Banerjee I am attaching few screenshots, please check if I am making any mistakes here. 

best response confirmed by SJamal85 (Copper Contributor)
Solution
1) The PsfScriptLauncher.ps1 file is missing from the root of the package. This file is part of the PSF. This file is required as it will be executed in PowerShell to then run your script.
2) The timeout value in the Json is too low. The 10 represents 10ms which is generally not long enough for PowerShell to even start up. Increase to 10000 to get 10 seconds, for example.
3) Add a sleep to the end of the powershell start-sleep 60 would give you time to see any error messages in the PowerShell window should they occur. If so, the timeout value will have to increase more.
4) The Unrestricted option in the json will cause a problem if there is any GPO setting the PowerShell restriction policy. As is in your ps1 file, the Bypass option might be a better choice
5) If you still have issues, use the Sysinternals DebugView tool which can display debugging information emitted by the PsfLauncher as it tries to start your script. Start that tool, then launch the shortcut.
Thanks for your inputs. My package finally worked as expected :)

hi @TIMOTHY MANGAN : just out of curiosity, does MSIX also support VB script or now all required scripting needs to be done through Powershell only with MSIX?

@SJamal85  It must be Powershell. You can provide a PS wrapper script that calls a VB Script.

 

@TIMOTHY MANGAN 

 

i have a question regarding a powershell script in my msix package. i want to copy files from the windowsapps folder to appdata. 

 

i added the script and also all psf files into the root of the package. When i start the application it says me 

sebastianpehlke_0-1694596545233.png

i tried Set-ExecutionPolicy -ExecutionPolicy ByPass -Scope Currentuser -Force and Set-ExecutionPolicy -ExecutionPolicy ByPass -Scope LocalMachine -Force in the package but it doesnt work.

 

what is my fault? Can you help?

 

thanks and best regards

You didn't indicate the source/version of the PSF that you are using. For the latest version from my branch, I find bypass works best, setting it in the config.json to handle it for you. Running the Set-Execution policy cmdlet yourself does not work if policy was previously set via GPO, so ByPass is the way to go.

@TIMOTHY MANGAN 

 

so you mean i can remove the set-executionplicy from my script and add the line scriptExecutionMode: to my config.json?

 

thanks

Yes. PsfLauncher calls an intermediate powershell script so you need the bypass.
Sounds good. i solved it but now i have another Problem and dont know if this is possible.
i need to copy a file from the "C:\Program Files\WindowsApps\10-****-556_7.3.0.0_x64__c7rwcv5qq3b5y" into "C:\Program Files\WindowsApps\10-****-556_7.3.0.0_x64__c7rwcv5qq3b5y\VFS\ProgramFilesX86\REDISwin" if a special requirement is true. I´ve added a script (ps1) and all required psf files, changed the manifest (target: psflauncher32.exe). But when i start the application the ps1 failes with the message:


Copy-Item : Access to the path 'C:\Program
Files\WindowsApps\10-****-556_7.3.0.0_x64__c7rwcv5qq3b5y\VFS\ProgramFilesX86\REDISwin\ErrorHandler.config' is denied.
At C:\Program Files\WindowsApps\10-****-556_7.3.0.0_x64__c7rwcv5qq3b5y\CC_StagesConfig.ps1:7 char:1
+ Copy-Item $sourcepath"\PU_ErrorHandler.config" -destination $targetpa ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (C:\Program File...rHandler.config:FileInfo) [Copy-Item], Unauthorized
AccessException
+ FullyQualifiedErrorId : CopyFileInfoItemUnauthorizedAccessError,Microsoft.PowerShell.Commands.CopyItemCommand



is there a way to handle that?

thanks for your help and have a nice afternoon.

@sebastianpehlke Yes there is a way to accomplish what you need.

 

Generally, you can't write to the WindowsApps area, but you can instead write to the redirection area that the PSF file-based fixups (FileRedirectionFixup or MfrFixup)  generally use.  Even without the file-based fixups in use in your package, the MSIX runtime will then find the VFS redirected files for Program Files and Windows.

 

The scripting engine provides two pseudo-variables to help you in specifying the file locations as arguments to your scripts.  %MsixPackageRoot% specifies the package folder under WindowsApps (which helps when you change package versions you don't need to edit that).  %MsixWritablePackageRoot% specifies the package folder under %LocalAppData%\Packages for this package (which is the version independent redirection area).  You can read more about this on the wiki page PsfLauncher · TimMangan/MSIX-PackageSupportFramework Wiki · GitHub 

 

Note that these pseudo-variables are referenced in the config.json file "Arguments" field and are passed into your script after they are dereferenced by Psflauncher.

1 best response

Accepted Solutions
best response confirmed by SJamal85 (Copper Contributor)
Solution
1) The PsfScriptLauncher.ps1 file is missing from the root of the package. This file is part of the PSF. This file is required as it will be executed in PowerShell to then run your script.
2) The timeout value in the Json is too low. The 10 represents 10ms which is generally not long enough for PowerShell to even start up. Increase to 10000 to get 10 seconds, for example.
3) Add a sleep to the end of the powershell start-sleep 60 would give you time to see any error messages in the PowerShell window should they occur. If so, the timeout value will have to increase more.
4) The Unrestricted option in the json will cause a problem if there is any GPO setting the PowerShell restriction policy. As is in your ps1 file, the Bypass option might be a better choice
5) If you still have issues, use the Sysinternals DebugView tool which can display debugging information emitted by the PsfLauncher as it tries to start your script. Start that tool, then launch the shortcut.

View solution in original post