Blog - Post List
    • 17 Nov 2017

    Power Tips: Using Windows EventLog for Script Logging

    Using the built-in Windows event log architecture for script logging is great, and very simple. Here are the initial steps to prepare logging (requires Administrator privileges): #requires -runasadministrator New-EventLog -LogName PSScriptLog -Source Logon , Installation , Misc , Secret Limit-EventLog -LogName PSScriptLog -MaximumSize 10 MB -OverflowAction OverwriteAsNeeded You may want to adjust the log name...
    • 16 Nov 2017

    Power Tips: Getting File Extension

    By converting a path to a FileInfo object, you can easily determine the path parent folder or file extension. Have a look: ([ IO.FileInfo ] ' c:\test\abc.ps1 ' ) . Extension ([ IO.FileInfo ] ' c:\test\abc.ps1 ' ) . DirectoryName ReTweet this Tip!
    • 15 Nov 2017

    Power Tips: Working with [FileInfo] Object

    Often, code needs to check on files, and for example test whether the file exists or exceeds a given size. Here is some commonly used code: $logFile = " $PSScriptRoot\mylog.txt " $exists = Test-Path -Path $logFile if ( $exists ) { $data = Get-Item -Path $logFile if ( $data . Length -gt 100 KB ) { Remove-Item -Path $logFile } } By immediately converting a string path into a FileInfo object, you can...
    • 14 Nov 2017

    Power Tips: Script Logging Made Easy

    Beginning in PowerShell 5, you can use Start-Transcript in any host to log all the output created by your script. Here is how you can easily add logging capabilities to any script: # add this: ############################ $logFile = " $PSScriptRoot\mylog.txt " Start-Transcript -Path $logFile -Append ######################################### "Hello" ( $a = Get-Service ) "I received $($a.Count) services....
    • 13 Nov 2017

    Power Tips: Multi-Language Voice Output

    On Windows 10, the operating system ships with a bunch of high-quality text-to-speech engines and is no longer limited to just the English language. The number of available TTS Engines depends on the languages you installed. PowerShell can send text to these TTS Engines, and via tags can also control the language used. If you have both the English and German TTS Engines installed, you could mix languages like below...
    • 10 Nov 2017

    Power Tips: Removing Text from Strings

    Occasionally, you might read about Trim(), TrimStart(), and TrimEnd() to remove text from strings. And this seems to really work well: PS C:\> $testvalue = "this is strange" PS C:\> $testvalue.TrimEnd("strange") this is PS C:\> But what about this? PS C:\> $testvalue = "this is strange" PS C:\> $testvalue.TrimEnd(" strange") this i PS C:\> The truth is that Trim() methods treat your argument as a list...
    • 9 Nov 2017

    Power Tips: Uncompressing Serialized Data

    In the previous tip you learned how you can use Export-CliXml to serialize data and then use Compress-Archive to shrink the huge XML files to only a fraction of original size. Today, we do the opposite: we take a ZIP file that contains XML serialization data, and restore (“rehydrate”) the serialized objects. This of course assumes you created such a file with yesterday’s tip. # path to existing ZIP file $ZipPath...
    • 8 Nov 2017

    Power Tips: Compressing Serialized Data

    With Export-CliXml, it is trivial to serialize results to a file, and with Import-CliXml, the serialized information can just as easily be restored. However, the resulting XML files can become rather large. Fortunately, in PowerShell 5 there is a new cmdlet called Compress-Archive. After you created the XML file, you could automatically refactor it into a ZIP file. Here is some code to illustrate: it gets a process...
    • 7 Nov 2017

    Power Tips: Multipass: Securely Storing Multiple Credentials

    If you’d like to safely store credentials (usernames and password) for your personal use in a file, here is a very simple yet extremely powerful approach. Take a look at this code: $Path = " $home\Desktop\multipass.xml " [ PSCustomObject ] @ { User1 = Get-Credential -Message User1 User2 = Get-Credential -Message User2 User3 = Get-Credential -Message User3 } | Export-Clixml -Path $Path When you run it, it...
    • 6 Nov 2017

    Power Tips: A Better (and Faster) Start-Job

    Start-Job transfers a script block to a new PowerShell process so that it can run separately and in parallel. Here is a very simple sample illustrating the idea behind jobs: # three separate "jobs" to do: $job1 = { Start-Sleep -Seconds 6 ; 1 } $job2 = { Start-Sleep -Seconds 8 ; 2 } $job3 = { Start-Sleep -Seconds 5 ; 3 } # execute two of them in background jobs $j1 = Start-Job -ScriptBlock $job1 $j3 = Start...
    • 3 Nov 2017

    Power Tips: Using Digital Signatures with Timestamp Server

    When you start signing script files, you want to make sure signatures stay intact even if the certificate that signed it expires at some day in the future. What matters is that the certificate was valid when it signed the script. To ensure this, you need a timestamp server from a trusted authority that adds a timestamp to the signature. This way, you not only signed a script. You also added the date when you signed...
    • 2 Nov 2017

    Power Tips: Digitally Signing PowerShell Scripts

    In the previous tips you learned how you can create a self-signed code signing certificate, save it to a PFX file, and read it back into memory. Today, assuming that you have a PFX file with a code signing certificate by now, we’ll look at how PowerShell scripts can be digitally signed. The below code searches for all PowerShell scripts in your user profile, and if the scripts do not have a digital signature yet...
    • 1 Nov 2017

    Power Tips: Loading Certificates from PFX Files

    In the previous tip we illustrated how you can use New-SelfSignedCertificate to create new code signing certificates, and store them as a PFX file. Let’s check out today how you can load a PFX file. Let’s assume your PFX file is located in $env:temp\codeSignCert.pfx. Then this is the code you need to read the file: $cert = Get-PfxCertificate -FilePath " $env:temp\codeSignCert.pfx " When you do this, you will...
    • 31 Oct 2017

    Power Tips: Creating Self-Signed Code Signing Certificates

    If you’d like to digitally sign your scripts, the first thing you need is a digital certificate with the designated purpose set to “Code Signing”. To play, you can easily create your own free self-signed certificates. Don’t expect anyone else to trust them, as anyone can create them. They are a great way to test-drive code signing. Beginning in PowerShell 4, the cmdlet New-SelfSignedCertificate can create code signing...
    • 30 Oct 2017

    Power Tips: Using LDAP Filters in Active Directory

    LDAP filters resemble the query language used by Active Directory, and if you have installed Microsoft’s RSAT tools, you can easily use the cmdlets found in the ActiveDirectory module to use LDAP filters to search for users, computers, or other resources. This would find all users with no email address: $filter = ' (&(objectCategory=person)(objectClass=user)(!mail=*)) ' Get-ADUser -LDAPFilter $filter -Prop * ...
    • 27 Oct 2017

    Power Tips: Comparing Computer Data Received from PowerShell Remoting

    PowerShell remoting is a very fast way to query multiple computers because PowerShell remoting works in parallel. Here is a real world use case that illustrates a couple of interesting techniques. The goal is to retrieve the list of running processes from two computers, then find the differences. For maximum speed, the process lists are queried via PowerShell remoting and Invoke-Command and results are received from...
    • 26 Oct 2017

    Power Tips: Generating MD5 Hashes from Text

    The Get-FileHash cmdlet can generate hash codes for file content. It cannot generate hash codes for arbitrary text, though. And it is available only in PowerShell 5 and better. So here is a small function that uses the .NET Framework to generate MD5 hashes from any text: Function Get-StringHash { param ( [ String ] $String , $HashName = "MD5" ) $bytes = [ System.Text.Encoding ] :: UTF8 . GetBytes ( $String...
    • 25 Oct 2017

    Power Tips: Finding File Duplicates

    In the previous tip we explained how the Get-FileHash cmdlet (new in PowerShell 5) can generate the unique MD5 hash for script files. Hashes can be easily used to find duplicate files. In essence, a hash table is used to check whether the file hash was discovered before. The code below examines all script files in your user profile and reports duplicate files: $dict = @ {} Get-ChildItem -Path $home -Filter * ....
    • 24 Oct 2017

    Power Tips: Creating MD5 File Hashes

    MD5 file hashes uniquely identify file content and can be used to check whether file content is identical. In PowerShell 5, there is a new cmdlet that creates the hashes for you. The code below looks for all PowerShell scripts in your user profile, and generates MD5 hashes for each file: Get-ChildItem -Path $home -Filter * . ps1 -Recurse | Get-FileHash -Algorithm MD5 | Select-Object -ExpandProperty Hash A better...
    • 23 Oct 2017

    Power Tips: Creating Balloon Tips Safely

    Inspired by an article by fellow MVP Boe Prox, below you’ll find a sophisticated function that creates balloon tip dialogs. You can find background information about the concepts in Boe’s original article: https://mcpmag.com/articles/2017/09/07/creating-a-balloon-tip-notification-using-powershell.aspx . You can find many tips showing how to display a balloon tip, but most of these approaches leave behind a non-functional...
    • 20 Oct 2017

    Power Tips: Creating Leading Zeros

    Did you ever need to convert numbers into strings with leading zeros, for example to compose server names? Simply use PowerShell’s “-f” operator: $id = 12 ' server{0:d4} ' -f $id Here is the output: server0012 The –f operator expects a text template on its left side, and value(s) on its right side. Inside the text template, use {x} as placeholder(s) for your values on the right side. Placeholders start...
    • 19 Oct 2017

    Power Tips: Demystifying Error Handling

    Any error in PowerShell code surfaces as an error record object. Check out the function below which extracts all relevant error information from such error record: function Get-ErrorInfo { param ( [ Parameter ( ValueFrompipeline )] [ Management.Automation.ErrorRecord ] $errorRecord ) process { $info = [ PSCustomObject ] @ { Exception = $errorRecord . Exception . Message Reason = $errorRecord . CategoryInfo...
    • 18 Oct 2017

    Power Tips: Determine Boot Time and Uptime Remotely

    Get-CimInstance is a useful cmdlet to retrieve WMI information because it uses standard .NET DateTime objects rather than the awkward WMI datetime format. However, Get-CimInstance uses WinRM for remote access whereas the older Get-WmiObject used DCOM for remote access. Very old systems may not yet be configured to use WinRM remoting, and may still require DCOM. Here is sample code that illustrates how you can use Get...
    • 17 Oct 2017

    Power Tips: Determine Boot Time and Uptime

    WMI can tell you when a system was booted, and this information can be re-calculated to find out the uptime: $bootTime = Get-CimInstance -ClassName Win32_OperatingSystem | Select-Object -ExpandProperty LastBootupTime $upTime = New-TimeSpan -Start $bootTime $min = [ int ] $upTime . TotalMinutes "Your system is up for $min minutes now." Note that Get-CimInstance uses WinRM remoting by default when you use...
    • 16 Oct 2017

    Power Tips: Pipe Information to Excel

    Here is a small yet very useful function that receives data from other cmdlets and sends them to Excel: function Out-Excel { param ( $path = " $env:temp\report$(Get-Date -Format yyyyMMddHHmmss).csv " ) $Input | Export-Csv $path -NoTypeInformation -UseCulture -Encoding UTF8 Invoke-Item $path } Simply pipe anything you want to Out-Excel. For example: PS C:\> Get-Process | Out-Excel ReTweet this...