Check installed Windows Server Features with NSIS - powershell

I'm trying to install a custom build software on Windows Server 2008R2, 2008 and 2003. The software needs the "Desktop-Experience" feature from Windows to be installed.
I know I can check with servermanagercmd.exe (even though it's kind of cumbersome) in 2003 and 2008 - unfortunately, this does no longer work in 2008R2 (64bit) from inside an NSIS installer - it does work if I just run the command. Called from the installer, I'm getting a "servermanagercmd.exe is not recognized as an internal or external command, operable program or batch file."-error, even if I'm setting the working directory to c:\windows\system32 (yes, on a 64 bit machine, but there's no servermanagercmd.exe in sysWOW64).
Here's the line of code inside NSIS:
nsExec::ExecToStack 'servermanagercmd.exe -query | findstr "Desktop-Experience"'
In 2008R2, I thought the situation would actually improve, as PowerShell is now installed by default. However, when trying to get the information, I need to first load the ServerManager module inside PowerShell - but this module is not available for reading for Trusted Installer . So I'm facing the same situation again: If I'm running my powershell command from a command line, it works, but not from inside the NSIS installer.
Again, here's the line of code inside NSIS:
nsExec::ExecToStack 'powershell.exe "& "Import-Module ServerManager"'
The three(!) (double)quotation marks are actually correct.
So, does anybody know of a way to check whether Desktop-Experience is installed (and install it if not) in Windows Server 2008R2 from inside an NSIS installer? The solution does not need to work on Server2003 or 2008, because the string parsing from servermanagercmd.exe works there.

Are you using the macros in x64.nsh to turn off WOW64 redirection? (Or use "$windir\sysnative\servermanagercmd.exe")

Related

Get Different Results of Running Command on Jenkins Job and on Slave Itself [duplicate]

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!
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
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.
OK, so the answer was pretty simple, yet maddening all at once. Basically, the module(s) didn't exist in both of the Powershell paths (x86 and x64), so copying the modules over to the 32-bit powershell environment fixed the issue.
further suggestions:
check path of 32bit-JRE, remove path or uninstall 32bit-JRE --
also swapping path-position with 64bit-JRE might work
check path(s) of PowerShell, remove path of 32bit PowerShell
(..\SysWOW64\..) and add the other one to the path (..\System32\..)
This worked for me!

Why is the Uninstall-ChocolateyPackage cmdlet not recognized?

I am trying to run a PowerShell script to uninstall owncloud-client from my Windows 10 virtual machine. The code shown below can be found at
https://chocolatey.org/packages/owncloud-client (tools\chocolateyUninstall.ps1)
I would like just to test the code by running it from PowerShell to see if it actually uninstalls the software.
$unfile = "ownCloud\uninstall.exe"
if (Test-Path "${Env:ProgramFiles(x86)}\$unfile") {
$unpath = "${Env:ProgramFiles(x86)}\$unfile"
} else {
$unpath = "${Env:ProgramFiles}\$unfile"
}
Uninstall-ChocolateyPackage 'owncloud-client' 'exe' '/S' "$unpath"
I run script from the directory that contains it by typying:
.\chocolateyUninstall.ps1
As output I get the following error:
Uninstall-ChocolateyPackage is not recognized as the name of cmdlet, function, script file, or operable program.
The Uninstall-ChocolateyPacakge.ps1 package is provided by chocolatey. I checked on my machine and this package is present under:
C:\ProgramData\chocolatey\helpers\functions\Uninstall-ChocolateyPackage.ps1
but still it is not recognized as cmdlet by powershell. How can I solve this problem? thanks
When running the installation/uninstallation scripts, Chocolatey first includes the Chocolatey PowerShell module. This is done in the background, and normally, the end user doesn't need to worry about it.
For what you are trying to do, you will need to first do an Import-Module on the Chocolatey module, to bring it into the current PowerShell session. You can find this here:
old: C:\ProgramData\chocolatey\lib\chocolatey\tools\chocolateyInstall\helpers\chocolateyInstaller.psm1
new: C:\ProgramData\chocolatey\helpers\chocolateyInstaller.psm1
That should allow you to test the script directly.
Alternatively, you could run the install of the package, and then run the uninstall to see if it works as well.
With the latest moderation tools, you don't need to check every package (I mean, unless it makes you feel safer). You can always check the automated tests. There's a status dot to the right of the package title.
You can find the test summary
owncloud-client v2.1.1.5837 - Passed - Package Test Results
https://chocolatey.org/packages/owncloud-client/2.1.1.5837
Tested 10 Feb 2016 12:51:22 +00:00
Tested against win2012r2x64 (Windows Server 2012 R2 x64)
Tested with the latest version of choco, possibly a beta version.
Tested with chocolatey-package-verifier service v0.4.0-15-g979d0cc
Install was successful.
Uninstall was successful.
https://gist.github.com/choco-bot/45f343e23cc12e101130#file-_summary-md
or explore the uninstall log directly.
https://gist.github.com/choco-bot/45f343e23cc12e101130#file-uninstall-txt

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!
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
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.
OK, so the answer was pretty simple, yet maddening all at once. Basically, the module(s) didn't exist in both of the Powershell paths (x86 and x64), so copying the modules over to the 32-bit powershell environment fixed the issue.
further suggestions:
check path of 32bit-JRE, remove path or uninstall 32bit-JRE --
also swapping path-position with 64bit-JRE might work
check path(s) of PowerShell, remove path of 32bit PowerShell
(..\SysWOW64\..) and add the other one to the path (..\System32\..)
This worked for me!

Perl Network Drive Installation

I need to be able to run a few simple Perl scripts off of an NTFS (win server 2003 R2) drive. Is there any way to install Perl on this network drive (Strawberry or ActiveState, Strawberry preferred for built in cpan module compiler) and be able to run the scripts with whatever real time mounting on machines that do not have have/need a Perl distribution installed?
So far not having much luck with any relevant documentation.
Yes, we do this all the time.
Install Perl on your fileshare. I prefer to do this from the Windows Server hosting the fileshare, but I don't think it's necessary. If you don't have Remote Desktop and Admin access to that server, you'll need 2 PC's, 1 for the install and 1 to test this out. You can't test this on the same PC/server that ran the install.
Run this Windows Registry script on the test PC:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\.pl]
#="Perl Script"
[HKEY_CLASSES_ROOT\Perl Script]
#="Perl Script"
[HKEY_CLASSES_ROOT\Perl Script\DefaultIcon]
#="C:\\WINDOWS\\system32\\Icons\\ActivePerl.ico,0"
[HKEY_CLASSES_ROOT\Perl Script\shell]
#="Open"
[HKEY_CLASSES_ROOT\Perl Script\shell\Open]
#="Open"
[HKEY_CLASSES_ROOT\Perl Script\shell\Open\command]
#="\"Z:\\network-folder\\Perl\\bin\\perl.exe\" \"%1\" %*"
[HKEY_CLASSES_ROOT\Perl Script\shellex]
[HKEY_CLASSES_ROOT\Perl Script\shellex\DropHandler]
#="{86C86720-42A0-1069-A2E8-08002B30309D}"
You will need to change this:
"C:\\WINDOWS\\system32\\Icons\\ActivePerl.ico,0"
to a path (preferably on the PC, not the network!) of an icon to go with the .PL files. You can drop those 2 lines from the reg script if you don't want a custom icon.
More importantly, you will need to change this:
"Z:\\network-folder\\Perl\\bin\\perl.exe\"
to the path where you installed Perl.
The DropHandler portion of that script is explained in more detailed in this other post: How do I create drag-and-drop Strawberry Perl programs?
Hope that helps!

How can I run the regedit.exe from a Perl script on Windows 2008 Server?

I have yet another subtle problem on Windows :(
The following one-line perl script doesn't work:
perl -e "system('regedit.exe /s C:\my.reg');"
It really runs regedit.exe tool (I'm sure since I tried to run it w/o "/s" and saw confirmation dialogs), but it doesn't create a key in the registry.
I tried to run
regedit.exe /s C:\my.reg
in from windows shell (cmd.exe) and it works fine.
The original command works fine on Windows XP, but doesn't work on 2008 server.
So I suspect that this is system-related issue.
Are you executing this with an elevated cmd prompt (i.e. admin privileges)? Regedit requires this.