Controlling Virtual Server through Microsoft PowerShell


In his post by the same name, Ben describe a series of steps required in order to manipulate Virtual Server from PowerShell.


I’m still a PowerShell novice, so I decided to use this problem as an opportunity to see if I could make things a little easier. 


The reason it’s hard is that you have to make a call to a native Win32 API, which is not accessible from PowerShell directly.  Ben’s solution includes a peice of C# code that makes this call via interop, and then you have to compile it & load the assembly before you can do any work.  In my solution, my script does that work, as well.


Here’s the code:



$csc = (join-path ($env:windir) Microsoft.NET\Framework\v2.0.50727\csc.exe)


$code = [IO.Path]::GetTempFileName() + “.cs”


echo @”
        using System;
        using System.Runtime.InteropServices;


        public class PowershellComSecurity
        {
            [DllImport(“Ole32.dll”, CharSet = CharSet.Auto)]
            public static extern int CoSetProxyBlanket(IntPtr p0, uint p1, uint p2, uint p3, uint p4, uint p5, IntPtr p6, uint p7);


            public static int EnableImpersonation(object objDCOM) { return CoSetProxyBlanket(Marshal.GetIDispatchForObject(objDCOM), 10, 0, 0, 0, 3, IntPtr.Zero, 0); }
        }
“@ > $code


$assembly = [IO.Path]::GetTempFileName() + “.dll”


& $csc /nologo /target:library /out:$assembly $code
[System.Reflection.Assembly]::LoadFrom($assembly) > $null


function SetSecurity { [PowershellComSecurity]::EnableImpersonation($args[0]) }


$vs = new-object -comObject “VirtualServer.Application”
SetSecurity($vs)


$vm = $vs.FindVirtualMachine(“public”)
SetSecurity($vm)


$guest = $vm.GuestOS
SetSecurity($guest)


$guest


It could use a little tuning.  If I was going to do this a lot, I’d put it all in to a new script.


 

Comments (2)

  1. Speedlinking #702 – SCVMM, Powershell, and the VHD program Here are some general Virtualization news…

  2. Lee says:

    That’s a good way to do it. In fact, for simple P/Invoke calls, you might also consider the Invoke-Win32 library I wrote some time back, or the inline C# library I wrote:

    http://www.leeholmes.com/blog/GetTheOwnerOfAProcessInPowerShellPInvokeAndRefOutParameters.aspx

    http://www.leeholmes.com/blog/MorePInvokeInPowerShell.aspx

    http://www.leeholmes.com/blog/LibraryForInlineCInMSH.aspx

    I believe this should work for the invoke — I don’t have the virtual server manager COM object to test with, though.

    $parameterTypes = [IntPtr], [uint32], [uint32], [uint32], [uint32], [uint32], [IntPtr], [uint32]

    $idispatch = [System.Runtime.InteropServices.Marshal]::GetIDispatchForObject($objDcom)

    $parameters = [IntPtr] $idispatch, [Uint32] 10, [UInt32] 0, [UInt32] 0, [UInt32] 0, [Uint32] 3, [IntPtr]::Zero, [Uint32] 0

    Invoke-Win32 "ole32" ([Int]) "CoSetProxyBlanket" $parameterTypes $parameters