🚀 Executive Summary
TL;DR: Scripts often fail on 64-bit Windows due to being inexplicably launched in 32-bit PowerShell sessions, caused by the WoW64 compatibility layer redirecting `powershell.exe` calls. Solutions include using the `Sysnative` virtual folder, explicitly configuring calling applications to use the 64-bit path, or implementing a self-elevating script to force 64-bit execution.
🎯 Key Takeaways
- Windows 64-bit operating systems maintain separate 64-bit (`C:\Windows\System32`) and 32-bit (`C:\Windows\SysWOW64`) PowerShell executables due to the WoW64 compatibility layer.
- The `Sysnative` virtual folder alias (`%windir%\Sysnative`) allows 32-bit processes to directly access 64-bit system files, including `powershell.exe`, providing a tactical fix.
- For robust, long-term solutions, explicitly specify the full 64-bit PowerShell path (`C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe`) in calling applications or implement a self-elevating script that re-launches itself in 64-bit if detected as 32-bit.
Tired of your scripts failing because they’re inexplicably running in a 32-bit PowerShell session on a 64-bit OS? Learn why this happens and discover three practical, real-world solutions to force the 64-bit version every time.
Wait, Why Am I in 32-Bit PowerShell? A Field Guide for the Perplexed.
I’ll never forget it. 2 AM, PagerDuty screaming bloody murder because the nightly backup job for `prod-db-01` had failed. I remote in, heart pounding, and run the backup script manually. It works perfectly. I check the logs from the automated run… “The module ‘SqlServer’ could not be loaded.” I stare at the screen, baffled. We installed that module weeks ago. After an hour of desperate debugging, I finally thought to check `[System.IntPtr]::Size` in the script context. It returned `4`. The monitoring agent, bless its outdated heart, was launching the 32-bit version of PowerShell, which couldn’t see the 64-bit module we’d installed. It’s one of those problems that makes you question your sanity, and it’s far more common than you think.
The Ghost in the Machine: Why Does This Even Happen?
This isn’t a bug; it’s a feature—a very old, often frustrating feature of Windows called WoW64 (Windows 32-bit on Windows 64-bit). It’s a compatibility layer designed to let 32-bit applications run seamlessly on 64-bit operating systems.
Here’s the rub: a 64-bit Windows OS has two different versions of PowerShell.exe, and two different “System” folders:
| Folder | Contains… | What it means for you |
C:\Windows\System32 |
64-bit system files | This is where the “real” 64-bit `powershell.exe` lives. This is what you want. |
C:\Windows\SysWOW64 |
32-bit system files | This is a compatibility folder. The 32-bit `powershell.exe` is here. |
The problem arises when an older 32-bit application (like a monitoring agent, a legacy deployment tool, or even a poorly configured Task Scheduler job) tries to launch “powershell.exe”. WoW64 automatically redirects that call to the 32-bit version in `SysWOW64` to maintain compatibility. The result? Your script runs in a 32-bit world, completely isolated from your 64-bit modules and registry keys.
Taming the Beast: Three Ways to Get Back to 64-Bit
Okay, enough theory. You’re in a firefight and you need a fix. Here are three ways to solve this, from a quick patch to a permanent solution.
Solution 1: The “Get Me Out of Here” Sysnative Trick
This is the fastest way to get your script running in 64-bit, especially when you can’t change the application that’s calling it. It relies on a special virtual folder alias called `Sysnative` that is only visible to 32-bit processes. It acts as a direct portal to the true 64-bit `System32` folder.
You simply change the command in your scheduler or tool to use this path.
%windir%\Sysnative\WindowsPowerShell\v1.0\powershell.exe -File "C:\Scripts\MyAwesomeScript.ps1"
Darian’s Pro Tip: This path, `%windir%\Sysnative\`, only works when called from a 32-bit process. If you try to browse to it in a 64-bit File Explorer, you’ll get a “Location is not available” error. Don’t panic; that’s expected behavior. It’s a magic door that only 32-bit apps can see.
This is a great, tactical fix. It’s a bit “hacky,” but it works reliably when you’re in a pinch.
Solution 2: The “Do It Right” Method – Fix the Calling Application
The `Sysnative` trick is a patch. The real solution is to find what’s launching the 32-bit process and configure it correctly. This is about fixing the root cause. Dig into the tool that’s running your script.
- Windows Task Scheduler: This is a common culprit. When you create a task, make sure you’re pointing to the full, explicit path of the 64-bit executable.
- CI/CD Agents (Jenkins, TeamCity, etc.): Check the configuration of your build agent or runner. Is it a 32-bit service? Does the step configuration allow you to specify the full path to the executable?
- Monitoring Tools (SCOM, SolarWinds, etc.): These agents often run as 32-bit services. Check the action/alert configuration to see if you can provide the full 64-bit path.
Don’t just type `powershell.exe`. Be explicit.
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -File "C:\Scripts\MyAwesomeScript.ps1"
This is the clean, long-term fix we should all strive for. It makes your environment predictable and easier to troubleshoot later.
Solution 3: The “I Don’t Trust Anything” Self-Elevating Script
Sometimes, you can’t control the calling application. Maybe it’s a locked-down, third-party tool, and you have no ability to change how it executes commands. In this scenario, you make your script smart enough to fix the problem itself.
You add a small block of code to the very beginning of your script. This code checks if it’s running in 32-bit. If it is, it re-launches itself using the 64-bit engine (via our old friend `Sysnative`) and immediately exits the 32-bit session.
# --- Start of self-elevation block ---
# Check if we are in a 32-bit process. If so, re-launch in 64-bit.
if ($env:PROCESSOR_ARCHITEW6432 -eq "AMD64") {
Write-Warning "Running in 32-bit PowerShell on a 64-bit OS. Re-launching in 64-bit..."
# Get the full path to the current script
$scriptPath = $MyInvocation.MyCommand.Path
# Re-launch using the sysnative path to the 64-bit powershell.exe
& "$env:windir\sysnative\windowspowershell\v1.0\powershell.exe" -ExecutionPolicy Bypass -File $scriptPath
# Exit the current 32-bit session
exit
}
# --- End of self-elevation block ---
# Your REAL script logic starts here.
# This part will only ever be executed by the 64-bit process.
Write-Host "Success! Now running in the correct 64-bit process."
# For example, try to load a 64-bit only module:
# Import-Module SqlServer
This approach is incredibly robust. It makes your script self-sufficient and resilient, no matter how it’s called. It’s defensive programming for your infrastructure, and I use it in any critical script that I know might be executed by an unpredictable external system.
My Two Cents
Look, we all use the `Sysnative` trick (Solution 1) to put out fires. There’s no shame in it. But for your core, production systems, take the time to implement Solution 2. A predictable, explicit environment will save you from that 2 AM PagerDuty call. And if you can’t trust the environment at all, make your scripts tough enough to fend for themselves with Solution 3.
Stay sane out there.
– Darian
🤖 Frequently Asked Questions
âť“ Why does PowerShell sometimes run in 32-bit on a 64-bit system?
This occurs due to WoW64 (Windows 32-bit on Windows 64-bit), a compatibility layer that redirects calls to `powershell.exe` from 32-bit applications to the 32-bit version located in `C:\Windows\SysWOW64`, preventing access to 64-bit modules and registry keys.
âť“ How do the different solutions for forcing 64-bit PowerShell compare?
The `Sysnative` trick is a quick patch for 32-bit callers. Explicitly fixing the calling application to use the full 64-bit path (`C:\Windows\System32\…`) is the clean, long-term solution. A self-elevating script provides robust self-correction when the calling environment is untrustworthy.
âť“ What is a common implementation pitfall when using the `Sysnative` trick?
A common pitfall is attempting to browse to `%windir%\Sysnative` from a 64-bit process like File Explorer, which will result in a ‘Location is not available’ error. The `Sysnative` virtual folder is only visible and accessible to 32-bit processes.
Leave a Reply