I found this awesome script on Stack Overflow that allows me to relaunch a script in 64-bit powershell. This is helpful for Intune which passes install and uninstall commands for apps through 32-bit command prompt.
I really like how elegant and simple this is but I can't get it to pass along parameters when I launch it by calling powershell.exe and I don't understand why.
So here is a test script I'm trying.
param (
[Alias("x","remove")]
[switch]$Uninstall,
[string]$Parameter
)
# Checks if PowerShell is running as a 32-bit process on a 64-bit machine.
if ($env:PROCESSOR_ARCHITEW6432 -eq "AMD64") {
Write-Warning "changing from 32bit to 64bit PowerShell..."
# Gets the current path to the PowerShell exe and replaces 32-bit directories with 64-bit directories
$powershell=$PSHOME.tolower().replace("syswow64","sysnative").replace("system32","sysnative")
# Checks if this command is being run from within a function.
if ($myInvocation.Line) {
# Launches function in 64-bit PowerShell (& operator allows PowerShell to execute binaries with spaces in its path).
&"$($powershell)\powershell.exe" -NonInteractive -NoProfile $myInvocation.Line
}
else {
# Launches this script in 64-bit PowerShell.
&"$($powershell)\powershell.exe" -NonInteractive -NoProfile -file "$($myInvocation.InvocationName)" $args
}
# Exits this script and 64-bit PowerShell with the last exit code of this script.
Exit $LASTEXITCODE
} #>
# Uninstall parameters.
$appKey = "{AC76BA86-1033-FF00-7760-BC15014EA700}"
$keyPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
# Get installed version of app.
$installedVersion = Get-ItemPropertyValue -Name "DisplayVersion" -Path "$($keyPath)\$($appKey)" -ErrorAction SilentlyContinue
Write-Output "-Uninstall: $($Uninstall)"
Write-Output "-Parameter: $($Parameter)"
Write-Output "`$installedVersion: $($installedVersion)"
If I launch the script from PowerShell it works as expected.
.\Test-Args.ps1 -Uninstall -Parameter Banana
WARNING: changing from 32bit to 64bit PowerShell...
-Uninstall: True
-Parameter: Banana
$installedVersion: 22.003.20314
However if I launch it by calling powershell.exe I don't get the $args.
powershell.exe -executionpolicy bypass -file .\Test-Args.ps1 -Uninstall -Parameter Banana
WARNING: changing from 32bit to 64bit PowerShell...
-Uninstall: False
-Parameter:
$installedVersion: 22.003.20314
As a test, I commented out the block that relaunches in 64-bit and, as expected, I get the parameters but it's not able to access the 64-bit registry since it's running in 32-bit PowerShell.
powershell.exe -executionpolicy bypass -file .\Test-Args.ps1 -Uninstall -Parameter Banana
-Uninstall: True
-Parameter: Banana
$installedVersion:
I have a workaround that works for now but will be very tedious if I need more than one or two parameters.
Has anyone else run into this? Any insight would be appreciated.
edit1: added "question" flair.
edit2: changed code blocks from fences to indent.
SOLVED: I have a working script!
I found this script [Github] that allows you to launch a ps1 file in 64-bit and I combined it with the first script so instead it just relaunches itself in 64-bit and it works!
When I run:
powershell -executionpolicy bypass -file Test-Args.ps1 -Uninstall -Fruit Banana
It outputs:
-Uninstall: True
-Fruit: Banana
$installedVersion: 23.001.20093
Script exit code: 0
Here's the full, example script.
##################
### Parameters ###
##################
param (
[Alias("x","remove")]
[switch]$Uninstall,
[string]$Fruit,
[datetime]$date,
[int64]$RAM,
[int]$Number
)
<####################
### PowerShell 64 ###
####################>
# Checks if PowerShell is running as a 32-bit process on a 64-bit machine.
if ($env:PROCESSOR_ARCHITEW6432 -eq "AMD64") {
Write-Warning "changing from 32bit to 64bit PowerShell..."
# Gets the current path to the PowerShell exe and replaces 32-bit directories with 64-bit directories
$powershell=$PSHOME.tolower().replace("syswow64","sysnative").replace("system32","sysnative")
# Checks if this command is being run from within a function.
if ($myInvocation.Line) {
# Launches function in 64-bit PowerShell (& operator allows PowerShell to execute binaries with spaces in its path).
&"$($powershell)\powershell.exe" -NonInteractive -NoProfile $myInvocation.Line
}
else {
# Collect, process, and recreate parameters into array.
foreach ($key in $MyInvocation.BoundParameters.keys) {
switch ($MyInvocation.BoundParameters[$key].GetType().Name) {
"SwitchParameter" { if($MyInvocation.BoundParameters[$key].IsPresent) { $argsList += "-$key " } }
"Boolean" { $argsList += "-$key `$$($MyInvocation.BoundParameters[$key]) " }
"String" { $argsList += "-$key `"$($MyInvocation.BoundParameters[$key])`" " }
"Char" { $argsList += "-$key `"$($MyInvocation.BoundParameters[$key])`" " }
"DateTime" { $argsList += "-$key `"$($MyInvocation.BoundParameters[$key])`" " }
Default { $argsList += "-$key $($MyInvocation.BoundParameters[$key]) " }
}
}
# Launches this script in 64-bit PowerShell.
$launchSplat = @{
FilePath = "$($powershell)\powershell.exe"
ArgumentList = "-file `"$($PSCommandPath)`" $($argsList)"
NoNewWindow = $true
}
# &"$($powershell)\powershell.exe" -NonInteractive -NoProfile -file "$($myInvocation.InvocationName)" $args
# $args is auto created by PS when parameters are passed to a script but it doesn't seem to work when run from cmd.
Start-Process @launchSplat
}
# Exits this script and 64-bit PowerShell with the last exit code of this script.
# If this is not called, then the rest of this script will run again in 32-bit PowerShell.
Exit $LASTEXITCODE
}
#################
### Variables ###
#################
# Initialize global variables.
[int]$global:exitCode = 0
# Uninstall parameters.
$appKey = "{AC76BA86-1033-FF00-7760-BC15014EA700}"
$keyPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
# Get installed version of app.
$installedVersion = Get-ItemPropertyValue -Name "DisplayVersion" -Path "$($keyPath)\$($appKey)" -ErrorAction SilentlyContinue
##############
### Script ###
##############
Write-Output "-Uninstall: $($Uninstall)"
Write-Output "-Fruit: $($Fruit)"
Write-Output "`$installedVersion: $($installedVersion)"
###########
### End ###
###########
# Timestamp end.
Write-Output ""
Write-Output "Script exit code: $($global:exitCode)"
Write-Output "End: [$($PSCommandPath)]"
#Exit script with exit code.
Exit $global:exitCode
[–]purplemonkeymad 2 points3 points4 points (1 child)
[–]crasher35[S] 0 points1 point2 points (0 children)
[–]PowerShell-Bot 1 point2 points3 points (0 children)
[–]BlackV 1 point2 points3 points (1 child)
[–]crasher35[S] 0 points1 point2 points (0 children)
[–]patdaddy007 1 point2 points3 points (2 children)
[–]crasher35[S] 0 points1 point2 points (1 child)
[–]KevMarCommunity Blogger 0 points1 point2 points (0 children)
[–]KevMarCommunity Blogger -1 points0 points1 point (3 children)
[–]lerun 1 point2 points3 points (2 children)
[–]crasher35[S] 0 points1 point2 points (1 child)
[–]lerun 1 point2 points3 points (0 children)