Identifying Essential Add-Type Statement

When you access .NET types and objects directly in your PowerShell code, you must make sure that the appropriate .NET assemblies are loaded. If you do not, you risk that your script will break once it runs in a simple PowerShell console.

Here is a way how you can find out the names of the assemblies required for objects and types in use. This would tell you what the assembly name is for the object stored in $window variable:

$window = New-Object -TypeName System.Windows.Window

And this is how you find the assembly name for types:



Once you know the assembly name, make sure you add a statement like this before you use the objects or types:

Add-Type -AssemblyName PresentationFramework

Twitter This Tip! ReTweet this Tip!

Friday, November 27, 2015
Posted by AsifSaif

Exporting and Importing Credentials

It is trivial to save credentials to disk so you can later re-import them. This is the part that takes a credential and saves it to disk:

#requires -Version 3

$path = "$home\Desktop\cred.xml"
$cred = Get-Credential
$cred | Export-Clixml -Path $path

And this is the part that imports it back in whenever it suits you:

$path = "$home\Desktop\cred.xml"
$cred = Import-Clixml -Path $path

You can then use the credential in $cred wherever a cmdlet requires the -Credential parameter.

Note that the credential is stored in encrypted format. It can be imported only from the very same person on the very same machine.

Twitter This Tip! ReTweet this Tip!

Thursday, November 26, 2015
Posted by AsifSaif

Understanding the –f Operator

You may have come across the –f operator before and wondered what it does. It’s the format operator and provides an extremely easy way of accessing array elements to create strings.

Let's start with an array of values, like this one:

$info = 'PowerShell', $PSVersionTable.PSVersion.Major, $pshome

You can now access the individual array elements by index:

PS> $info[0]

PS> $info[1]

PS> $info[2]

If you wanted to combine the content of this array into a string, this is when the -f operator shines. It lets you use the very same index numbers to access the array elements and put them into a string. Here are a couple of examples that all use the information contained in $info to produce different strings:

PS> '{0} Version is {1}. Location "{2}' -f $info

PowerShell Version is 4. Location "C:\Windows\System32\WindowsPowerShell\v1.0

PS> '{0} {1}' -f $info

PowerShell 4

PS> '{0} {1:0.0}' -f $info

PowerShell 4.0

PS> '{0}: {2}' -f $info

PowerShell: C:\Windows\System32\WindowsPowerShell\v1.0

Twitter This Tip! ReTweet this Tip!

Wednesday, November 25, 2015
Posted by AsifSaif

Creating Backup Copies of Many Files

PowerShell can quickly create backup files of your files. All you need to adjust is the type of files you want to backup, and the file extension you want to use for your backup files.

This example would affect all PowerShell scripts stored (directly) in your user profile. There are likely to be none in this location, so either copy one there to test drive the function, or specify a different folder path.

Each script would be backuped to a file with the same name and the extension ".ps1_old".

When you change the value of $Recurse to $true, the script would create backups of all PowerShell scripts anywhere in your user profile.

#requires -Version 1

$ExtensionToBackup = '.ps1'
$BackupExtension = '.ps1_old'
$FolderToProcess = $HOME
$Recurse = $false

Get-ChildItem -Path $FolderToProcess -Filter $ExtensionToBackup -Recurse:$Recurse |
  ForEach-Object { 
    $newpath = [System.IO.Path]::ChangeExtension($_.FullName, $BackupExtension)
    Copy-Item -Path $_.FullName -Destination $newpath

Twitter This Tip! ReTweet this Tip!

Tuesday, November 24, 2015
Posted by AsifSaif

Piping Results Straight Into Office Word

With only a few lines of code you can implement a command called Out-OfficeWord. It takes the data you pipe into it and inserts them into a new Word document (provided Word is installed).

#requires -Version 1

function Out-OfficeWord
    $Font = 'Courier',
    $FontSize = 12,
    $Width = 80,

  $Text = $Input | Out-String -Width $Width
  $WordObj = New-Object -ComObject Word.Application
  $document = $WordObj.Documents.Add()
  $document.PageSetup.Orientation = [Int][bool]$Landscape
  $document.Content.Text = $Text
  $document.Content.Font.Size = $FontSize
  $document.Content.Font.Name = $Font
  $document.Paragraphs | ForEach-Object { $_.SpaceAfter = 0 }
  $WordObj.Visible = $true

To create a list of running processes in Word, simply run this:

Get-Process | Out-OfficeWord -Landscape -Font Consolas -FontSize 8

From here, you can save the results as PDF, enhance formatting, or print them.

Twitter This Tip! ReTweet this Tip!

Monday, November 23, 2015
Posted by AsifSaif

Search WMI for Useful Information

WMI is a great source of information but it is not always easy to find out the names of valid WMI classes to query.

Here is a little search tool: it asks for a keyword, then searches WMI for all valid classes with this keyword. The results are shown in a grid view window, and when you choose a class and press OK, the tool queries the class for you, showing the results:

#requires -Version 3

function Search-WMI
    Get-WmiObject -Class "Win32_*$Keyword*" -List |
    Where-Object { $_.Properties.Count -gt 6 } |
    Where-Object { $_.Name -notlike 'Win32_Perf*' } |
    Sort-Object -Property Name |
    Select-Object -Property @{Name='Select one of these classes'; Expression={$_.Name }} |
    Out-GridView -Title 'Choose one' -OutputMode Single |
    ForEach-Object {
        Get-WmiObject -Class $_.'Select one of these classes' | Out-GridView

Search-WMI -Keyword network

Twitter This Tip! ReTweet this Tip!

Friday, November 20, 2015
Posted by AsifSaif

Use a Grid View Window as a Universal Dialog

Out-GridView can be much more than just a window showing results. You can turn it into a pretty useful universal dialog.

Let's assume you want to present to the user a number of running applications, and have him/her choose one to stop. The classic approach would look like this:

Get-Process | 
  Where-Object { $_.MainWindowTitle } |
  Out-GridView -OutputMode Single |
  Stop-Process -WhatIf

When you pipe original objects to Out-GridView, the user would see all the usual object properties. That may be OK, but if you want a better user experience, you can use some sophisticated PowerShell tricks:

#requires -Version 3

$prompt = 'Choose the process you want to terminate:'

Get-Process | 
  Where-Object { $_.MainWindowTitle } |
  ForEach-Object {
    New-Object PSObject -Property @{$prompt = $_ | Add-Member -MemberType ScriptMethod -Name ToString -Force -Value  { '{0} [{1}]' -f $this.Description, $this.Id } -PassThru }
  } |
  Out-GridView -OutputMode Single -Title $prompt |
  Select-Object -ExpandProperty $prompt |
  Stop-Process -WhatIf

Look at the user experience first: the grid view window now looks a lot less confusing to the user. Now let's check out what is needed to create this experience.

Before the results are piped to Out-GridView, they are repackaged in a new object with just a single property. This property carries the name you define in $prompt, so it is basically your message to the user.

When you do this and pipe the wrapped objects to Out-GridView, you would now see the text representation of the object. To control this text representation, the object ToString() method is overwritten with a new function that displays whatever you like. In the example, it displays the process description and process ID.

The process selected by the user is then unwrapped again. This way, you get back the original objects.

Twitter This Tip! ReTweet this Tip!

Thursday, November 19, 2015
Posted by AsifSaif

Outputting File Sizes in Different Formats

When you store a number in a variable, you may want to display the number in different units. Bytes are very precise, but sometimes displaying the bytes as kilobytes or megabytes would be more appropriate.

Here is a clever trick that overwrites the internal ToString() method with a more versatile one: it takes a unit, the number of digits you want, and the text of a suffix. This way, you can display the number in various formats, just as needed.

The content stays untouched, so the variable still holds an integer value that you can safely sort or compare to other values:

#requires -Version 1

$a = 1257657656
$a = $a | Add-Member -MemberType ScriptMethod -Name tostring -Force -Value { param($Unit = 1MB, $Digits=1, $Suffix=' MB') "{0:n$Digits}$Suffix" -f ($this/($Unit)) } -PassThru

And here are some examples on how you can use $a now:

PS> $a
1.199,4 MB

PS> $a.ToString(1GB, 0, ' GB')
1 GB

PS> $a.ToString(1KB, 2, ' KB')
1.228.181,30 KB

PS> $a -eq 1257657656

PS> $a -eq 1257657657

PS> $a.GetType().Name 

Twitter This Tip! ReTweet this Tip!

Wednesday, November 18, 2015
Posted by AsifSaif

Converting Date/Time Formats

Here is a simple PowerShell filter that can convert any DateTime object into any date/time-format you like:

#requires -Version 1

filter Convert-DateTimeFormat
  param($OutputFormat='yyyy-MM-dd HH:mm:ss fff')
  try {
  } catch {}

And here are some examples on how to run it:

PS> Get-Date | Convert-DateTimeFormat
2015-10-23 14:38:37 140

PS> Get-Date | Convert-DateTimeFormat -OutputFormat 'dddd'

PS> Get-Date | Convert-DateTimeFormat -OutputFormat 'MM"/"dd"/"yyyy'

PS> '2015-12-24' | Convert-DateTimeFormat -OutputFormat 'dddd'

As you see, you can pipe into Convert-DateTimeFormat anything that either is a DateTime object already, or can be turned into one. By default, the function displays the ISO format for it, but with -OutputFormat you can specify your own format as well.

When you look at the source code, you can see the letters that resemble date and time components. Note that these are case-sensitive ("m" represents a minute, whereas "M" represents a month), and the more of them you specify, the more detailed will that information be displayed.

Anything you want to appear as literal text needs to be included in quotes.

Twitter This Tip! ReTweet this Tip!

Tuesday, November 17, 2015
Posted by AsifSaif

Waiting for Process Launch

PowerShell has a built-in support to wait until a process or many processes end: simply use Wait-Process.

There is no support to do the opposite: wait until a process has started. Here is a function that can wait for any process:

#requires -Version 1
function Wait-ForProcess
        $Name = 'notepad',


    if ($IgnoreAlreadyRunningProcesses)
        $NumberOfProcesses = (Get-Process -Name $Name -ErrorAction SilentlyContinue).Count
        $NumberOfProcesses = 0

    Write-Host "Waiting for $Name" -NoNewline
    while ( (Get-Process -Name $Name -ErrorAction SilentlyContinue).Count -eq $NumberOfProcesses )
        Write-Host '.' -NoNewline
        Start-Sleep -Milliseconds 400

    Write-Host ''

So when you run this line, PowerShell will pause until you launch a new instance of Notepad:

Wait-ForProcess -Name notepad -IgnoreAlreadyRunningProcesses

When you omit -IgnoreAlreadyRunningProcesses, then PowerShell would continue immediately if there was at least one instance of Notepad already running.

Twitter This Tip! ReTweet this Tip!

Monday, November 16, 2015
Posted by AsifSaif

Recent Certifications

Popular Post

Recent Tweets

(c) 2011 - Asif R. Saif. Powered by Blogger.

- Copyright © Asif Saif -