How to install Windows PowerShell 4.0

Windows PowerShell 4.0 is part of the Windows Management Framework 4.0, which includes the following:

  • Windows PowerShell
  • Windows PowerShell Integrated Scripting Environment (ISE)
  • Windows PowerShell Web Services (Management OData IIS Extension)
  • Windows Remote Management (WinRM)
  • Windows Management Infrastructure (WMI)
  • Server Manager WMI provider
  • Windows PowerShell Desired State Configuration (DSC)


Windows Management Framework 4.0 supportability matrix

Operating system

Windows PowerShell 4.0 available


Installation file

Windows Server 2012 R2




Windows 8.1




Windows Server 2012

Yes, part of WMF 4.0

.NET 4.5 (built-in)

x64: Windows8-RT-KB2799888-x64.msu

Windows 8

No, user must upgrade to Windows 8.1



Windows Server 2008 R2

Yes, part of WMF 4.0

Windows Server 2008 R2 SP1

.NET 4.5

x64: Windows6.1-KB2819745-x64-MultiPkg.msu

Windows 7

Yes, part of WMF 4.0

Windows 7 SP1

.NET 4.5

x64: Windows6.1-KB2819745-x64-MultiPkg.msu

x86: Windows6.1-KB2819745-x86.msu



  • Verify that all prerequisites is installed according to the Windows Management Framework 4.0 supportability matrix above. To verify the presence of .NET 4.5, you may use the Test-Net45 function available in this article on the Hey Scripting Guy! Blog
  • Run the installation file applicable to the operating system
  • Reboot the computer, start Windows PowerShell and verify that the output of $PSVersionTable shows 4.0 as the value of the PSVersion property


Known issues


1 – Installation succeeds even if .NET 4.5 is not installed

Scenario: Installing WMF 4.0 on a computer that is not running .NET Framework 4.5 will report that the installation is successful, but the components of WMF 4.0 (such as Windows PowerShell, WMI, etc.) will not be updated.

Solution: Install .NET Framework 4.5, and then run the WMF 4.0 installer again.

More information:


2 – Compatibility issues

There are known compatibility issues with several Microsoft server-class applications:

· System Center 2012 Configuration Manager (not including SP1)

· System Center Virtual Machine Manager 2008 R2 (including SP1)

· Microsoft Exchange Server 2013, Microsoft Exchange Server 2010, and Microsoft Exchange Server 2007

· Microsoft SharePoint Server 2013 and Microsoft SharePoint Server 2010

· Windows Small Business Server 2011 Standard

Read the WMF 4.0 Release Notes for more information.


Related KB articles


This article is also posted on the Microsoft TechNet Wiki. If you have corrections or additional information, please update the Wiki-article.

Converting Hyper-V VHD-files to VHDX using Windows PowerShell

With the introduction of Windows Server 2012 Hyper-V, Microsoft also provided a new format for virtual hard disk files. The previous VHD-format is now updated to a new format called VHDX. Some of the new features of the new format is much larger storage capacity (from a maximum of 2 TB for VHD, to a new maximum of 64 TB for VHDX), as well as data corruption protection during power failures. You can find more information about the new VHDX format on the “Hyper-V Virtual Hard Disk Format Overview” article on Microsoft TechNet, as well as the “VHDX Format Specification v 1.0” document which provides detailed information.

When virtual machines are migrated (imported) to a Windows Server 2012 Hyper-V host, the virtual hard disk files is not automatically converted to the new VHDX format. This is something you must do manually, either by using the “Edit Virtual Hard Disk Wizard” or by using the Convert-VHD cmdlet in the Hyper-V PowerShell module.

As soon as a virtual machine is migrated from an earlier version of Hyper-V to Windows Server 2012 Hyper-V, best practice would be to convert the virtual hard disk files to the new VHDX format.

If you have more than a couple of virtual machines, it would be a good idea to automate the conversion process. You can start to explore the Convert-VHD cmdlet by running Get-Help “Convert-VHD” –ShowWindow:


If you do not get a similar result as above, run Update-Help from an elevated PowerShell session and try again.

If you scroll to the bottom you will also find a few examples:


Example 1 shows how to convert a single VHD file to a new VHDX file. There are several things to consider before doing this in a production environment:

  • Should you keep the source VHD in case something goes wrong? If no, add the –DeleteSource swich parameter.
  • Should you use Fixed disks or Dynamically expanding disks? There are different recommendations both in the community and in Microsoft. In the Performance Tuning Guidelines for Windows Server 2012 dynamically expanding is recommended, while in this Premier Field Engineering (PFE) blog article Fixed size is recommended. To read more opinions from the community, see this article by Virtual Machine MVP Aidan Finn as well as this article by Virtual Machine MVP Thomas Maurer.
  • The virtual machine must be stop before its virtual hard disk files can be expanded.
  • The old VHD file must be replaced by the new VHDX file in the virtual machine configuration.
  • Enough disk space must be available on the underlying data disk. For example, if the VHD file to be converted is 100 GB, you must have minimum 100 GB free space on the data disk for the destination VHDX file.

I have created a sample PowerShell script below which will convert VHD-files for stopped virtual machines to VHDX. If the virtual hard disk files for the stopped virtual machines is already of type VHDX, the virtual machine will be skipped.

You may want to add additional logging and error handling before using this script in a production environment. I would also encourage to always test the script in a lab environment before using it in production.

You can find the script here on the Microsoft TechNet Script Center.

Working with scheduled tasks from Windows PowerShell

Traditionally Windows administrators is used to work with the Windows Task Scheduler using the command line utilities at.exe and schtasks.exe. Schtasks.exe was introduced as a replacement for at.exe in Windows XP/Windows Server 2003, while at.exe still exists in the latest Windows versions for backwards compatibility.

Both of the utilities works in Windows PowerShell, but they both produce text, not objects. This means we can not use for example the object manipulation cmdlets Where-Object and Select-Object on the output from these utilities. There are some tricks you can use to get the output from external applications in PowerShell into objects. An example on this is the /fo parameter on schtasks.exe, which allow us to specify the format of the output from the command. Since PowerShell has a ConvertFrom-Csv cmdlet, this means we can do this to get all scheduled tasks in object form:

schtasks.exe /query /fo csv | ConvertFrom-Csv

This allows us to use for example the Where-Object cmdlet to filter the output based on the Status-property:


To make this utilities behave more PowerShell friendly we could create custom functions which for example wraps schtasks.exe /create in a New-Task function, but still it would require a lot of work to parse the text output into custom objects.

Task Scheduler 2.0 which was released in Windows Vista and Windows Server 2008 introduced a COM-interface. This makes possible to access the Task Scheduler interface using PowerShell: New-Object -ComObject Schedule.Service

By using this COM-object we can access the Task Scheduler Scripting Objects, which produces objects rather than text. Of course this still requires a bit of work and the need to read quite a bit of documentation in order to make it user friendly for an administrator. Luckily the PowerShell team released a TaskScheduler module which builds on this COM-object as part of the PowerShell Pack, released as part of the Windows 7 Resource Kit.

When you have installed the MSI-file from the PowerShell Pack download page, you can import the TaskScheduler module and have a look at the available functions:


We can for example use the Get-ScheduledTask function to retrieve all scheduled tasks on the local computer:


This is an example of how to schedule a PowerShell script to run every day at 06.00:

# Import the module
Import-Module TaskScheduler

# Create a new task
$task = New-Task
$task.Settings.Hidden = $true

# Add an action and a trigger
Add-TaskAction -Task $task -Path C:Windowssystem32WindowsPowerShellv1.0powershell.exe -Arguments "-File C:MyScript.ps1"
Add-TaskTrigger -Task $task -Daily -At "06:00"

# Register the task
Register-ScheduledTask -Name "PowerShell - MyScript.ps1" -Task $task

When the above example is run we can find the new scheduled task in the Task Scheduler:





Or of course by using the Get-ScheduledTask function:


Instead of configuring a script file (ps1-file) to be the task action, we could have specified a script block to the Add-TaskAction function:

Add-TaskAction -Task $task -Script {“Hello World”}

Then the script block would be passed as an encoded command to powershell.exe:


An advantage of this approach is that we do not need to save our code to disk in advance to configuring it as a scheduled task.

Scheduled jobs in PowerShell 3.0

With the new version of Windows coming out later this year, we will also get a new version of Windows PowerShell. One of the new features in PowerShell 3.0 is a new module called PSScheduledJobs, which allows us to schedule jobs natively from within PowerShell. In addition, the output and results from the job is actually stored so that we can retrieve them after the job is executed, just like we could with background jobs in PowerShell 2.0.

The following information and examples is based on the Windows PowerShell 3.0 version available in the Windows 8 Consumer Preview.

Here we can see the cmdlets available in the PSScheduledJob module:


The following example is using the PSScheduledJob module to do the same as the previous example which used the TaskScheduler module from the PowerShell Pack:

# Import the module (not necessary due to the new module autoloading in PowerShell 3.0)
Import-Module PSScheduledJob

# Add a job option
$joboption = New-ScheduledJobOption -HideInTaskScheduler

# Add a trigger
$trigger = New-JobTrigger -Daily -At "06:00"

# Register the job
Register-ScheduledJob -Name "PowerShell - MyScript.ps1" -Trigger $trigger -FilePath C:MyScript.ps1 -ScheduledJobOption $joboption

If we want to specify a script block instead of a script file, we can use the ScriptBlock parameter instead of the FilePath parameter of Register-ScheduledJob:

Register-ScheduledJob -Name “PowerShell – MyScript.ps1″ -Trigger $trigger -ScriptBlock {“Hello World”}

If we look at the new task that is created from the example above we can see the following:


The arguments passed to powershell.exe:

-NoLogo -NonInteractive -WindowStyle Hidden -Command “Import-Module PSScheduledJob; $jobDef = [Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition]::LoadFromStore(‘PowerShell – MyScript.ps1′, ‘C:Users<username>AppDataLocalWindowsPowerShellScheduledJobs’); $jobDef.Run()”

We can see that the job is stored in a separate folder in the current user`s AppData-folder:


The job is defined in the ScheduledJobDefinition XML-file, and there is an empty sub-folder named Output. If I manually start the job, we can see that the following is added to the Output folder:


Next I want to retrieve the results of the job, not by looking in the XML-files, but by using the Get-Job cmdlet. There is a gotcha to be aware of regarding this. If you open a new PowerShell session and run Get-Job, the scheduled jobs created using the PSScheduledJob cmdlets will not be available. You have to first import the PSScheduledJob module and then run Get-Job. By using Receive-Job we can get the results from our job:


To read about the reason for this in addition to more details about the new module you can read the “Scheduling Background Jobs in Windows PowerShell 3.0” article on the Windows PowerShell Team Blog.


How to Schedule a PowerShell Script

Sending Automated emails with Send-MailMessage, ConvertTo-HTML, and the PowerShellPack’s TaskScheduler module

Windows PowerShell Scheduled Job Module

How to Configure Clustered Tasks with Windows Server 2012


What`s New in Windows PowerShell 3.0

Since the release of Windows 7 and Windows Server 2008 R2, Windows PowerShell is included in the operating system and enabled by default. This means Windows PowerShell 3.0 will be available in the next version of Windows.

A preview version for developers of the next Windows version was released a few weeks ago, which means we also got a preview of Windows PowerShell 3.0. The  preview version of the client operating system is available here, while the server version is available on MSDN.

Earlier this week the PowerShell team announced that a Community Technology Preview (CTP 1) is available for download, which means we can also try out PowerShell 3.0 on computers running Windows 7 and Windows Server 2008 R2. The current version of the Windows Management Framework includes Windows PowerShell 2.0, Windows Remote Management (WinRM) 2.0 and Background Intelligent Transfer Service (BITS) 4.0, while the new Windows Management Framework CTP contains Windows PowerShell 3.0, Windows Management Instrumentation (WMI) and Windows Remote Management.

Some of the most important new features in PowerShell 3.0 is listed in the previous mentioned announcement from the PowerShell team, but there is also a huge number of other new features.

A great number of persons in the PowerShell community has already started to discover and write about the new features. One of them is the new Windows PowerShell Web Access in the next version of Windows Server, which Ive previously written an article about.

Instead of listing all the articles Ive discovered so far in this article, I posted them as a TechNet Wiki article as part of the existing PowerShell V3 Guide:

TechNet Wiki: PowerShell V3 Guide
TechNet Wiki: PowerShell V3 Featured articles

I would like to encourage you to contribute to the TechNet Wiki article when you discover new writings about Windows PowerShell 3.0.