Controlling Virtual Server through Microsoft PowerShell

Published 22 January 07 01:26 PM

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.

 

Filed under:

Comments

# Dugie's Pensieve said on January 27, 2007 11:14 PM:

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

# Lee said on January 31, 2007 1:52 AM:

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

New Comments to this post are disabled
Page view tracker