Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jenkins powershell plugin is running 32 bit Powershell and I need 64bit

I'm pretty new to powershell integration in Jenkins and my scripts won't run because (I believe) I need powershell to be executed in 64 bit. Running:

[Environment]::Is64BitProcess

in my execution sequence yields false an then a cmdlet that I use (Get-WindowsFeature) is shown as not recognized as a cmdlet, etc. Any way to execute 64 bit powershell scripts? Thanks!

like image 942
Andy G. Avatar asked Feb 04 '15 21:02

Andy G.


People also ask

How do I open PowerShell 64-bit?

The 64-bit version of PowerShell (the one that 64-bit Windows opens by default) is located under: “C:\Windows\SysWOW64\WindowsPowerShell\v1. 0.” To run the program as administrator, right-click on powershell.exe and then choose the “Run as administrator” option.

Is PowerShell 64 or 32-bit?

When you run Windows PowerShell, the 64-bit version runs by default. However, you might occasionally need to run Windows PowerShell (x86), such as when you're using a module that requires the 32-bit version or when you're connecting remotely to a 32-bit computer.

Does Jenkins support PowerShell?

Jenkins PowerShell PluginIntegrates with PowerShell by allowing you to directly write PowerShell scripts into the text box in Jenkins. Other than that, this plugin works pretty much like the standard shell script support.


2 Answers

Environment

  • Jenkins on Windows (mine happens to run as a service)
  • plus Powershell plugin (for running Powershell scripts as "build steps")

Jenkins will typically call upon the correct version of powershell.exe. However, the executor/slave process must be running a 64-bit JRE so that PowerShell can also operate in 64-bit mode.

A simple tester project with the following Powershell script can show the above 32-bit vs 64-bit nature:

$env:Path               # Path will have the right Powershell available
[intptr]::size          # outputs: 4 = 32-bit, 8 = 64-bit
Stop-WebAppPool FOOBAR  # fails when 32-bit, succeeds when 64-bit

Console output example (extra blank lines for clarity):

[Powershell Test] $ powershell.exe -NonInteractive -ExecutionPolicy ByPass "& 'C:\Windows\TEMP\hudson123456789.ps1'"

C:\Windows\system32;C:\Windows;C:\Windows\System32\WindowsPowerShell\v1.0\

4

Stop-WebAppPool : Retrieving the COM class factory for component with CLSID 
{688EEEE5-6A7E-422F-B2E1-6AF00DC944A6} failed due to the following error: 
80040154 Class not registered (Exception from HRESULT: 0x80040154 
(REGDB_E_CLASSNOTREG)).

At C:\Windows\TEMP\hudson123456789.ps1:7 char:1

Solution

tl;dr... Install 64-bit JRE, and configure Jenkins to be 64-bit.

I used chocolatey to install a fairly recent JRE, via "Administrator" PowerShell:

First, install chocolatey:

iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))

Looked for the latest version available https://chocolatey.org/packages?q=java (chocolatey has multiple packages for the same thing, often not kept fully up to date).

Then, install JRE (using the one with the higher JRE number):

choco install -y javaruntime

Or:

choco install -y jre8

Finally, I edited my jenkins.xml configuration so that it would run using the 64-bit JRE instead of the built-in JRE.

Changed:

<executable>%BASE%\jre\bin\java</executable>

To (set the path as appropriate for your instance):

<executable>C:\Program Files\Java\jre1.8.0_66\bin\java</executable>

This one should be an "always fresh" symlink (handled by system updates) that ought to allow your Jenkins instance to survive Restart and Update events:

<executable>C:\ProgramData\Oracle\Java\javapath\java.exe</executable>

Then I restarted Jenkins. Powershell execution woke up to the might of 64-bits. Note: I am using a single Jenkins instance that does double duty as the "server" and "execution slave" at the same time. For fully autonomous slaves, I would suppose doing whatever to get the slave-agents processes in 64-bit mode would result in a similar success.

Full automation? According to the chocolatey "jre8" package documentation, using command line switches, it's even be possible to force fixed destination paths for JRE, and exclude 32-bit and/or 64-bit editions, if fully automated non-interactive steps are needed. https://chocolatey.org/packages/jre8

like image 74
starlocke Avatar answered Sep 23 '22 22:09

starlocke


I am not familiar with Jenkins, but it seems like it's a 32 bit process itself.

Can you specify the location of the PowerShell executable? If so, try to use this path: C:\Windows\SysNative\WindowsPowerShell\v1.0\powershell.exe

If you can't do that, then you might be able to do it in code in your "execution sequence" with Invoke-Command:

Invoke-Command -ComputerName . -ScriptBlock { [Environment]::Is64BitProcess }

All the code in the scriptblock will be run in a separate 64 bit process and the results will be serialized and returned.

Explanations

Paths

On a 32 bit Windows OS, the system folder is C:\Windows\System32. On a 64 bit Windows OS, the 64 bit system folder is also C:\Windows\System32. But the system folder for 32 bit processes on a 64 bit Windows installation is in fact C:\Windows\SysWOW64.

For compatibility, a 32 bit process on a 64 bit OS will have any calls to C:\Windows\System32 transparently redirected to C:\Windows\SysWOW64, unbeknownst to the process.

To enable a 32 bit process to reference the real System32 on a 64 bit OS, you can you use C:\Windows\SysNative.

Since PowerShell has a 32 bit and a 64 bit version, and it lives inside the system folders, you need to use the above rules to reference the correct executable depending on whether you're calling it from a 64 or 32 bit process.

The typical scenario (you want to call the version of the same bitness) is easiest (just call powershell.exe or reference it via System32), but it gets hairy if you want to reference the other version.

Invoke-Command Method

The Invoke-Command cmdlet lets you run code, typically on another computer, but you can run it on the same computer as well. This will spawn a completely separate process, and any output gets serialized and sent back to the calling process.

The caveat to this method is that you must enable PowerShell remoting on the machine, via Enable-PSRemoting or Group Policy (shameless self plug).

The default profile (Microsoft.PowerShell) that you connect to on a 64 bit machine will be a 64 bit version of PowerShell, regardless of the OS of the caller.

Incidentally, if you wanted to use Invoke-Command to connect to a 32 bit version, you could do so by explicitly specifying the profile Microsoft.PowerShell32.

like image 28
briantist Avatar answered Sep 25 '22 22:09

briantist