- SmartDeploy: Rethinking software deployment to remote workers in times of a pandemic - Thu, Jul 30 2020
- Outlook attachments now blocked in Office 365 - Tue, Nov 19 2019
- PolicyPak MDM Edition: Group Policy and more for BYOD - Tue, Oct 29 2019
There are several ways to deploy PowerShell 4. You could build it into your image, use SCCM, or Group Policy scripts. Because Group Policy scripts are universally accessible and free, we will use them to deploy PowerShell 4.
In the Group Policy Management Console, create a new GPO named APP Windows Management Framework 4. Create a security group with the same name and scope it to the GPO. Populate this group with a few test computers.
The WMF4 Deployment GPO
PowerShell 4, part of the Windows Management Framework (WMF), has one application dependency. It requires .Net Framework 4.5 to be installed first. If .Net Framework 4.5 is not installed beforehand, clients will successfully process part of the update but will not completely install PowerShell 4.
Deploying .Net Framework 4.5
Before we go any further, download the offline installer for .Net Framework 4.5. Save the installer to a network share accessible to your domain computers. When .Net Framework 4.5 is installed, it will register itself in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319\SKUs as .NETFramework,Version=v4.5”. We can use REG QUERY to check to see if this key exists.
@ECHO OFF REM Check to see if .Net Framework 4.5 is installed REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319\SKUs\.NETFramework,Version=v4.5"
If this registry key exist, %errorlevel% will equal zero. To prevent installing .Net Framework 4.5 over and over again, we can use: IF %errorlevel%==1 GOTO INSTALLNET
Finally, we just need to insert our silent install command and tie the first script together:
@ECHO OFF REM Check to see if .Net Framework 4.5 is installed REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319\SKUs\.NETFramework,Version=v4.5" IF %errorlevel%==1 GOTO INSTALLNET IF %errorlevel%==0 GOTO EXIT :INSTALLNET Start /wait dotNetFx45_Full_setup.exe /CEIPconsent /norestart /q :EXIT exit
Save this script as a batch file and add it as a shutdown script to your GPO.
GPO shutdown script
Deploying Windows Management Framework 4
As we stated above, PowerShell 4 is installed when Windows Management Framework 4 is installed. WMF can be downloaded from here. The update comes in both architecture flavors; be sure to pick the one that matches your environment.
Downloading the X64 version of WMF 4
Because the package is a .MSU, we will use the Windows Update Standalone Installer (WUSA.exe). A quiet and passive restart install would look like this:
wusa.exe "Windows6.1-KB2819745-x64-MultiPkg.msu" /quiet /norestart
When PowerShell 4 is completely installed, we can query HKLM\SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine for the PowerShellVersion string. The value of this string should be 4.0
PowerShell version in Registry
Like before, we can use REG QUERY to check this key and then check %errorlevel% to ensure a value was found.
@ECHO OFF REG QUERY "HKLM\SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine" /f 4.0 IF %errorlevel%==1 GOTO INSTALLWMF IF %errorlevel%==0 GOTO EXIT :INSTALLWMF Start /wait wusa.exe "Windows6.1-KB2819745-x64-MultiPkg.msu" /quiet /norestart :EXIT Exit
Save this batch file and add it to your GPO as a shutdown script.
Shutdown script
Shutdown script always run synchronously so .Net Framework will install before Windows Management Framework. By using these two scripts, you can deploy PowerShell 4 with Group Policy scripts.
Can you please post the source for the InstallWMF4.bat? That seems to be missing from this article. I’d like to see it work the same way, where it doesn’t try to install if it is already installed. Since the WMF4.0 installer is an .msu file, It can use the wusa command line arguments, like /quiet. However, I don’t see one related to not installing again if present.
Hey Brian,
That script will be updated in a bit. Sorry for the confusion!
I uploaded only half of the article. 🙁 Sorry for that. The article should be complete now.
It looks like you copied in the wrong Powershell 4 install script (you have the .Net installer script). But I see what you are doing here. Thanks for correcting the article.
That should be fixed soon as well! Sorry again!
Yeah, embarrassing. 🙁
Great, but I wonder why it wasn’t packaged in *one* startup script. The commands inside .cmd run synchronously anyway.
I just followed this article to the ‘T’.. i have the GPO applied to a test OU with test machines within. first shutdown took quite a while longer than normal.. and I got all excited thinking the WMF and Net4.5 were being installed. Once I booted it back up and logged in.. nope. PowerShell version still 2.1 🙁
Cannot figure out what I did wrong when manually running the batch files works.
It should work fine as one script. I prefer granular setups – just a personal preference.
Hey Ben – does a GPResult show that the scripts were applied? Are you doing this with startup or shutdown scripts? Do your computers have read/execute to the network shares where the installers are located?
Hi Joseph
I was wondering about this scenario, i´m trying to deploy UE-V and get stuck on pre-req wmf4. I have .net 4.5 and 4.5.1 already in place and if i run a batch with silent install of wmf4 it goes through and exit with 0. Still i get no powershell update.
Is the only way to install wmf4 with a restart? If so i will surely run it on log off..but in the best of world i can apply this during computer is logged on.
Any hints would be most appreciated.
//Jörgen
I had to add the complete path to the msu file instead of just the filename, maybe thats an obstacle for some…
how did you mention the complete path? did you mount the network share to a drive and then mention it or just gave the full netowork share path?
Hi Joseph,
How does your wmf install batch script know where to look for the msu file? Does it have to be on a share mounted on every machine in the AD? We do not mount such shares in our AD, so is there an alternate way? I would still like to implement this installation using GPO only since we dont have SCCM in house.
You can stick it in SYSVOL if you would like or stick it on a share that domain computers have read/execute access to. If you stick it on a separate share, change the path to the MSU to be the complete file path (\\server\share\folder\nameoffile.msu)
code appears to work but doesnt.. When checking the registry to see if powershell is installed we saw false positives if powershell 3.0 was installed
Below works better
REG QUERY “HKLM\SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine” /v PowerShellVersion |find “4.0”
This is why..
echo Checking for powershell v 4.0
REG QUERY “HKLM\SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine” /f 4.0
IF %errorlevel%==1 GOTO WMF
IF %errorlevel%==0 GOTO EXIT
Now if I run the reg query on a server which has PSv3 then we get the following:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine
ApplicationBase REG_SZ C:\Windows\System32\WindowsPowerShell\v1.0
PSPluginWkrModuleName REG_SZ C:\Windows\System32\WindowsPowerShell\v1.0\pspluginwkr-v3.dll
PSCompatibleVersion REG_SZ 1.0, 2.0, 3.0
RuntimeVersion REG_SZ v4.0.30319
ConsoleHostAssemblyName REG_SZ Microsoft.PowerShell.ConsoleHost, Version=3.0.0.0, Culture=neutral, PublicKeyTo
ken=31bf3856ad364e35, ProcessorArchitecture=msil
ConsoleHostModuleName REG_SZ C:\Windows\System32\WindowsPowerShell\v1.0\Microsoft.PowerShell.ConsoleHost.dll
PowerShellVersion REG_SZ 3.0
Using get-host and $psversiontable we can see that yes this is PSv3 we are running.
PS C:\Users\> get-host
Name : ConsoleHost
Version : 3.0
InstanceId : 5207ce93-a273-4784-a029-c67a416d9bad
UI : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture : en-US
CurrentUICulture : en-US
PrivateData : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
IsRunspacePushed : False
Runspace : System.Management.Automation.Runspaces.LocalRunspace
PS C:\Users\> $psversiontable
Name Value
—- —–
PSVersion 3.0
WSManStackVersion 3.0
SerializationVersion 1.1.0.1
CLRVersion 4.0.30319.18444
BuildVersion 6.2.9200.16481
PSCompatibleVersions {1.0, 2.0, 3.0}
PSRemotingProtocolVersion 2.2
This is what we should get if we are running PSv4:
PS C:\Users\> REG QUERY “HKLM\SOFTWARE\Microsoft\Powershell\3\PowerShellEngine”
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Powershell\3\PowerShellEngine
ApplicationBase REG_SZ C:\Windows\System32\WindowsPowerShell\v1.0
PSPluginWkrModuleName REG_SZ C:\Windows\System32\WindowsPowerShell\v1.0\pspluginwkr-v3.dll
PSCompatibleVersion REG_SZ 1.0, 2.0, 3.0, 4.0
RuntimeVersion REG_SZ v4.0.30319
ConsoleHostAssemblyName REG_SZ Microsoft.PowerShell.ConsoleHost, Version=3.0.0.0, Culture=neutral, PublicKeyTo
ken=31bf3856ad364e35, ProcessorArchitecture=msil
ConsoleHostModuleName REG_SZ C:\Windows\System32\WindowsPowerShell\v1.0\Microsoft.PowerShell.ConsoleHost.dll
PowerShellVersion REG_SZ 4.0
PS C:\Users\> get-host
Name : ConsoleHost
Version : 4.0
InstanceId : 6d6280b8-b5be-4af6-bc7c-684167e934aa
UI : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture : en-US
CurrentUICulture : en-US
PrivateData : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
IsRunspacePushed : False
Runspace : System.Management.Automation.Runspaces.LocalRunspace
The problem with your query is that it looks for the value “4.0”. It finds this under RunTimeVersion regardless of the PS version. This refers to .net version and is not the version of powershell (which is shows by PowerShellVersion).
Thanks for the feedback Stewart and your detection method!
This was the detection method we ended up using in System Center 2012.
$PSVersionTable is not updated before the computer is rebooted. Same with the registry. So we ended up checking for the existence of the KB or the right $PSVersionTable.
IF ((Get-hotfix -id “KB2819745” -ErrorAction SilentlyContinue) -or ($PSVersionTable.psversion.Major -ge “4”))
{
Write-Host True
}