PowerShell

Find out in which version a PowerShell Cmdlet was introduced

![23641293904fe946df4a_m](https://powershellone.files.wordpress.com/2015/11/2364129390_4fe946df4a_m.jpg) Some days ago Thomas Rayner (whom I admire for his passion and consistency when it comes to sharing his knowledge) posted about the same topic on his blog. He mentioned a method on how to utilize GitHub in order to find out the earliest Version a PowerShell Cmdlet was introduced. When I read the Thomas’s post, I couldn’t resist thinking about an option to automate the process. My first attempt was to check whether the information is already part of the help system or could be retrieved using Get-Command (using ‘Expand-Archive’ as an example): [code language=”powershell”] Get-Command Expand-Archive | Format-List * | Out-String -Stream | Where-Object {$ -like ‘version’} Get-Help Expand-Archive -Full | fl * | Out-String -Stream | Where-Object {$_ -like ‘version’} [/code] While both commands return some information in relation to a version, in general, there is nothing telling us about the PowerShell version the Cmdlet was first introduced. The next thought I had, looking at Get-Help was the online version. [code language=”powershell”] Get-Help Expand-Archive -Online [/code] This command opens the default browser opening the HelpURI, which in this case looked like https://docs.microsoft.com/en-us/powershell/module/Microsoft.PowerShell.Archive/Expand-Archive?view=powershell-5.1. See the last part of the URI? There seemed to be some hope following this route. The webpage features a drop-down where users can select a PowerShell version (3-6). Selecting Version 3 from the drop-down for the Expand-Archive help page brought me to this URI https://docs.microsoft.com/en-us/powershell/module/Microsoft.PowerShell.Archive/Expand-Archive?view=powershell-6&viewFallbackFrom=powershell-3.0. Version 4 revealed a similar result, while the Version 5 URI did not contain the “viewFallback…” part. Similarly, when pasting a URI like https://docs.microsoft.com/en-us/powershell/module/Microsoft.PowerShell.Archive/Expand-Archive?view=powershell-3.0 into the browser’s address bar, it redirects automatically to the “viewFallback…” version. Great, there we have it, a pattern that can be automated :-):

1 min read

Get .net Format Strings for given input

2364129390_4fe946df4a_m Yet again, long time no post! .net Format Strings are very useful when it comes to taking control over the output of your scripts. e.g.: [code language=”powershell”] ‘{0:t}’ -f (Get-Date) #output: h:mm tt ‘{0:n1}’ -f 2.45 #output: 2.5 [/code] The problem with those Format Strings is, that hardly anyone can remember them. While there they are thoroughly documented and several nice folks have created cheat-sheets (e.g. here), I thought it would be nice to be able to get (at least the most common) Format Strings for a given input automatically along with the respective outputs within PowerShell. Get-FormatStringOutput The function returns output for Integer, Double, and DateTime input. You can download Get-FormatStrings from my GithHub repository or just grab the code below: https://gist.github.com/25ec562a8bb21b1899044ca7913ae7ef

~1 min read

PowerShell tricks – Convert copied range from excel to an array of PSObjects

26919750041_937f0af14b_m In this post, I would like to share a simple function that converts tables copied from Excel to the clipboard into PowerShell objects. While there are several more efficient ways to retrieve data out of Excel files (e.g. COM, EPPlus), I sometimes just want something quick and dirty to get the job at hand done. https://gist.github.com/12f06bec82dc4cc93370b2fa7dc750f4 Usage: ConvertFromExcelClip

~1 min read

Full text search using PowerShell, Everything, and Lucene

26803605966_33613e76a6_m Searching for files is something everyone does on a very regular basis. While Windows is consistently changing the way this is done with every new operating system, the built-in functionality is still far from being sufficient. Therefore, I’m always looking for methods on how to improve this (you can also find several blog posts in relation to file searches around here). In regards to searching for files based on file names or paths, I’m pretty happy with the performance of Everything. If it is about searching for files based on their content (aka full-text search), there is still room for improvement in my opinion. Recently I’ve been watching the session recordings from the PowerShell Conference Europe 2016 (I can highly recommend anyone that is interested in PowerShell to watch those).

2 min read

Get help for Windows built-in command-line tools with PowerShell

26709891580_b8657b36d2_m One of the reasons I like PowerShell is its built-in help system (here is a nice post in case you don’t know how to use PowerShell’s built-in help). E.g.: [code language=”powershell”] Get-Help Get-Command Get-Help Get-Command -Examples Get-Help Get-Command -Parameter Name [/code] In fact, once you get comfortable using PowerShell help aka Get-Help, you start missing similar built-in documentation for other tools/scripting languages. Wouldn’t it be nice if one could use Get-He.lp for Windows command-line tools?: [code language=”powershell”] Get-Help chkdsk Get-Help chkdsk -Examples Get-Help chkdsk -Paramater c [/code]

1 min read

Reporting against Pester test results

26464648144_721725d757_m Pester is (for very good reasons) getting more and more popular. If you don’t know about Pester I would highly recommend you to start using it. Here are some good resources to learn about the framework:

2 min read

PowerShell tricks – Open a dialog as topmost window

26738830652_745071e136_m Windows.Forms provides easy access to several built-in dialogs (see MSDN: Dialog-Box Controls and Components). Here is an usage example to show a “FolderBrowse” dialog: [code language=”powershell”] Add-Type -AssemblyName Windows.Forms $FolderBrowser = New-Object System.Windows.Forms.FolderBrowserDialog $FolderBrowser.Description = ‘Select the folder containing the data’ $result = $FolderBrowser.ShowDialog() if ($result -eq [Windows.Forms.DialogResult]::OK){ $FolderBrowser.SelectedPath } else { exit } [/code] While this works as expected, the dialog won’t show up as the topmost window. This could lead to situations where users of your script might miss the dialog or simply complain because they have to switch windows. Even though there is no built-in property to set the dialog as the topmost window, the same can be achieved using the second overload of the ShowDialog method (MSDN: ShowDialog method). This overload expects a parameter which indicates the parent windows of the dialog. Since the owning window will not be used after the dialog has been closed we can just create a new form on the fly within the method call: [code language=”powershell” highlight=”4”] Add-Type -AssemblyName System.Windows.Forms $FolderBrowser = New-Object System.Windows.Forms.FolderBrowserDialog $FolderBrowser.Description = ‘Select the folder containing the data’ $result = $FolderBrowser.ShowDialog((New-Object System.Windows.Forms.Form -Property @{TopMost = $true })) if ($result -eq [Windows.Forms.DialogResult]::OK){ $FolderBrowser.SelectedPath } else { exit } [/code]

1 min read

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:

~1 min read

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:

1 min read

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:

1 min read

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:

1 min read

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

[![310749483260009ec22b_m](https://powershellone.files.wordpress.com/2015/10/3107494832_60009ec22b_m.jpg)](https://powershellone.files.wordpress.com/2015/10/3107494832_60009ec22b_m.jpg) 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’.: [code language=”powershell”] 1..10 | where {$ -gt 5 -and -lt 8} #correct version 1..10 | where {$_ -gt 5 -and $_ -lt 8} [/code] 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: [code language=”powershell”] 1..10 | where {$_ (-gt 5 -and -lt 8)} #or Get-Process | where {$_.Name (-like ‘power’ -and -notlike ‘ise’)} [/code] 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: https://gist.github.com/d24442b2bbb72f5ff269 What do you think, would you also like to see this kind of syntax for Where-Object? shareThoughts

1 min read

Review of methods to download files using PowerShell

557483263_190baee82f_m The goal of this post is to review and compare different methods to download files using PowerShell. As part of the review I would like to share (in addition to the inline source code you can also download a module (Get-FileMethods) that contains all functions via GitHub) some wrapper functions that follow the same pattern:

4 min read

PowerShell tricks - Use Show-Command to add a simple GUI to your functions

211707_b06dae339d_m The Show-Command cmdlet has been introduced in PowerShell Version 3 and is very useful to help discovering and learning more about PowerShell cmdlets and their respective parameters (also built into the ISE as the Show-Command Add-on).: [code language=”powershell”] #Discover commands by running Show-Command without parameters Show-Command #Run Show-Command for a specific cmdlet Show-Command Get-ChildItem [/code] Show-Command can be also utilized for your own functions in order to provide your users with a simple GUI as it builds a graphical user interface for the provided function on the fly. Show-Command displays:

1 min read

PowerShell tricks – Useful default parameters to add to your profile

15389627623_7ef1f7595f_m Since version 3 PowerShell introduced $PSDefaultParameterValues which is a built-in preference variable which lets you specify default values for any cmdlet or advanced function. You can read much more about it inside the respective help file. In a nutshell $PSDefaultParameterValues is a hash-table where (in its most common version) the key consists of the cmdlet name and parameter name separated by a colon (:) and the value is the custom default value: [code language=”powershell”]

:"=" [/code] I've added the following default parameter values to my profile (You can read [here](http://www.computerperformance.co.uk/powershell/powershell_profile_ps1.htm) and [here](http://blogs.technet.com/b/heyscriptingguy/archive/2012/05/21/understanding-the-six-powershell-profiles.aspx) on how to work with profiles): [code language="powershell"] $PSDefaultParameterValues.Add("Get-ChildItem:Force",$true) $PSDefaultParameterValues.Add("Receive-Job:Keep",$true) $PSDefaultParameterValues.Add("Format-Table:AutoSize",$true) $PSDefaultParameterValues.Add("Import-Module:Force",$true) $PSDefaultParameterValues.Add('Export-Csv:NoTypeInformation', $true) $PSDefaultParameterValues.Add('Get-Member:Force', $true) $PSDefaultParameterValues.Add('Format-List:Property', '*') $PSDefaultParameterValues.Add('Set-Location:Path', '..') $PSDefaultParameterValues.Add('Get-Help:Detailed', $true ) [/code] What are other default parameter values that you use?
~1 min read

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: https://gist.github.com/9db6632423d673ff18f6 Usage:

1 min read

PowerShell tricks - Using dot(s) to refer to the current location

9663950111_c97678228e_m Most people are aware that PowerShell supports commandline navigation in the same way as the good old command prompt (see my previous post Improve PowerShell commandline navigation for ways to enhance this): [code language=”powershell”] cd $env:USERPROFILE\Desktop Resolve-Path ‘.’ #change to the current direction (doing nothing) cd . #move up one level Resolve-Path ‘..’ cd .. [/code] The above is using cd as the alias for the Set-Location Cmdlet providing:

1 min read

Using the String.Split method with multiple separator characters in PowerShell

15703896368_bfc55bdd19_m This post is about what I thought of an odd behaviour when calling the .NET String.Split method with multiple separator characters from PowerShell. I first came across this myself but didn’t really pay much attention to it. Only after reading about it again over on Tommy Maynard’s blog, I decided to find out more. Let’s have a look at an example first: [code language=”powershell”] #using String.Split with one separator character works as expected ‘This is a test’.Split(‘e’) #using multiple characters not so much ‘c:\test’.Split(‘\’) ‘c:\test’.Split(‘\’).Count [/code] When running the second example trying to split a string based on double backslashes the result is an array of 3 strings instead of two. Let’s try to see why this is happening by retrieving the specific overload definition we are using: [code language=”powershell”] #get the overload definition of the method we are using ‘‘.Split.OverloadDefinitions[0] #string[] Split(Params char[] separator) [/code] Ok, it looks like this overload of the Split method expects a character array for the separator parameter. That is why we saw an additional split, every character of the string argument ‘\’ is considered as a unique separator. Let’s see if String.Split has other overload definitions that accept a String as the separator argument: [code language=”powershell”] ‘‘.Split.OverloadDefinitions | Select-String ‘string[] separator’ -SimpleMatch <# string[] Split(string[] separator, System.StringSplitOptions options) string[] Split(string[] separator, int count, System.StringSplitOptions options) #> [/code] Indeed, there are two overloads that accept a String array argument instead. Let’s use the first one. We don’t need the StringSplitOptions parameter in this case and can therefore use a value of ‘None’ for the argument. [code language=”powershell”] #this doesn’t work since we need a String array ‘c:\test’.Split(‘\’, ‘None’) #finally we get only two parts back ‘c:\test’.Split(@(‘\’), ‘None’) ‘c:\test’.Split(@(‘\’), ‘None’).Count [/code] We could have used the -split operator in the first place, but that would have been to easy, right ;-). Furthermore with the String.Split method we can also split a string by multiple strings in just one go: [code language=”powershell”] #using -split operator we need to escape the \ by doubling them since we are dealing with regular expressions ‘c:\test’ -split ‘\\’ #splitting by two strings ‘split by xx and yy in one go’.Split((‘xx’,’yy’),’None’) #can be done also with -split using a scriptBlock

2 min read

Adding ‘Edit with PowerShell ISE’ and ‘Open PowerShell here (as Admin)’ to the context menu

1002140874_11967e2e51_m In order to edit PowerShell files within PowerShell ISE I used to just drag and drop them from Windows Explorer into the ISE scripting pane. Unfortunately this doesn’t work anymore (I believe since Windows 8). The best explanation for the behaviour I found is here. In short drag and drop doesn’t work from Windows Explorer to an elevated application because of the higher Mandatory Integrity Control (MIC) level of the drag & drop source (Windows Explorer has a default level of medium while the elevated application runs with a high MIC level). There are several workarounds available but they all have negative side effects (elevating explorer to a higher privileges, disabling UAT…). The workaround I’m using is adding a context menu for all PowerShell related files to Edit them with PowerShell ISE (while there is already a default ‘Edit’ context menu entry for PowerShell ISE I like to have it open a specific platform version elevated without loading profile). In addition to that I also like to add a context menu entry to open up a PowerShell command prompt from any folder or drive in Windows Explorer: editWithPowerShellISE openPowerShellHere I wrapped the creation of the context menu into a function. The function offers to following options:

1 min read

A nicer PromptForChoice for the PowerShell Console Host

378322049_c01db2cbf5_m Sometimes it’s not possible to fully automate a certain process and we need some input from the user(s) of the script in order to determine the further path of action. If this is based on a fixed set of choices the built-in PromptForChoice method can come to the rescue. Here is an example: https://gist.github.com/778414455f932e1f9ac8 Running the code below in PowerShell ISE will produce the following result:

1 min read

Use PowerShell to open regedit at a specific path or RegJump for PowerShell

12206559615_2b81475662_m Even though PowerShell contains everything to read and write to the registry I still find myself quite frequently opening the registry editor (aka regedit.exe). Since navigating the tree manually can be quite time consuming I used to rely on RegJump developed by Mark Russinovich. I was wondering if the same could be implemented using PowerShell and maybe even adding some features like opening multiple registry keys either from the clipboard or provided as an argument to the function. Say hello to Open-Registry alias regJump. The function opens (instances of) the registry editor for provided paths from the clipboard or as argument to the regKey parameter. The registry paths can contain hive name shortnames like HKLM, HKCU, HKCR or PowerShell provider paths syntax like HKLM:\, HKCU:. Similar to how RegJump.exe handles non-existing paths Open-Registry also ignores those parts of the path and works its way backwards until it finds a valid path or returns an error message if the path doesn’t contain any valid parts. Let’s look at some example use cases:

1 min read

Using PowerShell to clean-up excel data with multiple entries per cell

8231960108_b07671cb72_m How many times did you come across a situation where you were supposed to work with Data that looks like this?: CleanUpData Some of the cells have multiple entries that are either separated by comma or line-breaks (via Alt+Enter). Furthermore several of those entries contain extraneous spaces. Happy days! What would be actually needed in order to work with the data is one clean entry per cell. In order to do that the columns for those rows that contain multiple entries per cell also need to be cross-joined (or Cartesian product) so that all possible combinations for the entries are accounted for. The end result should look like this: CleanUpData2 How could we do the same using PowerShell? Let’s first have a look on how to do the cross-join part. This can be done quite easily with nested loops. Taking the second row from the example, the following will lead to the desired result: [code language=”powershell”] $name= @(‘Nigel’) $products = ‘Product 1’, ‘Product 2’ $preferences = ‘Fast Delivery’, ‘Product Quality’ foreach($n in $name){ foreach($product in $products){ foreach($preference in $preferences){ “$n, $product, $preference” } } } [/code] One way to turn this into a more generic solution is using recursion (You need to understand recursion in order to understand recursion ;-) ). Here is an implementation of the same: https://gist.github.com/a7209498dbaacb1ef951 Ok, having covered the difficult part we now only need to read the data from excel clean it up and apply the Cartesian product function to it. Here is the full code to automate the whole process: https://gist.github.com/67a2b18e59f440184f47 The above contains a modified version of the CartesianProduct function in order handle objects (actually ordered hashtables since they preserve the column order). If time permits I would like to implement the same as an Excel macro and share it as part of another post. Update: I’ve added another post outlining how to do the same (using another approach) via an Excel Macro

1 min read

Add a default code template to the PowerShell ISE

tree Some of the 3rd party PowerShell editors offer already built-in support for a default code template where the content of the code template replaces the default blank sheet for every new tab as a starting point for new scripts. While the PowerShell ISE does not provide this functionality out-of-the-box, it can be quite easily added through the $psISE object model by registering a custom action for the $psise.CurrentPowerShellTab.Files ‘CollectionChanged’ event. This event is triggered whenever a tab is closed or opened: https://gist.github.com/ae270d78e2a469398ddf After pasting and running the above code inside the ISE we first need to create the template. The code template is required to be located at “MyDocuments\WindowsPowerShell\ISETemplate.ps1” it can be created and/or edited using the Edit-ISETemplate function. Once the ISETemplate.ps1 contains some text. Every new tab should now be pre-filled with the content of the code template file. In order to make this persistent the code should be added to your profile. You can find the path(s) to your profile by running ‘$profile | select *’. I personally favor the ‘CurrentUserAllHosts’ profile since I don’t want to maintain multiple profile files. Host specific code can be added by using conditions like: [code language=”powershell”] if ($host.Name -eq ‘Windows PowerShell ISE Host’){ #ISE specific code here } elseif ($host.Name -eq ‘ConsoleHost’){ #console specific code here } [/code] I’ve also added this functionality to my ISE Add-On over on GitHub.

1 min read

Search file content by keyword using Everything + PowerShell + GUI

tree Even with Windows 10 MS still didn’t manage to include a proper in-built file search functionality. If it is about searching for files I definitely prefer the excellent Everything search engine (see also my post on a PowerShell wrapper around Everything commandline) .But quite frequently I also need to search for keywords/pattern within files. PowerShell’s Get-ChildItem and Select-String can certainly do this together: [code language=”powershell”] #search through all .ps(m)1 files for instances of the word ‘mySearchString’ $path = ‘c:\scripts\powershell’ Get-ChildItem $path -Include (“.ps1”,”.psm1”)) -Recurse | Select-String ‘mySearchString’ | select Path, Line, LineNumber [/code] While this does the job it doesn’t follow my preferred workflow and is also not very quick when running it against a large set of files. I would prefer to have the ability to search and drill down a list of files within a Graphical User Interface just like Everything and then search through the filtered list of files using keyword(s)/pattern(s) and get back the search results within a reasonable time-frame. Say hello to “File Searcher” (I didn’t spend any time thinking about a catchy name): FileSearcher The three text boxes at the top of the UI can be used to:

4 min read

Finding the index of an object within an array by property value using PowerShell

![1500333523685c69638c_m](https://powershellone.files.wordpress.com/2015/08/1500333523_685c69638c_m.jpg) Today I was looking for an option to find the index of an object within an array of objects. Using an array of one dimensional objects like integers this is as simple as using the static IndexOf method of the Array class in the System namespace: [code language=”powershell”] $array=10..1 $index = $array.IndexOf(3) $array[$index] [/code] But in my case I wanted to get the index of an item within an array of multidimensional or rich objects. As an example let’s say after running Get-Process we would like to find the index of the process whose Name property equals “powershell” (the return type here is an array of System.Diagnostics.Process objects). My first approach was to use the Select-String cmdlet since I knew it returns a LineNumber property. After some trial and error I came up with the following: [code language=”powershell”] $processes = Get-Process $index = (($processes | Out-String).Split(“n") | Select-String "powershell").LineNumber #index needs to be decremented by 4 since the data starts at line 3 and LineNumber is 1 based $processes[$index-4] [/code] While this returns the desired result it's not a very robust solution. If there is, for example, powershell and powershell_ise running at the same time this would return two line numbers instead of one. Furthermore, the approach does not permit to look for items by property values (unless you throw in some crazy regex). Ok, let's give it another try. The problem with the $processes array is that it doesn't have an index property, but fortunately, with PowerShell it's not a problem at all to add one: [code language="powershell"] $processes = Get-Process | foreach {$i=0} {$_ | Add-Member Index ($i++) -PassThru} $index = ($processes | where {$_.Name -eq "powershell"}).Index $processes[$index] [/code] This looks already better. Adding an Index property to the array makes it easy to replicate the IndexOf method's functionality with an array of rich objects. It still involves quite some steps, though. Looking for yet another approach, I came across the [FindIndex method](https://msdn.microsoft.com/en-us/library/x1xzf2ca(v=vs.110).aspx) that is part of the System.Collections.Generic namespace: [code language="powershell"] $processes = [Collections.Generic.List[Object]](Get-Process) $index = $processes.FindIndex( {$args[0].Name -eq "powershell"} ) $processes[$index] [/code] With that approach, we first need to cast the array to generic list. Generics are a concept of strongly typed languages like C# which make it possible to write a method that can be used against multiple types of objects (hence generic). For PowerShell, this doesn't matter so much since its type system is rather dynamic and mainly implicit therefore we just use a generic list of objects (kind of a generic generic list) here. The FindIndex method expects a typed predicate as its only argument which in PowerShell conveniently translates to a ScriptBlock. The predicate is exactly the same as what is used as the FilterScript parameter for the Where-Object cmdlet. The only difference is that we need to use the built-in [$args variable](https://technet.microsoft.com/en-us/library/hh847768.aspx) in order to access the current ("Pipeline") element instead of "$_". How do those approaches compare in terms of execution speed?: [code language="powershell"] @' (gps | foreach {$i=0} {$_ | Add-Member Index ($i++) -PassThru} | where Name -eq "powershell").Index ((gps | out-string).split("n”) | sls “powershell”).LineNumber (Collections.Generic.List[Object]).FindIndex({$args[0].Name -eq “powershell”}) ‘@ -split “`n” | foreach{ (Measure-Command ([ScriptBlock]::Create($))).TotalSeconds } [/code] On my machine I got 0.21, 1.67, 0.02 respectively. Looks like the last approach also outperformed the others by at least an order of magnitude.

2 min read

PowerShell tricks - Build an array of strings without quotation marks

tree This is one of the tricks I keep forgetting about and therefore document it here for myself but also in case someone else might find it useful. In order to create an array of strings one usually does something like this: [code language=”powershell” light=”true”] $stringArray = “first”, “second”, “third”, “fourth” [/code] It involves quite some redundant characters in order to do a simple thing. This can be made easier using a simple function that is part of the excellent PowerShell Communicty Extensions. The QL (QL is short for Quote-List an idea borrowed from Perl) function has the following definition: [code language=”powershell”] function ql {$args} ql first second third fourth [/code] Note that extraneous commas and quotation marks can be avoided using this approach. There is actually even a built-in cmdlet that can be used for the same purpose. Write-Output alias echo or write: [code language=”powershell” light=”true”] echo first second third fourth [/code] If an element of the string array we’d like to create contains a space the element needs to be surrounded in quotes: [code language=”powershell” light=”true”] echo first second third fourth “with space” [/code] As a bonus tip we can use a similar idea as for the ql function in order to create strings without having to limit them by quotation marks: [code language=”powershell”] function qs {“$args”} qs this is a long string without any quotes #only gotcha is when using quotes (single or double) within the argument #qs this does not’ work qs quotes require escaping using a 'backtick’ otherwise it will not work [/code]

1 min read
Back to Top ↑

Excel

Automatically convert an Excel table to a checklist for JIRA

3161323938_3bb7be6248_m JIRA supports a subset of Wiki Markup to add tables and other formatting to fields like Description or Comments. Writing the Wiki Markup manually is quite time consuming though. To make the process a bit easier I ended up writing a Macro that converts an Excel based task tracker list into JIRA. From this: jiraTable Into that: jiraWikiMarkup Running the Macro will copy the Wiki Markup to the clipboard from where it can be pasted into JIRA. The Macro relies on a mapping between Status values and supported Markup symbols and assumes that the selected cell is within the range that needs to be converted before running the Macro. The VBA project requires the following additional references:

~1 min read

Automatically clean-up excel data with multiple entries per cell separated by comma or line-breaks

tree This is a follow-up from a previous post where I did the same using PowerShell. A short recap first. The goal is to turn something like this: CleanUpData Into this: CleanUpData2 In the original state some of the cells have multiple entries that are either separated by comma or line-breaks (via Alt+Enter). Furthermore several of those entries contain extraneous spaces. In order to tabulate the data the columns for those rows that contain multiple entries per cell also need to be cross-joined (or Cartesian product) to ensure all possible combinations for the entries are accounted for. Rather than merely translating the recursive CartesianProduct function from the previous post into VBA I decided to follow a different approach. Utilizing ADO to build a cross-join (without duplicates) across columns for rows that contain multiple entries. In order do that (I’m not really good at VBA and there might be better ways, that I’d love to hear about) the columns need to be copied to separate sheets so that the ADODB adapter recognizes them as separate tablesI actually found that there is no need to copy the columns to separate sheets since ADO also accepts range references.The SQL for the cross-join with only unique entries is very simple. Assuming the following setup (for the separated entries of the second row from our example): cross-join3 The Macro to build the cross-join looks like this: https://gist.github.com/d840be45ba5c82e6d874 If you like to follow along here are the steps:

2 min read

Using the Excel intersection operator

tree One of the lesser-known features of Excel is the intersection operator which can be used to simplify look-up operations. An intersection is the overlap of two or more cell ranges within excel. For instance: In the screenshot below the ranges C1:C5 and B3:D3 (Cell ranges in Excel are written by using the range operator “:”) overlap in the cell C3. intersection1 The intersection operator “ “ (a space) can be used to find the intersection of ranges. To find the intersection of the two ranges one can just use the following formula “=C1:C5 B3:D3”: intersection2 Combining the intersection operator with named ranges yields to pretty intuitive look-ups in Excel. Let’s take up another example using monthly revenue data by region: intersection3 Highlighting the table and pressing CTRL+SHIFT+F3 will bring up the “Create Names from Selection” dialog. We can go with the defaults (Top row, Left column) in order to create named ranges for each column and row within the table based on their labels: intersection4 Now, in order to retrieve the March Results for the East region we can simply use “=March East”: intersection5 Getting the Sum of the revenues from January-April for the West region is equally simple “=Sum(January:April West)”: intersection6 Even non-consecutive ranges can be easily referred to. Pulling up the Sum of revenues for the month of January, March, and May for the South region is as easy as typing “=Sum((January,March,May) South)”: intersection7

1 min read
Back to Top ↑

Troubleshooting

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:

~1 min read

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:

1 min read
Back to Top ↑

Uncategorized

Back to Top ↑

Word

Back to Top ↑