## Invoke Win32 API via PowerShell

.NET provides pretty good support to for calling Win32 APIs and there’s a free Visual Studio Add-In from redgate available which helps your dealing with the Win32 API: http://www.red-gate.com/products/dotnet-development/pinvoke/

But what to do if you want to call Win32 APIs or your own .NET functionality in PowerShell?

As always there is more than one way: You can write your .NET code in Visual Studio, compile it to a class library and make it available in PowerShell using Reflection:

[System.Reflection.Assembly]::LoadFrom("path\to\your.dll")

Another – cool – way is to compile your code directly to the memory without generating a dll in the file system and consume it form within PowerShell!

The following code sample shows how to accomplish this by creating a compiler function, embed C# source code as a string, compile the code and invoke the C# function in PowerShell:

##################################################################
# Compiler
##################################################################
function Compile-Csharp ([string] $code,$FrameworkVersion="v4.0.30319")
{
$provider = New-Object Microsoft.CSharp.CSharpCodeProvider$framework = [System.IO.Path]::Combine($env:windir, "Microsoft.NET\Framework\$FrameWorkVersion")
$references = New-Object System.Collections.ArrayList$references.AddRange( @("${framework}\System.dll","${framework}\System.Core.dll"))
$parameters = New-Object System.CodeDom.Compiler.CompilerParameters$parameters.GenerateInMemory = $true$parameters.GenerateExecutable = $false$parameters.ReferencedAssemblies.AddRange($references)$result = $provider.CompileAssemblyFromSource($parameters, $code) if ($result.Errors.Count)
{
$codeLines =$code.Split("n");
foreach ($ce in$result.Errors)
{
write-host "Error: $($codeLines[$($ce.Line - 1)])"
$ce | out-default } Throw "Compilation of C# code failed" } } ################################################################## # C# Code ##################################################################$code = @'
using System;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace CompileTest
{
public class Sound
{
[DllImport("User32.dll", SetLastError = true)]
static extern Boolean MessageBeep(UInt32 beepType);

public static void Beep(BeepTypes type)
{
if (!MessageBeep((UInt32)type))
{
Int32 err = Marshal.GetLastWin32Error();
throw new Win32Exception(err);
}
}
}

public enum BeepTypes
{
Simple = -1,
Ok = 0x00000000,
IconHand = 0x00000010,
IconQuestion = 0x00000020,
IconExclamation = 0x00000030,
IconAsterisk = 0x00000040
}
}
'@

##################################################################
# Compile the code and access the .NET object within PowerShell
##################################################################
Compile-Csharp $code [CompileTest.Sound]::Beep([CompileTest.BeepTypes]::IconAsterisk) ` If you want to use other references than “System” in your C# code, make sure to introduce them to the compiler by adding the dll to the$references ArrayList. Also make sure to pass the appropriate framework version to the Compile-Csharp function. A list of available framework versions and the System*.dlls can be found here: C:\Windows\Microsoft.NET\Framework or C:\Windows\Microsoft.NET\Framework64

Over all this is a quite simple and very cool way to provide .NET functionality within PowerShell. Happy coding!

By the way: Make sure your speakers are turned on when running this example since it leads to a beep sound on your machine :-)

This entry was posted in powerJobs, PowerShell, Visual Studio. Bookmark the permalink.

### One Response to Invoke Win32 API via PowerShell

1. Hi,
to compile the code in memory you can also use the Add-Type cmdlet.