VSoft Technologies BlogsVSoft Technologies Blogs - posts about our products and software development.https://www.finalbuilder.com/resources/blogsFinalBuilder 6 : PowerShell (Part Three, Custom Actions)https://www.finalbuilder.com/resources/blogs/postid/620/finalbuilder-6-powershell-part-three-custom-actiFinalBuilderWed, 02 Apr 2008 03:00:00 GMT<p>This is the last in a series of blog posts about PowerShell support in FinalBuilder 6.</p> <ul> <li><a href="/resources/blogs/finalbuilder-6-powershell-part-one-execute-condi">Part One</a> showed how to use one-liners to create powerful PowerShell execute conditions.</li> <li><a href="/resources/blogs/finalbuilder-6-powershell-part-two-script-events">Part Two</a> showed how to use PowerShell script events to parse output and change the behaviour of an action.</li> </ul> <p> </p> <p>For this last post, I'm going to walk through creating a custom action which scans the Event Log and reports the frequency of messages from different sources.</p> <h2>The Script</h2> <p>Here are the parts of the PowerShell script that I'm going to use to implement the new action.</p> <p><strong>1) A custom function</strong></p> <p>WMI uses dmtf date formatting. This is a PowerShell function to create a dmtf datetime string representing (Now - $x hours) ago.</p> <blockquote>function dmtfWithin([int] $hours)<br /> {<br />   [System.Management.ManagementDateTimeconverter]::ToDmtfDateTime `<br />     ([DateTime]::Now.AddHours(- $hours))<br /> }</blockquote> <p> </p> <p><strong>2) Read Action Properties</strong></p> <p>Action properties are loaded using the same syntax as other custom actions. If you've used ActionStudio before then this will look familiar. Coming in-the-pipeline are some CmdLets to make this look more like PowerShell and less like .NET.</p> <blockquote># Set up parameters<br /> $computerName = $Context.ExpandExpression($Context.Properties.PropertyAsString("ComputerName"), $True)<br /> $hours = $Context.Properties.PropertyAsString("Hours")</blockquote> <p> </p> <p><strong>3) Process Event Log</strong></p> <p>This is where the dirty work happens - build a WQL filter string, get the WMI objects for the event log entries, and build a hashtable mapping event source names to their frequencies. The particularly neat line is the last one with the % sign - that's shorthand for "for each".</p> <blockquote># Read results<br /> $filter = "TimeWritten > '" + (dmtfWithin($hours)) + "'"<br /> $results = Get-WmiObject -computer $computerName -class Win32_NTLogEvent -filter $filter<br /> $freqTable = @{}<br /> $results | % { $freqTable[$_.SourceName] += 1 }</blockquote> <p> </p> <p><strong>4) Log the Results</strong></p> <p>Log the contents of our hash table, sorted and formatted into a table:</p> <blockquote># Log Results<br /> $freqTable.GetEnumerator() | sort -descending Value | ft Value, Name -autosize -wrap</blockquote> <p> </p> <p><strong>5) Set Result to True</strong><br /> <br /> The Result parameter determines whether or not to fail the action.</p> <blockquote>$Result = $True</blockquote> <p> </p> <h2>Download</h2> <p><a href="/blogimages/PowerShell/PowerShellCustomAction.zip">Click here to download</a> a zip file with the custom action package. The unzipped .fbap file needs to be saved in the ActionDefs directory inside the FinalBuilder 6 program directory.</p> <h2>More Resources</h2> <p>The example action package "FBScriptExamples.fbap" comes with FinalBuilder, and contains some more sample PowerShell actions which can be loaded in ActionStudio.</p> <p>The ActionStudioManual.pdf file (located in the FinalBuilder Program directory) contains a reference section with built-in custom action types and methods, and also some more information on creating PowerShell actions.</p> <h2>Some Notes</h2> <ul> <li>This is a pretty simple example, but (like the others) it is fairly simple to extend it to cover lots of other Windows-related tasks.</li> <li>FYI, there is a dedicated Get-EventLog command in PowerShell. In this instance, I chose to use WMI instead because WMI can read from remote machines, and can read across all event logs. If you use the dedicated command, you need to choose a single event log to read from.</li> </ul> 620FinalBuilder 6 : PowerShell (Part Two, Script Events)https://www.finalbuilder.com/resources/blogs/postid/619/finalbuilder-6-powershell-part-two-script-eventsFinalBuilderTue, 25 Mar 2008 18:00:00 GMT<h2> PowerShell Script Events</h2> <p>This is Part Two in a series about the new PowerShell support in FinalBuilder 6. In <a href="/resources/blogs/finalbuilder-6-powershell-part-one-execute-condi">Part One</a>, we learned how to create an action Execute Condition using PowerShell.</p> <p>In this article we will show how to use PowerShell as a scripting language in the FinalBuilder IDE, in order to customize the behaviour of a built-in FinalBuilder action. We'll also showcase some of the powerful string processing features in PowerShell.</p> <h2>Script Events</h2> <p>When you add an action to a FinalBuilder project, you also add at least three script events:</p> <ul> <li>BeforeAction - This script event is called before the action runs.</li> <li>OnStatusMessage - This script event is called each time the action outputs something to the log.</li> <li>AfterAction - This script event is called after the action has finished running.</li> </ul> <p>You can access the script events by clicking on the "Script Editor" tab in FinalBuilder. For this blog post, we're going to use PowerShell to create an implementation for each of these script events.</p> <p> </p> <h2>PsLogList</h2> <p>I'm going use scripting to extend the built-in FinalBuilder action for the PsLogList tool. PsLogList is part of the <a href="http://technet.microsoft.com/en-us/sysinternals/bb896649.aspx" target="_blank">PsTools suite from SysInternals/Microsoft</a>. It dumps the contents of the event log on a local or remote machine.</p> <p>We're going to customize the action so it parses the list of log entries to automatically extract data about the frequency of events from different sources.</p> <h2>Output format</h2> <p>Here's an example log entry, as output from PsLogList:</p> <blockquote>[16664] Service Control Manager<br /> Type: INFORMATION<br /> Computer: DYNAMO<br /> Time: 3/03/2008 3:09:18 PM ID: 7035<br /> User: NT AUTHORITY\SYSTEM<br /> The IMAPI CD-Burning COM Service service was successfully sent a start control.</blockquote> <p> </p> <p>For our example, the piece of data want to extract would be "Service Control Manager" in the expression above. To extract this, we can use the following Regular Expression:</p> <blockquote>^\[\d+\] (.+)$</blockquote> <p>Regular expressions are supported directly in PowerShell. You can create a regular expression using a code snippet like this:</p> <blockquote>$headerExpr = [regex] "\[\d+\] (.+)"</blockquote> <p>(If you ever need help remembering Regular Expression syntax, I recommend <a href="http://www.regular-expressions.info/reference.html" target="_blank">www.regular-expressions.info</a>.)</p> <p> </p> <h2>Hash tables</h2> <p>The other piece of PowerShell functionality that we're going to make use of is the hash table. We're going to create an empty PowerShell hash table, and then use it as a dictionary to store event source names along with the frequency that each source appears.</p> <p>Here's the script used to create a new empty hashtable:</p> <blockquote>$hashTable = ${}</blockquote> <p>To increment the frequency of an item in the table, we can use the increment operation += on the hashtable entry. If there is no entry, PowerShell returns $null, but ($null + 1) == 1 so it will work properly.</p> <blockquote>$hashTable[$name] += 1<br />  </blockquote> <p> </p> <h2>Scripting it up</h2> <p>Here are the complete script events: (<a href="https://www.finalbuilder.com/blogimages/PowerShell Script Event Example.zip">download as project</a>.)</p> <h3>BeforeAction Script Event</h3> <blockquote># Create empty hash table for use in action (we need to store it in a Project Variable)<br /> $FBVariables["FrequencyTable"] = @{ } </blockquote> <blockquote> </blockquote> <h3>OnStatusMessage Script Event</h3> <blockquote># When output comes from the action, check if it is an Event header line<br /> <br /> $headerPattern = "^\[\d+\] (.+)$"<br /> $RegexOptions = [System.Text.RegularExpressions.RegexOptions]<br /> <br /> foreach ( $match in [regex]::Matches( $StatusMessage.MessageText, $headerPattern, $RegexOptions::MultiLine ) )<br /> {<br />   $appName = $match.Groups[1].Value.Trim()<br />   $freqTable = $FBVariables["FrequencyTable"]<br />   $freqTable[$appName] += 1<br /> }</blockquote> <p> </p> <h3>AfterAction Script Event</h3> <blockquote># Log the frequencies, sorted by value<br /> "Frequencies for different sources"<br /> $FBVariables["FrequencyTable"].GetEnumerator() | sort -descending Value | ft Value, Name -autosize -wrap<br /> #<br /> # (the .GetEnumerator() call in the expression above is a trick which allows us to sort the contents of the hashtable.)</blockquote> <h2>Download the Project</h2> <p><a href="https://www.finalbuilder.com/blogimages/PowerShell Script Event Example.zip">Click here to download a sample project with this action</a>.</p> <p>The downloaded project has one more feature: it suppresses the normal output from PsLogList. Only our custom information is shown in the log.</p> <h2>Action output</h2> <p>Here's the log output from when the action is run normally:</p> <blockquote>Frequencies for different sources<br /> Value Name<br /> ----- ----<br /> 29 Service Control Manager<br /> 3 Application Popup<br /> 2 W32Time<br /> 2 IPSec<br /> 2 EventLog<br /> 2 WinHttpAutoProxySvc<br /> 1 DCOM<br /> 1 AeLookupSvc<br /> 1 Tcpip6<br /> 1 Tcpip<br /> 1 redbook</blockquote> <h2>Why this is Useful</h2> <p>OK, so this example isn't particularly relevant for automated builds. However, this technique (or one like it) can be used to parse information from any tool which is run by FinalBuilder.</p> <h2>Notes</h2> <ul> <li>Having a script event run every time data is logged decreases the performance of the action. For actions which log very large amounts of data, it's better to use Log To Variable and then process the output all-at-once in a separate action.</li> </ul> <ul> <li>You'll note that the actual regular expression call used in the script event is different to the example  expression showed at the beginning. We have to call the .NET RegularExpression class directly in order to use MultiLine mode. (If anyone from the PowerShell Team is reading this, please try and find a way to set the expression mode with simpler syntax!)</li> </ul> <ul> <li>You can actually do everything shown in the example with JavaScript instead of PowerShell, using a Regexp object and an associative array. However, some steps (like automatically printing the results) are much more complex to do with JavaScript.</li> </ul> <ul> <li>You could also get the same results from a PowerShell action by using get-wmi and the Win32_NTLogEvent class. That will be the subject of upcoming blog post Part Three: Custom actions.</li> </ul> 619FinalBuilder 6 : PowerShell (Part One, Execute Conditions)https://www.finalbuilder.com/resources/blogs/postid/618/finalbuilder-6-powershell-part-one-execute-condiFinalBuilderMon, 17 Mar 2008 18:00:00 GMT<h2>Introduction</h2> <p>PowerShell support in FinalBuilder 5.5 was limited to the Execute PowerShell Action. For FinalBuilder 6, we've made PowerShell a "first class" scripting language, alongside JavaScript and VBScript.</p> <p>This is the first in a series of blog posts which show the different ways PowerShell can integrate with FinalBuilder. Today's example is the Execute Condition.</p> <h2>Execute Conditions</h2> <p>Every action in FinalBuilder has a field called the "Execute Condition", on the Runtime property page.</p> <p>This lets you place a single line of script which evaluates as a boolean condition. If the script evaluates "True", the action will execute. If the script evaluates "False", the action will be skipped.</p> <h2>PowerShell Execute Conditions</h2> <p>Due to it's terse but expressive syntax, PowerShell seems to lend itself to one-line expressions (a quick <a href="http://www.google.com.au/search?q=PowerShell+one-liners" target="_blank">Google search</a> will confirm this.) This can be great for execute conditions.</p> <h2>Examples</h2> <p>If you want an action to only run if Notepad is executing, you can use this one-line expression:</p> <p><strong>get-Process | where {$_.name -eq "NotePad"}</strong></p> <p><img alt="PowerShell Execute Condition" src="/blogimages/PowerShell/PowerShellExecuteCondition.png" /></p> <p>If you want an action to run only if a remote computer is online, you can use this expression:</p> <p><strong>gwmi Win32_PingStatus -Filter "Address='remotePC'" |where {$_.StatusCode -eq 0}</strong></p> <p>PowerShell treats any non-null value as equivalent to $True, so any result will be regarded as True, while no result will be regarded as False.</p> <h2>Caveats</h2> <p>I think one-liners are neat. It's probably because they remind me of growing up with my Apple //e and <a href="http://en.wikipedia.org/wiki/Nibble_(magazine)" target="_blank">Nibble magazine's</a> one-liner competition. However, like anything else, one liners can be abused. They can be the stuff of programming horror stories.</p> <p>My suggestions for responsible Execute Condition use:</p> <ul> <li>Put something in the action comment field if the Execute Condition isn't self-documenting.</li> <li>Use a script event if the Execute Condition gets longer than the text field on the Runtime page.</li> </ul> <p> </p> <p>Next - <a href="/resources/blogs/finalbuilder-6-powershell-part-two-script-events">Part Two : Script Events</a></p> <p> </p> <p>( Credits : thanks to beta tester Robert for the Notepad suggestion.)</p> 618Windows Powershellhttps://www.finalbuilder.com/resources/blogs/postid/581/windows-powershellAutomiseTue, 31 Oct 2006 03:00:00 GMT<p>Was just reading <a href="https://arnonel.com">Arno Nel's blog</a>, and he reminded me about Windows Powershell.<br /> <br /> All of us here had a look at Powershell a few weeks back and were really impressed - and we're going to be investigating adding support into FinalBuilder and Automise for Powershell soonish hopefully :)<br /> <br /> Here's a few links:</p> <ul> <li><a href="http://www.microsoft.com/windowsserver2003/technologies/management/powershell/default.mspx">Windows PowerShell</a></li> <li><a href="http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx">Scripting with Windows PowerShell</a></li> <li><a href="http://blogs.msdn.com/PowerShell/">Windows PowerShell Blog</a></li> <li><a href="http://en.wikipedia.org/wiki/Windows_PowerShell">Windows PowerShell - Wikipedia, the free encyclopedia</a></li> </ul> <p> </p> 581