<?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>WinSoft.se &#187; PowerShell</title>
	<atom:link href="http://www.winsoft.se/category/dotnet/powershell/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.winsoft.se</link>
	<description>Development with focus on Visual Basic .NET</description>
	<lastBuildDate>Thu, 26 Jan 2012 19:28:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Reading out SQL Data with named columns</title>
		<link>http://www.winsoft.se/2011/12/reading-out-sql-data-with-named-columns/</link>
		<comments>http://www.winsoft.se/2011/12/reading-out-sql-data-with-named-columns/#comments</comments>
		<pubDate>Fri, 02 Dec 2011 16:39:13 +0000</pubDate>
		<dc:creator>Anders Hesselbom</dc:creator>
				<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://www.winsoft.se/?p=1794</guid>
		<description><![CDATA[This code reads out names from the Employees table of the Northwind database. You must correct the Data Source property in the connection string for it to run. #Create a connection object and open it. [String]$cns="Data Source=XXX;Initial Catalog=Northwind; Integrated Security=True" [System.Data.SqlClient.SqlConnection]$connection=New-Object -TypeName System.Data.SqlClient.SqlConnection -ArgumentList $cns $connection.Open() #Create a command and execute it. [String]$query="SELECT FirstName, LastName [...]]]></description>
			<content:encoded><![CDATA[<p>This code reads out names from the Employees table of the Northwind database. You must correct the Data Source property in the connection string for it to run.</p>
<pre class="csharpcode">
#Create a connection <span class="kwrd">object</span> and open it.
[String]$cns=<span class="str">"Data Source=XXX;Initial Catalog=Northwind;
   Integrated Security=True"</span>
[System.Data.SqlClient.SqlConnection]$connection=New-Object
   -TypeName System.Data.SqlClient.SqlConnection -ArgumentList $cns
$connection.Open()

#Create a command and execute it.
[String]$query=<span class="str">"SELECT FirstName, LastName
   FROM dbo.Employees ORDER BY LastName, FirstName"</span>
[System.Data.SqlClient.SqlCommand]$command=New-Object
   -TypeName System.Data.SqlClient.SqlCommand
$command.Connection=$connection
$command.CommandText=$query
$r=$command.ExecuteReader()

#Iterate the result.
<span class="kwrd">while</span>($r.Read()) {

    #Read <span class="kwrd">out</span> first name.
    [String]$firstname=<span class="str">""</span>
    <span class="kwrd">if</span>( -not $r.IsDBNull(0)) {
        $firstname=$r.GetString(0)
    }

    #Read <span class="kwrd">out</span> last name.
    [String]$lastname=<span class="str">""</span>
    <span class="kwrd">if</span>( -not $r.IsDBNull(1)) {
        $lastname=$r.GetString(1)
    }

    #Display.
    Write-Output ($firstname + <span class="str">" "</span> + $lastname)
}

#Close the reader.
$r.Close()

$connection.Close()
$connection.Dispose()</pre>
<p>Here I use column indexes when referring to columns. A change in the SQL query will produce errors in the code that reads out the result. The solution is to call the GetOrdinal function of the reader to get the indexes of the columns, like this:</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode">
#Create a connection <span class="kwrd">object</span> and open it.
[String]$cns=<span class="str">"Data Source=XXX;Initial Catalog=Northwind;
   Integrated Security=True"</span>
[System.Data.SqlClient.SqlConnection]$connection=New-Object
   -TypeName System.Data.SqlClient.SqlConnection -ArgumentList $cns
$connection.Open()

#Create a command and execute it.
[String]$query=<span class="str">"SELECT FirstName, LastName
   FROM dbo.Employees ORDER BY LastName, FirstName"</span>
[System.Data.SqlClient.SqlCommand]$command=New-Object
   -TypeName System.Data.SqlClient.SqlCommand
$command.Connection=$connection
$command.CommandText=$query
$r=$command.ExecuteReader()

#Get use named columns.
[<span class="kwrd">int</span>]$Index_FirstName=$r.GetOrdinal(<span class="str">"FirstName"</span>)
[<span class="kwrd">int</span>]$Index_LastName=$r.GetOrdinal(<span class="str">"LastName"</span>)

#Iterate the result.
<span class="kwrd">while</span>($r.Read()) {

    #Read <span class="kwrd">out</span> first name.
    [String]$firstname=<span class="str">""</span>
    <span class="kwrd">if</span>( -not $r.IsDBNull($Index_FirstName)) {
        $firstname=$r.GetString($Index_FirstName)
    }

    #Read <span class="kwrd">out</span> last name.
    [String]$lastname=<span class="str">""</span>
    <span class="kwrd">if</span>( -not $r.IsDBNull($Index_LastName)) {
        $lastname=$r.GetString($Index_LastName)
    }

    #Display.
    Write-Output ($firstname + <span class="str">" "</span> + $lastname)
}

#Close the reader.
$r.Close()

$connection.Close()
$connection.Dispose()
</pre>
<p>Now, if you change the the query, the reader will still find the desired columns.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.winsoft.se/2011/12/reading-out-sql-data-with-named-columns/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The shortest code you need to draw vector graphics</title>
		<link>http://www.winsoft.se/2011/07/the-shortest-code-you-need-to-draw-vector-graphics/</link>
		<comments>http://www.winsoft.se/2011/07/the-shortest-code-you-need-to-draw-vector-graphics/#comments</comments>
		<pubDate>Sat, 16 Jul 2011 20:42:17 +0000</pubDate>
		<dc:creator>Anders Hesselbom</dc:creator>
				<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://www.winsoft.se/?p=1715</guid>
		<description><![CDATA[This example shows the shortest code you need to draw vector graphics in PowerShell. However, this code demonstrates a problem rather than a solution. The .NET Framework wants you to inherit a Form class when you describe a picture, because you will need to be able to access protected properties and to respond to events. [...]]]></description>
			<content:encoded><![CDATA[<p>This example shows the shortest code you need to draw vector graphics in PowerShell. However, this code demonstrates a problem rather than a solution. The .NET Framework wants you to inherit a Form class when you describe a picture, because you will need to be able to access protected properties and to respond to events. But since the CreateGraphics function is public, you can still do some hacking with an instance of a Form class. This code creates a window, draws an X on it, and leaves it visible for 5 seconds.</p>
<pre>#Load the Windows Forms library.
[string]$WindowsFormsLibrary =
"System.Windows.Forms,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089"
[System.Reflection.Assembly]::Load($WindowsFormsLibrary)

#Load the Drawing library.
[string]$DrawingLibrary =
"System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
[System.Reflection.Assembly]::Load($DrawingLibrary)

#Create a window, and set its properties.
[System.Windows.Forms.Form]$f = New-Object System.Windows.Forms.Form
$f.Width = 500
$f.Height = 300

#Display the form.
$f.Show()
#Force a complete draw before we add any graphics.
$f.Refresh()

#Acquire the graphics interface.
[System.Drawing.Graphics]$g = $f.CreateGraphics()

#Draw anything you like here using GDI+.
$g.DrawLine([System.Drawing.Pens]::Black, 50, 20, 450, 250)
$g.DrawLine([System.Drawing.Pens]::Black, 450, 20, 50, 250)

#Dispose the graphics interface.
$g.Dispose()

#Wait for 5 seconds before closing it all down.
Start-Sleep -s 5
$f.Close()
$f.Dispose()</pre>
<p>If we take the trouble to create a custom type based on the Form class, we can create form has double buffering enabled by definition, and is of correct size by definition. The size can be set from outside the form as shown above, but the DoubleBuffered property that controls double buffering could not. So by just replacing the predefined Form class with a custom extension, we are slightly closer to our goal.</p>
<pre>#Load the Windows Forms library.
[string]$WindowsFormsLibrary =
"System.Windows.Forms,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089"
[System.Reflection.Assembly]::Load($WindowsFormsLibrary)

#Load the Drawing library.
[string]$DrawingLibrary =
"System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
[System.Reflection.Assembly]::Load($DrawingLibrary)

<b>#Create a custom form with double buffering.
$Refs = @("System.Windows.Forms", "System.Drawing")
Add-Type -ReferencedAssemblies $Refs @'
public class MyGraphicsForm:System.Windows.Forms.Form
{
   private System.ComponentModel.IContainer components = null;

   protected override void Dispose(bool disposing)
   {
      if (disposing &amp;&amp; (components != null))
      {
         components.Dispose();
      }
      base.Dispose(disposing);
   }

   private void InitializeComponent()
   {
      this.SuspendLayout();
      this.ClientSize = new System.Drawing.Size(500, 300);
      this.DoubleBuffered = true;
      this.Text = "My graphics form";
      this.ResumeLayout(false);

   }
}
'@

#Create our custom window.
[System.Windows.Forms.Form]$f = New-Object MyGraphicsForm</b>

#Display the form.
$f.Show()
#Force a complete draw before we add any graphics.
$f.Refresh()

#Acquire the graphics interface.
[System.Drawing.Graphics]$g = $f.CreateGraphics()

#Draw anything you like here using GDI+.
$g.DrawLine([System.Drawing.Pens]::Black, 50, 20, 450, 250)
$g.DrawLine([System.Drawing.Pens]::Black, 450, 20, 50, 250)

#Dispose the graphics interface.
$g.Dispose()

#Wait for 5 seconds before closing it all down.
Start-Sleep -s 5
$f.Close()
$f.Dispose()</pre>
<p>To be continued.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.winsoft.se/2011/07/the-shortest-code-you-need-to-draw-vector-graphics/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Piping objects</title>
		<link>http://www.winsoft.se/2011/06/piping-objects/</link>
		<comments>http://www.winsoft.se/2011/06/piping-objects/#comments</comments>
		<pubDate>Wed, 29 Jun 2011 09:48:26 +0000</pubDate>
		<dc:creator>Anders Hesselbom</dc:creator>
				<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://www.winsoft.se/?p=1706</guid>
		<description><![CDATA[If you want to create and run a ps1 script, make sure to give yourself the permission to execute scripts. If you are running a newer operating system, you must start PowerShell as an administrator the time that you grant yourself the right to run scripts. When you type DIR, a list of DirectoryInfo and/or [...]]]></description>
			<content:encoded><![CDATA[<p>If you want to create and run a ps1 script, make sure to <a href="http://www.winsoft.se/2008/12/download-powershell-and-activate-scripting/">give yourself the permission to execute scripts</a>. If you are running a newer operating system, you must start PowerShell as an administrator the time that you grant yourself the right to run scripts.</p>
<p>When you type <strong>DIR</strong>, a list of <strong>DirectoryInfo</strong> and/or <strong>FileInfo</strong> objects are created and sent to the script host. Each object, no matter type, are displayed as strings, meaning that the directory name or file name is displayed. How ever, you can use the pipeline to access actual objects. I have some directories and a few files in my C root, so if I pipe the output from the <strong>DIR</strong> command to an iteration that displays the object&#8217;s type name, like so:</p>
<pre>DIR C:\ | ForEach-Object { Write-Host $_.GetType().Name }</pre>
<p>From that I will get the word <strong>DirectoryInfo</strong> for each directory and the word <strong>FileInfo</strong> for each file in my C root. These are the .NET classes that represent directories and files. Since the PowerShell pipeline actually is handling objects, you can use these objects by accessing the properties or calling the functions of each object. A simple task such as displaying the number of files in each directory, is a walk in the park, when the actual object you need to do this, already is in the pipeline.</p>
<pre>DIR C:\ | ForEach-Object {
If ($_.GetType().Name -like "DirectoryInfo")
   {
      Write-Host $_.Name "(" $_.GetDirectories().Length
         " dirs and " $_.GetFiles().Length " files.)"
   }
}</pre>
<p>The output for this, is the name of the directory and the number of child directories and files that it holds. I can see that my Windows folder holds 66 directories and 45 files.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.winsoft.se/2011/06/piping-objects/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PowerShell functions argument catching</title>
		<link>http://www.winsoft.se/2011/04/powershell-functions-argument-catching/</link>
		<comments>http://www.winsoft.se/2011/04/powershell-functions-argument-catching/#comments</comments>
		<pubDate>Sat, 09 Apr 2011 19:05:36 +0000</pubDate>
		<dc:creator>Anders Hesselbom</dc:creator>
				<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://www.winsoft.se/?p=1649</guid>
		<description><![CDATA[PowerShell is not very object oriented. The support for creating classes is implemented through the Add-Type cmdlet that takes C# code. Here I show how to use Add-Type to define and expose classes that use any part of the .NET Framework. These classes can then be instantiated using the New-Object cmdlet. Functions are defined using [...]]]></description>
			<content:encoded><![CDATA[<p>PowerShell is not very object oriented. The support for creating classes is implemented through the <strong>Add-Type</strong> cmdlet that takes C# code. <a href="http://www.winsoft.se/2011/02/adding-references-to-custom-types/">Here</a> I show how to use <strong>Add-Type</strong> to define and expose classes that use any part of the .NET Framework. These classes can then be instantiated using the <strong>New-Object</strong> cmdlet.</p>
<p>Functions are defined using the <strong>function</strong> keyword. This code defines a function that doesn&#8217;t require any arguments:</p>
<pre>#Define a function.
function DoSomething()
{
   Write-Output "Hello!"
}

#Call a function.
DoSomething</pre>
<p>When defining parameters, you can choose what parameters that need to be strongly typed by adding the desired type name in front of the parameter. Here I have 3 calls to the <strong>TwoParams</strong> function. The first parameter can be anything, but the second must be and int. Both call 1 and call 2 will run, becase <strong>$a</strong> can accept a string or an int. Call 3 will fail because <strong>$b</strong> cannot be a string.</p>
<pre>function TwoParams($a, [int]$b)
{
	$b = $b + 1
	Write-Output "a=$a"
	Write-Output "b=$b"
}

#Two correct calls.
Write-Output "Call 1"
TwoParams "Hello!" 10

Write-Output "Call 2"
TwoParams 20 20

Write-Output "Call 3 will fail!"
TwoParams 30 "Hello!"</pre>
<p>Default values can be provided, so that omitted arguments still will have a value. In this case, it is assumed that the values 1 and 2 is passed to the function. All parameters are passed by value.</p>
<pre>function TestingDefaults($a=1, $b=2)
{
	Write-Output "$a $b"
}

TestingDefaults</pre>
<p>Now, let&#8217;s look at the strange things. All arguments that are sent in, but not declared in the function head, will be captured by the <strong>$args</strong> array. In this case, <strong>$args</strong> in <strong>SomeFunction</strong> will contain 4 elements, because 4 arguments are sent:</p>
<pre>function SomeFunction()
{
	$NumberOfArguments=$args.length
	Write-Output "You gave me $NumberOfArguments arguments."
}

SomeFunction "10" "Hej" 5 10</pre>
<p>But here, still 4 arguments are sent, but the first argument is declared, so that only 3 arguments are catched by the <strong>$args</strong> array:</p>
<pre>function SomeFunction($x)
{
	$NumberOfArguments=$args.length
	Write-Output "You gave me $NumberOfArguments arguments."
}

SomeFunction "10" "Hej" 5 10</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.winsoft.se/2011/04/powershell-functions-argument-catching/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PowerShell knows about your USB devices</title>
		<link>http://www.winsoft.se/2011/03/powershell-knows-about-your-usb-devices/</link>
		<comments>http://www.winsoft.se/2011/03/powershell-knows-about-your-usb-devices/#comments</comments>
		<pubDate>Wed, 02 Mar 2011 17:30:14 +0000</pubDate>
		<dc:creator>Anders Hesselbom</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[USB]]></category>

		<guid isPermaLink="false">http://www.winsoft.se/?p=1591</guid>
		<description><![CDATA[One of many things you can do with the Management assembly is to get the USB devices that is currently connected to your computer. To load the Management assembly, use this line of code (no line break here): [System.Reflection.Assembly]::Load("System.Management, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a") The class you want to create an instance from is called ManagementClass, and [...]]]></description>
			<content:encoded><![CDATA[<p>One of many things you can do with the <strong>Management</strong> assembly is to get the USB devices that is currently connected to your computer. To load the <strong>Management</strong> assembly, use this line of code (no line break here):</p>
<pre>[System.Reflection.Assembly]::Load("System.Management, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")</pre>
<p>The class you want to create an instance from is called <strong>ManagementClass</strong>, and to its constructor you pass the management path that you want to use. USB devices are located in the <strong>Win32_USBHub</strong> path, so that is the argument that I pass to the constructor.</p>
<pre>$Man = New-Object System.Management.ManagementClass("Win32_USBHub")</pre>
<p>The <strong>GetInstances</strong> function returns a collection of objects, each object representing a device that actually is connected. Just for being crazy, I will make my target variable type safe.</p>
<pre>[System.Management.ManagementObjectCollection]$Devs = $Man.GetInstances()</pre>
<p>Now I can use <strong>ForEach-Obect</strong> cmdlet to iterate through the collection. For each device, I will write out the name of the device, the system ID and a blank line.</p>
<pre>$Devs | ForEach-Object {
	Write-Output $_.GetPropertyValue("Name").ToString()
	Write-Output $_.GetPropertyValue("DeviceID").ToString()
	Write-Output ""
}</pre>
<p>Finally, I have to free the resouces I have used.</p>
<pre>$Devs.Dispose()
$Man.Dispose()</pre>
<p>When you run this code, you should see a list of devices that is registered as connected to your machine, including the USB hubs. If you connect a device and run the script again, that device will show up in the list. With this code as base, you could easily write programs that detects changes to the list. That is, programs that detects when a new device is added or removed. The last item should be the device you inserted while your computer was running, and the first items are the devices that were available at system startup.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.winsoft.se/2011/03/powershell-knows-about-your-usb-devices/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Adding references to custom types</title>
		<link>http://www.winsoft.se/2011/02/adding-references-to-custom-types/</link>
		<comments>http://www.winsoft.se/2011/02/adding-references-to-custom-types/#comments</comments>
		<pubDate>Sun, 20 Feb 2011 17:33:07 +0000</pubDate>
		<dc:creator>Anders Hesselbom</dc:creator>
				<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://www.winsoft.se/?p=1588</guid>
		<description><![CDATA[In a great number of blog posts, I have used the Load function of System.Reflection.Assembly to load types from the .NET Framework. This (without line break) is an example that gives you access to the Forms library&#8230; [System.Reflection.Assembly]::Load("System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") &#8230;so that calls like this is possible: [System.Windows.Forms.MessageBox]::Show("Hello!") (To see the available assemblies, check [...]]]></description>
			<content:encoded><![CDATA[<p>In a great number of blog posts, I have used the Load function of <strong>System.Reflection.Assembly</strong> to load types from the .NET Framework. This (without line break) is an example that gives you access to the Forms library&#8230;</p>
<pre>[System.Reflection.Assembly]::Load("System.Windows.Forms, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089")</pre>
<p>&#8230;so that calls like this is possible:</p>
<pre>[System.Windows.Forms.MessageBox]::Show("Hello!")</pre>
<p>(To see the available assemblies, check the <strong>assembly</strong> folder in your <strong>Windows</strong> folder.)</p>
<p>When you use the <strong>Add-Type</strong> cmdlet to create your own types, the string that describes the type might need references as well. The required assemblies are specified in an array, and passed to the cmdlet as the <strong>-ReferencedAssemblies</strong> argument. This code adds a custom type&#8230;</p>
<pre>$references = @("System.Windows.Forms")
Add-Type -ReferencedAssemblies $references @'
public class Test
{
   public void hej()
   {
      System.Windows.Forms.MessageBox.Show("Hello!");
   }
}
'@</pre>
<p>&#8230;gives you a code that when invoked, does the same thing:</p>
<pre>$test = New-Object Test
$test.hej()</pre>
<p>The problem will show up if you have made any changes to your type and run your program again. The type called Test will already be loaded, so the <strong>Add-Type</strong> cmdlet will fail.</p>
<p>(If you run your program again, without changing your custom type definition, <strong>Add-Type</strong> will just be ignored &#8211; your type is there and everything is fine.)</p>
<p>Since types cannot be unloaded, you will need to unload your entire appdomain, and the easiest way to do this, is to close your PowerShell window. So any changes to a custom type, will be reflected in a new instance of PowerShell, thus in a new appdomain.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.winsoft.se/2011/02/adding-references-to-custom-types/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Calling C functions</title>
		<link>http://www.winsoft.se/2011/02/calling-c-functions/</link>
		<comments>http://www.winsoft.se/2011/02/calling-c-functions/#comments</comments>
		<pubDate>Mon, 07 Feb 2011 21:15:45 +0000</pubDate>
		<dc:creator>Anders Hesselbom</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Windows API]]></category>

		<guid isPermaLink="false">http://www.winsoft.se/?p=1575</guid>
		<description><![CDATA[Like I mentioned earlier, functions that only are exposed through an external .NET interface are unreachable from PowerShell, but can be called using reflection. But how about C functions? This is not a problem at all. Like always when you attempt to call a C function in a DLL, you must know how it is [...]]]></description>
			<content:encoded><![CDATA[<p>Like I mentioned <a href="http://www.winsoft.se/2011/01/create-an-exe-using-powershell/">earlier</a>, functions that only are exposed through an external .NET interface are unreachable from PowerShell, but can be called using reflection. But how about C functions?</p>
<p><img alt="" src="http://imghost.winsoft.se/upload/614761297114088ps.jpg" class="aligncenter" width="496" height="334" /></p>
<p>This is not a problem at all. Like always when you attempt to call a C function in a DLL, you must know how it is exposed. This is not unique for PowerShell. The name of the link library, the name of the entry point, and the parameter types. This gives you a huge number of functionality ready to call, including third party libraries and the <a href="http://msdn.microsoft.com/en-us/library/aa383749%28v=vs.85%29.aspx" target="_blank">Windows API</a>.</p>
<p>I am going to use PowerShell to move the mouse cursor to location 100, 100 (left, top). The <strong>SetCursorPos</strong> function takes two integer values (X and Y) and returns a boolean. According to the Windows API documentation, the function resides in a library called <strong>User32.dll</strong>.</p>
<p>One way to do this, is to <a href="http://www.winsoft.se/2011/01/create-an-exe-using-powershell/">write Visual Basic code, use PowerShell to compile it</a> to an assembly, and then use reflection to call it. But there is another way.</p>
<p>Create one array of arguments, and an array of argument types. In my case, since I&#8217;m calling the <strong>SetCursorPos</strong> function, this is what I need:</p>
<pre>$parameterTypes = [UInt32], [UInt32]
$parameters = 100, 100</pre>
<p>Then, the rest of the code is something written by <a href="http://groups.google.com/group/microsoft.public.windows.server.scripting/tree/browse_frm/thread/119e0fa82488d979/210252657306e4aa?rnum=1&amp;hl=en&amp;_done=/group/microsoft.public.windows.server.scripting/browse_frm/thread/119e0fa82488d979/76ff3029b9b269cb?lnk%3Dst%26q%3D%26rnum%3D1%26hl%3Den%26&amp;pli=1" target="_blank">Jouko Kynsijärvi</a>, that <a href="http://www.leeholmes.com/blog/2006/07/21/get-the-owner-of-a-process-in-powershell-%E2%80%93-pinvoke-and-refout-parameters/" target="_blank">Lee Holmes</a> used to make the <strong>Invoke-Win32</strong> function. This is my complete code. Three lines! Check this out!</p>
<pre>#The parameter types.
$parameterTypes = [Int], [Int]

#The arguments.
$parameters = 100, 100

#The call. Library, return type, function name, types and values.
Invoke-Win32 "User32.dll" ([Bool]) "SetCursorPos" $parameterTypes $parameters</pre>
<p>The rest of the listing is the definition of the <strong>Invoke-Win32</strong> function that I extracted from this <a href="http://www.leeholmes.com/blog/2006/07/21/get-the-owner-of-a-process-in-powershell-%E2%80%93-pinvoke-and-refout-parameters/" target="_blank">Lee Holmes&#8217; post</a>.</p>
<p>As you run this script, note how the mouse cursor jumps up to the upper left corner, 100 pixels from the left edge, 100 pixels from the top.</p>
<p>(I have a huge smile across my face when I&#8217;m writing this.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.winsoft.se/2011/02/calling-c-functions/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Create an exe using PowerShell</title>
		<link>http://www.winsoft.se/2011/01/create-an-exe-using-powershell/</link>
		<comments>http://www.winsoft.se/2011/01/create-an-exe-using-powershell/#comments</comments>
		<pubDate>Thu, 06 Jan 2011 17:52:59 +0000</pubDate>
		<dc:creator>Anders Hesselbom</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Reflection]]></category>

		<guid isPermaLink="false">http://www.winsoft.se/?p=1552</guid>
		<description><![CDATA[This is, from what I know, the lest code you will need to write, to make PowerShell create a exe-file that do what you want it to do. It uses the VB compiler that is installed together with the .NET Framework together with the VB-specific CreateCompiler function, also installed with the .NET Framework. Before you [...]]]></description>
			<content:encoded><![CDATA[<p>This is, from what I know, the lest code you will need to write, to make PowerShell create a exe-file that do what you want it to do. It uses the VB compiler that is installed together with the .NET Framework together with the VB-specific <strong>CreateCompiler</strong> function, also installed with the .NET Framework.</p>
<p>Before you run it, make sure that the folder you write your exe to really exists. In my case, C:\temp.</p>
<p>First, let&#8217;s load an assembly. Remember, no line breaks here.</p>
<pre>#Load the Visual Basic assembly go get the code
#that creates a compiler.
[System.Reflection.Assembly]::Load("Microsoft.VisualBasic, Version=8.0.0.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")</pre>
<p>Then we create the objects we need. The second line will cause some problems. The object returned by the <strong>CreateCompiler</strong> function has a method that isn&#8217;t exposed, so we can&#8217;t call it directly. Also note that we are specifying an output path here.</p>
<pre>$VB = New-Object Microsoft.VisualBasic.VBCodeProvider
$Compiler = $VB.CreateCompiler()
$Params = New-Object System.CodeDom.Compiler.CompilerParameters
$Params.GenerateExecutable = $true
$Params.OutputAssembly = "C:\temp\myprogram.exe"</pre>
<p>This is the code I want in my exe:</p>
<pre>[String]$S = "Imports System`n"
$S = $S + "Module MyModule`n"
$S = $S + "Sub Main(ByVal Args() As String)`n"
$S = $S + "Console.WriteLine(`"Hello! Press Enter!`")`n"
$S = $S + "Console.ReadLine()`n"
$S = $S + "End Sub`n"
$S = $S + "End Module`n"</pre>
<p>Now, I must use reflection to call the unexposed method. In C# or VB, this is not a problem because we can use interfaces. PowerShell can&#8217;t. Since the method expects two arguments, I will create an array with the two elements. Then, the <strong>Invoke</strong> method takes the object where the function resides and the arguments. Typing is important so that the correct function overload will be found.</p>
<pre>#Extract the method "CompileAssemblyFromSource". (No line break here!)
$CompileMethod=
[System.CodeDom.Compiler.ICodeCompiler].GetMethod("CompileAssemblyFromSource")

#We must pass in the parameters and the source
#when calling.
$Args = New-Object System.Object[] 2
$Args[0] = [System.CodeDom.Compiler.CompilerParameters]$Params
$Args[1] = $S
$Res = $CompileMethod.Invoke($Compiler, $Args);

$VB.Dispose()</pre>
<p>Now, you have your own executable file that greets you when you start it!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.winsoft.se/2011/01/create-an-exe-using-powershell/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Visual Basic/PowerShell interaction</title>
		<link>http://www.winsoft.se/2010/12/visual-basicpowershell-interaction/</link>
		<comments>http://www.winsoft.se/2010/12/visual-basicpowershell-interaction/#comments</comments>
		<pubDate>Sat, 18 Dec 2010 16:45:28 +0000</pubDate>
		<dc:creator>Anders Hesselbom</dc:creator>
				<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://www.winsoft.se/?p=1514</guid>
		<description><![CDATA[Through the .NET Framework, Visual Basic can talk to PowerShell. If PowerShell is installed, you can add a reference to an assembly named System.Management.Automation. You will have to browse for it, and you will find it here: C:\Program Files\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0 Also, scripting needs to be activated in PowerShell. A RunSpace is a context where PowerShell [...]]]></description>
			<content:encoded><![CDATA[<p>Through the .NET Framework, Visual Basic can talk to PowerShell. If PowerShell is installed, you can add a reference to an assembly named <strong>System.Management.Automation</strong>. You will have to browse for it, and you will find it here:</p>
<p>C:\Program Files\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0</p>
<p>Also, scripting needs to be activated in PowerShell.</p>
<p>A <strong>RunSpace</strong> is a context where PowerShell scripts run. Any variables that are set in one runspace, can be read from that same runspace, but not any other runspace. Before the opening <strong>Using</strong>, I will create a variable (<strong>Result</strong>) that will hold the response from PowerShell.</p>
<pre>Dim Result As _
   System.Collections.ObjectModel.Collection(Of System.Management.Automation.PSObject)

 Using R As System.Management.Automation.Runspaces.Runspace = _
   System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace()</pre>
<p>Next, you open the runspace and create a pipeline.</p>
<pre>R.Open()
Dim P As System.Management.Automation.Runspaces.Pipeline = R.CreatePipeline()</pre>
<p>The pipeline has a <strong>Commands</strong> collection where you add your commands or complete scripts. These two lines will create two output objects.</p>
<pre>P.Commands.Add("C:\test.ps1")</pre>
<p>When you&#8217;re done, you can execute the script using the Invoke function of the pipeline object, and close your runspace. The response is saved in the Result variable I created earlier.</p>
<pre>Result = P.Invoke()
R.Close()
End Using

For Each Res As System.Management.Automation.PSObject In Result
   MessageBox.Show(Res.ToString())
Next</pre>
<p>The content of my script file, <strong>test.ps1</strong>, is:</p>
<pre>Write-Output "Hello!"
$x = 10 + 3
Write-Output $x</pre>
<p>The output of course will be one message box saying <strong>Hello!</strong> and another saying <strong>13</strong>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.winsoft.se/2010/12/visual-basicpowershell-interaction/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Easy archiving of files using PowerShell</title>
		<link>http://www.winsoft.se/2010/12/easy-archiving-of-files-using-powershell/</link>
		<comments>http://www.winsoft.se/2010/12/easy-archiving-of-files-using-powershell/#comments</comments>
		<pubDate>Wed, 15 Dec 2010 18:21:39 +0000</pubDate>
		<dc:creator>Anders Hesselbom</dc:creator>
				<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://www.winsoft.se/?p=1510</guid>
		<description><![CDATA[This example shows easy compressing and archiving of files using the WindowsBase library and PowerShell. This code will use the WindowsBase library to create a ZIP archive from a couple of images. In this example, I am working in the C root, and the files I want to add to my ZIP archive are also [...]]]></description>
			<content:encoded><![CDATA[<p>This example shows easy compressing and archiving of files using the WindowsBase library and PowerShell. This code will use the WindowsBase library to create a ZIP archive from a couple of images. In this example, I am working in the C root, and the files I want to add to my ZIP archive are also located there.</p>
<pre>#Load some assemblys. (No line break!)
[System.Reflection.Assembly]::Load("WindowsBase,
   Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")

#Create a zip file named "MyZipFile.zip". (No line break!)
$ZipPackage=[System.IO.Packaging.ZipPackage]::Open("C:\MyZipFile.zip",
   [System.IO.FileMode]"OpenOrCreate", [System.IO.FileAccess]"ReadWrite")

#The files I want to add to my archive:
$files = @("/Penguins.jpg", "/Lighthouse.jpg")

#For each file you want to add, we must extract the bytes
#and add them to a part of the zip file.
ForEach ($file In $files)
{
   $partName=New-Object System.Uri($file, [System.UriKind]"Relative")
   #Create each part. (No line break!)
   $part=$ZipPackage.CreatePart($partName, "application/zip",
      [System.IO.Packaging.CompressionOption]"Maximum")
   $bytes=[System.IO.File]::ReadAllBytes($file)
   $stream=$part.GetStream()
   $stream.Write($bytes, 0, $bytes.Length)
   $stream.Close()
}

#Close the package when we're done.
$ZipPackage.Close()</pre>
<p>Now, my image files are archived to one ZIP file.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.winsoft.se/2010/12/easy-archiving-of-files-using-powershell/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

