• Testing Well Formed URLs

    PowerShell is API-based so often, you don’t need to dive into regular expressions and text patterns. Instead, there is a multitude of specialized testing methods accessible in the .NET Framework. The hard part is rather to find and know them, not so much to run them and perform the tests.

    For example, to test whether a URL is well-formed, try this:

    $url = 'powershell.one'
    $kind = [UriKind]::Absolute
  • Running on Windows PowerShell – Or Not? (Part 2)

    In the previous tip we featured a backward-compatible one-liner that can tell whether your script is running in the classic Windows PowerShell environment or on the new PowerShell 7 portable shell.

    If you do use the new platform-neutral PowerShell 7, then there is a new type called [Management.Automation.Platform] that returns even more platform information. This type did not yet exist in Windows PowerShell so you can…

  • Running on Windows PowerShell – Or Not? (Part 1)

    PowerShell can run on various platforms these days, and in the previous tip we explained how you find out the operating system that your scripts are running on.

    If the operating system is Windows, you still don’t know whether your script is run by the built-in Windows PowerShell or by the new portable PowerShell 7.

    Here is a safe and backward-compatible way to find out whether your script currently runs on Windows…

  • Determining Your Platform

    PowerShell today is cross-platform so even though you may still use Windows PowerShell on Windows servers, your scripts may well end up running on different operating systems.

    If your script wants to know the platform it is running on, in a backward-compatible way, try these lines:

    $RunOnWindows = (-not (Get-Variable -Name IsWindows -ErrorAction Ignore)) -or $IsWindows
    $RunOnLinux = (Get-Variable -Name IsLinux -Error…
  • Escaping Individual Characters

    In previous tips we explained how you can escape entire string sequences. If you just need to escape an individual character, use HexEscape() like so:

    PS> [Uri]::HexEscape('a')

    This method actually retrieves the ASCII code and converts it to hexadecimal.

    Actually, there is even the opposite route, and you can convert escaped characters back to normal. The ASCII code for “A” is 65, for example, which…

  • Safely Escaping Data Strings

    Typically you use methods like EscapeUriString() to safely escape string data that you want to append to URLs (as pointed out in our previous tip).

    However, this can cause severe headaches because EscapeUriString() is specifically designed to escape a full URL including the domain part, not just your arguments. That’s why it can corrupt the data you want to send to someone else, i.e. a morse web service. Try for yourself…

  • Escaping Strings in URLs

    When adding string information to URLs, i.e. to construct requests for calling REST web services, it is important to escape special characters. The type [Uri] comes with methods to escape and unescaped string for use in URLs:

    $Text = 'SOS Save me please!'
    $Escaped = [Uri]::EscapeUriString($Text)

    The result looks like this:


    Now you can safely send the escaped string data…

  • Dynamically Composed IntelliSense

    When designing PowerShell functions, you can improve usability tremendously by adding clever argument completion IntelliSense.

    To compose argument IntelliSense completion, you can equip each parameter of your function with a piece of PowerShell code that dynamically composes the IntelliSense list. Of course, the code you use should be quick to compute so IntelliSense won’t time out.

    If you need to add methods (commands…

  • Auto-Logon After Windows-Reboot

    If your automation script needs to restart the machine, and you want to auto-logon after the reboot, here is a quick script that saves the logon credentials to the Windows registry:

    # ask for logon credentials:
    $cred = Get-Credential -Message 'Logon automatically'
    $password = $cred.GetNetworkCredential().Password
    $username = $cred.UserName
    # save logon credentials to registry (WARNING: clear text password used…
  • Automating Lenovo Driver Downloads (Part 2)

    In the previous example we illustrated how you can scrape Lenovo driver information from the web. In this example, some of the information returned was raw numeric information: the number “3” represented “Reboot required”, for example.

    In this tip we’d like to show how you can translate cryptic numeric values to friendly text. First, let’s take a look at the improved Lenovo function:…

  • Automating Lenovo Driver Downloads (Part 1)

    Many hardware vendors offer web-based self-service portals. Here is an example taken from Lenovo that returns detailed information about driver and other update downloads:


    If you need to manage hundreds or thousands of machines or need to regularly lookup information, you would of course want to automate this resource. The typical first approach would be to examine…

  • Out-GridView with Custom Columns

    Out-GridView can be a universal dialog when you use the -OutputMode or -PassThru parameters. When you do, a grid view window displays additional buttons in its lower right corner so you can choose items and pass them on to additional cmdlets.

    This line could help picking a service to stop, for example:

    Get-Service | Where-Object CanStop | Out-GridView -Title 'Service to stop?' -OutputMode Single | Stop-Servic…
  • Accessing Lenovo BIOS Downloads (Part 2)

    In this mini-series we illustrate how you can automate the process of looking up vendor information. While this mini-series focuses on Lenovo and returns the current BIOS update URI for selected models, many of the techniques illustrated here can be reused in similar scenarios as well.

    In part 2 we illustrate how you can use Out-GridView as a universal dialog yet exclude unwanted properties from displaying.

    Here is the…

  • Accessing Lenovo BIOS Downloads (Part 1)

    In this mini-series we illustrate how you can automate the process of looking up vendor information. While this mini-series focuses on Lenovo and returns the current BIOS update URI for selected models, many of the techniques illustrated here can be reused in similar scenarios as well.

    In part 1 we start by accessing the raw Lenovo information which is a static XML document publicly available in the internet.


  • Creating New Objects (Part 4)

    While most PowerShell users still use hash tables to create new objects, our previous tips have shown that classes aren’t hard to use and provide a range of advantages. Objects created by hash table conversion aren’t type safe, and you can only define properties. If you want to add methods to your object, you need to individually add them using Add-Member.

    Here is what most people do:

    $o = [PSCustomObject
  • Creating New Objects (Part 3)

    While most PowerShell users still use hash tables to create new objects, in the previous tip we introduced classes and their superior type safety. Another benefit are freely definable constructors. This way, you can easily instantiate new objects from your class and at the same time initialize properties with the values you want.

    This is what most people do:

    $o = [PSCustomObject]@{
        Name = "Tobias"
  • Creating New Objects (Part 2)

    Most PowerShell users use hash tables to create objects, and so did we in the previous tip:

    $o = [PSCustomObject]@{
        Name = "Tobias"
        Id = 19
        Submission = Get-Date
        Birthday = '1999-02-12 18:33:12' -as [DateTime]

    A much better way is to first define a type-safe template class, and whenever you need an object of this type, instantiate one:

    class Person  
        [string]$Name = "Tobias…
  • Creating New Objects (Part 1)

    In PowerShell, you can use hash tables to create ad-hoc objects:

    $o = [PSCustomObject]@{
        Name = "Tobias"
        Id = 19
        Submission = Get-Date
        Birthday = '1999-02-12 18:33:12' -as [DateTime]

    Each hash table key turns into a property, and each value turns into the property value. Very simple.

    If you need to add methods (commands) to your object, add them via Add-Member:

    $o = [PSCustom…
  • Repair PowerShellGet and Publish-Module

    Publish-Module is a cmdlet used to publish (upload) a module to a NuGet repository. Occasionally, this cmdlet raises strange exceptions. The reason in this case is an outdated version of nuget.exe. This application is responsible for packaging a module and saving it as .nupkg file, and this application is automatically downloaded the first time you use Publish-Module.

    To correct this problem and refresh your version of…

  • Check for Pending Reboot

    The code below tests whether a reboot is pending:

    $rebootRequired = Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending"
    "Pending reboot: $rebootRequired"

    Twitter This Tip! ReTweet this Tip!

  • Disabling Webcams

    Looking for privacy? Here is a short script that looks for enabled cameras on your system and offers you to disable any camera you don’t want to use:

       # find working cameras
      $result = Get-PnpDevice -FriendlyName *Camera* -Status OK -ErrorAction Ignore | 
        Out-GridView -Title 'Select Camera Device To Disable' -OutputMode Single | 
        Disable-PnpDevice -Confirm:$false -Passthru -whatif # remove -WhatIf…
  • Using SOAP Webservices

    Even though SOAP hasn’t been used widely for public webservices (in favor of more simplistic REST services), internally many companies do use SOAP for their webservices.

    PowerShell comes with excellent SOAP support so you don’t need a lot of complex code to connect to and utilize SOAP webservices. Here is one of the few remaining free public SOAP webservices (translating a German “bankleitzahl” into the bank details…

  • COVID Webservice with PowerShell

    Do you want to stay up-to-date with Covid pandemic parameters? Try this simply webservice:

    $result = Invoke-RestMethod -Uri "https://coronavirus-19-api.herokuapp.com/countries"
    $result -match "Germany"

    The result looks similar to this:

    country             : Germany
    cases               : 4480066
    todayCases          : 0
    deaths              : 95794
    todayDeaths         : 0
    recovered           : 4215200…
  • Enabling Active Directory Cmdlets

    On both server and client, Windows ships with the “ActiveDirectory” PowerShell module. It adds numerous cmdlets to manage users and resources in the Active Directory.

    By default, the module is hidden though. To enable it on clients, with Administrator privileges run this:

    $element = Get-WindowsCapability -Online -Name "Rsat.ActiveDirectory.DS*" 
    Add-WindowsCapability -Name $element.Name -Online 
  • Four PowerShell Critical Prerequisites

    If you are switching to a new computer, you may want to do a quick sanity check to see if PowerShell is set up correctly. Here are four things you should definitely check:

    1 Check PowerShell Version
    Run $PSVersionTable to check your PowerShell version.

    PS> $PSVersionTable
    Name                           Value
    ----                           -----
    PSVersion                      5.1.19041.1237
    PSEdition              …