PowerShell and XML part 1 – Visualize XPath expression

25284059970_e955b4e014_m

This is supposed to be the start of a small series of posts on how to deal with XML through PowerShell. While PowerShell already comes with built-in support for XML, there is quite a lot to learn. As part of the learning path, there might be some good opportunities where we can try to make things a little bit easier and extend the capabilities of the built-in commands.
Before diving any deeper into the details of PowerShell in conjunction with XML, I would like to start the series with XPath. This post’s goal is not to provide you with an XPath reference nor will it be an extensive tutorial. According to the principle…

Give a man a fish and you feed him for a day; teach a man to fish and you feed him for a lifetime.

… I will rather guide you through the first steps, point you to some references, and share a PowerShell script that will hopefully help you also on journey to learn XPath. In layman’s terms, XPath can be considered as SQL for XML. Hence, it is essential to learn XPath if you would like to do any serious XML (yes, with PowerShell one can get around this by using dot notation and built-in filter commands, but once you know XPath a lot of the tasks can be done easier and more efficient) related job.
Actually I haven’t used XPath a lot so far myself and also never really bothered to learn it either (the latter might have caused the former in this case 😉 ).
In terms of references I can recommend the following as a starting point:

I will use a slightly modified version of the example inventory.xml XML file that Microsoft uses as part of their XPath reference. The file can be downloaded from here.
The easiest way to use XPath through PowerShell is via the Select-XML cmdlet. The query part of Select-XML is basically a wrapper around SelectNodes (with the downside that it does not support most of the XPath functions (more on that in a future post)). The Select-XML cmdlet supports input via Path[], String[] or XML (array of XML modes) through its ParameterSets:

Get-Command Select-XML -Syntax

The XPath expression argument for Select-XML’s XPath parameter is one of the few places where case matters in PowerShell(i.e. XPath expressions are case-sensitive). The output is an array of matching XML nodes. Using above mentioned inventory.xml let’s look at some examples:

$path = 'c:\inventory.xml'
$xml = Select-Xml -Path $path -XPath / 
#Select the first book element that is the child of the bookstore element.
$xml | Select-XML /bookstore/book[1] | foreach { $_.Node }
#Select all the title elements that have a "lang" attribute with a value of "en"
$xml | Select-XML //title[@lang='en'] | foreach { $_.Node }

Before throwing more random XPath examples at you I would like to share ‘Test-XPath’ ( download is available here). Test-XPath loads XML into a tree-view and provides a combobox to type an XPath expression that is used to query parts of the XML, matching XML nodes are then highlighted within the tree-view. If no XML argument is provided Test-XPath will load the mentioned inventory.XML and populate the combobox with most of the example XPath expressions from the Microsoft XPath reference. Test-XPath will hopefully help you to get a better grasp of XPath by example:
Test-XPath

While this just scratches the surface of what can be done with XPath I will leave those details for another post (e.g. Namespaces, XPath functions, more general XML related tasks).

shareThoughts


Photo Credit: herdiephoto via Compfight cc

Use Bing Search and Synonyms APIs through PowerShell

25405489655_5f659402e7_m

bing

This is a short post on how to use the Bing Search and Bing Synonyms APIs via PowerShell (I would like to credit this post from Svendsen Tech as it really helped me to understand the usage). Both APIs can be used free of charge for up to 5,000 transactions per month. Prerequisite for the usage of the APIs is a valid subscription verified through an account key. Subscribing to the APIs and retrieving the account key can be done through the Micrsoft Azure Marketplace. The usage of the APIs through PowerShell is pretty easy:

shareThoughts


Photo Credit: Thomas Hawk via Compfight cc

Add spell checking to PowerShell ISE

4126262859_88a806a90e_m

While the PowerShell ISE is obviously for writing PowerShell code rather than text, I usually have a fair amount of it in some of my scripts due to comments or hard coded text elements. Therefore, I thought that it would be handy to have the ability to verify selected text against a spell checker.

spellcheck

I have extended my ISEUtils (It can be downloaded from my GitHub repository) module with the functionality. The spell checking works against the selected text within the ISE and can be activated by pressing F7.
The spell checking is based on the built-in ability of the WPF TextBox which automatically adds the squiggly lines for misspelled words and the spelling suggestions within the context menu. Clicking on the button “Auto Correct” will automatically correct the whole text using the first spelling suggestion (this can lead to some funny results). The spelling uses the “en-us” dictionary if you want to change this you will need to modify the code.
The “spell-checking code” is fairly simple (using ShowUI to build the GUI):

New-DockPanel {
        New-Button 'Auto-Correct (use first spelling suggestion)' -Dock Bottom -On_Click{
            $txtBox = $this.Parent.Children | where {$_.Name -eq 'txtBox'}
            $startIndex = 0
            $errorIndex = $txtBox.GetNextSpellingErrorCharacterIndex($startIndex, [System.Windows.Documents.LogicalDirection]::Forward)
            while ($errorIndex -ne -1){
                $startIndex = $errorIndex
                $error = $txtBox.GetSpellingError($errorIndex)
                $suggestion = @($error.suggestions)[0]
                if ($suggestion){
                    $error.Correct($suggestion)
                }
                $errorIndex = $txtBox.GetNextSpellingErrorCharacterIndex($startIndex, [System.Windows.Documents.LogicalDirection]::Forward)
                if ($errorIndex -eq $startIndex){
                    $errorIndex = $txtBox.Text.IndexOf(' ',$startIndex) + 1
                }
            }
        }
        New-TextBox -Language 'en-us' -Dock Top -TextWrapping Wrap -VerticalAlignment Stretch -HorizontalAlignment Stretch -Name txtBox  -FontSize 15 -AcceptsReturn -On_Loaded {                       
            $this.Text = $psise.CurrentPowerShellTab.Files.SelectedFile.Editor.SelectedText           
            $this.SpellCheck.IsEnabled = $true          
        }
} -Show

shareThoughts


Photo Credit: Will Montague via Compfight cc

Fix: Clipboard is not working + Restart-Process with PowerShell

24460391384_1668f05155_m
Sometimes it happens that the clipboard stops working. The routine of copy and paste we all rely on so many times a day suddenly refuses to do its job. The reason this happens is usually an application blocking the keyboard, making it impossible for other applications to get access to the clipboard. In order to fix this, one needs to find out which application is the culprit and either stop or restart the respective process in order to “free up” the clipboard.
I put together a small PowerShell function (Clear-Clipboard), that does just that:

clipboardBlocking

  1. It identifies the process that currently blocks the clipboard (Using GetOpenClipboardWindow and GetWindowThreadProcessId API calls)
  2. Opens a small GUI offering options to either stop or restart the process

Other than the mentioned Clear-Clipboard function. I’m also sharing Restart-Process as a separate function as it might be useful at times. Both can be downloaded from my GitHub repository.

shareThoughts


Photo Credit: Andi Campbell-Jones via Compfight cc

Fix: Chrome won’t start or taking a long time to start

25187751746_7369950f8d_m

Two simple, yet not intuitive solutions to solve two quite annoying Chrome problems (worked for me on Windows 10 and Windows 8).

1. Chrome browser refuses to launch

Solution: Reset the winsock catalog (see https://support.microsoft.com/en-us/kb/811259 and https://technet.microsoft.com/en-us/library/cc753591%28v=ws.10%29.aspx for more details).:

  1. Open an elevated command prompt (see here)
  2. Type: netsh winsock reset and hit Enter
  3. Restart your PC

2. Chrome takes a very long time to launch:

Solution: Disable hardware acceleration:

  1. Open chrome and type chrome://settings into the address bar and hit Enter
  2. Scroll down and click “Show advanced setttings…”
  3. Scroll further down and untick the box next to “Use hardware accelartion when available”

shareThoughts


Photo Credit: Dakiny via Compfight cc

Retrieve UninstallStrings to fix installer issues

24356667904_413b3b0856_m
Recently I have encountered several installer related issues on my machine. Most of them seemed to be caused by insufficient privileges.
This kind of issue can be usually fixed by running the installer “As Administrator”. In case the issue is in relation to an already installed software packet, it’s sometimes not so easy to locate the respective uninstaller/MSI packet, though. For that purpose, I’ve written a small PowerShell function that scans the registry (it turned out that if you are using PowerShell v5, there is a better way of doing this. See below for more details) (have a look here on why I didn’t want to use WMI Win32_Product instead) for the information. The function has the following features:

  • Search for software by name including wildcards (parameter DisplayName defaults to ‘*’)
  • Search through user specific (HKCU) and/or machine specific (HKLM) registry hives (parameter Hive defaults to HKLM, HKCU only accepts a combination of ‘HKCU’ and/or ‘HKLM’)
  • If a key is found matching the DisplayName. Output an object with the following properties: RegistryHive, DisplayName, UninstallString, msiGUID (if present), InstallLocation=$subKey.InstallLocation, Version (DisplayVersion)

Usage (if your PowerShell version < 5):

#search for the chrome uinstaller only in the machine wide registry hive
Get-Uninstaller *chrome* -Hive HKLM

Output:
GetUninstaller
If you happen to be on PowerShell v5 ($PSVersionTable.PSVersion.Major -eq 5) you can use the built-in Get-Package to retrieve the same information:

Armed with that information one can easily run the installer (MSI) or uninstall routine with elevated privileges in order to fix some installer related issues. For msi installer packets the following command will reinstall the respective software (see here for more details on the reinstall mode). It hopefully goes without saying, that you should only run those commands if you know what you are doing:

msiexec /i {msiGUID} REINSTALL=ALL REINSTALLMODE=omus /l*v log.txt

Below is the source of the helper function for older PowerShell version. I have also uploaded another adaption that uses the best approach depending on the PowerShell version, to my GitHub repo.

shareThoughts


Photo Credit: Chad Sparkes via Compfight cc

Use PowerShell to set Exchange Out of Office status from any PC

24549821590_a4ce2a15cd_m
I’m sure this has also happened already several times to you. You finish up your work to start into your well deserved holidays and only after you arrive at home do you realize that you forgot about to set your “Out of Office” status (considering that you actually do that). Usually, this would mean that you need to use your company device in order to connect back to work and set it up. If your company is running Exchange mail servers there is actually another option available which enables you to do the same from any PC that is connected to the Internet. The EWS Managed API is the technology that enables this.
I’ve written a module that uses the API in order to set an Out of Office message. The function has the following features:

  • Check whether the EWS Managed API is installed and offer an option to download and install in case it is not
  • Option to provide credentials (-ProvideCredentials switch) or use the current
  • A pop-up calendar to select the duration of the absence.
  • Automatic calculation of the return date based on the next business day after the duration end date
  • A custom OOTO message including start and return date (based on next business day after duration end date) and your Outlook signature (the signature is copied from your work PC ($env:APPDATE\Microsoft\Outlook\Signatures\) if available or should be within the same location as the module)
  • The function also creates an appointment in your Outlook based on the provided start and end date

Usage:

Import-Module Set-OOTO
Set-OOTO 'email@domain.com' -ExchangeVersion Exchange2007_SP1 -ProvideCredential

I’ve added my email and Exchange server version as default parameters to the function (if you are using Exchange 2007SP3 you can also need to use Exchange2007_SP1 as the value for the ExchangeVersion parameter (this took me quite a while to figure out)). Other than that you can of course modify the function with your own custom message and additional features (please share).
I’m posting the code below including helper functions to set the appointment and the calendar window. The code can also be downloaded from my GitHub repo:

shareThoughts


Photo Credit: nousku via Compfight cc