Controlling Virtual Server through PowerShell

A number of people have been asking me about using PowerShell to control Virtual Server.  This is a very cool idea – however, out of the box it does not work.  If you try and access the Virtual Server COM object (with a command like: $vs=new-object –com VirtualServer.Application –Strict) it will succeed – but inspecting the object will show no data:

Virtual Server and PowerShell

The reason this happens is that PowerShell is a .Net application – and as a .Net application it does not run with sufficient privilege to be able to talk to our COM interfaces.  In order to address this – you will need to make a library that allows you to set the COM security level on an object to ‘impersonate’.  Below is a chunk of C# code that does exactly this (I have attached this code in a file to this post as well):

using System;
using System.Runtime.InteropServices;
using System.Reflection;

namespace Microsoft.VirtualServer.Interop
using System;
using System.Runtime.InteropServices;
using System.Reflection;

public class 
const uint EOAC_NONE = 0;
const uint RPC_C_AUTHN_WINNT = 10;
const uint RPC_C_AUTHZ_NONE = 0;

         CharSet =
public static extern int 
IntPtr pProxy, 
uint dwAuthnSvc, 
uint dwAuthzSvc,
uint pServerPrincName, 
uint dwAuthLevel,
uint dwImpLevel, 
IntPtr pAuthInfo,
uint dwCapabilities

      public static int 
object objDCOM
IntPtr dispatchInterface = Marshal.GetIDispatchForObject(objDCOM);
int hr = CoSetProxyBlanket(
RPC_C_AUTHZ_NONE, //dwAuthzSvc
0, //pServerPrincName
IntPtr.Zero, //pAuthInfo
EOAC_NONE //dwCapabilities
return hr;

You can compile this code into a DLL by saving it in a .CS file, opening the Visual Studio 2005 Command Prompt and running ‘csc /t:library VSWrapperForPSH.cs’.  Once you have done this – you can load this DLL into PowerShell by running ‘[System.Reflection.Assembly]::LoadFrom(“<<path to DLL>>”)’ (note that you need to use the full path to the DLL – if the path is excluded – PowerShell will look in Windows\System32 and complain if the file is not there).

Once you have done all of this – you can now change the COM security level on an object by running ‘[Microsoft.VirtualServer.Interop.Powershell]::SetSecurity($objectName)’.  And as you can see here – you will then be able to access the object properly:

Virtual Server and PowerShell

However – if you make any new objects (which you will):

Virtual Server and PowerShell

You will get bitten again.  This is simply handled by setting the COM security on objects as you create them:

Virtual Server and PowerShell

Well.  Now that we have all of that working – you can expect to see some posts from me in the near future about how to perform different tasks under PowerShell.  But for now – a couple of final notes to make are:

  1. Under Vista hosts – PowerShell needs to be running ‘As Administrator’ for this to work (otherwise you will fail to create the first COM object)

  2. I could not have done this without the help of Mike Kolitz and Jon White (from the PowerShell team) – thanks guys!