• Left Side of Comparison

    When using comparison operators, always make sure the relevant part is placed left. That’s because PowerShell looks at the left side of an operator and may automatically change types of the right side. Also, comparison operators may work as filters when there is an array on the left side.

    Check out the differences:

    $array = @()
    '-'* 80
    $array -eq $null
    '-'* 80
    $null -eq $array
    '-'* 80

    • 19 Jun 2019
  • Subscribe to Lock and Unlock Events

    Whenever a user locks his machine, and whenever a user unlocks a machine, Windows emits an event. PowerShell can subscribe to these events and do things, for example use the text-to-speech engine to emit greetings.

    But there are a number of useful actions as well. Maybe you want to clean up when you lock your machine, close all Windows Explorer windows, start a backup, or do something else. Here is the sample code:

    • 18 Jun 2019
  • Finding Installed Updates (Part 2)

    The Windows Update Client maintains its own log of installed updates. Rather than querying the generic system event log, or actively searching for updates which can take some time, here is example code to query and read the installation history from your Windows Update Client:

    $Session = New-Object -ComObject Microsoft.Update.Session
      $Searcher = $Session.CreateUpdateSearcher()
      $HistoryCount = $Searcher.GetTotalHi…
    • 17 Jun 2019
  • Finding Installed Updates (Part 1)

    Get-Hotfix returns installed hotfixes but really only is a wrapper around the Win32_QuickFixEngineering WMI class. It is not returning all installed updates.

    A better way may be querying the event log:

    Get-EventLog  -LogName System -InstanceId 19  |
        ForEach-Object {
                Time = $_.TimeGenerated
                Update = $_.ReplacementStrings[0]

    Even this may not be complete…

    • 14 Jun 2019
  • Finding Missing Updates

    PowerShell can access the same logic that is used by the Windows Update Client, and query for missing updates:

    $UpdateSession = New-Object -ComObject Microsoft.Update.Session
    $UpdateSearcher = $UpdateSession.CreateupdateSearcher()
    $Updates = @($UpdateSearcher.Search("IsHidden=0 and IsInstalled=0").Updates)
    $Updates | Select-Object Title

    Here is a more sophisticated approach returning update title and KB number…

    • 13 Jun 2019
  • Who is Starting Hidden Programs?

    Ever wondered why your CPU load is so high at times, or why black windows open up for a split second? Then check your event log for program launches, and find out when and what was started automatically:

    Get-EventLog -LogName System -InstanceId 1073748869 |
    ForEach-Object {
            Date = $_.TimeGenerated
            Name = $_.ReplacementStrings[0]
            Path = $_.ReplacementStrings[1]
    • 12 Jun 2019
  • Finding Logon Events

    Provided you have Administrator privileges, here is a quick and easy way of dumping all login events. This way you can find out who logged in to a particular computer, and which authentication type was used:

    #requires -RunAsAdministrator
    Get-EventLog -LogName Security -InstanceId 4624 |
      ForEach-Object {
              Time = $_.TimeGenerated
              LogonType = $_.ReplacementStrings[8]
    • 11 Jun 2019
  • Resolving URLs

    Often, URLs redirect to the final URL, so if you’d like to know where a given URL really points to, use a function like this:

    function Resolve-Url
      $request = [System.Net.WebRequest]::Create($url)
      $response = $request.GetResponse()
      $url = $response.GetResponseHeader("Location"…
    • 10 Jun 2019
  • Finding Size of Download

    When you download files from the internet and use PowerShell, you may want to find out how long the download will take. While you can check the size of the already downloaded binaries, to calculate a progress percentage you also know the size of the total download.

    Here is a quick way of finding out the size of a file:

    function Get-DownloadSize
    • 7 Jun 2019
  • Detecting Key Press

    Sometimes it would be nice if a script was able to detect a key press without interfering with the script and its inputs. This way, you could add logic where pressing SHIFT would abort a script or enable verbose logging, and in your profile script, you could load modules and perform other adjustments based on whether you hold some key while PowerShell starts.

    Which boils down to the question: what is the best and least…

    • 6 Jun 2019
  • Using FileSystemWatcher Asynchronously

    In the previous tip we looked at the FileSystemWatcher object and how it can monitor folders for changes. To not miss any changes, however, an asynchronous approach is required which looks like this:

    $FileSystemWatcher = New-Object System.IO.FileSystemWatcher
    $FileSystemWatcher.Path  = "$home\Desktop"
    $FileSystemWatcher.IncludeSubdirectories = $true
    $FileSystemWatcher.EnableRaisingEvents = $true
    • 5 Jun 2019
  • Using FileSystemWatcher Synchronously

    Here is a chunk of code illustrating how PowerShell can use the FileSystemWatcher to synchronously watch a folder including subfolders for file changes:

    $folder = $home 
    $filter = '*'  
        $fsw = New-Object System.IO.FileSystemWatcher $folder, $filter -ErrorAction Stop
    catch [System.ArgumentException]
        Write-Warning "Oops: $_"
    $fsw.IncludeSubdirectories = $true
    • 4 Jun 2019
  • Using Default Credentials for Proxy

    When your company uses an authenticated proxy, PowerShell may not always be able to contact the Internet. You may have to instruct the web proxy to use your default credentials from the credential cache:


    psconf.eu – PowerShell Conference EU 2019 – June 4-7, Hannover Germany – visit www.psconf.eu There…

    • 3 Jun 2019
  • PowerShell 7

    Today we are not talking about code but about PowerShell in general. Microsoft has announced that the next release of PowerShell is called “PowerShell 7” and will be based on .NET Core 3.0. This is significant because .NET Core 3.0 re-introduces WPF (Windows Presentation Foundation, GUIs), at least on Windows machines. This way, PowerShell can re-introduce GUI-dependent cmdlets such as Out-GridView, and it is also expected…

    • 31 May 2019
  • RSAT Tools Built-In

    The Remote Server Administration Tools (RSAT) used to be an external download that added two important PowerShell modules: ActiveDirectory and GroupPolicy. Unfortunately, major Windows updates removed installed RSAT tools so if your scripts require Active Directory cmdlets on your client, you were forced to manually identify and download the appropriate RSAT package for your new Windows 10 and install it manually.


    • 30 May 2019
  • Searching Files Using Index Search

    Windows Indexing indexes most files in your user profile and drives the fast file search in File Explorer. PowerShell can access the same mechanism. Here is a function that returns files based on content:

    function Search-FileContent ([String][Parameter(Mandatory)]$FilterText, $Path = $home ) 
        $objConnection = New-Object -COM ADODB.Connection 
        $objRecordset  = New-Object -COM ADODB.Recordset 
    • 29 May 2019
  • Turn on Streaming for Loops

    PowerShell comes with a number of looping constructs. These looping constructs cannot stream, so you cannot pipe the results to other cmdlets and use the pipeline real-time benefits. Instead, you must store all data in variables first, and only when the loop is completed can you pipe the variable to someone else.

    While you can resort to ForEach-Object to replace classic foreach and for loops, it slows down code and is…

    • 28 May 2019
  • Marking Scripts for PowerShell Core or Windows PowerShell

    As you probably know, there are two breeds of PowerShell: Windows PowerShell ships with Windows operating systems and is based on the full .NET Framework whereas PowerShell 6 and better is open-source, cross-platform, and based on the (limited) .NET Core and Standard.

    If you write scripts that run on both breeds, that’s awesome! If, however you know that your code requires either one, make sure you add the appropriate…

    • 27 May 2019
  • Controlling Audio Volume and Mute Status

    To adjust an audio volume and mute/unmute the speaker, PowerShell can use C# code and access API functions like this:

    Add-Type -TypeDefinition @'
    using System.Runtime.InteropServices;
    [Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    interface IAudioEndpointVolume {
      // f(), g(), ... are unused COM method slots. Define these if you care
      int f(); int g(); int h(…
    • 24 May 2019
  • Checking for Bad (Insecure) Passwords (Part 2)

    In the previous tip we explained how you can use web services to safely test passwords and find out whether they have been compromised before.

    Infosec code sometimes looks pretty “funny” in an effort to be short, so in part 1 we shared nice and readable code with you. Here is the “infosec” variant which shows how much PowerShell code can be compressed and auto-obfuscated. It returns how often a particular password was…

    • 23 May 2019
  • Checking for Bad (Insecure) Passwords (Part 1)

    Complex passwords are not necessarily safe. For example, “P@ssw0rd” is a very complex password, however extremely insecure. That’s why security communities start to recommend that you replace complexity criteria with more relevant tests and prevent the use of passwords that have been seen in previous hacker breaches. Such passwords – however complex they may be – are a regular part of dictionary attacks and highly insecure…

    • 22 May 2019
  • Specifying Bit Flags Smart

    In the previous tip you have seen how you can enable all SSL security protocols in PowerShell to connect to web services and web sites:

    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Ssl3 -bor [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12

    Funny enough, a much shorter line will work just as well:

    • 21 May 2019
  • Using SSL/HTTPS from PowerShell

    Depending on your PowerShell and .NET Framework version and update, the default security protocol for secure web connections may still be SSL3. You can easily find out:


    If the protocol returned does not contain Tls12, you may not be able to connect to secure web services and websites using PowerShell. Simply enable more protocols like this:

    • 20 May 2019
  • Splitting Texts by Fixed Width

    Let’s assume you need to split a text using a fixed width. For example, if you needed the first 5 character of a text, plus the remainder, how would you do this?

    Most PowerShell users would probably use string methods like these:

    $text = 'ID12:Here is the text'
    $prefix = $text.Substring(0,5)
    $suffix = $text.Substring(5)

    Of course, if you had a split character such as “:”, you could also…

    • 18 May 2019
  • Get Hashes from Texts

    Before the advent of PowerShell 5 (and Get-FileHash), to calculate hashes for strings and files, you’d need to resort to pure .NET methods. Here is sample code to create a MD5 hash for a string:

    $Text = 'this is the text that you want to convert into a hash'
    $Provider = New-Object -TypeName Security.Cryptography.MD5CryptoServiceProvider
    $Encodiner = New-Object -TypeName Text.UTF8Encoding
    $Bytes = $Enc…
    • 17 May 2019