On Windows PowerShell and other admin-related topics

How to configure AntiAffinityClassNames in Failover Clustering using Windows PowerShell

AntiAffinityClassNames is a cluster group property in Windows Failover Clustering used to identify cluster groups that should not be hosted on the same node. When working with clustered Hyper-V environments there is a 1:1 relationship between a cluster group and a virtual machine, and thus we can configure Anti-Affinity for virtual machines using the AntiAffinityClassNames property. For more information, see the links in the resource section in the bottom of the article.

What I want to show in this article is how to configure the AntiAffinityClassNames property using PowerShell. Most articles I have seen in regards to AntiAffinityClassNames covers how to use cluster.exe to configure the property, and since the cluster.exe was deprecated in Windows Server 2008 R2 (it`s still available as a deprecated command) it might be a good idea to learn how to configure this using the new Failover Clustering PowerShell module. In addition you also get other benefits available in PowerShell such as pipelining, export/import to/from different data sources, grouping and so on.

AntiAffinityClassNames is a property of a cluster group, but before we configure the property we need to look at what type it is. We can do this by piping the output of Get-ClusterGroup to the Get-Member cmdlet:


We can see in the definition of the property that it is a System.Collections.Specialized.StringCollection type. This means we can not just pass a text string as the property value, we need to create a object of the correct type. The reason this property is not just a System.String (text string) is that a Cluster Group can have more than one AntiAffinityClassNames values. System.Collections.Specialized.StringCollection has a method called Add which can be used to to add values to the collection. Here is a complete example on how to create such an object, add a couple of values to it and at the end assign it to the AntiAffinityClassNames property of a cluster group:

$value = New-Object System.Collections.Specialized.StringCollection
$value.Add("Domain Controllers")
$value.Add("Infrastructure Server Group")
(Get-ClusterGroup "SCVMM SRV01 Resources").AntiAffinityClassNames = $value

Note that this will overwrite any existing values. As we can see it is not very hard to configure a new value, but it might be harder if you want to preserve existing values remove single items of the existing value and so on. In order to make this easier I have created a PowerShell module which contains 3 script cmdlets for managing AntiAffinityClassNames:


As you can see in the cmdlet help there is support for pipeline input, which makes it possible to configure the AntiAffinityClassNames values based on input such as a CSV-file:


I have also provided examples for the script cmdlets:



Installing the AntiAffinityClassNames module

Download and unzip in the following location: %userprofile%\Documents\WindowsPowerShell\Modules\AntiAffinityClassNames

Alternatively you may save the module in any of the folders in the $Env:PSMODULEPATH variable or import the module from a custom path (Import-Module <path>\AntiAffinityClassNames). Here is some more examples to get you started:

# Import the module
Import-Module AntiAffinityClassNames

# Example usage of the Get-AntiAffinityClassNames script cmdlet

Get-AntiAffinityClassNames -Cluster cluster01.domain.local

Get-AntiAffinityClassNames -Cluster cluster01.domain.local -ClusterGroup "SC VMM SRV01 Resources"

Get-AntiAffinityClassNames -Cluster cluster01.domain.local | Export-Csv -Path c:\temp\AntiAffinityClassNames_cluster01.csv -NoTypeInformation

# Example usage of the Set-AntiAffinityClassNames script cmdlet

Set-AntiAffinityClassNames -Cluster cluster01.domain.local -ClusterGroup "SC VMM SRV01 Resources" -Value "Domain Controllers"

Set-AntiAffinityClassNames -Cluster cluster01.domain.local -ClusterGroup "SC VMM SRV01 Resources" -Value "Domain Controllers" -Keep

Set-AntiAffinityClassNames -Cluster cluster01.domain.local -ClusterGroup "SC VMM SRV01 Resources" -Value "Domain Controllers" -Verbose

# Example usage of the Remove-AntiAffinityClassNames script cmdlet

Remove-AntiAffinityClassNames -Cluster cluster01.domain.local -ClusterGroup "SC VMM SRV01 Resources" -Clear

Remove-AntiAffinityClassNames -Cluster cluster01.domain.local -ClusterGroup "SC VMM SRV01 Resources" -Value "Domain Controllers"

Remove-AntiAffinityClassNames -Cluster cluster01.domain.local -ClusterGroup "SC VMM SRV01 Resources" -Value "Domain Controllers" -Verbose



MSDN: AntiAffinityClassNames

Failover behavior on clusters of three or more nodes

Understanding Hyper-V Virtual Machine (VM) Failover Policies

Private Cloud: Configuring anti-affinity between VMs on Hyper-V 2008 R2 SP1 and VMM 2012

How to automatically avoid running Exchange VMs on the same Hyper-V server after a host failure

Get started with the Failover Clustering PowerShell-module

Enable Persistent Mode for Cluster Resource Groups using the PowerShell Failover Clustering module

February 23, 2012 Posted by | Failover Clustering, Hyper-V R2, Virtualization, Windows PowerShell, Windows Server 2008 R2 | , | Leave a comment

Hyper-V: How to unbind a physical NIC from a Virtual Switch using WMI and PowerShell

If you`re not already familiar with networking in Microsoft Hyper-V I would recommend you to have a look at this whitepaper from Microsoft, which described how networking works in Hyper-V.

The following solution will describe a problem which might occur when configuring virtual networks in Hyper-V. Consider the following scenario:

  • You`re about to configure a new external virtual network in Hyper-V using Hyper-V Manager remotely from another computer. This is a common scenario when working with the Core edition of Windows Server 2008/2008 R2.
  • When selecting the physical NIC to bind to the new virtual network, you choose the adapter which you are remotely connecting to the Hyper-V host through.

What happens in this scenario is that the Virtual Switch Management Service is binding the external Ethernet port for the selected NIC to the Microsoft Windows Virtualization network subsystem. What normally should happen next is that the converted Ethernet port should be bound to the new virtual switch you are creating. However, this never happens since the NIC you are remotely managing the Hyper-V host through is no longer available in the parent operating system. This leaves the NIC in an “orphaned” state, since you cannot use the NIC in the parent operating system, and it`s not in use by any virtual networks.

To resolve this issue, whether using the full GUI version or the Core version of Windows Server, you need to manually unbind the the Ethernet port. There is an UnbindExternalEthernetPort available on the Msvm_VirtualSwitchManagementService WMI class, which is fully documented in this article on MSDN.

To invoke the WMI method we can use Windows PowerShell. To ease the procedure I`ve created a PowerShell function you can use if you ever come into the need for manually unbinding an external Ethernet port in Hyper-V:


Function Select-List
    Param   ([Parameter(Mandatory=$true  ,valueFromPipeline=$true )]$InputObject, 

    begin   { $i= @()  }
    process { $i += $inputobject  }
    end     { if ($i.count -eq 1) {$i[0]} elseif ($i.count -gt 1) {
                  $Property=@(@{Label=“ID”; Expression={ ($global:Counter++) }}) + $Property
                  format-table -inputObject $i -autosize -property $Property | out-host
                 $Response = Read-Host “Select NIC to unbind”
                  if ($response -gt “”) { 

function Remove-HVExternalEthernetPort {

$ExternalEthernetPort = Get-WMIObject -class “Msvm_ExternalEthernetPort” -namespace “root\virtualization” | Select-List -Property name

$HVSwitchObj = Get-WMIObject -class “MSVM_VirtualSwitchManagementService” -namespace “root\virtualization”

if ($ExternalEthernetPort) {
else {
throw “An error occured. Choose a valid ExternalEthernetPort from the provided list”


Note: The Select-List function is a modified version of the Select-List function available in the PowerShell Management Library for Hyper-V available on CodePlex (see link below).

You can either paste the function into a PowerShell session or save it into ps1-file and dot source it. When done you can invoke the function like this:


When you`ve entered the index number for the NIC you want to remove, a return value of 0 indicates the operation succeeded. Any other value indicates an error (look at the previous mentioned MSDN-article for more information).


More resources on managing Hyper-V using PowerShell

PowerShell Management Library for Hyper-V – this is an excellent PowerShell module for managing Hyper-V available on CodePlex

System Center Virtual Machine Manager 2012: Scripting

System Center Virtual Machine Manager 2008 R2: Scripting

Hyper-V WMI Using PowerShell Scripts

Script: Determining Virtual Switch Type Under Hyper-V

August 30, 2011 Posted by | Hyper-V, Hyper-V R2, Scripting, Virtualization, Windows PowerShell | , , | 1 Comment

Enable Persistent Mode for Cluster Resource Groups using the PowerShell Failover Clustering module

In Failover Clustering in Windows Server 2008 R2, Persistent Mode is intended to allow resource groups to come online on the node which an admin last moved them to. This setting is enabled by default when a virtual machine is created with Failover Cluster Manager. If you create virtual machine via System Center Virtual Manager this setting is not enabled.

By default, cluster roles have this setting disabled, except for Hyper-V virtual machine cluster roles, which have this enabled by default. This setting is useful when the cluster is shutdown and later started, in order to better distribute the resources across the nodes and allow them to come online faster, as they were likely spread across the nodes before the cluster was offlined. Otherwise, all the resources will attempt to restart on the first nodes which achieve quorum and compete for resources. This only applies to a group if it did not failover after being placed by the administrator. If a group has failed over since the last administrator placement, it is brought online on the node which the administrator last move it to.

Reference and more info regarding the Auto Start, Persistent Mode and Group Wait Delay features is available on the Clustering and High-Availability blog.

Auto Start can be enabled/disabled in bulk by marking all Cluster Resource Groups in Failover Cluster Manager and selecting “Enable auto start”/”Disable auto start”.

For Persistent Mode the only available option in Failover Cluster Manager is to right click each Cluster Resource Group and selecting/de-selecting the checkbox for “Enable persistent mode”:


To change this setting for all Cluster Resource Groups in an automated fashion you can use the Failover Cluster module for PowerShell, which I wrote an introduction to here.

Here is an example on how you can do this:

Import-Module FailoverClusters
$clustergroups = Get-ClusterGroup -Cluster cluster01.domain.local
foreach ($clustergroup in $clustergroups) {
#To enable persistent mode: x To disable persistent mode: 4294967295

Although you can change the Auto Start setting in bulk in Failover Cluster Manager you might also want to do this in an automated fashion:

Import-Module FailoverClusters
$clustergroups = Get-ClusterGroup -Cluster cluster01.domain.local
foreach ($clustergroup in $clustergroups) {
#To enable Auto Start: 1 To disable Auto Start: 0

You can also change the Group Wait Delay cluster-wide property from the PowerShell Failover Clustering module, how to do this is explained in the above referenced blog-post from the Clustering and High-Availability blog.

For the next version of System Center Virtual Machine Manager I would expect that Persistent Mode is enabled by default, since Microsoft do recommend customers to enable this setting.

Update 08.12.2011: The value of the DefaultOwner property for configuring Persistent Mode is the number of the node you want to be the default owner. In example a value of 1 means the first node in the cluster.

June 3, 2011 Posted by | Failover Clustering, Hyper-V, Hyper-V R2, Scripting, Windows PowerShell, Windows Server 2008 R2 | , | 3 Comments

Hyper-V R2 and storage location for snapshot differencing disks

I recently worked with a Hyper-V case, where the differencing disk files (.AVHD) for snapshots didn`t appear at the expected location. As we figured this out, I would like to share the experience we had regarding this.

A virtual machine has two important directories, the VM root and the snapshot root. The VM root is where we store the virtual machine configuration file (XML) and the saved state files (.BIN and .VSV). The snapshot root is where we store the config and saved state files for each snapshot of a virtual machine.

Virtual hard disks (.VHDs) are stored where ever the user specifies when creating the virtual machine (or when creating a new virtual hard disk).

What has changed in Hyper-V between Windows Server 2008 and Windows Server 2008 R2 is the placement of .AVHD files (these are the differencing disks created for each snapshot). In Windows Server 2008 the .AVHD is always created in the snapshot root location, which by default are located at C:\ProgramData\Microsoft\Windows\Hyper-V\Snapshots. This caused a lot of people problems – as they would run out of space on the partition where the snapshot root folder was. In Windows Server 2008 R2 the .AVHD file is always created in the same location as its parent virtual hard disk.

This means that with R2 .AVHD files will always appear beside their respective .VHD files. The one exception to this is if you bring across a Windows Server 2008 virtual machine with .AVHDs already in the snapshot root. In this case new .AVHDs will be created beside their parent .AVHDs (in the snapshot root).


Microsoft TechNet Resources

Hyper-V in Windows Server 2008
Hyper-V R2 in Windows Server 2008 R2

February 23, 2010 Posted by | Hyper-V, Hyper-V R2, Windows Server 2008, Windows Server 2008 R2 | | 1 Comment