<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>"Captain Literal".NET</title>
	
	<link>http://www.captainliteral.net</link>
	<description>Mark Sheppard's occasional musings about dissimilar technology</description>
	<pubDate>Thu, 08 May 2008 23:29:39 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.2</generator>
	<language>en</language>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/CaptainLiteral" type="application/rss+xml" /><item>
		<title>Windows Server Longhorn (2008) Beta 3 â€“ Installing SQL Server 2005</title>
		<link>http://feedproxy.google.com/~r/CaptainLiteral/~3/7Lye8w-0rpI/</link>
		<comments>http://www.captainliteral.net/2007/06/03/windows-server-longhorn-2008-beta-3-%e2%80%93-installing-sql-server-2005/#comments</comments>
		<pubDate>Sun, 03 Jun 2007 14:19:27 +0000</pubDate>
		<dc:creator>Mark Sheppard</dc:creator>
		
		<category><![CDATA[SQL Server 2005]]></category>

		<category><![CDATA[Windows Server 2008]]></category>

		<category><![CDATA[Windows-Server-Longhorn-Beta-3]]></category>

		<guid isPermaLink="false">http://www.captainliteral.net/2007/06/03/windows-server-longhorn-2008-beta-3-%e2%80%93-installing-sql-server-2005/</guid>
		<description><![CDATA[

If you want to install SQL Server 2005 on Windows Server 2008 (formally Longhorn server), you need to be aware of the process.

Note:  This was worked out on Windows Server Longhorn Beta 3 (build 6001), so procedures may change by the time Windows Server 2008 RTM&#8217;s.

Prerequisites

If you&#8217;re planning on installing SQL Reporting on Windows [...]]]></description>
			<content:encoded><![CDATA[
<!-- ALL ADSENSE ADS DISABLED -->
<p>If you want to install SQL Server 2005 on Windows Server 2008 (formally Longhorn server), you need to be aware of the process.
</p>
<p>Note:  This was worked out on Windows Server Longhorn Beta 3 (build 6001), so procedures may change by the time Windows Server 2008 RTM&#8217;s.
</p>
<p><strong>Prerequisites<br />
</strong></p>
<p>If you&#8217;re planning on installing SQL Reporting on Windows Server 2008, you need to add the IIS Role through server manager and you need the following service components installed:
</p>
<ul>
<li>
<div>Common HTTP Features
</div>
<ul>
<li>Static Content
</li>
<li>Default Document
</li>
<li>HTTP Redirection
</li>
<li>Directory Browsing
</li>
</ul>
</li>
<li>
<div>Application Development
</div>
<ul>
<li>ASP.Net
</li>
<li>ISAPI Extension
</li>
<li>ISAPI Filters
</li>
</ul>
</li>
<li>
<div>Security
</div>
<ul>
<li>Windows Authentication
</li>
</ul>
</li>
<li>
<div>Management Tools
</div>
<ul>
<li>IIS Metabase
</li>
<li>IIS 6 WMI
</li>
</ul>
</li>
</ul>
<p>For more information I suggest that you read <a href="http://blogs.msdn.com/williaml/archive/2006/09/22/767255.aspx">William Li&#8217;s blog post on the subject</a>.  It&#8217;s referring to an older version of Longhorn Server, but is still pretty sound.
</p>
<p><strong>Installation<br />
</strong></p>
<p>Installing SQL Server 2005 is a little painful now-a-days; the process goes like this if you do a complete install like I did:
</p>
<ol>
<li>Install SQL Server 2005 - Click &#8220;Run Program&#8221; to every prompt (a total of three for my install.  2 for SQL and 1 for Visual Studio because it&#8217;s installed as part of the client install)
</li>
<li>Install SQL Server 2005 Service Pack 2 (<a href="http://support.microsoft.com/kb/921896/en-us">KB921896</a>)
</li>
<li>Install SQL Server 2005 post SP2 hot fix rollup (<a href="http://support.microsoft.com/kb/933508/en-us">KB933508</a>)
</li>
<li>Install <a href="http://www.microsoft.com/downloads/details.aspx?familyid=be6a2c5d-00df-4220-b133-29c1e0b6585f&amp;displaylang=en">SQL Server 2005 Book Online update for February 2007</a> (optional)
</li>
<li>Install critical update for SQL Server 2005 SP2 (<a href="http://support.microsoft.com/?kbid=934458">KB934458</a>)
</li>
<li>Install Visual Studio 2005 Service Pack 1 (<a href="http://support.microsoft.com/kb/918526/en-us">KB918526</a>)
</li>
<li>Install Visual Studio 2005 SP1 Vista extensions (<a href="http://support.microsoft.com/kb/929470/en-us">KB929470</a>)
</li>
</ol>
<p>Windows update will take care of all of the updating for you if you prefer not to do it by hand or by script, but it takes a while.  Personally, I prefer the scripted approach because it&#8217;s more re-usable.
</p>
<p>What would be really nice is a SQL Server 2005 R2 with all of this integrated so you don&#8217;t have to run 6 update packages just to get SQL updated!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/CaptainLiteral?a=7Lye8w-0rpI:PnlJsIDbams:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/CaptainLiteral?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/CaptainLiteral?a=7Lye8w-0rpI:PnlJsIDbams:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/CaptainLiteral?i=7Lye8w-0rpI:PnlJsIDbams:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.captainliteral.net/2007/06/03/windows-server-longhorn-2008-beta-3-%e2%80%93-installing-sql-server-2005/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.captainliteral.net/2007/06/03/windows-server-longhorn-2008-beta-3-%e2%80%93-installing-sql-server-2005/</feedburner:origLink></item>
		<item>
		<title>How long will that download take?</title>
		<link>http://feedproxy.google.com/~r/CaptainLiteral/~3/2Bcw7zp8PWs/</link>
		<comments>http://www.captainliteral.net/2007/03/01/how-long-will-that-download-take/#comments</comments>
		<pubDate>Thu, 01 Mar 2007 00:58:00 +0000</pubDate>
		<dc:creator>Mark Sheppard</dc:creator>
		
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://www.captainliteral.net/2007/03/01/how-long-will-that-download-take/</guid>
		<description><![CDATA[

I&#8217;m currently downloading the March CTP of Visual Studio Orcas.  There&#8217;s two versions this month, a Virtual PC image and for the first time a full install.  Combined this all totals 11.9GB and 20 files  to download!

So how long will it take to download on my 4Mbs Internet Connection?

1&#62;  New-TimeSpan -seconds [...]]]></description>
			<content:encoded><![CDATA[
<!-- ALL ADSENSE ADS DISABLED -->
<p>I&#8217;m currently downloading the <a href="http://blogs.msdn.com/webdevtools/archive/2007/02/28/visual-studio-orcas-march-ctp-is-available.aspx">March CTP of Visual Studio Orcas</a>.  There&#8217;s two versions this month, a Virtual PC image and for the first time a full install.  Combined this all totals 11.9GB and 20 files  to download!
</p>
<p>So how long will it take to download on my 4Mbs Internet Connection?
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">1&gt;  New-TimeSpan -seconds $(11.9gb / (4mb / 8))<br/><br/>Days              : 0<br/>Hours             : 6<br/>Minutes           : 46<br/>Seconds           : 11<br/>Milliseconds      : 0<br/>Ticks             : 243710000000<br/>TotalDays         : 0.282071759259259<br/>TotalHours        : 6.76972222222222<br/>TotalMinutes      : 406.183333333333<br/>TotalSeconds      : 24371<br/>TotalMilliseconds : 24371000<br />
</span></p>
<p>Of cause, that&#8217;s the theoretical maximum of my line, in reality I tend to get about 480KBs:
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">2&gt;  New-TimeSpan -seconds $(11.9gb / (480kb))<br/><br/>Days              : 0<br/>Hours             : 7<br/>Minutes           : 13<br/>Seconds           : 16<br/>Milliseconds      : 0<br/>Ticks             : 259960000000<br/>TotalDays         : 0.30087962962963<br/>TotalHours        : 7.22111111111111<br/>TotalMinutes      : 433.266666666667<br/>TotalSeconds      : 25996<br/>TotalMilliseconds : 25996000<br />
</span></p>
<p>Not bad, it&#8217;ll e done by breakfast <span style="font-family:Wingdings">J</span>
	</p>
<p>I often compute this on a calculator, but PowerShell offers us a better alternative, but typing it into the command line every time will get old very fast.  So I&#8217;ve just knocked together a little script to do this for me.
</p>
<p>Usage: Calc-DownloadTime.ps1 &lt;downloadSize&gt; [connectionSpeed]
</p>
<p>Both parameters are int64&#8217;s and if connectionSpeed is not supplied, it will try to use a global variable named $networkSpeed.  Should the $networkSpeed global variable not exist, the script will throw an exception.
</p>
<p style="background: #012456"><span style="font-family:Lucida Console; font-size:10pt"><span style="color:#eeedf0">3&gt; .\Calc-DownloadTime.ps1 11.9gb 480kb<br/>Your download will take 07:13:16 to complete<br/><br/>4&gt; .\Calc-DownloadTime.ps1 11.9gb<br/>Usage: calc-downloadTime.ps1 &lt;downloadSize&gt; [connectionSpeed]<br/>If connectionSpeed is not supplied, global variable $networkSpeed will be used.<br/></span><span style="color:red">Please specify a connectionSpeed or set $networkSpeed variable to use as default<br/>At D:\PsScripts\Calc-DownloadTime.ps1:13 char:7<br/>+     throw  &lt;&lt;&lt;&lt; &#8220;Please specify a connectionSpeed or set `$networkSpeed variable to use as default&#8221;;</span><span style="color:#eeedf0"><br/><br/>5&gt; $networkSpeed = 480kb<br/><br/>6&gt; .\Calc-DownloadTime.ps1 11.9gb<br/>Your download will take 07:13:16 to complete<br />
</span></span></p>
<p>Because I do this a lot and my connection speed is generally static, I&#8217;ve added this variable to my profile so it&#8217;s there every time I load PowerShell.  I&#8217;ve seen some people connect that PowerShell profiles should be a light as possible, so if you prefer you can customise the script to default to your connection speed.
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">1&gt; .\Calc-DownloadTime.ps1 11.9gb<br/>Your download will take 07:13:16 to complete<br />
</span></p>
<p>I can still override this default though should I need to.
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">2&gt; .\Calc-DownloadTime.ps1 11.9gb $(100mb/8) # My Local LAN<br/>Your download will take 00:16:15 to complete<br/><br/>3&gt; .\Calc-DownloadTime.ps1 11.9gb $(54mb/8) # My WiFi connection<br/>Your download will take 00:30:05 to complete<br/><br/>4&gt; .\Calc-DownloadTime.ps1 11.9gb $(33kb/8) # My phone (GPRS)<br/>Your download will take 35.00:16:23 to complete<br />
</span></p>
<p>Ouch!  I better not do this over GPRS!
</p>
<p>Download the script here: <a href="http://www.captainliteral.net/wp-content/uploads/Calc-DownloadTime.ps1">Calc-DownloadTime.ps1</a></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/CaptainLiteral?a=2Bcw7zp8PWs:fs8_RvwKJVA:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/CaptainLiteral?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/CaptainLiteral?a=2Bcw7zp8PWs:fs8_RvwKJVA:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/CaptainLiteral?i=2Bcw7zp8PWs:fs8_RvwKJVA:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.captainliteral.net/2007/03/01/how-long-will-that-download-take/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.captainliteral.net/2007/03/01/how-long-will-that-download-take/</feedburner:origLink></item>
		<item>
		<title>Whatâ€™s that machine called?</title>
		<link>http://feedproxy.google.com/~r/CaptainLiteral/~3/KuXRyV0BkRE/</link>
		<comments>http://www.captainliteral.net/2007/02/27/what%e2%80%99s-that-machine-called/#comments</comments>
		<pubDate>Tue, 27 Feb 2007 02:22:33 +0000</pubDate>
		<dc:creator>Mark Sheppard</dc:creator>
		
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://www.captainliteral.net/2007/02/27/what%e2%80%99s-that-machine-called/</guid>
		<description><![CDATA[

Mamood had a problem!  He needed to get some information on a bunch of machines he manages and like a good follower of the church of PowerShell, he fired up his favourite blue and white command line tool (which he for some reason changes to be black with green text) and set about trying [...]]]></description>
			<content:encoded><![CDATA[
<!-- ALL ADSENSE ADS DISABLED -->
<p>Mamood had a problem!  He needed to get some information on a bunch of machines he manages and like a good follower of the church of PowerShell, he fired up his favourite blue and white command line tool (which he for some reason changes to be black with green text) and set about trying to obtain the information required.
</p>
<p>Somewhere along the way he got stuck, so somehow he managed to find his Office Communicator window in amongst what must have been at least 50 others including several terminal server client sessions (each containing at least another 20 windows) and contacted me.  He needed to perform a nslookup on an IP Address and grep the resolved host name for his information.
</p>
<p>I sent him back the following three functions (cobbled together on the spur of the moment):
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">function Ping-Host([string]$hostName) {<br/>     $pinger = new-object system.Net.NetworkInformation.Ping;<br/>     $pinger.Send($hostName);<br/>}<br/><br/>function Resolve-HostByAddress([string]$ipAddress) {<br/>     return [System.Net.Dns]::GetHostByAddress($ipAddress);<br/>}<br/><br/>function Resolve-HostByName([string]$hostName) {<br/>     return [System.Net.Dns]::GetHostByName($hostName);<br/>}<br />
</span></p>
<p>I then told him to save them in a script called networkTools.ps1 and then Dot-source them into his session and have a play to see if they do what he wanted:
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[D:\PsScripts]<br/>1&gt; . .\networkTools.ps1<br/><br/>[D:\PsScripts]<br/>2&gt; resolve-hostByName &#8220;localhost&#8221;<br/>HostName                                Aliases                                 AddressList<br/>&#8212;&#8212;&#8211;                                &#8212;&#8212;-                                 &#8212;&#8212;&#8212;&#8211;<br/>machine1.cpatinliteral.net              {}                                      {127.0.0.1}<br/><br/>[D:\PsScripts]<br/>3&gt; resolve-hostByAddress &#8220;192.168.8.5&#8243;<br/>HostName                                Aliases                                 AddressList<br/>&#8212;&#8212;&#8211;                                &#8212;&#8212;-                                 &#8212;&#8212;&#8212;&#8211;<br/>machine1.cpatinliteral.net              {}                                      {192.168.8.5}<br/><br/>[D:\PsScripts]<br/>4&gt; &#8220;machine1&#8243;, &#8220;machine2&#8243;, &#8220;machine3&#8243; | % { resolve-hostByName $_ }<br/>HostName                                Aliases                                 AddressList<br/>&#8212;&#8212;&#8211;                                &#8212;&#8212;-                                 &#8212;&#8212;&#8212;&#8211;<br/>machine1.captainliteral.net             {}                                      {192.168.8.5}<br/>machine2.captainliteral.net             {}                                      {192.168.8.3}<br/>machine3.captainliteral.net             {}                                      {192.168.8.8}<br />
</span></p>
<p>He said they were spot on and went away happy â€“ until a little while later.  He was struggling to tie in all the information he had obtained into a single report (formatted table) and wondered if I had any ideas.  Of cause I did, but I didn&#8217;t know if they would work!  I spend a lot of time piping objects to Get-Member and see a lot of extras provided by the Extendible Type System that PowerShell provides and wondered if I could use this to make a struct of sortsâ€¦
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[D:\PsScripts]<br/>5&gt; $machine = New-Object System.Object<br/><br/>[D:\PsScripts]<br/>6&gt; Add-Member -InputObject $machine -MemberType NoteProperty -name &#8220;HostName&#8221; -Value &#8220;&#8221;<br/><br/>[D:\PsScripts]<br/>7&gt; $machine | gm<br/><br/>   TypeName: System.Object<br/><br/>Name        MemberType   Definition<br/>&#8212;-        &#8212;&#8212;&#8212;-   &#8212;&#8212;&#8212;-<br/>Equals      Method       System.Boolean Equals(Object obj)<br/>GetHashCode Method       System.Int32 GetHashCode()<br/>GetType     Method       System.Type GetType()<br/>ToString    Method       System.String ToString()<br/>HostName    NoteProperty System.String HostName=<br/><br/>[D:\PsScripts]<br/>8&gt; $machine.hostName = &#8220;machine2&#8243;<br/><br/>[D:\PsScripts]<br/>9&gt; $machine<br/><br/>HostName<br/>&#8212;&#8212;&#8211;<br/>machine2<br />
</span></p>
<p>Looking good â€“ I&#8217;ve managed to create a basic object and add an extra property (HostName) to it, assign to this new property and then output is back to the console â€“ and I&#8217;ve done all this without going near the C# compiler.  This is new for me!
</p>
<p>Lets add some more properties:
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[D:\PsScripts]<br/>10&gt; Add-Member -InputObject $machine -MemberType NoteProperty -name &#8220;IpAddress&#8221; -Value &#8220;&#8221;<br/><br/>[D:\PsScripts]<br/>11&gt; Add-Member -InputObject $machine -MemberType NoteProperty -name &#8220;MacAddress&#8221; -Value &#8220;&#8221;<br/><br/>[D:\PsScripts]<br/>12&gt; $machine | gm<br/><br/>   TypeName: System.Object<br/><br/>Name        MemberType   Definition<br/>&#8212;-        &#8212;&#8212;&#8212;-   &#8212;&#8212;&#8212;-<br/>Equals      Method       System.Boolean Equals(Object obj)<br/>GetHashCode Method       System.Int32 GetHashCode()<br/>GetType     Method       System.Type GetType()<br/>ToString    Method       System.String ToString()<br/>HostName    NoteProperty System.String HostName=machine2<br/>IpAddress   NoteProperty System.String IpAddress=<br/>MacAddress  NoteProperty System.String MacAddress=<br/><br/>[D:\PsScripts]<br/>13&gt; $machine.IpAddress = $(resolve-hostbyname $machine.HostName).AddressList[0]<br/><br/>[D:\PsScripts]<br/>14&gt; $machine<br/>HostName                                IpAddress                               MacAddress<br/>&#8212;&#8212;&#8211;                                &#8212;&#8212;&#8212;                               &#8212;&#8212;&#8212;-<br/>machine2                                192.168.8.3<br />
</span></p>
<p>This might just work!  Lets wrap it in another function that we&#8217;ll append to the end of networkTools.ps1:
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">function New-MachineObject($hostName = &#8220;&#8221;, $ipAddress = &#8220;&#8221;, $macAddress = &#8220;&#8221;, $alive = &#8220;&#8221;) {<br/>Â Â Â Â $machine = New-Object System.Object;<br/>Â Â Â Â Add-Member -InputObject $machine -MemberType NoteProperty -name &#8220;HostName&#8221; -Value $hostName;<br/>Â Â Â Â Add-Member -InputObject $machine -MemberType NoteProperty -name &#8220;IpAddress&#8221; -Value $ipAddress;<br/>Â Â Â Â Add-Member -InputObject $machine -MemberType NoteProperty -name &#8220;MacAddress&#8221; -Value $macAddress;<br/>Â Â Â Â Add-Member -InputObject $machine -MemberType NoteProperty -name &#8220;Alive&#8221; -Value $alive;<br/>Â Â Â Â return $machine;<br/>}<br />
</span></p>
<p>Dot-source this into the current session again and we&#8217;re up and running.
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[D:\PsScripts]<br/>15&gt; . .\networkTools.ps1<br/><br/>[D:\PsScripts]<br/>16&gt; New-MachineObject &#8220;localhost&#8221; &#8220;127.0.0.1&#8243; &#8220;0&#215;00000000&#8243; $false<br/><br/>HostName                      IpAddress                     MacAddress           Alive<br/>&#8212;&#8212;&#8211;                      &#8212;&#8212;&#8212;                     &#8212;&#8212;&#8212;-           &#8212;&#8211;<br/>localhost                     127.0.0.1                     0&#215;00000000           False<br />
</span></p>
<p>Mamood&#8217;s total scenario was that he had a list of machine names (in a .csv file), and needed to get the fully-qualified domain name for the host along with the IP address, corresponding MAC Address and then test to see if it was responding to ping requests.  Actually, I added in the test part as the only way I have of getting the MAC Address is WMI and there&#8217;s no point trying to connect to the device if it&#8217;s down is there?  I had a quick look at the System.Net namespace, but couldn&#8217;t see how to get a remote machines MAC address â€“ please, if you know how to do it within .NET, let me know.
</p>
<p>Before we solve the complete problem however, yet another function (or two) is required for networkTools.ps1 (and it needs dot-sourcing into the current session again):
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">function Get-MacAddressForHost($hostName, $ipAddress) {<br/>Â Â Â Â $networkAdapters = get-wmiobject Win32_NetworkAdapterConfiguration -computername $hostName -Filter &#8220;IPenabled = &#8216;True&#8217;&#8221;;<br/>        foreach ($adapter in $networkAdapters) {<br/>Â Â Â Â Â Â Â Â if ($adapter.IPAddress -eq $ipAddress) {<br/>                Â Â Â Â return $adapter.MACAddress; <br/>Â Â Â Â Â Â Â Â }<br/>        } <br/>}<br/><br/>function Get-AliveStatus($hostName) {<br/>Â Â Â Â $response = Ping-Host $hostName;<br/>Â Â Â Â if ($response.Status -eq [System.Net.NetworkInformation.IPStatus]::Success) {<br/>Â Â Â Â Â Â Â Â return $true;<br/>Â Â Â Â }<br/>Â Â Â Â else {<br/>Â Â Â Â Â Â Â Â return $false;<br/>Â Â Â Â }<br/>}<br />
</span></p>
<p>A little crude perhaps, but works and gets around the issue of virtual network adapter from programs like VMWare and Windows Mobile 5 devices <span style="font-family:Wingdings">J</span>
	</p>
<p>It&#8217;s worth noting that you may need some credentials to connect to the remote machine with WMI â€“ Mamood certainly did!  If so, just append <em>â€“credential $creds</em> the first line of Get-MacAddressForHost and then type the following into your session to get PowerShell to prompt you for the username and password that you&#8217;ll use to connect to remote machines. Don&#8217;t worry, your password is stored in a Secure String, so it shouldn&#8217;t be possible to read it by typing $creds â€“ doesn&#8217;t stop a call into the .NET classes to get the clear-text version though.  So when you&#8217;re finished, set it to $null (<em>$creds = $null;</em>)
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[D:\PsScripts]<br/>48&gt; $creds = Get-Credential<br />
</span></p>
<p>And now the final solutionâ€¦
</p>
<p style="background: #012456"><span style="font-family:Lucida Console; font-size:10pt"><span style="color:#eeedf0">[D:\PsScripts]<br/>36&gt; . .\networkTools.ps1<br/><br/></span><span style="color:yellow"># Create a CSV file, just like Mamood has</span><span style="color:#eeedf0"><br/>[D:\PsScripts]<br/>38&gt; &#8220;MachineName&#8221;, &#8220;machine1&#8243;, &#8221; machine2&#8243;, &#8221; machine3&#8243;, &#8221; machine4&#8243; &gt; machineList.csv<br/><br/></span><span style="color:yellow"># Get machine information from DNS</span><span style="color:#eeedf0"><br/>[D:\PsScripts]<br/>40&gt; $machines = @();<br/><br/>[D:\PsScripts]<br/>41&gt; import-csv machineList.csv | % { $machineInfo = resolve-hostByName $_.MachineName; $machines += New-MachineObject $machineInfo.Hostname $machineInfo.AddressList[0] }<br/><br/></span><span style="color:yellow"># Ping each host to get alive status</span><span style="color:#eeedf0"><br/>[D:\PsScripts]<br/>43&gt; $machines | % { $_.Alive = Get-AliveStatus $_.HostName }<br/><br/></span><span style="color:yellow"># Get MAC Address for each alive host</span><span style="color:#eeedf0"><br/>[D:\PsScripts]<br/>45&gt; $machines | ? { $_.Alive } | % { $_.MacAddress = Get-MacAddressForHost $_.HostName $_.IpAddress }<br/><br/></span><span style="color:yellow"># Finally, output as a table (or you could export to CSV if you prefer)</span><span style="color:#eeedf0"><br/>[D:\PsScripts]<br/>47&gt; $machines | ft<br/><br/>HostName                      IpAddress      MacAddress               Alive<br/>&#8212;&#8212;&#8211;                      &#8212;&#8212;&#8212;      &#8212;&#8212;&#8212;-               &#8212;&#8211;<br/>machine1.captainliteral.net   192.168.8.3    00:04:FF:0B:23:B2         True<br/>machine2.captainliteral.net   192.168.8.8                             False<br/>machine3.captainliteral.net   192.168.7.1                             False<br/>machine4.captainliteral.net   192.168.8.5    00:16:17:0E:23:B2         True<br />
</span></span></p>
<p>And that&#8217;s that.
</p>
<p>This is an interesting procedure because it required multiple passes the get all the required data.  Sure, I could have put this into one (long) line and there are probably other, more concise ways of achieving the same task (please post comments if you have one), but what I wanted to show here is that by using the Extensible Type System, you can create simple struct like objects to store information in a typed fashion.
</p>
<p>I for one had not played much with the type extensions possible in PowerShell, but I&#8217;m going to go a read all about them now (and find out what I did wrong in the process <span style="font-family:Wingdings">J</span>)  <a href="http://blogs.msdn.com/powershell/archive/2007/02/24/extended-types-and-types-xsd.aspx">Jeffrey Snover recently blogged</a> about this feature of PowerShell and points to you <a href="http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!148.entry">Jim Truher&#8217;s blog post</a> explaining it all a lot further and a lot better then I.
</p>
<p>If you want my original version of networkTools.ps1, <a href="http://www.captainliteral.net/wp-content/uploads/networkTools.ps1">download it here</a>.
</p>
<p>For more information on dot-sourcing and running scripts, <a href="http://www.captainliteral.net/2007/01/29/powershell-basics-%e2%80%93-running-scripts/">read my previous entry on the subject here</a>.
</p>
<p>The earlier functions in networktools.ps1 use the .NET Framework, <a href="http://www.captainliteral.net/2007/02/18/powershell-basics-%e2%80%93-net/">read more about what the syntax means here</a>.
</p>
<p>In the end Mamood got what he needed and the next time he has to produce the same report (probably tomorrow, or at least by next week), he&#8217;ll have it done In a couple of seconds.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/CaptainLiteral?a=KuXRyV0BkRE:Th2PEwWuNxU:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/CaptainLiteral?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/CaptainLiteral?a=KuXRyV0BkRE:Th2PEwWuNxU:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/CaptainLiteral?i=KuXRyV0BkRE:Th2PEwWuNxU:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.captainliteral.net/2007/02/27/what%e2%80%99s-that-machine-called/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.captainliteral.net/2007/02/27/what%e2%80%99s-that-machine-called/</feedburner:origLink></item>
		<item>
		<title>PowerShell Basics â€“ .NET</title>
		<link>http://feedproxy.google.com/~r/CaptainLiteral/~3/SHTCnX6yNuo/</link>
		<comments>http://www.captainliteral.net/2007/02/18/powershell-basics-%e2%80%93-net/#comments</comments>
		<pubDate>Sun, 18 Feb 2007 23:27:49 +0000</pubDate>
		<dc:creator>Mark Sheppard</dc:creator>
		
		<category><![CDATA[PowerShell]]></category>

		<category><![CDATA[.NET]]></category>

		<category><![CDATA[automation]]></category>

		<category><![CDATA[dotNET]]></category>

		<category><![CDATA[scripting]]></category>

		<category><![CDATA[SharePoint]]></category>

		<category><![CDATA[WSS]]></category>

		<guid isPermaLink="false">http://www.captainliteral.net/2007/02/18/powershell-basics-%e2%80%93-net/</guid>
		<description><![CDATA[

One of the reasons why PowerShell is so good and so easy to sell to people is because of .NET.  PowerShell is a .NET 2.0 application and it uses .NET to achieve virtually everything it does â€“ but how can users leverage to power of .NET from within PowerShell?

How do I create an object?

There [...]]]></description>
			<content:encoded><![CDATA[
<!-- ALL ADSENSE ADS DISABLED -->
<p>One of the reasons why PowerShell is so good and so easy to sell to people is because of .NET.  PowerShell is a .NET 2.0 application and it uses .NET to achieve virtually everything it does â€“ but how can users leverage to power of .NET from within PowerShell?
</p>
<p><strong>How do I create an object?<br />
</strong></p>
<p>There are basically two way to get an object to work with in PowerShell, either call <strong>new-object</strong> or get one returned by calling something.
</p>
<p><strong>Things return objects?<br />
</strong></p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[D:\PsScripts]<br/>1&gt; get-process<br/><br/>Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName<br/>&#8212;&#8212;-  &#8212;&#8212;    &#8212;&#8211;      &#8212;&#8211; &#8212;&#8211;   &#8212;&#8212;     &#8212; &#8212;&#8212;&#8212;&#8211;<br/>    256      12    77716      70736   558     0.91   5680 powershell<br />
</span></p>
<p>What&#8217;s actually going on here?  It turns out that the get-process cmdlet returns .NET objects, in the above case it&#8217;s an array of System.Diagnosticts.Process objects and that allows us to work with them the same as if we had created them in code.
</p>
<p>You can work with objects by either keeping a reference to them or by passing them down the pipeline to another cmdlet, object or piece of script.  If you want to know what you can do with an object, call <strong>get-member</strong>:
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[D:\PsScripts]<br/>2&gt; $processes = get-process<br/>[D:\PsScripts]<br/>3&gt; $processes.Length<br/>90<br/>[D:\PsScripts]<br/>4&gt; get-member -InputObject $processes<br/><br/>   TypeName: System.Object[]<br/><br/>Name               MemberType    Definition<br/>&#8212;-               &#8212;&#8212;&#8212;-    &#8212;&#8212;&#8212;-<br/>Count              AliasProperty Count = Length<br/>&#8230;                &#8230;           &#8230;<br />
</span></p>
<p>An object array?  Where are the process objects?
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[D:\PsScripts]<br/>5&gt; get-member -InputObject $processes[0]<br/><br/>   TypeName: System.Diagnostics.Process<br/><br/>Name                           MemberType     Definition<br/>&#8212;-                           &#8212;&#8212;&#8212;-     &#8212;&#8212;&#8212;-<br/>Handles                        AliasProperty  Handles = Handlecount<br/>Name                           AliasProperty  Name = ProcessName<br/>&#8230;                            &#8230;            &#8230;<br />
</span></p>
<p>An you can achieve the same by passing the object down the pipeline:
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[D:\PsScripts]<br/>6&gt; Get-Process | Get-Member<br/><br/>   TypeName: System.Diagnostics.Process<br/><br/>Name                           MemberType     Definition<br/>&#8212;-                           &#8212;&#8212;&#8212;-     &#8212;&#8212;&#8212;-<br/>Handles                        AliasProperty  Handles = Handlecount<br/>Name                           AliasProperty  Name = ProcessName<br/>&#8230;                            &#8230;            &#8230;<br />
</span></p>
<p><strong>What if I don&#8217;t want an object of type System.Diagnostics.Process?<br />
</strong></p>
<p>The other way to get an object is to call the <strong>new-object</strong> cmdlet.
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[D:\PsScripts]<br/>7&gt; $date = New-Object DateTime<br/>[D:\PsScripts]<br/>8&gt; $date<br/><br/>01 January 0001 00:00:00<br />
</span></p>
<p>And if you need to specify arguments to the constructer, just pass them in after the type:
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[D:\PsScripts]<br/>9&gt; $date2 = New-Object DateTime 2007, 2, 18<br/>[D:\PsScripts]<br/>10&gt; $date2<br/><br/>18 February 2007 00:00:00<br />
</span></p>
<p><strong>How to I call a method on my object?<br />
</strong></p>
<p>Calling methods is the same in PowerShell as it is in C# (object.method()):
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[D:\PsScripts]<br/>11&gt; $date2.ToShortDateString()<br/>18/02/2007<br />
</span></p>
<p>Properties are also the same (object.Property):
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[D:\PsScripts]<br/>12&gt; $date2.Year<br/>2007<br />
</span></p>
<p>Tab complete works with object methods and properties by the way, making it easier to get at what you want.
</p>
<p><strong>What type is my object?<br />
</strong></p>
<p>The easiest way to determine an objects type is to just call the GetType() method of the object;
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[D:\PsScripts]<br/>13&gt; $date2.GetType()<br/><br/>IsPublic IsSerial Name                                     BaseType<br/>&#8212;&#8212;&#8211; &#8212;&#8212;&#8211; &#8212;-                                     &#8212;&#8212;&#8211;<br/>True     True     DateTime                                 System.ValueType<br/><br/>[D:\PsScripts]<br/>14&gt; $processes.GetType()<br/><br/>IsPublic IsSerial Name                                     BaseType<br/>&#8212;&#8212;&#8211; &#8212;&#8212;&#8211; &#8212;-                                     &#8212;&#8212;&#8211;<br/>True     True     Object[]                                 System.Array<br/><br/>[D:\PsScripts]<br/>15&gt; $processes[0].GetType()<br/><br/>IsPublic IsSerial Name                                     BaseType<br/>&#8212;&#8212;&#8211; &#8212;&#8212;&#8211; &#8212;-                                     &#8212;&#8212;&#8211;<br/>True     False    Process                                  System.ComponentModel.Component<br />
</span></p>
<p><strong>What about Statics?<br />
</strong></p>
<p>Statics can be invoked by using the following syntax: [Type]::Property or [Type]::Method().  For example:
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[D:\PsScripts]<br/>16&gt; [DateTime]::DaysInMonth(2007, 2)<br/>28<br/><br/>[D:\PsScripts]<br/>17&gt; [DateTime]::Now<br/><br/>18 February 2007 20:16:55<br />
</span></p>
<p><strong>OK, but I have this assembly with types in it I&#8217;d like to callâ€¦<br />
</strong></p>
<p>Before we talk about loading a custom assembly into the PowerShell Application Domain, you&#8217;re going to want to know if you need to or not.  The following shows how to get all the loaded assemblies:
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[D:\PsScripts]<br/>18&gt; $psAppDomain = [AppDomain]::CurrentDomain<br/><br/>[D:\PsScripts]<br/>19&gt; $psAppDomain.GetAssemblies()<br/><br/>GAC    Version        Location<br/>&#8212;    &#8212;&#8212;-        &#8212;&#8212;&#8211;<br/>True   v2.0.50727     C:\WINDOWS\Microsoft.NET\Framework64\v2.0.50727\mscorlib.dll<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\Microsoft.PowerShell.ConsoleHos&#8230;<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\System\2.0.0.0__b77a5c561934e08&#8230;<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\System.Management.Automation\1&#8230;.<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\System.Configuration.Install\2&#8230;.<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\Microsoft.PowerShell.Commands.M&#8230;<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\Microsoft.PowerShell.Security\1&#8230;<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\Microsoft.PowerShell.Commands.U&#8230;<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\System.Xml\2.0.0.0__b77a5c56193&#8230;<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\System.Management\2.0.0.0__b03f&#8230;<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\System.DirectoryServices\2.0.0&#8230;.<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_64\System.Data\2.0.0.0__b77a5c561934&#8230;<br/>False  v2.0.50727     C:\Program Files (x86)\PowerShell Community Extensions\pscx.dll<br />
</span></p>
<p>The best way to load an additional assembly into the PowerShell App Domain is to use the System.Reflection.Assembly class.  It exposes several statics methods for loading assemblies.  You can find details of <a href="http://msdn2.microsoft.com/en-us/library/system.reflection.assembly_members.aspx">these methods on MSDN</a>, they all begin Load â€“ I suggest that they be studied so you know which methods to call for what type of assembly:
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[D:\PsScripts]<br/>20&gt; [System.Reflection.Assembly]::Load(&#8221;System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a&#8221;)<br/><br/>GAC    Version        Location<br/>&#8212;    &#8212;&#8212;-        &#8212;&#8212;&#8211;<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_64\System.Web\2.0.0.0__b03f5f7f11d50a3a\System.Web.dll<br/><br/>[D:\PsScripts]<br/>21&gt; [System.Reflection.Assembly]::LoadFrom(&#8221;SolveSudoku.dll&#8221;)<br/><br/>GAC    Version        Location<br/>&#8212;    &#8212;&#8212;-        &#8212;&#8212;&#8211;<br/>False  v2.0.50727     d:\PsScripts\SolveSudoku.dll<br/><br/>[D:\PsScripts]<br/>22&gt; $psAppDomain.GetAssemblies()<br/><br/>GAC    Version        Location<br/>&#8212;    &#8212;&#8212;-        &#8212;&#8212;&#8211;<br/>True   v2.0.50727     C:\WINDOWS\Microsoft.NET\Framework64\v2.0.50727\mscorlib.dll<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\Microsoft.PowerShell.ConsoleHos&#8230;<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\System\2.0.0.0__b77a5c561934e08&#8230;<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\System.Management.Automation\1&#8230;.<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\System.Configuration.Install\2&#8230;.<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\Microsoft.PowerShell.Commands.M&#8230;<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\Microsoft.PowerShell.Security\1&#8230;<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\Microsoft.PowerShell.Commands.U&#8230;<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\System.Xml\2.0.0.0__b77a5c56193&#8230;<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\System.Management\2.0.0.0__b03f&#8230;<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\System.DirectoryServices\2.0.0&#8230;.<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_64\System.Data\2.0.0.0__b77a5c561934&#8230;<br/>False  v2.0.50727     C:\Program Files (x86)\PowerShell Community Extensions\pscx.dll<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_64\System.Web\2.0.0.0__b03f5f7f11d50&#8230;<br/>False  v2.0.50727     d:\PsScripts\SolveSudoku.dll<br />
</span></p>
<p><strong>What&#8217;s next?<br />
</strong></p>
<p>Well, that&#8217;s all you need to know to really get going with calling .NET from within Windows PowerShell.  Using the information provided here and armed with what-ever SDK you need, you can use PowerShell to script anything that exposes a .NET API.  This includes SharePoint and your own custom .NET application.
</p>
<p>IT Pro&#8217;s â€“ you better start asking developers for better class documentation so you can maintain and support bespoke applications better.
</p>
<p>Whilst invoking .Net from the command line is powerful, it&#8217;s no substitute for cmdlets and providers.  That said, application developers need to start creating cmdlets before they can be used.  In the meantime use .NET API&#8217;s to script what couldn&#8217;t be scripted before <span style="font-family:Wingdings">J</span>
	</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/CaptainLiteral?a=SHTCnX6yNuo:fjuhTgW_EtM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/CaptainLiteral?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/CaptainLiteral?a=SHTCnX6yNuo:fjuhTgW_EtM:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/CaptainLiteral?i=SHTCnX6yNuo:fjuhTgW_EtM:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.captainliteral.net/2007/02/18/powershell-basics-%e2%80%93-net/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.captainliteral.net/2007/02/18/powershell-basics-%e2%80%93-net/</feedburner:origLink></item>
		<item>
		<title>Measure-Object { PowerShell }</title>
		<link>http://feedproxy.google.com/~r/CaptainLiteral/~3/uAIdlA82h4M/</link>
		<comments>http://www.captainliteral.net/2007/02/01/measure-object-powershell/#comments</comments>
		<pubDate>Thu, 01 Feb 2007 00:37:49 +0000</pubDate>
		<dc:creator>Mark Sheppard</dc:creator>
		
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://www.captainliteral.net/2007/02/01/measure-object-powershell/</guid>
		<description><![CDATA[

I&#8217;ve been using PowerShell now for a few months and it&#8217;s become a standard feature on my desktop.  Having used it for a while I have some observations to share:

IDE

PowerShell doesn&#8217;t have an IDE shipped as part of the product, so the out-of-the-box experience of scripting it limited to nothing more fancy than Notepad. [...]]]></description>
			<content:encoded><![CDATA[
<!-- ALL ADSENSE ADS DISABLED -->
<p>I&#8217;ve been using PowerShell now for a few months and it&#8217;s become a standard feature on my desktop.  Having used it for a while I have some observations to share:
</p>
<p><strong>IDE<br />
</strong></p>
<p>PowerShell doesn&#8217;t have an IDE shipped as part of the product, so the out-of-the-box experience of scripting it limited to nothing more fancy than Notepad.  My experience though has been that an IDE of some sorts really is required for working with anything but the most basic  .ps1 script files.  Additionally, I&#8217;ve had bugs in one-liners that pipe together several command and full IDE support for pipelines would be a real winner â€“ imagine being able to set a breakpoint between piped commands.
</p>
<p>The main features that I would like an  IDE for PowerShell to provide are:
</p>
<ul>
<li>Colourisation of text â€“ Different types and operators get different colours when viewed in an IDE, so you can see what you&#8217;re working on more clearly.
</li>
<li>Full Debugging capabilities â€“ Including breakpoints and watch windows.  Without these basic tools, scripts get littered with write-Debug commands all over the place, it kind of reminds me of days gone by when I&#8217;ve been debugging ASP3 web applications â€“ doable, but not as easy as it should be.
</li>
<li>IntelliSense â€“ tab completion is a godsend, but you need to know what&#8217;s there before it really works, I&#8217;m constantly piping to get-member to find out what an object supports.
</li>
<li>Code-snippets â€“ I know this is a very Visual studio term, but in essence I&#8217;m talking about templated commands rather than scripts.  For example, a simple getNamedProcesses snippet could contain: Get-Process [ProcessName], where the user just overwrites the [ProcessName] block with the desired information and away it runs.  Again, linked with a visual menu so one can browse code-snippets would be the ultimate.<br/>This could be a very powerful tool for PowerShell as it provides another way to reuse functionally.
</li>
<li>Source code Control â€“ Creating a corporate or personal script library will take time and require multiple scripter&#8217;s/developers working on the same solution.  This is a situation that cries out for source code control and solution management and not just a bunch of files on a share somewhere.
</li>
</ul>
<p>I know there are a few IDE&#8217;s for PowerShell already and over the next couple of week I intend to install them all to see how they are, but what I&#8217;d really like is Visual studio to understand PowerShell, or at least .ps1 files.  I use Visual Studio every day so I&#8217;m very comfortable in it, but I understand that the vast majority of PowerShell users are going to be IT Pro&#8217;s who do not have Visual Studio at hand â€“ but that&#8217;s no reason not to use it for this purpose.  Of cause, a lighter-weight version would be required for the non-development activities that occur on production servers inside the data-centre â€“ I really would not like to be the one who says &#8220;Install VS on all those servers please.&#8221;
</p>
<p><strong>Right Tool, Right Job<br />
</strong></p>
<p>PowerShell is a new tool for the  toolbox, but unlike other tools it isn&#8217;t another item to carry around and only get out when required.  PowerShell is much more like a multi-function screwdriver â€“ the ones with a billion different mutli-changeable bits to achieve anything (bad simile I know and not to be taken literally).  It&#8217;s a tool that does away with several others and like all multi-purpose tools has some drawbacks and isn&#8217;t suited for every job.  Fortunately, it interfaces with tools that can be used like .NET or native .exe&#8217;s.
</p>
<p>One area where I found PowerShell suffers is for performance.  Normally performance is not necessarily at the top of the features list â€“ especially when we&#8217;re talking about admin scripting, which is what PowerShell is designed for.  But sometimes you want a script to run as quickly as possible, you need a script to run as quickly as possible.  Take the Sudoku solving script I posted a couple of weeks ago, I wanted to make it perform.  True, I did not take advantage of any unique-to-shell-features (such as Pipelines) and as a result those features (which are normally what I use PowerShell for) added an overhead.  The correct tool for that job was .NET itself, invoked through PowerShell of cause.
</p>
<p>Maybe it&#8217;ll get optimised in a future version and my only purpose for listing it here is to try and make people aware of the choices that are available and to know the pros/cons of each so the best tool can be chosen for the particular job at hand.  I really don&#8217;t see performance as a problem for this tool, so don&#8217;t worry too much about it â€“ it&#8217;s quick enough for 99.999% of the things I do in it.
</p>
<p>Because I can create .NET classes or call static methods at the command line and interact with them, I will be able to throw functionality into .NET classes and have .DLL&#8217;s as part of my personal script library without having the overhead and formality of writing an entire cmdlet/snapin.
</p>
<p><strong>Operators<br />
</strong></p>
<p>PowerShell has good support for a wide array of operators, but it doesn&#8217;t support all that are provided to other .NET languages like C#.  Examples are <a href="http://msdn2.microsoft.com/en-us/library/ydwa9zh0(VS.80).aspx"><em>%=</em> (modulus assignment)</a>, <a href="http://msdn2.microsoft.com/en-us/library/a1sway8w(VS.80).aspx"><em>&lt;&lt;</em> (left-shift)</a>, <a href="http://msdn2.microsoft.com/en-us/library/xt18et0d(VS.80).aspx"><br />
			<em>&gt;&gt;</em> (right-shift)</a> and <a href="http://msdn2.microsoft.com/en-us/library/ty67wk28(VS.80).aspx"><em>?:</em> (conditional)</a>.  <a href="http://blogs.msdn.com/powershell/archive/2006/12/29/dyi-ternary-operator.aspx">Jeffrey Snover has blogged about ?: on the PowerShell Team blog.</a>
	</p>
<p>This isn&#8217;t a big problem as you can wrap these operators up in managed code and invoke them as statics if required â€“ perhaps the first class I should add to my .dll-enhanced script library?
</p>
<p>I hope that future releases of PowerShell will provide additional operator support, but right now, the main operators (the ones used daily) are supported.
</p>
<p><strong>Remote Machine Support<br />
</strong></p>
<p>One of the IT Pro&#8217;s where I work, who is very pro-scripting has commented that PowerShell&#8217;s lack of remote machine working ability is a problem for him.  This is a fair comment, PowerShell is set-up for local working and very little support is provided for remote connectivity and management of computers.  I say very little because PowerShell has great support for WMI, ADSI and .NET â€“ so you can do all this, it&#8217;s just not a simple as the following examples:
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">get-process â€“machineName server.domain.local<br />
</span></p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">stop-service â€“name serviceName â€“machineName server.domain.local<br />
</span></p>
<p>The IT Pro mentioned above isn&#8217;t a developer and I think that WMI and .NET are not the simplest things to pickup and learn â€“ they both have massive object models â€“ so I think that the community is going to come out with these sorts of tools more.
</p>
<p>To mitigate this, I know that <a href="http://mshforfun.blogspot.com/">PowerShell Remoting</a> addresses this issue by providing a service on a remote machine that allowing a client to connect â€“ like telnet â€“ and even goes one further by providing extra cmdlets that you can use to get the information over the network to the client computer.  It&#8217;s nicely thought out and it&#8217;s another one that I&#8217;m going to add to my //ToInvistigateFurther: list.
</p>
<p>Looking ahead to Longhorn Server, administrators will be able to expose PowerShell as a remote application â€“ imagine a Remote Desktop Session, but for only one application instead of the entire desktop.  I&#8217;m not sure I like this approach though, I want tools that don&#8217;t encourage administrators to use mstsc and don&#8217;t require them to start a desktop session on a server.
</p>
<p>Finally, I don&#8217;t mind this as I believe that all changes to servers in data centres should be run through a central controller so the command, output and executing user can all be logged and queried later â€“ how else are you going to know what happened on any given machine?  I&#8217;m a big fan of <a href="http://www.microsoft.com/windowsserver2003/technologies/management/ads/default.mspx">Automated Deployment Services (ADS)</a> and this is the administration model it promotes.  As an aside, you can run PowerShell commands and scripts from ADS by calling powershell.exe as the command and â€“command &#8220;command list&#8221; as a parameter.  For example:
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">powershell.exe â€“command &#8220;&amp; { gps }&#8221;<br />
</span></p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">powershell.exe â€“command &#8220;&amp; { C:\PsScripts\dosomething.ps1 }&#8221;<br />
</span></p>
<p>Type powershell -? for more details from the command line.
</p>
<p><strong>Documentation<br />
</strong></p>
<p>I like the way that the get-command and get-help cmdlets are used to get help, but it&#8217;s not always easy to find the help topic I&#8217;m interested in â€“ Example: param â€“ can&#8217;t find any help on it using get-help, I had to resort to Windows Search to find the xml file it&#8217;s in â€“ perhaps a simple search-help cmdlet might work?  Again, I think that the community will provide this over time.
</p>
<p>Whilst on the subject of documentation, one thing that really bugs me with the x64 release of PowerShell on a machine with Office installed is that clicking on any of the start menu documentation shortcuts results in Word not being able to find the requested document because it&#8217;s a 32bit process and PowerShell only installed the .rft files to the 64bit version of System32.  Still, you can open them in WordPad or just copy them to the correct place in the SysWow64 folder.
</p>
<p><strong>To Finish<br />
</strong></p>
<p>Phew, what a lot to type and I&#8217;m sure that I&#8217;m going to have forgotten loads that will come to me over time, so I may end up doing another one of these posts in the future.
</p>
<p>I hope that this doesn&#8217;t read like a rant, because I didn&#8217;t intend it to be one.  If you haven&#8217;t gathered already, I really like PowerShell and think that it has massive potential.  Given time, I&#8217;m sure that we&#8217;ll see more and more support for it in other application â€“ perhaps Microsoft will add it to their <a href="http://www.microsoft.com/windowsserversystem/cer/default.mspx">Common Engineering Criteria</a> for server based applications?
</p>
<p>I mention the community a lot in the above essay and I am part of that community.  Right now, I&#8217;m working on some network tools for PowerShell that should make life a little easier.</p>
<p><strong>Edit: Thanks to /\/\o\/\/ for point out that I missed that PowerShell does actually have the modulus assignment operator (%=) - missed that one, D&#8217;Oh!</strong></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/CaptainLiteral?a=uAIdlA82h4M:xQxI28xsY0I:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/CaptainLiteral?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/CaptainLiteral?a=uAIdlA82h4M:xQxI28xsY0I:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/CaptainLiteral?i=uAIdlA82h4M:xQxI28xsY0I:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.captainliteral.net/2007/02/01/measure-object-powershell/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.captainliteral.net/2007/02/01/measure-object-powershell/</feedburner:origLink></item>
		<item>
		<title>SharePoint automation with PowerShell</title>
		<link>http://feedproxy.google.com/~r/CaptainLiteral/~3/dnW0E0btaY4/</link>
		<comments>http://www.captainliteral.net/2007/01/31/sharepoint-automation-with-powershell/#comments</comments>
		<pubDate>Wed, 31 Jan 2007 00:21:41 +0000</pubDate>
		<dc:creator>Mark Sheppard</dc:creator>
		
		<category><![CDATA[PowerShell]]></category>

		<category><![CDATA[SharePoint]]></category>

		<category><![CDATA[Windows-SharePoint-Services]]></category>

		<category><![CDATA[WSS]]></category>

		<guid isPermaLink="false">http://www.captainliteral.net/2007/01/31/sharepoint-automation-with-powershell/</guid>
		<description><![CDATA[

I spent a lot of time automating SharePoint when the company I work for installed SharePoint Portal Server 2003, so I was quite disappointed when SharePoint version 3 was released without PowerShell support â€“ after all, Exchange 2007 managed it and it&#8217;s part of the Office 2007 Server suite, so why didn&#8217;t the other server [...]]]></description>
			<content:encoded><![CDATA[
<!-- ALL ADSENSE ADS DISABLED -->
<p>I spent a lot of time automating SharePoint when the company I work for installed SharePoint Portal Server 2003, so I was quite disappointed when SharePoint version 3 was released without PowerShell support â€“ after all, Exchange 2007 managed it and it&#8217;s part of the Office 2007 Server suite, so why didn&#8217;t the other server products?
</p>
<p>On a positive note though, I did find that stsadm.exe had been extended to now support a lot more operations:
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN]<br/>3&gt; .\stsadm.exe â€“help<br/><br/>Usage:<br/>           stsadm.exe -o &lt;operation&gt; [&lt;parameters&gt;]<br/>           stsadm.exe -help [&lt;operation&gt;]<br/><br/>Operations:<br/><br/><br/>           activatefeature<br/>           addalternatedomain<br/>           addcontentdb<br/>           addpath<br/>           addpermissionpolicy<br/>           addsolution<br/>           addtemplate<br/>           adduser<br/>           addwppack<br/>           addzoneurl<br/>           authentication<br/>           backup<br/>           backuphistory<br/>           binddrservice<br/>           blockedfilelist<br/>           canceldeployment<br/>           changepermissionpolicy<br/>           copyappbincontent<br/>           createadminvs<br/>           creategroup<br/>           createsite<br/>           createsiteinnewdb<br/>           createweb<br/>           databaserepair<br/>           deactivatefeature<br/>           deleteadminvs<br/>           deletealternatedomain<br/>           deleteconfigdb<br/>           deletecontentdb<br/>           deletegroup<br/>           deletepath<br/>           deletepermissionpolicy<br/>           deletesite<br/>           deletesolution<br/>           deletetemplate<br/>           deleteuser<br/>           deleteweb<br/>           deletewppack<br/>           deletezoneurl<br/>           deploysolution<br/>           deploywppack<br/>           disablessc<br/>           displaysolution<br/>           email<br/>           enablessc<br/>           enumalternatedomains<br/>           enumcontentdbs<br/>           enumdeployments<br/>           enumgroups<br/>           enumroles<br/>           enumservices<br/>           enumsites<br/>           enumsolutions<br/>           enumsubwebs<br/>           enumtemplates<br/>           enumusers<br/>           enumwppacks<br/>           enumzoneurls<br/>           execadmsvcjobs<br/>           export<br/>           extendvs<br/>           extendvsinwebfarm<br/>           forcedeletelist<br/>           getadminport<br/>           getproperty<br/>           getsitelock<br/>           geturlzone<br/>           import<br/>           installfeature<br/>           listlogginglevels<br/>           localupgradestatus<br/>           managepermissionpolicylevel<br/>           migrateuser<br/>           provisionservice<br/>           refreshdms<br/>           refreshsitedms<br/>           registerwsswriter<br/>           removedrservice<br/>           removesolutiondeploymentlock<br/>           renameserver<br/>           renameweb<br/>           restore<br/>           retractsolution<br/>           retractwppack<br/>           scanforfeatures<br/>           setadminport<br/>           setapppassword<br/>           setconfigdb<br/>           setlogginglevel<br/>           setproperty<br/>           setsitelock<br/>           setworkflowconfig<br/>           siteowner<br/>           spsearch<br/>           spsearchdiacriticsensitive<br/>           syncsolution<br/>           unextendvs<br/>           uninstallfeature<br/>           unregisterwsswriter<br/>           updateaccountpassword<br/>           updatealerttemplates<br/>           updatefarmcredentials<br/>           upgrade<br/>           upgradesolution<br/>           upgradetargetwebapplication<br/>           userrole<br/><br/>For information about other operations and parameters, <br/>use &#8220;stsadm.exe -help&#8221; or &#8220;stsadm.exe -help &lt;operation&gt;&#8221;<br />
</span></p>
<p>But how useful are these commands?  Consider the example of enumsites â€“ this command lists all Site Collections or a given Web Application.
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN]<br/>5&gt; .\stsadm.exe -help enumsites<br/><br/>stsadm.exe -o enumsites <br/>           -url &lt;virtual server url&gt;<br/>           -showlocks<br/>           -redirectedsites<br/><br/>[C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN]<br/>7&gt; .\stsadm.exe -o enumsites -url http://localhost<br/><br/>&lt;Sites Count=&#8221;1&#8243;&gt;<br/>  &lt;Site Url=&#8221;http://wss&#8221; Owner=&#8221;domain\administrator&#8221; SecondaryOwner=&#8221;domain\user&#8221; ContentDatabase=&#8221;WSS_C<br/>ontent_Default&#8221; StorageUsedMB=&#8221;0.5&#8243; StorageWarningMB=&#8221;0&#8243; StorageMaxMB=&#8221;0&#8243; /&gt;<br/>&lt;/Sites&gt;<br />
</span></p>
<p>Great, it gives me the output as XML, so I suppose that I can assign it to a variable within PowerShell and perform some XML queries on it - Not quite what I had in mind though when I thought about how PowerShell could automate SharePoint.
</p>
<p>Fortunately though the SharePoint Team do an excellent API that exposed 100% via .NET â€“ so PowerShell is right at home here thanks to its ability to just consume all things .NET, including the System.Reflection.Assembly class which can be used to load an assembly into the PowerShell Application Domain, so it can be called directly from the command line.  T load Microsoft.SharePoint.dll, all we need do is the following:
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[C:\PsScripts]<br/>3&gt; [System.Reflection.Assembly]::Load(&#8221;Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c&#8221;);<br/><br/>GAC    Version        Location                                                                                         <br/>&#8212;    &#8212;&#8212;-        &#8212;&#8212;&#8211;                                                                                         <br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\Microsoft.SharePoint\ 12.0.0.0__71e9bce111e9429c\Microsoft.SharePo&#8230;<br />
</span></p>
<p>Now we can call into the SharePoint object model to get the Application that we wish to enumerate the Site Collections for:
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[C:\PsScripts]<br/>4&gt; $webApplication = [Microsoft.SharePoint.Administration.SPWebApplication]::Lookup(&#8221;http://localhost&#8221;)<br/><br/>[C:\PsScripts]<br/>5&gt; $webApplication.Sites.Count<br/>1<br/><br/>[C:\PsScripts]<br/>6&gt; $webApplication.Sites | ft url, Owner, SecondaryContact<br/><br/>Url                                     Owner                                   SecondaryContact                       <br/>&#8212;                                     &#8212;&#8211;                                   &#8212;&#8212;&#8212;&#8212;&#8212;-                       <br/>http://wss                              domain\administrator                    domain\user<br />
</span></p>
<p>How cool is that?  The PowerShell Team have given us a full scripting tool for SharePoint because the SharePoint Team wrote a very good API and we can work with object, not strings or XML.
</p>
<p>As a final demo, I&#8217;ll show you that PowerShell can write through the SharePoint API as well as read from it:
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[C:\PsScripts]<br/>3&gt; . .\Load-sharePoint.ps1;<br/><br/>GAC    Version        Location                                                                                         <br/>&#8212;    &#8212;&#8212;-        &#8212;&#8212;&#8211;                                                                                         <br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\Microsoft.SharePoint\ 12.0.0.0__71e9bce111e9429c\Microsoft.SharePo&#8230;<br/>True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\Microsoft.SharePoint.Workflows\ 12.0.0.0__71e9bce111e9429c\Microso&#8230;<br/><br/>[C:\PsScripts]<br/>4&gt; $sc = new-object Microsoft.SharePoint.SPSite &#8220;http://localhost&#8221;;<br/><br/>[C:\PsScripts]<br/>5&gt; $rootWeb = $sc.Rootweb;<br/><br/>[C:\PsScripts]<br/>6&gt; write-host $rootWeb.Title;<br/>WSS Root Web<br/><br/>[C:\PsScripts]<br/>7&gt; $rootWeb.Title = &#8220;PowerShell has change the title!&#8221;;<br/><br/>[C:\PsScripts]<br/>8&gt; $rootweb.update();<br/><br/>[C:\PsScripts]<br/>9&gt; write-host $rootWeb.Title;<br />
</span></p>
<p><strong>Conclusion<br />
</strong></p>
<p>Job Done!  Not only have we got the same functionality that stsadm.exe provides us for the enumsites operation, but we&#8217;ve got the ability to change the WSS installation on the fly â€“ Now that&#8217;s what I mean when I talk about automating SharePoint!
</p>
<p>When we get round to deploying MOSS 2007 at my place of work, I&#8217;ll probably end up recreating all of stsadm.exe&#8217;s operations into PowerShell functions.  But for now, I&#8217;ve created a PowerShell script (<a href="http://www.captainliteral.net/wp-content/uploads/Load-SharePoint.ps1">Load-SharePoint.ps1</a>) that will load a couple of the SharePoint dll&#8217;s and then create a few functions:
</p>
<ul>
<li>Get-SiteCollection â€“ Returns the site collection at the specified URL.
</li>
<li>Get-SiteCollections â€“ Returns an array of Site Collections for the given Web Application, same as demo above
</li>
<li>Get-Sites â€“ Returns an array of sites for the given Site Collection
</li>
</ul>
<p>For details on running .ps1 scripts, please see my previous post - <a href="http://www.captainliteral.net/2007/01/29/powershell-basics-%e2%80%93-running-scripts/">PowerShell Basics â€“ Running Scripts</a>.
</p>
<p>If you want to explore the SharePoint object model (with or without PowerShell), you&#8217;re going to want to get the <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=05e0dd12-8394-402b-8936-a07fe8afaffd&amp;DisplayLang=en">WSS 3 SDK</a> and/or the <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=6d94e307-67d9-41ac-b2d6-0074d6286fa9&amp;DisplayLang=en">MOSS 2007 SDK</a> as it&#8217;s the only place to get a full description of the classes that you&#8217;re going to work with.
</p>
<p>This post is only the tip of the iceberg, I&#8217;ve been using PowerShell and the MOSS 2007/WSS 3 API to upload InfoPath form templates, create sites/lists and to try things out before I commit  them to C# assemblies.  As a developer, PowerShell saves me from the write, compile, run loop that I usually get into when I&#8217;m learning an API.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/CaptainLiteral?a=dnW0E0btaY4:D6tQE8WvWYw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/CaptainLiteral?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/CaptainLiteral?a=dnW0E0btaY4:D6tQE8WvWYw:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/CaptainLiteral?i=dnW0E0btaY4:D6tQE8WvWYw:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.captainliteral.net/2007/01/31/sharepoint-automation-with-powershell/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.captainliteral.net/2007/01/31/sharepoint-automation-with-powershell/</feedburner:origLink></item>
		<item>
		<title>PowerShell Basics â€“ Running Scripts</title>
		<link>http://feedproxy.google.com/~r/CaptainLiteral/~3/fV2t957KuJ0/</link>
		<comments>http://www.captainliteral.net/2007/01/29/powershell-basics-%e2%80%93-running-scripts/#comments</comments>
		<pubDate>Tue, 30 Jan 2007 00:38:58 +0000</pubDate>
		<dc:creator>Mark Sheppard</dc:creator>
		
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://www.captainliteral.net/2007/01/29/powershell-basics-%e2%80%93-running-scripts/</guid>
		<description><![CDATA[

One of the comments I had on a post I did last week was about how to run scripts.  It&#8217;s a fair point, somebody new to PowerShell will find it a little odd that they can&#8217;t just run a script found on the Internet â€“ I find it reassuring.

On a newly installed PowerShell system, [...]]]></description>
			<content:encoded><![CDATA[
<!-- ALL ADSENSE ADS DISABLED -->
<p>One of the comments I had on a post I did last week was about how to run scripts.  It&#8217;s a fair point, somebody new to PowerShell will find it a little odd that they can&#8217;t just run a script found on the Internet â€“ I find it reassuring.
</p>
<p>On a newly installed PowerShell system, running a script will result in something like the following:
</p>
<p style="background: #012456"><span style="font-family:Lucida Console; font-size:10pt"><span style="color:#eeedf0">[D:\PsScripts]<br/>1&gt; &amp; D:\PsScripts\test-scriptExecution1.ps1<br/></span><span style="color:red">File D:\PsScripts\test-scriptExecution1.ps1 cannot be loaded because the execution of scripts is disabled on this syste<br/>m. Please see &#8220;get-help about_signing&#8221; for more details.<br/>At line:1 char:38<br/>+ D:\PsScripts\test-scriptExecution1.ps1 &lt;&lt;&lt;&lt;<br />
</span></span></p>
<h1>Understanding the Execution Policy<br />
</h1>
<p>The reason for this is the Execution Policy in place on the machine prevents all scripts from running by default.  There are 4 Execute Policies defined in PowerShell, according to the help files, they are:
</p>
<ul>
<li>Restricted â€“ Does not load configuration files or run scripts. &#8220;Restricted&#8221; is the default.
</li>
<li>AllSigned â€“ Requires that all scripts and configuration files be signed by a trusted publisher, including scripts that you write on the local computer.
</li>
<li>RemoteSigned â€“ Requires that all scripts and configuration files downloaded from the Internet be signed by a trusted publisher.
</li>
<li>Unrestricted â€“ Loads all configuration files and runs all scripts. If you run an unsigned script that was downloaded from the Internet, you are prompted for permission before it runs.
</li>
</ul>
<p>To control execution policies, PowerShell ships with a couple of cmdlets Get-ExecutionPolicy and Set-ExecutionPolicy.  They basically do what they say on the tin:
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[D:\PsScripts]<br/>2&gt; Get-ExecutionPolicy<br/>Restricted<br/><br/>[D:\PsScripts]<br/>3&gt; Set-ExecutionPolicy Unrestricted<br/><br/>[D:\PsScripts]<br/>4&gt; Get-ExecutionPolicy<br/>Unrestricted<br/><br/>[D:\PsScripts]<br/>5&gt; &amp; D:\PsScripts\test-scriptExecution1.ps1<br/>this output is from test-scriptExecution1.ps1<br />
</span></p>
<p>Using an Unrestricted Execution Policy will allow you to execute any script.  I would not recommend that you run with this setting on a production server in your data centre though â€“ the next script from hackmybox.com you download could include a command to uninstall IIS from your web server!
</p>
<p>For more information about setting execution policies and signing scripts (something that I&#8217;m not going to go into here) try the following help commands:
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[D:\PsScripts]<br/>7&gt; Get-Help Set-ExecutionPolicy | more<br/><br/>[D:\PsScripts]<br/>8&gt; Get-Help about_signing | more<br />
</span></p>
<h1>Invoking Scripts<br />
</h1>
<p>Scripts are text file with a .ps1 extension.  When a script is invoked, the commands inside the script are executed.  The scope that the script executes in is local to the script, so functions and variables will not be accessible to the calling scope.
</p>
<p>To invoke a script you use the call/invoke operator (&amp;) and either the local or the full path to the script:
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[D:\PsScripts]<br/>9&gt; &amp; D:\PsScripts\test-scriptInvoking1.ps1          #Execute with full path<br/>This output is from test-scriptInvoking1.ps1.  Arguments: No arguments passed<br/><br/>[D:\PsScripts]<br/>10&gt; &amp; .\test-scriptInvoking1.ps1          #Execute with local path<br/>This output is from test-scriptInvoking1.ps1.  Arguments: No arguments passed<br />
</span></p>
<p>The call/invoke operator (&amp;) isn&#8217;t always needed though, .\test-scriptExecution.ps1 works just fine, providing you&#8217;re in the same location as the script.
</p>
<p>To pass arguments to the script, just invoke it with a space-separated list of arguments after the script file:
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[D:\PsScripts]<br/>18&gt; &amp; .\test-scriptInvoking1.ps1 &#8220;Argument 1&#8243;<br/>This output is from test-scriptInvoking1.ps1.  Arguments: Argument 1<br />
</span></p>
<h1>Dot Sourcing Scripts<br />
</h1>
<p>Dot Sourcing a script alters the way the script&#8217;s scope is created.  When a script is Dot Sourced, it executes under the current scope and not a local one.  Consider the following:
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[D:\PsScripts]<br/>19&gt; type test-scriptInvoking2.ps1<br/># internal function to the script<br/>function internalScriptFunction() {<br/>        write-host &#8220;this is from internalScriptFunction&#8221;;<br/>}<br/><br/># call function from within script<br/>internalScriptFunction;<br/><br/>[D:\PsScripts]<br/>20&gt; &amp; D:\PsScripts\test-scriptInvoking2.ps1Â Â Â Â #Invoke script<br/>this is from internalScriptFunction<br/><br/>[D:\PsScripts]<br/>21&gt; dir function: | where-object { $_.Name -match &#8220;internal&#8221; }Â Â Â Â #Check for function in current scope<br/><br/>[D:\PsScripts]<br/>22&gt; . D:\PsScripts\test-scriptInvoking2.ps1Â Â Â Â #Dot Source script<br/>this is from internalScriptFunction<br/><br/>[D:\PsScripts]<br/>23&gt; dir function: | where-object { $_.Name -match &#8220;internal&#8221; }Â Â Â Â #Check for function in current scope<br/><br/>CommandType     Name                                                Definition<br/>&#8212;&#8212;&#8212;&#8211;     &#8212;-                                                &#8212;&#8212;&#8212;-<br/>Function        internalScriptFunction                              write-host &#8220;this is from internalScriptFunction&#8221;&#8230;<br/><br/>[D:\PsScripts]<br/>24&gt; internalScriptFunctionÂ Â Â Â #Invoke function directly from current scope<br/>this is from internalScriptFunction<br />
</span></p>
<h1>Invoking Scripts from the Internet<br />
</h1>
<p>OK, so we know how to run scripts and control execution scope, but why the following when a script is run from the Internet?
</p>
<p style="background: #012456"><span style="color:#eeedf0; font-family:Lucida Console; font-size:10pt">[D:\PsScripts]<br/>25&gt; &amp; D:\PsScripts\test-invokeScriptFromInternet.ps1<br/><br/>Security Warning<br/>Run only scripts that you trust. While scripts from the Internet can be useful, this script can potentially harm your<br/>computer. Do you want to run D:\PsScripts\test-invokeScriptFromInternet.ps1?<br/>[D] Do not run  [R] Run once  [S] Suspend  [?] Help (default is &#8220;D&#8221;):<br />
</span></p>
<p>It seems that the PowerShell Team thought about this scenario and made PowerShell take note of files that IE marks as coming from an untrusted or partially-trusted source such as sites Internet Explorer classes as coming from the Internet Zone.  When PowerShell comes across such a script file, it gives you a chance to say &#8220;no thanks, don&#8217;t run that script!&#8221;
</p>
<p>What&#8217;s really neat though is that you can copy the file around, rename it and even edit it and PowerShell will still know the file came from the Internet and present you with the extra challenge/response prompt â€“ very nice feature.
</p>
<h1>To Finish<br />
</h1>
<p>Well, that&#8217;s all you need to know about executing scripts in PowerShell â€“ I&#8217;m happy to know that it&#8217;s not easy to run a script, and the error messages do guide you towards getting the Execution Policy right for your situation.
</p>
<p>There is just one last thing that should be mentioned to complete the story â€“ The PowerShell Team released an Admin Template (.adm file used in Group plicy) for PowerShell that can be found on the <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=2917a564-dbbc-4da7-82c8-fe08b3ef4e6d&amp;DisplayLang=en">Microsoft Downloads site</a>.  The template only contains one setting that can be controlled via Group Policy â€“ Execution Policy.
</p>
<p><img src="http://www.captainliteral.net/wp-content/uploads/2007/01/012907-2342-powershellb13.png" alt=""/>
	</p>
<p>This will allow you to enforce a policy on machines where you don&#8217;t want people to just execute scripts that aren&#8217;t signed.  What&#8217;s really good about this is that PowerShell will not let the user override this from the command line:
</p>
<p style="background: #012456"><span style="font-family:Lucida Console; font-size:10pt"><span style="color:#eeedf0">PS C:\&gt; Set-ExecutionPolicy unrestricted<br/></span><span style="color:red">Set-ExecutionPolicy : Windows PowerShell updated your local preference successfully, but the setting is overridden by t<br/>he group policy applied to your system.  Due to the override, your shell will retain its current effective execution po<br/>licy of &#8220;AllSigned&#8221;. Contact your group policy administrator for more information.<br/>At line:1 char:20<br/>+ Set-ExecutionPolicy  &lt;&lt;&lt;&lt; unrestricted<br />
</span></span></p>
<p>Of cause, this isn&#8217;t full proof â€“ there&#8217;s nothing to stop me opening a script in notepad and copy/pasting the contents to a PowerShell session â€“ but is should be enough to remind people that they are on a restricted server.</p>
<p><strong>Update:</strong> The PowerShell Team has just posted <a href="http://blogs.msdn.com/powershell/archive/2007/02/15/execution-policy-and-vista.aspx">here</a> details of how to manage the execution policy on Windows Vista.  Their post completes the story detailed in this post.  If you run Windows Vista and run PowerShell scripts, you need to read it.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/CaptainLiteral?a=fV2t957KuJ0:yIaDSvYY7k0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/CaptainLiteral?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/CaptainLiteral?a=fV2t957KuJ0:yIaDSvYY7k0:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/CaptainLiteral?i=fV2t957KuJ0:yIaDSvYY7k0:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.captainliteral.net/2007/01/29/powershell-basics-%e2%80%93-running-scripts/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.captainliteral.net/2007/01/29/powershell-basics-%e2%80%93-running-scripts/</feedburner:origLink></item>
		<item>
		<title>Goodbye Windows Live Spaces â€“ Hello CaptainLiteral.NET!</title>
		<link>http://feedproxy.google.com/~r/CaptainLiteral/~3/-VaB4KDVtKE/</link>
		<comments>http://www.captainliteral.net/2007/01/28/goodbye-windows-live-spaces-%e2%80%93-hello-captainliteralnet/#comments</comments>
		<pubDate>Sun, 28 Jan 2007 18:56:35 +0000</pubDate>
		<dc:creator>Mark Sheppard</dc:creator>
		
		<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.captainliteral.net/2007/01/28/goodbye-windows-live-spaces-%e2%80%93-hello-captainliteralnet/</guid>
		<description><![CDATA[

I&#8217;m moving my blog away from Windows Live Spaces to CaptainLiteral.NET, so if anybody has subscribed to my feed, then you&#8217;d best update it to point at http://feeds.feedburner.com/CaptainLiteral. I&#8217;ve also set-up a FeedBurner thing for my RSS, so people won&#8217;t be hit by changes in the future.
Why Captain Literal? The guys as work call me [...]]]></description>
			<content:encoded><![CDATA[
<!-- ALL ADSENSE ADS DISABLED -->
<p>I&#8217;m moving my blog away from Windows Live Spaces to <a href="http://www.captainliteral.net/">CaptainLiteral.NET</a>, so if anybody has subscribed to my feed, then you&#8217;d best update it to point at <a href="http://feeds.feedburner.com/CaptainLiteral">http://feeds.feedburner.com/CaptainLiteral</a>. I&#8217;ve also set-up a FeedBurner thing for my RSS, so people won&#8217;t be hit by changes in the future.</p>
<p>Why Captain Literal? The guys as work call me Captain Literal because lunchtime conversations&#8217; can go something like this:<br />
<a href="http://www.istherefood.com">Dan</a>: &#8220;You can&#8217;t reboot a computer on a plane, it&#8217;ll crash,&#8221; followed by a hand movement to indicate that a plane would fall from the sky.<br />
Mark (aka Captain Literal): &#8220;That&#8217;s why life-critical systems such as planes have multiple fail-safe&#8217;s on them. The space shuttle for example has multiple computers and they all vote on what&#8217;s going to happen. You could reboot one of those with no problems and the shuttle wouldn&#8217;t spiral off into outer-space.&#8221;<br />
So that&#8217;s it, I have been nick-named Captain Literal and now Mark really is CaptainLiteral.NET.</p>
<p>Before I go out on a rant and document why I&#8217;m moving away from Spaces, I first need to thank Ashleigh (<a href="http://www.nakedcleaner.com">http://www.nakedcleaner.com</a>) for firstly, hosting CaptainLiteral.NET. Secondly, for forcing me to setup CaptainLiteral.NET. And thirdly, for spending time last night actually setting up CaptainLIteral.NET â€“ thanks Ashleigh.</p>
<p>And now for the fun bit â€“ why am I leaving Windows Live Spaces?</p>
<p>Live Spaces has some things that merely annoying â€“ these are the things that one can live with. But it also has some things that are <strong>very</strong> annoying â€“ things that, when realised, encourage you to drop Windows Live Spaces and go look for some other blog provisioning service or friend to host for you.</p>
<p>The merely annoying stuff (in no particular order):</p>
<ul>
<li>The statistics page is so badly laid out, it&#8217;s next to meaningless. For example, every page begins with the name of the blog the stats page chops the page title, so all I see if somebody viewed a page on my blog followed by â€¦ - very useful!.</li>
<li>You have to read the refer URL to work out what people searched for to find you on the stats page.</li>
<li>You can pay to get rid of adverts by subscribing to the hotmail advanced package, but don&#8217;t get any other features for doing so (i.e. being able to change the page layout more than anybody else.) for somebody like myself, who doesn&#8217;t even have a hotmail account, this is never going to work!</li>
<li>Trackbacks don&#8217;t seem to work like they should.</li>
</ul>
<p>But the killer, the one that got me to move blog was that fact that you can&#8217;t upload non-image files! So when I posted <a href="http://www.captainliteral.net/2007/01/22/sudoku-vs-powershell/">Sudoku vs. PowerShell</a> last week and wanted to upload 3 simple text files, I couldn&#8217;t! again, Ashleigh came to the rescue and allowed me to host the files on his other blog (<a href="http://www.f1-blog.co.uk">http://www.f1-blog.co.uk</a>) â€“ thanks again Ashleigh.</p>
<p>Anyway, now that&#8217;s off my chest, I hope to see you over at CaptainLIteral.NET â€“ where I intend to blog more often as I&#8217;ve realised that I actually have quite a lot to say in the technology space. I will not be posting personal posts as I really don&#8217;t have an interesting life unlike professionals (aka celebrities.)</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/CaptainLiteral?a=-VaB4KDVtKE:VUCYK3VFfc0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/CaptainLiteral?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/CaptainLiteral?a=-VaB4KDVtKE:VUCYK3VFfc0:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/CaptainLiteral?i=-VaB4KDVtKE:VUCYK3VFfc0:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.captainliteral.net/2007/01/28/goodbye-windows-live-spaces-%e2%80%93-hello-captainliteralnet/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.captainliteral.net/2007/01/28/goodbye-windows-live-spaces-%e2%80%93-hello-captainliteralnet/</feedburner:origLink></item>
		<item>
		<title>Contact Form</title>
		<link>http://feedproxy.google.com/~r/CaptainLiteral/~3/xdYxLFdl-NA/</link>
		<comments>http://www.captainliteral.net/2007/01/24/about/#comments</comments>
		<pubDate>Wed, 24 Jan 2007 14:59:37 +0000</pubDate>
		<dc:creator>Mark Sheppard</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.captainliteral.net/?page_id=2</guid>
		<description><![CDATA[

Fill in the form below, and I will get back to you.&#160;


Your Name: 

 (required)
Your Email:

 (required)
Your Website:


Your Message: 






&#160;
]]></description>
			<content:encoded><![CDATA[
<!-- ALL ADSENSE ADS DISABLED -->
<p>Fill in the form below, and I will get back to you.&nbsp;</p>
<div class="contactform">
<form action="http://www.captainliteral.net/2007/01/24/about/" method="post">
<div class="contactleft"><label for="wpcf_your_name">Your Name: </label></div>
<div class="contactright">
<input type="text" name="wpcf_your_name" id="wpcf_your_name" size="30" maxlength="50" value="" /> (required)</div>
<div class="contactleft"><label for="wpcf_email">Your Email:</label></div>
<div class="contactright">
<input type="text" name="wpcf_email" id="wpcf_email" size="30" maxlength="50" value="" /> (required)</div>
<div class="contactleft"><label for="wpcf_website">Your Website:</label></div>
<div class="contactright">
<input type="text" name="wpcf_website" id="wpcf_website" size="30" maxlength="100" value="" /></div>
<div class="contactleft"><label for="wpcf_msg">Your Message: </label></div>
<div class="contactright"><textarea name="wpcf_msg" id="wpcf_msg" cols="35" rows="8" ></textarea></div>
<div class="contactright">
<input type="submit" name="Submit" value="Submit" id="contactsubmit" />
<input type="hidden" name="wpcf_stage" value="process" /></div>
</p></form>
</p></div>
<div style="clear:both; height:1px;">&nbsp;</div>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/CaptainLiteral?a=xdYxLFdl-NA:bNrX0SE42xg:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/CaptainLiteral?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/CaptainLiteral?a=xdYxLFdl-NA:bNrX0SE42xg:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/CaptainLiteral?i=xdYxLFdl-NA:bNrX0SE42xg:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.captainliteral.net/2007/01/24/about/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.captainliteral.net/2007/01/24/about/</feedburner:origLink></item>
		<item>
		<title>Sudoku Vs PowerShell</title>
		<link>http://feedproxy.google.com/~r/CaptainLiteral/~3/_ZKCBZuFRCM/</link>
		<comments>http://www.captainliteral.net/2007/01/22/sudoku-vs-powershell/#comments</comments>
		<pubDate>Tue, 23 Jan 2007 00:27:23 +0000</pubDate>
		<dc:creator>Mark Sheppard</dc:creator>
		
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://www.captainliteral.net/?p=4</guid>
		<description><![CDATA[

I&#8217;ve been obsessed since Adrian (ps1.soapyfrog.com) posted his Sudoku solving PowerShell script a couple of weeks ago. When I first read his post on the subject, I pulled down his script and ran it - at the time he didn&#8217;t know how long it would take to solve the harder of the two puzzles he [...]]]></description>
			<content:encoded><![CDATA[
<!-- ALL ADSENSE ADS DISABLED -->
<p>I&#8217;ve been obsessed since <a href="http://ps1.soapyfrog.com/2007/01/05/sudoku/trackback/">Adrian (ps1.soapyfrog.com)</a> posted his Sudoku solving PowerShell script a couple of weeks ago. When I first read his post on the subject, I pulled down his script and ran it - at the time he didn&#8217;t know how long it would take to solve the harder of the two puzzles he posted - after about an hour PowerShell had crashed on my computer! Since then Adrian has posted saying that his script takes 1.2 days to solve his harder puzzle!</p>
<p>Having peeked at his script I quickly discovered that it works on a brute-force principle (i.e. if you don&#8217;t know what number you should have in a square, guess), this seemed to work well for the easier of his samples (solved in less than a second). I decided that I&#8217;d see if I could do better and learn a few things along the way. And so started my obsession with implementing a speedy Sudoku solver in PowerShell â€“ this shouldn&#8217;t have taken two weeks, but work, life and a couple of other things got in the way. I swear, I don&#8217;t know how people play with technology and constantly post about it.</p>
<p>To start with, I had no idea how to solve a Sudoku puzzle with a computer, yet alone in PowerShell â€“ Enter a trusty search engine to the rescue. I quickly found <a href="http://www.scanraid.com/sudoku.htm">Andrew&#8217;s Sudoku solver</a>. Now, what&#8217;s interesting about Andrew&#8217;s site is that he not only solves Sudoku, he shows you step by step how to do it and he&#8217;s published over 30 different strategies for solving Sudoku, complete with pictures. <span style="font-family: Wingdings">J</span></p>
<p>Armed with details of how to solve Sudoku, I set about scripting it and making it perform better than the couple of minutes it took when I first solved the problem. In the end I got the script to solve Adrian&#8217;s hard puzzle in <strong>12 seconds</strong> â€“ not bad! For a comparison I ported the script into C# and got it to solve the same puzzle in less than 0.1 seconds. Now, I know that PowerShell isn&#8217;t designed for processing performance, but rather admin performance, but it&#8217;s important to know the limits of a piece of software so you can get the right tool out of the toolbox when you need it. The C# port was written as a static and I just invoked it directly from within PowerShell and has the exact same output as from a .ps1 script â€“ I could just have easily written this as a cmdlet.</p>
<p>Fortunately, I only had to implement a few of the &#8220;basic&#8221; strategies described on Andrew&#8217;s site to solve the harder puzzle â€“ some of the advanced strategies didn&#8217;t look like they&#8217;d be fun to implement. I&#8217;ve taken this script as far as I want to take it and learnt a lot about PowerShell and the way it works. My lessons and observations will form the thesis of a blog post to follow in the next few days.</p>
<p>In the meantime, here&#8217;s my <a href="http://www.f1-blog.co.uk/mark/solve-sudoku.ps1">solve-sudoku </a>script, Adrian&#8217;s original <a href="http://www.f1-blog.co.uk/mark/sample-puzzle.txt">simple puzzle </a>and his original <a href="http://www.f1-blog.co.uk/mark/profile-puzzle.txt">hard puzzle </a>for you to play with. Just execute the script specifying the puzzle to solve as an argument (<em>.\solve-Sudoku.ps1 profile-puzzle.txt</em>)</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/CaptainLiteral?a=_ZKCBZuFRCM:e-BXoPSvC0Y:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/CaptainLiteral?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/CaptainLiteral?a=_ZKCBZuFRCM:e-BXoPSvC0Y:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/CaptainLiteral?i=_ZKCBZuFRCM:e-BXoPSvC0Y:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.captainliteral.net/2007/01/22/sudoku-vs-powershell/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.captainliteral.net/2007/01/22/sudoku-vs-powershell/</feedburner:origLink></item>
	</channel>
</rss>
