Blog - Post List
  • 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…

    • 10 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…
    • 9 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 list…

    • 8 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…

    • 7 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…
    • 6 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 it…

    • 3 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…

    • 2 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…

    • 1 Nov 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…

    • 31 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 
    • 30 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 both…

    • 27 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]:…
    • 26 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 *.ps1 -Rec…
    • 25 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 approach…

    • 24 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…

    • 23 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…

    • 20 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.C…
    • 19 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…

    • 18 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 it to access…

    • 17 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
     …
    • 16 Oct 2017
  • Power Tips: Evaluating Event Log Information

    Get-EventLog provides access to the content written to the classic Windows event logs. The most valuable information can be found in a secret property called ReplacementStrings. Here is an approach to make this information visible so you can examine it and build reports.

    In the example, the event ID 44 written by the Windows Update Client is retrieved, and the code outputs the replacement strings. They tell you exactly…

    • 13 Oct 2017
  • Power Tips: Converting Weird Data Formats

    Sometimes, you stumble across weird data formats, i.e. in log files, that won’t autoconvert to DateTime objects. Here is a quick approach for parsing such date and time information:

    $weirdDate = '03 12 --- 1988'
    
    [DateTime]::ParseExact($weirdDate, 'MM dd --- yyyy', $null)
    

    As you can see, ParseExact() does the job for you and wants you to specify the custom date and time format, using the standard…

    • 12 Oct 2017
  • Power Tips: Finding All Domain Controllers (no module required)

    In the previous tip we explained how you can use the ActiveDirectory module and its cmdlets to find all domain controllers in your organization, or perform any other LDAP query.

    Here is the same approach with pure .NET methods. It runs without the need for any additional PowerShell module and does not require the RSAT tools to be installed. It does require your computer to be member of an Active Directory.

    $ldapFilte…
    • 11 Oct 2017
  • Power Tips: Find All Domain Controllers

    If you have installed the free Microsoft RSAT tools, you have access to the ActiveDirectory module. Here is a simple approach to find all domain controllers in your organization:

    #requires -Module ActiveDirectory
    
    $filter = '(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=8192))'
    Get-ADComputer -LDAPFilter $filter
    

    Basically, you can run any LDAP filter query. Simply choose the appropriate…

    • 10 Oct 2017
    • 9 Oct 2017