<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>VincentH on .NET &#187; Powershell</title>
	<atom:link href="http://vincenth.net/blog/archive/category/powershell/feed" rel="self" type="application/rss+xml" />
	<link>http://vincenth.net/blog</link>
	<description>Software : Factories &#38; Architecture</description>
	<lastBuildDate>Thu, 26 Nov 2009 16:30:03 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>Detect 32 or 64 bits Windows &#8211; regardless of WoW64 &#8211; with the PowerShell OSArchitecture function</title>
		<link>http://vincenth.net/blog/archive/2009/11/02/detect-32-or-64-bits-windows-regardless-of-wow64-with-the-powershell-osarchitecture-function.aspx</link>
		<comments>http://vincenth.net/blog/archive/2009/11/02/detect-32-or-64-bits-windows-regardless-of-wow64-with-the-powershell-osarchitecture-function.aspx#comments</comments>
		<pubDate>Mon, 02 Nov 2009 15:09:32 +0000</pubDate>
		<dc:creator>Vincent</dc:creator>
				<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Solutions Factory Features]]></category>

		<guid isPermaLink="false">http://vincenth.net/blog/?p=181</guid>
		<description><![CDATA[In 64-bits versions of Windows Operating Systems, a subsystem called Windows on Windows 64 (WoW64) enables you to run 32 bits applications. Even to date, many Windows applications only exist in a 32 bits version – not the least of which is Microsoft&#8217;s own Visual Studio(!) The purpose of WoW64 is to hide many of [...]]]></description>
			<content:encoded><![CDATA[<p>In 64-bits versions of Windows Operating Systems, a subsystem called <a href="http://en.wikipedia.org/wiki/WoW64">Windows on Windows 64</a> (WoW64) enables you to run 32 bits applications. Even to date, many Windows applications only exist in a 32 bits version – not the least of which is Microsoft&#8217;s own Visual Studio(!)</p>
<p>The purpose of WoW64 is to hide many of the structural differences between 32 bits and 64 bits Windows for 32 bits applications. This is a good thing. Most of the time, anyway&#8230;</p>
<p>However, when your PowerShell script runs in a 32 bits process on a 64 bits OS, and you want to integrate with 64-bits applications (e.g. you want to integrate SharePoint or SQL Server within Visual Studio), WoW64 can get in the way.</p>
<p>E.g., WoW64 hides the 64 bit registry and changes the environment variables for processor architecture and for the program files folder – in short, WoW64 hides that you are running on a 64 bits OS.</p>
<p>To detect a 64 bits OS from PowerShell on Vista, W2008 and later Windows versions, we could use WMI:</p>

<div class="wp_syntax"><div class="code"><pre class="powershell" style="font-family:monospace;"><span style="color: #000000;">&#40;</span><span style="color: #008080; font-weight: bold;">Get-WMIObject</span> win32_operatingsystem<span style="color: #000000;">&#41;</span>.OSArchitecture</pre></div></div>

<p>However, this is not supported on W2003.</p>
<p>Fortunately, Microsoft provided an alternative, which is supported on all Windows versions that have Wow64: the <strong>IsWow64Process</strong> function. Since this is an unmanaged API call to Kernel32.dll, we need to do some extra work to call this in PowerShell.</p>
<p>We can write a simple managed C# wrapper around IsWow64Process:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF; font-weight: bold;">using</span> <span style="color: #008080;">System</span><span style="color: #008000;">;</span>
<span style="color: #0600FF; font-weight: bold;">using</span> <span style="color: #008080;">System.Runtime.InteropServices</span><span style="color: #008000;">;</span>
&nbsp;
<span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">class</span> Kernel32
<span style="color: #008000;">&#123;</span>
    <span style="color: #008000;">&#91;</span>DllImport<span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;kernel32.dll&quot;</span>, SetLastError <span style="color: #008000;">=</span> <span style="color: #0600FF; font-weight: bold;">true</span>, CallingConvention <span style="color: #008000;">=</span> CallingConvention<span style="color: #008000;">.</span><span style="color: #0000FF;">Winapi</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span>
    <span style="color: #008000;">&#91;</span><span style="color: #0600FF; font-weight: bold;">return</span><span style="color: #008000;">:</span> MarshalAs<span style="color: #008000;">&#40;</span>UnmanagedType<span style="color: #008000;">.</span><span style="color: #6666cc; font-weight: bold;">Bool</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span>
    <span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #0600FF; font-weight: bold;">static</span> <span style="color: #0600FF; font-weight: bold;">extern</span> <span style="color: #6666cc; font-weight: bold;">bool</span> IsWow64Process<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#91;</span><span style="color: #0600FF; font-weight: bold;">In</span><span style="color: #008000;">&#93;</span> IntPtr hProcess, <span style="color: #008000;">&#91;</span><span style="color: #0600FF; font-weight: bold;">Out</span><span style="color: #008000;">&#93;</span> <span style="color: #0600FF; font-weight: bold;">out</span> <span style="color: #6666cc; font-weight: bold;">bool</span> lpSystemInfo<span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
    <span style="color: #008080; font-style: italic;">// This overload returns True if the current process is running on Wow, False otherwise</span>
    <span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">bool</span> CurrentProcessIsWow64<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #6666cc; font-weight: bold;">bool</span> retVal<span style="color: #008000;">;</span>
        <span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #008000;">!</span><span style="color: #008000;">&#40;</span>IsWow64Process<span style="color: #008000;">&#40;</span><span style="color: #000000;">System.<span style="color: #0000FF;">Diagnostics</span></span><span style="color: #008000;">.</span><span style="color: #0000FF;">Process</span><span style="color: #008000;">.</span><span style="color: #0000FF;">GetCurrentProcess</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Handle</span>, <span style="color: #0600FF; font-weight: bold;">out</span> retVal<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> <span style="color: #0600FF; font-weight: bold;">throw</span> <span style="color: #008000;">new</span> Exception<span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;IsWow64Process() failed&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span> <span style="color: #008000;">&#125;</span>
        <span style="color: #0600FF; font-weight: bold;">return</span> retVal<span style="color: #008000;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>When we use the PowerShell <a href="http://vincenth.net/blog/archive/2009/10/27/call-inline-c-from-powershell-with-invokecsharp.aspx">InvokeCSharp</a> function, we can put this C# inline in our PowerShell script:</p>

<div class="wp_syntax"><div class="code"><pre class="powershell" style="font-family:monospace;"><span style="color: #0000FF;">Function</span> global:CurrentProcessIsWOW64
<span style="color: #000000;">&#123;</span>
    <span style="color: #008000;"># Use some inline C# code to call the unmanaged IsWow64Process() function in Kernel32.dll and return its result:</span>
    <span style="color: #800080;">$code</span> <span style="color: pink;">=</span> <span style="color: pink;">@</span><span style="color: #800000;">&quot;
        using System;
        using System.Runtime.InteropServices;
&nbsp;
        public class Kernel32
        {
            [DllImport(&quot;</span>kernel32.dll<span style="color: #800000;">&quot;, SetLastError = true, CallingConvention = CallingConvention.Winapi)]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool IsWow64Process([In] IntPtr hProcess, [Out] out bool lpSystemInfo);
&nbsp;
            // This overload returns True if the current process is running on Wow, False otherwise
            public bool CurrentProcessIsWow64()
            {
                bool retVal;
                if (!(IsWow64Process(System.Diagnostics.Process.GetCurrentProcess().Handle, out retVal))) { throw new Exception(&quot;</span>IsWow64Process<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> failed<span style="color: #800000;">&quot;); }
                return retVal;
            }
        }
&quot;</span><span style="color: pink;">@</span>
    InvokeCSharp <span style="color: pink;">-</span>code <span style="color: #800080;">$code</span> <span style="color: #008080; font-style: italic;">-class</span> <span style="color: #800000;">'Kernel32'</span> <span style="color: pink;">-</span>method <span style="color: #800000;">'CurrentProcessIsWow64'</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #0000FF;">Function</span> global:ProcessArchitecture
<span style="color: #000000;">&#123;</span>
    <span style="color: #0000FF;">switch</span> <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#91;</span>System.IntPtr<span style="color: #000000;">&#93;</span>::Size<span style="color: #000000;">&#41;</span>
    <span style="color: #000000;">&#123;</span>
        <span style="color: #804000;">4</span> <span style="color: #000000;">&#123;</span> <span style="color: #804000;">32</span> <span style="color: #000000;">&#125;</span>
        <span style="color: #804000;">8</span> <span style="color: #000000;">&#123;</span> <span style="color: #804000;">64</span> <span style="color: #000000;">&#125;</span>
        default <span style="color: #000000;">&#123;</span> <span style="color: #0000FF;">throw</span> <span style="color: #800000;">&quot;Unknown Process Architecture: $([System.IntPtr]::Size * 8) bits&quot;</span> <span style="color: #000000;">&#125;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #0000FF;">Function</span> global:OSArchitecture
<span style="color: #000000;">&#123;</span>
    <span style="color: #0000FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span>ProcessArchitecture<span style="color: #000000;">&#41;</span> <span style="color: #FF0000;">-eq</span> <span style="color: #804000;">32</span><span style="color: #000000;">&#41;</span> <span style="color: #FF0000;">-and</span> <span style="color: #000000;">&#40;</span>CurrentProcessIsWOW64<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #804000;">64</span> <span style="color: #000000;">&#125;</span> <span style="color: #0000FF;">else</span> <span style="color: #000000;">&#123;</span> ProcessArchitecture <span style="color: #000000;">&#125;</span>
    <span style="color: #008000;"># Note that on Vista, W2008 and later Windows versions, we could use (Get-WMIObject win32_operatingsystem).OSArchitecture.</span>
    <span style="color: #008000;"># We don't use that because we also support W2003</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>So there you have it, some simple PowerShell functions to detect the process architecture and the OS architecture, regardless of whether or not you are running under WoW64.</p>
<p>P.S. I also added these functions to the global functions in the <a href="http://solutionsfactory.macaw.nl/">Macaw Solutions Factory</a>, so they can be leveraged by anyone who wants to extend the Factory.</p>
]]></content:encoded>
			<wfw:commentRss>http://vincenth.net/blog/archive/2009/11/02/detect-32-or-64-bits-windows-regardless-of-wow64-with-the-powershell-osarchitecture-function.aspx/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Call inline C# from PowerShell with InvokeCSharp</title>
		<link>http://vincenth.net/blog/archive/2009/10/27/call-inline-c-from-powershell-with-invokecsharp.aspx</link>
		<comments>http://vincenth.net/blog/archive/2009/10/27/call-inline-c-from-powershell-with-invokecsharp.aspx#comments</comments>
		<pubDate>Tue, 27 Oct 2009 11:58:52 +0000</pubDate>
		<dc:creator>Vincent</dc:creator>
				<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Solutions Factory Features]]></category>

		<guid isPermaLink="false">http://vincenth.net/blog/?p=174</guid>
		<description><![CDATA[Out of the box PowerShell 1.0 makes it very easy to call any managed code in an assembly. However, one of the strong points of a scripted language such as PowerShell is that you can debug and extend it in any environment without the need for development tools or additional source code. This is especially [...]]]></description>
			<content:encoded><![CDATA[<p>Out of the box PowerShell 1.0 makes it very easy to call any managed code in an assembly. However, one of the strong points of a scripted language such as PowerShell is that you can debug and extend it in any environment without the need for development tools or additional source code. This is especially valuable in scripts that integrate heavily with production environments, e.g. with automated deployment scripts such as we use in the <a href="http://solutionsfactory.macaw.nl/">Macaw Solutions Factory</a>.</p>
<p>Ideally you would want the ability to call any C# source code from PowerShell, either inline or as a separate source file, effectively adding the maintainability benefits of a scripted language to C#. Based on <a href="http://www.leeholmes.com/blog/LibraryForInlineCInMSH.aspx">a library created by Lee Holmes</a> I created an improved PowerShell 1.0 function called <strong>InvokeCSharp</strong> that does just this.</p>
<p>Note that in PowerShell V2, this functionality is available through the built-in <a href="http://technet.microsoft.com/en-us/library/dd315241.aspx">Add-Type cmdlet</a>. </p>
<p>InvokeCSharp is completely self-contained and can be used in any PowerShell script.</p>
<h2>Usage</h2>
<p>Here are some simple examples on how to use InvokeCSharp:</p>
<p>Let&#8217;s say we have a file <strong>MyClass.cs</strong>:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF; font-weight: bold;">using</span> <span style="color: #008080;">System</span><span style="color: #008000;">;</span>
&nbsp;
<span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">class</span> MyClass
<span style="color: #008000;">&#123;</span>
    <span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">string</span> AString<span style="color: #008000;">;</span>
&nbsp;
    <span style="color: #0600FF; font-weight: bold;">public</span> MyClass<span style="color: #008000;">&#40;</span><span style="color: #6666cc; font-weight: bold;">string</span> aString<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        AString <span style="color: #008000;">=</span> aString<span style="color: #008000;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>Then we can invoke it like this in PowerShell:</p>

<div class="wp_syntax"><div class="code"><pre class="powershell" style="font-family:monospace;"><span style="color: #008000;"># Create a class instance from a .cs file, passing a parameter to the class constructor:</span>
<span style="color: #008000;"># Note that the class name can be omitted here, since it is implied from the .cs file name</span>
<span style="color: #800080;">$myClassInstance</span> <span style="color: pink;">=</span> InvokeCSharp <span style="color: #FF0000;">-file</span> <span style="color: #800000;">'.\MyClass.cs'</span> <span style="color: pink;">-</span>parameters <span style="color: #800000;">'A text'</span></pre></div></div>

<p>Or we can put some C# code inline in the PowerShell script itself, and invoke it:</p>

<div class="wp_syntax"><div class="code"><pre class="powershell" style="font-family:monospace;"><span style="color: #008000;"># Call some simple inline code. Note that you could also wrap the code in a namespace,</span>
<span style="color: #008000;"># add using statements and reference other assemblies.</span>
<span style="color: #800080;">$code</span> <span style="color: pink;">=</span> <span style="color: pink;">@</span><span style="color: #800000;">&quot;
	public class MyClass2
	{
		public static int MyStaticMethod(int a, int b)
		{
			return a * b;
		}
	}
&quot;</span><span style="color: pink;">@</span>
<span style="color: #800080;">$result</span> <span style="color: pink;">=</span> InvokeCSharp <span style="color: pink;">-</span>code <span style="color: #800080;">$code</span> <span style="color: #008080; font-style: italic;">-class</span> <span style="color: #800000;">'MyClass2'</span> <span style="color: pink;">-</span>method <span style="color: #800000;">'MyStaticMethod'</span> <span style="color: pink;">-</span>parameters <span style="color: #804000;">3</span><span style="color: pink;">,</span> <span style="color: #804000;">7</span> <span style="color: #008000;"># Will return 21</span></pre></div></div>

<p>Although these are very simple examples, all the rich goodness of PowerShell &#8211; .NET integration is available. Passing any type of parameters back and forth is simple and completely transparent. All C# features can be used; e.g. you can use the C# DllImport attribute to call unmanaged API&#8217;s when COM interop is not available or not preferred.</p>
<p>After initial compilation the performance is equivalent to calling compiled assemblies from PowerShell.</p>
<h2>Extending the Macaw Solutions Factory PowerShell scripts with inline C#</h2>
<p>I added InvokeCSharp to the global functions in the <a href="http://solutionsfactory.macaw.nl/">Macaw Solutions Factory</a>. This makes it possible to simply extend or modify any Factory script – including the scripts that deploy a MAST Product from a package to (production) machines.</p>
<p>For anyone who is more adept with C# than with PowerShell this will make it easier to extend the Factory scripts. This also enables leveraging existing C# libraries from PowerShell while keeping the entire solution maintainable as a script.</p>
<h2>Improvements</h2>
<p>The improvements I added to InvokeCSharp when compared to the original version are:</p>
<ul>
<li>The C# code you specify is completely self-contained; no more C# wrapper code where your code is pasted into. This improves readability and maintainability of inline C# code.</li>
<li>Simpler parameter passing; no more wrapper code needed for parameters and return values.</li>
<li>Automatically un-wraps parameters that PowerShell wraps in a PSObject. This eliminates the need to explicitly cast parameters to make them strongly typed on each call to InvokeCSharp, and to always wrap them in @().<br />
Figuring this one out was interesting; it required diving in the innards of the <a href="http://msdn.microsoft.com/en-us/library/ms714419(VS.85).aspx">PowerShell Extended Type System</a> (ETS) which gets in the way when you work with .NET reflection classes from PowerShell. PowerShell tries to make the ETS transparent to the PowerShell user, which in general is a good thing but in this case meant it was hard to see what was happening.</li>
<li>Adds support for calling static methods, including overloaded methods, without creating a class instance.</li>
<li>Adds support for creating a class instance and providing constructor parameters.</li>
<li>Caches compiled assemblies instead of class instances. This improves performance because it eliminates duplicate compilation when the same C# code is called more than once. In addition to assembly caching you can of course also cache the object instances using any of the standard PowerShell mechanisms; however this is better handled outside the InvokeCSharp function.</li>
<li>Support for inline C# and separate C# source files; the latter allows you to easily edit the C# in Visual Studio, e.g. to use IntelliSense and compile the source to catch compile time errors.</li>
</ul>
<h2>PowerShell Source</h2>
<p>So here are the goods &#8211; the complete PowerShell source for InvokeCSharp:</p>

<div class="wp_syntax"><div class="code"><pre class="powershell" style="font-family:monospace;"><span style="color: #008000;">#&amp;lt; # #.Synopsis #   Create a class instance and/or invoke a method on C# source code. #   For details, see: #   http://vincenth.net/blog/archive/2009/10/27/call-inline-c-from-powershell-with-invokecsharp.aspx  #.Description #   This function compiles the provided C# source code (only if necessary, compiled #   assemblies are cached). The code can be supplied either inline in a string or #   in a source file. Relative source filename paths are interpreted #   relative to the parent folder of the calling script. #   This enables simple organization and reference of related .ps1 and .cs files. # #   If a method name is specified, that method is invoked with any supplied #   parameters and the function then returns the result of the method. #   Both static and nonstatic methods are supported, including overloaded #   methods. # #   If no method name is specified, an instance of the specified class is #   created, passing any supplied parameters to the class constructor, and the #   function then returns the class instance. You can then program against the #   class instance in standard PowerShell fashion. # #   If necessary for compilation, you can specify names of any referenced #   assemblies. #.Parameter code #   The complete C# source code - effectively this is an inline C# source file. #   Note that it is possible but not necessary to declare classes within a #   namespace. #   Either the code parameter or the file parameter must be specified. #.Parameter file #   Absolute or relative path to a C# source file. Relative paths (beginning #   with '.\' or '..\') are interpreted relative to the folder that contains #   the calling script (i.e. the script that calls this function). #   Either the code parameter or the file parameter must be specified. #.Parameter class #   The name of the class to be instantiated / that contains the method to #   be invoked. Include the namespace in which the class is declared, if any. #   If you specify the -file parameter and the class name is identical to the #   file name, you can omit the -class parameter. #.Parameter method #   Either the name of the method to be invoked, '()' to invoke a  #   constructor to create and resturn a class instance, or '' to return #   the cached assembly. The last option allows you to precompile assemblies #   without calling a method or creating a class instance. #     #   If the specified method is not static, an instance of the class will #   be created on the fly. #.Parameter parameters #   To pass parameters to the constructor or method, specify them as an #   array of objects (e.g. with the comma operator or @() ). #.Parameter reference #   If necessary, specify an array of assembly filenames to be added as #   assembly references when the source code is compiled. #.Parameter forceCompile #   Specify this switch to force recompilation. This is useful if you specify #   the file parameter and the file contents has changed (when specifying a #   source file name, the cache key is the file name only - changes to the file #   do not automatically cause cache invalidation). #.Returns #   Either the cached assembly, a class instance or a method result (depending  #   on the value specified for the method parameter). #.Example #   # Create a class instance from a .cs file, passing a parameter to the class constructor: #   # Note that the class name can be omitted here, since it is implied from the .cs file name #   $myClassInstance = InvokeCSharp -file '.\MyClass.cs' -parameters 'A text' #     #   # Call some simple inline code. Note that you could also wrap the code in a namespace,  #   # add using statements and reference other assemblies. #   $code = @&quot; #       public class MyClass2 #       { #           public static int MyStaticMethod(int a, int b) #           { #               return a * b; #           } #       } #   &quot;@ #   $result = InvokeCSharp -code $code -class 'MyClass2' -method 'MyStaticMethod' -parameters 3, 7 # Will return 21 ##&amp;gt;</span>
<span style="color: #0000FF;">function</span> global:InvokeCSharp
<span style="color: #000000;">&#123;</span>
    <span style="color: #0000FF;">param</span><span style="color: #000000;">&#40;</span>
        <span style="color: #000000;">&#91;</span><span style="color: #008080;">string</span><span style="color: #000000;">&#93;</span> <span style="color: #800080;">$code</span> <span style="color: pink;">=</span> <span style="color: #800000;">''</span><span style="color: pink;">,</span>
        <span style="color: #000000;">&#91;</span><span style="color: #008080;">string</span><span style="color: #000000;">&#93;</span> <span style="color: #800080;">$file</span> <span style="color: pink;">=</span> <span style="color: #800000;">''</span><span style="color: pink;">,</span>
        <span style="color: #000000;">&#91;</span><span style="color: #008080;">string</span><span style="color: #000000;">&#93;</span> <span style="color: #800080;">$class</span> <span style="color: pink;">=</span> <span style="color: #800000;">''</span><span style="color: pink;">,</span>
        <span style="color: #000000;">&#91;</span><span style="color: #008080;">string</span><span style="color: #000000;">&#93;</span> <span style="color: #800080;">$method</span> <span style="color: pink;">=</span> <span style="color: #800000;">'()'</span><span style="color: pink;">,</span>
        <span style="color: #000000;">&#91;</span><span style="color: #008080;">Object</span><span style="color: #000000;">&#91;</span><span style="color: #000000;">&#93;</span><span style="color: #000000;">&#93;</span> <span style="color: #800080;">$parameters</span> <span style="color: pink;">=</span> <span style="color: #800080;">$null</span><span style="color: pink;">,</span>
        <span style="color: #000000;">&#91;</span>string<span style="color: #000000;">&#91;</span><span style="color: #000000;">&#93;</span><span style="color: #000000;">&#93;</span> <span style="color: #800080;">$reference</span> <span style="color: pink;">=</span> <span style="color: pink;">@</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: pink;">,</span>
        <span style="color: #000000;">&#91;</span><span style="color: #0000FF;">switch</span><span style="color: #000000;">&#93;</span> <span style="color: #800080;">$forceCompile</span>
    <span style="color: #000000;">&#41;</span>
&nbsp;
    <span style="color: #008000;"># Stores a cache of generated assemblies. If this library is dot-sourced</span>
    <span style="color: #008000;"># from a script, these objects go away when the script exits.</span>
    <span style="color: #0000FF;">if</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">-not</span> <span style="color: #000000;">&#40;</span><span style="color: #008080; font-weight: bold;">Test-Path</span> Variable:\macaw.solutionsfactory.assemblycache<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
    <span style="color: #000000;">&#123;</span>
        $<span style="color: #000000;">&#123;</span>GLOBAL:macaw.solutionsfactory.assemblycache<span style="color: #000000;">&#125;</span> <span style="color: pink;">=</span> <span style="color: pink;">@</span><span style="color: #000000;">&#123;</span><span style="color: #000000;">&#125;</span>
    <span style="color: #000000;">&#125;</span>
&nbsp;
    <span style="color: #0000FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #800080;">$code</span> <span style="color: #FF0000;">-eq</span> <span style="color: #800000;">''</span><span style="color: #000000;">&#41;</span> <span style="color: #FF0000;">-and</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$file</span> <span style="color: #FF0000;">-eq</span> <span style="color: #800000;">''</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #0000FF;">throw</span> <span style="color: #800000;">'Neither code nor file are specified. Specify either one or the other.'</span> <span style="color: #000000;">&#125;</span>
&nbsp;
    <span style="color: #008000;"># If a source file was specified, see if it was already loaded, compiled and cached:</span>
    <span style="color: #0000FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$file</span> <span style="color: #FF0000;">-ne</span> <span style="color: #800000;">''</span><span style="color: #000000;">&#41;</span>
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0000FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$code</span> <span style="color: #FF0000;">-ne</span> <span style="color: #800000;">''</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #0000FF;">throw</span> <span style="color: #800000;">'Both code and file are specified. Specify either one or the other.'</span> <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #008000;"># We interpret the current directory as the directory containing the calling script, instead of the currect directory of the current process.</span>
        <span style="color: #0000FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$file</span>.StartsWith<span style="color: #000000;">&#40;</span><span style="color: #800000;">'.'</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            <span style="color: #800080;">$callingScriptFolder</span> <span style="color: pink;">=</span> <span style="color: #008080; font-weight: bold;">Split-Path</span> <span style="color: #008080; font-style: italic;">-path</span> <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #008080; font-weight: bold;">Get-Variable</span> MyInvocation <span style="color: #008080; font-style: italic;">-Scope</span> <span style="color: #804000;">1</span><span style="color: #000000;">&#41;</span>.Value<span style="color: #000000;">&#41;</span>.MyCommand.Path <span style="color: #008080; font-style: italic;">-Parent</span>
            <span style="color: #800080;">$file</span> <span style="color: pink;">=</span> <span style="color: #008080; font-weight: bold;">Join-Path</span> <span style="color: #008080; font-style: italic;">-Path</span> <span style="color: #800080;">$callingScriptFolder</span> <span style="color: #008080; font-style: italic;">-ChildPath</span> <span style="color: #800080;">$file</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #008000;"># If no class name is  specified, we assume by convention that the file name is equal to the class name.</span>
        <span style="color: #0000FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$class</span> <span style="color: #FF0000;">-eq</span> <span style="color: #800000;">''</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #800080;">$class</span> <span style="color: pink;">=</span> <span style="color: #000000;">&#91;</span>System.IO.Path<span style="color: #000000;">&#93;</span>::GetFileNameWithoutExtension<span style="color: #000000;">&#40;</span><span style="color: #800080;">$file</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #008000;"># Use the real full path as the cache key:</span>
        <span style="color: #800080;">$file</span> <span style="color: pink;">=</span> <span style="color: #000000;">&#91;</span>System.IO.Path<span style="color: #000000;">&#93;</span>::GetFullPath<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #008080; font-weight: bold;">Convert-Path</span> <span style="color: #008080; font-style: italic;">-path</span> <span style="color: #800080;">$file</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
        <span style="color: #800080;">$cacheKey</span> <span style="color: pink;">=</span> <span style="color: #800080;">$file</span>
    <span style="color: #000000;">&#125;</span>
    <span style="color: #0000FF;">else</span>
    <span style="color: #000000;">&#123;</span>
        <span style="color: #008000;"># See if the code has already been compiled and cached</span>
        <span style="color: #800080;">$cacheKey</span> <span style="color: pink;">=</span> <span style="color: #800080;">$code</span>
    <span style="color: #000000;">&#125;</span>
    <span style="color: #0000FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$class</span> <span style="color: #FF0000;">-eq</span> <span style="color: #800000;">''</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #0000FF;">throw</span> <span style="color: #800000;">'Required parameter missing: class'</span> <span style="color: #000000;">&#125;</span>
&nbsp;
    <span style="color: #008000;"># See if the code must be (re)compiled:</span>
    <span style="color: #800080;">$cachedAssembly</span> <span style="color: pink;">=</span> $<span style="color: #000000;">&#123;</span>macaw.solutionsfactory.assemblycache<span style="color: #000000;">&#125;</span><span style="color: #000000;">&#91;</span><span style="color: #800080;">$cacheKey</span><span style="color: #000000;">&#93;</span>
    <span style="color: #0000FF;">if</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #800080;">$cachedAssembly</span> <span style="color: #FF0000;">-eq</span> <span style="color: #800080;">$null</span><span style="color: #000000;">&#41;</span> <span style="color: #FF0000;">-or</span> <span style="color: #800080;">$forceCompile</span><span style="color: #000000;">&#41;</span>
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0000FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$code</span> <span style="color: #FF0000;">-eq</span> <span style="color: #800000;">''</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #800080;">$code</span> <span style="color: pink;">=</span> <span style="color: #000000;">&#91;</span>System.IO.File<span style="color: #000000;">&#93;</span>::ReadAllText<span style="color: #000000;">&#40;</span><span style="color: #800080;">$file</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#125;</span>
        <span style="color: #008080; font-weight: bold;">Write-Verbose</span> <span style="color: #800000;">&quot;Compiling C# code:<span style="color: #008080; font-weight: bold;">`r</span><span style="color: #008080; font-weight: bold;">`n</span>$code<span style="color: #008080; font-weight: bold;">`r</span><span style="color: #008080; font-weight: bold;">`n</span>&quot;</span>
&nbsp;
        <span style="color: #008000;"># Obtains an ICodeCompiler from a CodeDomProvider class.</span>
        <span style="color: #800080;">$provider</span> <span style="color: pink;">=</span> <span style="color: #008080; font-weight: bold;">New-Object</span> Microsoft.CSharp.CSharpCodeProvider 
&nbsp;
        <span style="color: #008000;"># Get the location for System.Management.Automation DLL</span>
        <span style="color: #800080;">$dllName</span> <span style="color: pink;">=</span> <span style="color: #000000;">&#91;</span><span style="color: #008080;">PsObject</span><span style="color: #000000;">&#93;</span>.Assembly.Location
&nbsp;
        <span style="color: #008000;"># Configure the compiler parameters</span>
        <span style="color: #800080;">$compilerParameters</span> <span style="color: pink;">=</span> <span style="color: #008080; font-weight: bold;">New-Object</span> System.CodeDom.Compiler.CompilerParameters 
&nbsp;
        <span style="color: #800080;">$assemblies</span> <span style="color: pink;">=</span> <span style="color: pink;">@</span><span style="color: #000000;">&#40;</span><span style="color: #800000;">&quot;System.dll&quot;</span><span style="color: pink;">,</span> <span style="color: #800080;">$dllName</span><span style="color: #000000;">&#41;</span>
        <span style="color: #800080;">$compilerParameters</span>.ReferencedAssemblies.AddRange<span style="color: #000000;">&#40;</span><span style="color: #800080;">$assemblies</span><span style="color: #000000;">&#41;</span>
        <span style="color: #800080;">$compilerParameters</span>.ReferencedAssemblies.AddRange<span style="color: #000000;">&#40;</span><span style="color: #800080;">$reference</span><span style="color: #000000;">&#41;</span>
        <span style="color: #800080;">$compilerParameters</span>.IncludeDebugInformation <span style="color: pink;">=</span> <span style="color: #800080;">$true</span>
        <span style="color: #800080;">$compilerParameters</span>.GenerateInMemory <span style="color: pink;">=</span> <span style="color: #800080;">$true</span> 
&nbsp;
        <span style="color: #008000;"># Invokes compilation.</span>
        <span style="color: #800080;">$compilerResults</span> <span style="color: pink;">=</span> <span style="color: #800080;">$provider</span>.CompileAssemblyFromSource<span style="color: #000000;">&#40;</span><span style="color: #800080;">$compilerParameters</span><span style="color: pink;">,</span> <span style="color: #800080;">$code</span><span style="color: #000000;">&#41;</span>
&nbsp;
        <span style="color: #008000;"># Write any errors if generated.</span>
        <span style="color: #0000FF;">if</span><span style="color: #000000;">&#40;</span><span style="color: #800080;">$compilerResults</span>.Errors.Count <span style="color: #FF0000;">-gt</span> <span style="color: #804000;">0</span><span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            <span style="color: #800080;">$errorLines</span> <span style="color: pink;">=</span> <span style="color: #800000;">&quot;&quot;</span>
            <span style="color: #0000FF;">foreach</span><span style="color: #000000;">&#40;</span><span style="color: #800080;">$error</span> <span style="color: #0000FF;">in</span> <span style="color: #800080;">$compilerResults</span>.Errors<span style="color: #000000;">&#41;</span>
            <span style="color: #000000;">&#123;</span>
                <span style="color: #800080;">$errorLines</span> <span style="color: pink;">+=</span> <span style="color: #800000;">&quot;<span style="color: #008080; font-weight: bold;">`n</span><span style="color: #008080; font-weight: bold;">`t</span>&quot;</span> <span style="color: pink;">+</span> <span style="color: #800080;">$error</span>.Line <span style="color: pink;">+</span> <span style="color: #800000;">&quot;:<span style="color: #008080; font-weight: bold;">`t</span>&quot;</span> <span style="color: pink;">+</span> <span style="color: #800080;">$error</span>.ErrorText
            <span style="color: #000000;">&#125;</span>
            <span style="color: #008080; font-weight: bold;">Write-Error</span> <span style="color: #800080;">$errorLines</span>
        <span style="color: #000000;">&#125;</span>
        <span style="color: #008000;"># There were no errors.  Store the resulting assembly in the cache.</span>
        <span style="color: #0000FF;">else</span>
        <span style="color: #000000;">&#123;</span>
            $<span style="color: #000000;">&#123;</span>macaw.solutionsfactory.assemblycache<span style="color: #000000;">&#125;</span><span style="color: #000000;">&#91;</span><span style="color: #800080;">$cacheKey</span><span style="color: #000000;">&#93;</span> <span style="color: pink;">=</span> <span style="color: #800080;">$compilerResults</span>.CompiledAssembly
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #800080;">$cachedAssembly</span> <span style="color: pink;">=</span> $<span style="color: #000000;">&#123;</span>macaw.solutionsfactory.assemblycache<span style="color: #000000;">&#125;</span><span style="color: #000000;">&#91;</span><span style="color: #800080;">$cacheKey</span><span style="color: #000000;">&#93;</span>
    <span style="color: #000000;">&#125;</span>
&nbsp;
    <span style="color: #008000;"># Prevent type mismatch issues caused by PowerShell wrapping of managed objects in PSObject.</span>
    <span style="color: #008000;"># We need to explicitly unwrap those objects because otherwise the .NET reflection classes will</span>
    <span style="color: #008000;"># not find the constructor or method whose signature matches the specified parameters.</span>
    <span style="color: #008000;"># This unwrapping eliminates the need to always wrap all your parameters in @() and to explicitly</span>
    <span style="color: #008000;"># cast each parameter to the correct type in each call to InvokeCSharp.</span>
    <span style="color: #0000FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$parameters</span> <span style="color: #FF0000;">-ne</span> <span style="color: #800080;">$null</span><span style="color: #000000;">&#41;</span>
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0000FF;">for</span><span style="color: #000000;">&#40;</span><span style="color: #800080;">$i</span> <span style="color: pink;">=</span> <span style="color: #804000;">0</span>; <span style="color: #800080;">$i</span> <span style="color: #FF0000;">-lt</span> <span style="color: #800080;">$parameters</span>.Length; <span style="color: #800080;">$i</span><span style="color: pink;">++</span><span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            <span style="color: #800080;">$parameters</span><span style="color: #000000;">&#91;</span><span style="color: #800080;">$i</span><span style="color: #000000;">&#93;</span> <span style="color: pink;">=</span> <span style="color: #000000;">&#91;</span>System.Management.Automation.LanguagePrimitives<span style="color: #000000;">&#93;</span>::ConvertTo<span style="color: #000000;">&#40;</span> `
                <span style="color: #800080;">$parameters</span><span style="color: #000000;">&#91;</span><span style="color: #800080;">$i</span><span style="color: #000000;">&#93;</span><span style="color: pink;">,</span> `
                <span style="color: #000000;">&#91;</span>System.<span style="color: #008080; font-weight: bold;">Type</span><span style="color: #000000;">&#93;</span>::GetType<span style="color: #000000;">&#40;</span><span style="color: #800080;">$parameters</span><span style="color: #000000;">&#91;</span><span style="color: #800080;">$i</span><span style="color: #000000;">&#93;</span>.GetType<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>.FullName<span style="color: #000000;">&#41;</span> `
            <span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#125;</span>
    <span style="color: #000000;">&#125;</span>
&nbsp;
    <span style="color: #0000FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$method</span> <span style="color: #FF0000;">-eq</span> <span style="color: #800000;">''</span><span style="color: #000000;">&#41;</span> <span style="color: #008000;"># We return the assembly</span>
    <span style="color: #000000;">&#123;</span>
        <span style="color: #800080;">$result</span> <span style="color: pink;">=</span> <span style="color: #800080;">$cachedAssembly</span>
    <span style="color: #000000;">&#125;</span>
    <span style="color: #0000FF;">elseif</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$method</span> <span style="color: #FF0000;">-eq</span> <span style="color: #800000;">'()'</span><span style="color: #000000;">&#41;</span> <span style="color: #008000;"># We create and return a class instance</span>
    <span style="color: #000000;">&#123;</span>
        <span style="color: #800080;">$result</span> <span style="color: pink;">=</span> <span style="color: #800080;">$cachedAssembly</span>.CreateInstance<span style="color: #000000;">&#40;</span><span style="color: #800080;">$class</span><span style="color: pink;">,</span> <span style="color: #800080;">$false</span><span style="color: pink;">,</span> <span style="color: #000000;">&#91;</span>System.Reflection.BindingFlags<span style="color: #000000;">&#93;</span>::CreateInstance<span style="color: pink;">,</span> <span style="color: #800080;">$null</span><span style="color: pink;">,</span> <span style="color: #800080;">$parameters</span><span style="color: pink;">,</span> <span style="color: #800080;">$null</span><span style="color: pink;">,</span> <span style="color: pink;">@</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
    <span style="color: #000000;">&#125;</span>
    <span style="color: #0000FF;">else</span> <span style="color: #008000;"># We invoke the method and return the method result</span>
    <span style="color: #000000;">&#123;</span>
        <span style="color: #800080;">$classType</span> <span style="color: pink;">=</span> <span style="color: #800080;">$cachedAssembly</span>.GetType<span style="color: #000000;">&#40;</span><span style="color: #800080;">$class</span><span style="color: #000000;">&#41;</span>
&nbsp;
        <span style="color: #800080;">$parameterTypes</span> <span style="color: pink;">=</span> <span style="color: pink;">@</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
        <span style="color: #0000FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$parameters</span> <span style="color: #FF0000;">-ne</span> <span style="color: #800080;">$null</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #0000FF;">foreach</span><span style="color: #000000;">&#40;</span><span style="color: #800080;">$p</span> <span style="color: #0000FF;">in</span> <span style="color: #800080;">$parameters</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #800080;">$parameterTypes</span> <span style="color: pink;">+=</span> <span style="color: #800080;">$p</span>.GetType<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#125;</span> <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #800080;">$methodInfo</span> <span style="color: pink;">=</span> <span style="color: #800080;">$classType</span>.GetMethod<span style="color: #000000;">&#40;</span><span style="color: #800080;">$method</span><span style="color: pink;">,</span> <span style="color: #000000;">&#91;</span>System.<span style="color: #008080; font-weight: bold;">Type</span><span style="color: #000000;">&#91;</span><span style="color: #000000;">&#93;</span><span style="color: #000000;">&#93;</span><span style="color: #800080;">$parameterTypes</span><span style="color: #000000;">&#41;</span>
        <span style="color: #0000FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$methodInfo</span>.IsStatic<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            <span style="color: #800080;">$instance</span> <span style="color: pink;">=</span> <span style="color: #800080;">$null</span>
        <span style="color: #000000;">&#125;</span>
        <span style="color: #0000FF;">else</span>
        <span style="color: #000000;">&#123;</span>
            <span style="color: #800080;">$instance</span> <span style="color: pink;">=</span> <span style="color: #800080;">$cachedAssembly</span>.CreateInstance<span style="color: #000000;">&#40;</span><span style="color: #800080;">$class</span><span style="color: pink;">,</span> <span style="color: #800080;">$false</span><span style="color: pink;">,</span> <span style="color: #000000;">&#91;</span>System.Reflection.BindingFlags<span style="color: #000000;">&#93;</span>::CreateInstance<span style="color: pink;">,</span> <span style="color: #800080;">$null</span><span style="color: pink;">,</span> <span style="color: #800080;">$null</span><span style="color: pink;">,</span> <span style="color: #800080;">$null</span><span style="color: pink;">,</span> <span style="color: pink;">@</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#125;</span>
        <span style="color: #800080;">$result</span> <span style="color: pink;">=</span> <span style="color: #800080;">$methodInfo</span>.Invoke<span style="color: #000000;">&#40;</span><span style="color: #800080;">$instance</span><span style="color: pink;">,</span> <span style="color: #800080;">$parameters</span><span style="color: #000000;">&#41;</span>;
    <span style="color: #000000;">&#125;</span>
&nbsp;
   <span style="color: #0000FF;">return</span> <span style="color: #800080;">$result</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://vincenth.net/blog/archive/2009/10/27/call-inline-c-from-powershell-with-invokecsharp.aspx/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

