WMI query filters with PowerShell syntax instead of WQL

2465120031_ebb0a49e45_m
PowerShell comes already with tight integration to WMI with its built-in Get-WmiObject and Get-CimInstance cmdlets. One of the things that people already familiar with PowerShell syntax bothers about WMI is that it comes with its very own query language WQL. While WQL is very similar to SQL. Wouldn’t it be nicer if we could use the same operators and wild-card patterns we are already familiar with?
Well, for myself the answer is Yes:

PowerShellInsteadOfWQL
Let’s first build a proof of concept before creating a proxy function for Get-WmiObject. We can make us of the (newer) PowerShell parser to identify the different elements of the Filter for conversion and the WildcardPattern.ToWql method to convert the wild-card pattern for the LIKE operator:

All it takes are 35 lines of code to implement the functionality.
Now that we have the proof of concept working we can go ahead and dynamically create the proxy functions for Get-WmiObject and Get-CimInstance to keep it simple we just add an additional parameter (PowerShellFilter) that takes the PowerShell syntax, converts the PowerShell to WQL and passes it on to the ‘Filter’ parameter without worrying about adding an additional parameter set to mutually exclude the ‘Filter’ and ‘PowerShellFilter’ parameters. After retrieving the code for the proxy command using the command meta data we need to add the statements for the new parameter (considering the same parameter sets as for the existing ‘Filter’ parameter) at the the top of the param statement and insert the additional logic between the following lines (e.g. Get-WmiObject)…

if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
{
$PSBoundParameters['OutBuffer'] = 1
}
$wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Management\Get-WmiObject', [System.Management.Automation.CommandTypes]::Cmdlet)

… before creating the new function based on a script block made of the updated code:

Putting the above into your profile (You can read here and here on how to work with profiles) will enable you to use PowerShell syntax with Get-WmiObject and Get-CimInstance:

$state = 'Running'
Get-WmiObject -Class Win32_Service -PowerShellFilter {Name -like '*srv*' -and State -eq $state}
Get-CimInstance -ClassName Win32_Service -PowerShellFilter {Name -like '*srv*' -and State -eq 'Running'}

How do you like PowerShell syntax to query WMI?

shareThoughts


Photo Credit: Svedek via Compfight cc

Zen Coding for the PowerShell console and ISE

8381892061_eb3babe76a_m
First of all let’s clarify what Zen Coding actually is. According to their website: Emmet (formerly known as Zen Coding) is …

… a web-developer’s toolkit that can greatly improve your HTML & CSS workflow.

But what does this have to do with PowerShell? At least I find myself quite often trying to convert PowerShell output into HTML or even using the text manipulation capabilities of PowerShell to dynamically construct some static web content. Yes, I hear you shouting already isn’t that why we have ConvertTo-HTML and Here-Strings (and here)? Granted that those can make the job already pretty easy (I would definitely recommend you to have a look into Creating HTML Reports in PowerShell if you haven’t yet), but there is still an even better way to (dynamically) generate static HTML pages from within PowerShell. Before looking into the implementation details let’s have a look at some examples on what zen coding looks like (considering we would have a PowerShell function called zenCode that expands zen code expressions):

zenCode 'html:5'
<# output:
<!DOCTYPE html []>
<html lang="en">
	<head>
		<title></title>
		<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
	</head>
	<body></body>
</html>
#>
zencode 'ul.generic-list>(li.item>lorem10)*4'
<# output:
<ul class="generic-list">
	<li class="item">Sapien elit in malesuada semper mi, id sollicitudin urna fermentum.</li>
	<li class="item">Sapien elit in malesuada semper mi, id sollicitudin urna fermentum.</li>
	<li class="item">Sapien elit in malesuada semper mi, id sollicitudin urna fermentum.</li>
	<li class="item">Sapien elit in malesuada semper mi, id sollicitudin urna fermentum.</li>
</ul>
#>
zencode 'div+div>p>span+em^bq'
<# output:
<div></div>
<div>
	<p>
		<span></span>
		<em></em>
	</p>
	<blockquote></blockquote>
</div>
#>
zencode 'html>head>title+body>table>tr>th{name}+th{ID}^(tr>(td>lorem2)*3)*2'
<# output:
<html>
	<head>
		<title></title>
		<body>
			<table>
				<tr>
					<th>name</th>
					<th>ID</th>
				</tr>
				<tr>
					<td>Dolor sit.</td>
					<td>Dolor sit.</td>
					<td>Dolor sit.</td>
				</tr>
				<tr>
					<td>Dolor sit.</td>
					<td>Dolor sit.</td>
					<td>Dolor sit.</td>
				</tr>
			</table>
		</body>
	</head>
</html>
#>

You can have a look at the Zen Coding Cheat Sheet for more examples The syntax might look a bit cryptic at the first glance but once you get the hang of it it’s pretty easy. While this is all already pretty cool I wanted a way to combine this with the PowerShell pipeline in order to do things like that:

zenCode 'ul>li.item{$_}'
<# output
<ul>
	<li class="item">5</li>
	<li class="item">4</li>
	<li class="item">3</li>
	<li class="item">2</li>
	<li class="item">1</li>
</ul>
#>
gps | zenCode 'html>head>title+body>table>tr>th{name}+th{ID}^(tr>td{$_.name}+td{$_.id})'
<# output (excerpt):
<html>
	<head>
		<title></title>
		<body>
			<table>
                                <tr>
					<td>conhost</td>
					<td>14956</td>
				</tr>
				<tr>
					<td>csrss</td>
					<td>600</td>
				</tr>
#>
gps | select -first 10 | zenCode 'html>head>title+body>table[border=1]>(tr>td{$_.Name}+td{$_.ID})+td{$_.Modules | select -first 10}'
<# output (excerpt):
<head>
		<title></title>
		<body>
			<table border="1">
				<tr>
					<th>Name</th>
					<th>ID</th>
					<th>Modules</th>
				</tr>
				<tr>
					<td>iexplore</td>
					<td>8048</td>
					<td></td>
				</tr>
				<tr>
					<td>iexplore</td>
					<td>8488</td>
					<td>
						<table>
							<tr>
								<th>pstypenames</th>
								<th>BaseAddress</th>
								<th>Container</th>
								<th>EntryPointAddress</th>
								<th>FileName</th>
								<th>FileVersionInfo</th>
								<th>ModuleMemorySize</th>
								<th>ModuleName</th>
								<th>Site</th>
								<th>Company</th>
								<th>Description</th>
								<th>FileVersion</th>
								<th>Product</th>
								<th>ProductVersion</th>
								<th>Size</th>
							</tr>
							<tr>
								<td>
									<table>
										<tr>
											<td>System.Diagnostics.ProcessModule</td>
										</tr>
										<tr>
											<td>System.ComponentModel.Component</td>
										</tr>
										<tr>
											<td>System.MarshalByRefObject</td>
										</tr>
										<tr>
											<td>System.Object</td>
										</tr>
									</table>
								</td>
								<td>18612224</td>
								<td></td>
								<td>18619984</td>
								<td>C:\Program Files (x86)\Internet Explorer\IEXPLORE.EXE</td>
								<td>File:             C:\Program Files (x86)\Internet Explorer\IEXPLORE.EXE
InternalName:     iexplore
OriginalFilename: IEXPLORE.EXE.MUI
FileVersion:      11.00.9600.16428 (winblue_gdr.131013-1700)
FileDescription:  Internet Explorer
#>

The solution to make this happen relies on the zencoding implementation Mad Kristensen has developed (https://github.com/madskristensen/zencoding) which he has also part made part of his awesome Web Essentials Visual Studio extension.
I’ve made a PowerShell function (Get-ZenCode alias zenCode) and also an ISE Add-on that expand Zen Code expressions and also work with the PowerShell pipeline. Get-ZenCode also supports output to a file (outPath parameter) and showing the result in the default browser (-Show Switch). I’m posting the source code for Get-ZenCode below but you can also download the same including full help and more examples from my GitHub page (the function requires the zenCoding.dll within a resources subfolder) . The ISE Add-On (including Get-ZenCode) is part of my ISEUtils Add-On. With the Add-On the expressions can be typed into the Editor (without the preceding zenCode call) and expanded by pressing CTRL+SHIFT+J (or the respective menu entry):
ExpandZenCode

How do you like Zen Coding?

shareThoughts


Photo Credit: jurvetson via Compfight cc

Simplified Where-Object for multiple conditions on the same property for PowerShell?

3107494832_60009ec22b_m
While PowerShell version 3 already introduced a (quite controversial) simplified syntax for the Where-Object cmdlet (alias where). It still doesn’t account for a quite common error PowerShell beginners encounter when using where with multiple conditions on the same property. As an example let’s say we would like to filter the range 1-10 to get only those numbers that are between 6 and 7. I’ve seen many people (yes that includes me) attempting to do it like below since it seems a logical translation of ‘where x is greater than 5 and lower than 8’.:

1..10 | where {$_ -gt 5 -and -lt 8}
#correct version
1..10 | where {$_ -gt 5 -and $_ -lt 8}

Granted that this failing makes mathematically total sense since it should say ‘where x is greater 5 than and x is lower than 8′ . I’d wish there would be a syntax supporting something like this:

1..10 | where {$_ (-gt 5 -and -lt 8)}
#or
Get-Process | where {$_.Name (-like 'power*' -and -notlike '*ise')}

The idea is that the parentheses would indicate that the preceding variable should be considered as the (left-hand) parameter for the operator. I came up with a crude proof of concept on how this could be done:

What do you think, would you also like to see this kind of syntax for Where-Object?
shareThoughts


Photo Credit: Ana Sofia Guerreirinho via Compfight cc

Show-CommandGUI an enhanced Show-Command for PowerShell

2036545266_e1f19d8cdd_m
After my last post (PowerShell tricks – Use Show-Command to add a simple GUI to your functions). I was thinking how one could write a function that would not have the deficiencies that Show-Command has when it comes to providing a GUI for functions. In addition to what Show-Command does I wanted a function that:

  • Considers advanced function parameters (i.e. ValidateScript, ValidatePattern, ValidateRange, ValideLength)
  • Populates the fields with the respective default values (if applicable)
  • Provides a browse for file or browse for folder option (if the parameter name contains ‘file’ or ‘folder’)
  • Provides meaningful error messages via message boxes
  • Doesn’t require the use of Invoke-Expression in order to run the parameters against the command
  • Can be customized to my own preferences

Say hello to Show-CommandGUI.

Show-CommandGUI
The screenshot above is produced with the following test function:

function test{
    [CmdletBinding(DefaultParameterSetName='Basic')]
    Param
    (
        [Parameter(Mandatory=$true, 
                   Position=0,
                   ParameterSetName='Basic')]
        [ValidateNotNullOrEmpty()]
        [ValidateSet("sun", "moon", "earth")] 
        [string]$choice,
        [ValidateRange(2,5)]
        $number,
        [ValidatePattern("^[a-z]")]
        [ValidateLength(2,5)]
        [String]$pattern,
        [ValidateScript({$_ -like '*test'})]
        $string,
        [Parameter(ParameterSetName='Advanced')]
        [switch]$switch,
        [Parameter(Mandatory=$true, ParameterSetName='Advanced')]
        $filePath = 'c:\test.txt',
        [Parameter(Mandatory=$true, ParameterSetName='Basic')]
        $folderPath = 'c:\'
    )
    "pattern: $pattern"
    "number: $number"
    "string: $string"
    if ($PSCmdlet.ParameterSetName -eq 'Advanced'){
        "switch: $switch"
        "filePath: $filePath"
    }
    else{
        "choice: $choice"
        "folderPath: $folderPath"
    }
}

Producing the GUI is as simple as this:

Import-Module "$PATHTOMODULE\Show-CommandGUI.psm1"
Show-CommandGUI test

The module and the test function can be downloaded via GitHub. Please let me know if you have any questions or ideas on how to improve the function.

shareThoughts


Photo Credit: Fernando X. Sanchez via Compfight cc

Expanding aliases in PowerShell ISE or any PowerShell file

393790664_da5b0ddb12_m
Further extending my PowerShell ISE module (ISEUtils) I’ve added a function to convert aliases either in the currently active ISE file or (in case a a path is provided) within any PowerShell file (that way the function can be also used from the PowerShell Console) to their respective definitions.
Aliases are very useful when working interactively, since they help saving extra keystrokes when you just want to get things done fast. At the same time if we are speaking about production code where readability, and easy comprehension of the code are much more important the usage of aliases should be avoided ( read here for a good article on best practices for PowerShell alias usage).
With the Expand-Alias function you can get the best of both worlds. Writing clearer code while avoiding extraneous keystrokes. For the code samples in my blog posts I’m also using aliases quite a lot, but would like to start using the new function from now on.
Below is the source code for Expand-Alias:

Usage:

  1. If the function is called without any parameter it will expand all aliases within the current ISE file.
  2. Providing a full-path to the path parameter will expand all aliases within the respective PowerShell file instead.

Adding the following lines to your PowerShell profile (you can read here and here on how to work with profiles) will automatically load the function and add an item to the AddOn menu to call it on every ISE startup:

$FULLPATHTOEXPANDALIAS = 'c:\expand-alias.ps1'
. $FULLPATHTOEXPANDALIAS
$null  = $psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add('Expand-Alias', { Expand-Alias }, 'CTRL+SHIFT+X')

shareThoughts


Photo Credit: Martin Gommel via Compfight cc