As you may know (or have not realised so far) is that all your Win32 apps in Intune are being run in the 32 Bit environment. Usually this is not an issue as most executables elevate themselves into the 64 Bit environment if required. But there are some edge cases, where this is relevant, like creating some entries in the registry.
But let’s start from the beginning: We usually pack more complex Applications into a Win32 App / Intune-Win File. There we pack the executable and usually two PowerShell Files for installation and uninstallation and those a triggered as follows from Intune: powershell.exe -ExecutionPolicy Bypass -WindowStyle hidden -File install.ps1
As mentioned above, this script is being run in a 32 Bit environment and if you need to create registry items in the HKLM:\SOFTWARE\
node, you will notice, that the items you just added are ending up in the HKLM:\SOFTWARE\WOW6432Node
. Not what you wanted and expected.
We can check that behaviour by adding the following lines of code to our PowerShell script and make sure the output is being saved by Start-Transcript or another solution for logging.
Write-Host "checking environment"
Write-Host " PowerShell Version: $($PSVersionTable.PSVersion)"
Write-Host " is 64bit os: $([Environment]::Is64BitOperatingSystem)"
Write-Host " is 64bit process: $([Environment]::Is64BitProcess)"
On a 64 Bit system, this will then return the following output:
checking environment
PowerShell Version: 5.1.26100.2161
is 64bit os: True
is 64bit process: False
So, what can we do about that? We can simply trigger the 64 Bit PowerShell to run our commands. And if you were wondering, the PowerShell 5 executable is hiding under the following path if you’re in a 32 Bit environment.
"$($env:SystemRoot)\sysnative\WindowsPowerShell\v1.0\powershell.exe"
There are multiple options to solve that issue, and we’re going to look into the following three:
- Pass the cmlets to 64 Bit PowerShell
We can call the 64Bit PowerShell executable and pass the required commands via the Command parameter. - Use a dedicated 64 Bit script
We can use a dedicated Script containing the code to be run in 64 Bit PowerShell - Run the whole file itself
Or we can call the Install-Script itself in 64 Bit PowerShell
Pass the cmlets to 64 Bit PowerShell
This is the simplest variant, but it gets quite messy if you need to run multiple or complex commands. But we just call the 64 Bit PowerShell executable with the Command
Parameter.
C:\Windows\sysnative\WindowsPowerShell\v1.0\powershell.exe -Command { "is 64bit process: $([Environment]::Is64BitProcess)" }
Use a dedicated 64 Bit script
Another option is to create a dedicated script containing all the commands that need to be run in 64 Bit PowerShell. And we’re going to add that script to the Intunewin File we’re packing.
From the initial Install-Script, we can then run the 64 Bit PowerShell Executable with the File
Parameter. In the following code, we’re assuming that the dedicated script is in the same folder as the Install-Script.
$PowershellX64Executable = "$($env:SystemRoot)\sysnative\WindowsPowerShell\v1.0\powershell.exe"
$Arguments = "-File `"$($PSScriptRoot)\MyCustomScript.ps1`""
$Process = Start-Process `
-FilePath $PowershellX64Executable `
-ArgumentList $Arguments `
-PassThru `
-Wait
Run the whole file itself
The last option is to call the Install-Script from the Install-Script. But, with some extra steps.
First we check, if we’re on a 64 Bit OS and if the Process is running in the 32 Bit environment. If this is true, we’re calling our script in the 64 Bit Environment. And due to above check, we run the following if
statement only once. Make sure to exit the Script after launching the Process.
Of course, we need to be careful about recursion (to understand recursion, you first have to understand recursion. You may Google it as well.)
if ([Environment]::Is64BitOperatingSystem -eq $true -and [Environment]::Is64BitProcess -eq $false) {
$PowershellX64Executable = "$($env:SystemRoot)\sysnative\WindowsPowerShell\v1.0\powershell.exe"
$Arguments = "-File `"$($MyInvocation.MyCommand.Definition)`""
Write-Host "starting process in 64bit powershell"
Write-Host " using executable '$($PowershellX64Executable)'"
Write-Host " using arguments '$($Arguments)'"
Stop-Transcript
$Process = Start-Process `
-FilePath $PowershellX64Executable `
-ArgumentList $Arguments `
-PassThru `
-Wait
exit $Process.ExitCode
}
With this option we only require to have one script, if you call the Script in 64 Bit PowerShell already it will run the required commands as expected and if not, it will spawn a new PowerShell Session in 64 Bit. Make sure to add your commands after the if-Statement.
A whole script could look as follows:
Write-Host "checking environment"
Write-Host " PowerShell Version: $($PSVersionTable.PSVersion)"
Write-Host " is 64bit os: $([Environment]::Is64BitOperatingSystem)"
Write-Host " is 64bit process: $([Environment]::Is64BitProcess)"
if ([Environment]::Is64BitOperatingSystem -eq $true -and [Environment]::Is64BitProcess -eq $false) {
$PowershellX64Executable = "$($env:SystemRoot)\sysnative\WindowsPowerShell\v1.0\powershell.exe"
$Arguments = "-File `"$($MyInvocation.MyCommand.Definition)`""
Write-Host "starting process in 64bit powershell"
Write-Host " using executable '$($PowershellX64Executable)'"
Write-Host " using arguments '$($Arguments)'"
Stop-Transcript
$Process = Start-Process `
-FilePath $PowershellX64Executable `
-ArgumentList $Arguments `
-PassThru `
-Wait
exit $Process.ExitCode
}
# your commands in 64 bit PowerShell
Start-Process "msiexec.exe" `
-ArgumentList '/i "YourApp.msi" /qn /norestart' `
-Wait
$registryPath = "HKLM:\SOFTWARE\YourApp\YourNode"
if ((Test-Path -Path $registryPath ) -eq $false) {
New-Item -Path $registryPath
}
New-ItemProperty `
-Path $registryPath `
-Name "YourItem" `
-Value "YourValue" `
-PropertyType "String"
exit 0
Schreiben Sie einen Kommentar