• A Better NetStat (Part 3)

    In the previous tip we introduced the Get-NetTCPConnection cmdlet as a better alternative to the network utility netstat.exe on Windows systems, and with a couple of tricks, you can even resolve IP addresses and process IDs. However, this slows down the command considerably because DNS lookup may take time, especially when it runs into network time outs.

    Let’s examine how the new PowerShell 7 parallel processing capabilities…

    • 19 Jan 2021
  • A Better NetStat (Part 2)

    In the previous tip we introduced the Get-NetTCPConnection cmdlet as a better alternative to the netstat.exe network utility on Windows systems. It can list open ports and connections, and we left off with an example that lists all connections to HTTPS (port 443):

     
    PS> Get-NetTCPConnection -RemotePort 443 -State Established 
    
    LocalAddress  LocalPort RemoteAddress  RemotePort State       AppliedSetting OwningProcess
    …
    • 15 Jan 2021
  • A Better NetStat (Part 1)

    On Windows systems, netstat.exe is a useful utility to check for open ports and listeners. However, the tool returns text only, has cryptic arguments, and isn’t available cross-platform.

    On Windows systems, you can use a new PowerShell cmdlet named Get-NetTCPConnection which mimics much of the functionality found in netstat.exe. For example, you can list all HTTPS connections (port 443) currently open by any of…

    • 13 Jan 2021
  • Controlling Uptime

    PowerShell 7 comes with a new cmdlet called Get-Uptime. It returns a timespan object with the time that has passed since the last reboot:

     
    PS> Get-Uptime 
    
    
    Days              : 9
    Hours             : 23
    Minutes           : 21
    Seconds           : 14
    Milliseconds      : 0
    Ticks             : 8616740000000
    TotalDays         : 9,9730787037037
    TotalHours        : 239,353888888889
    TotalMinutes      : 14361,2333333333
    TotalSeconds…
    • 11 Jan 2021
  • Finding Unused (or Used) Drive Letters

    By concatenating type conversions, you can easily create a list of letters:

     
    PS> [Char[]](65..90) 
    A
    B
    C
    D 
    ...  
     

    From this list, you can generate a list of drive letters that are in use:

     
    PS> [Char[]](65..90) | Where-Object { Test-Path "${_}:\" }
    C
    D
     

    Likewise, to find free (unused) drive letters, try this:

     
    PS> [Char[]](65..90) | Where-Object { (Test-Path "${_}:\") -eq $false }
    A
    B
    E
    F 
    ...  
    …
    • 7 Jan 2021
  • Understanding REST Web Services in PowerShell

    There are many different types of web services, and PowerShell can access many of them using Invoke-RestMethod. Here is a quick intro to get you started.

    In its most simple form, a web service is just a web page with structured data on it. You can use the very same URL in your browser to view the data. PowerShell uses Invoke-RestMethod to retrieve the data. This gets you the latest PowerShell team blogs:

    Invoke-RestM…
    • 5 Jan 2021
  • A Better Recursion

    When a function calls itself, this is called “recursion”. You can see this technique often when a script wants to traverse part of the filesystem: a function processes folder content, and when it encounters a subfolder, it calls itself.

    Recursion can be powerful but it’s very hard to debug and potentially dangerous because when you do a mistake, you end up in endless loops. Also, there is always the risk of…

    • 1 Jan 2021
  • Managing Local Group Members (Part 2)

    In the previous tip we explained why accessing local group members will not always work with built-in cmdlets like Get-LocalGroupMember, and ways to work around it using the old (but still functional) ADSI interface.

    If you’d like to build solutions on top of this, you may be wondering how local accounts can be added to or removed from groups, and how you can enable and disable local Administrator accounts.

    Here…

    • 30 Dec 2020
  • Managing Local Group Members (Part 1)

    Fortunately, PowerShell 5 and better comes with cmdlets like Get-LocalGroupMember which list the members of local groups. Unfortunately, these cmdlets have a flaw: if the group contains one or more orphaned members, the cmdlet fails to list any group member.

    Orphaned group members could be users or groups that were added to the group but later deleted in Active Directory. Such orphans show as SID numbers instead of names…

    • 28 Dec 2020
  • Identifying Name of Local Administrator Account

    Occasionally, PowerShell scripts need to access or use the built-in Administrator account or the built-in Administrators group. Unfortunately, their names are localized, so their names can change based on the language of your Windows operating system.

    They do use constant (well-known) SIDs (security identifiers), though. By using the SID, you can get the name. For the local Administrator group, this is trivial because…

    • 24 Dec 2020
  • Reading Installed Software (Part 2)

    In the previous tip we illustrated how powerful Get-ItemProperty is and that you can create an entire software inventory with just one line of code by reading multiple registry locations.

    Today, let’s add two important pieces of information to our software inventory: the scope (was a software installed per user or for all users?) and the architecture (x86 or x64).

    Each information is not found in any registry value…

    • 22 Dec 2020
  • Reading Installed Software (Part 1)

    The Get-ItemProperty cmdlet can read registry values in a much more powerful way than most users know. The cmdlet supports multiple registry paths, and it supports wildcards. This way, it takes only a one-liner to read all installed software (plus their uninstall strings) from four registry keys:

    # list of registry locations where installed software is stored
    $paths = 
    # all users x64
    'HKLM:\SOFTWARE\Microsoft\Windows…
    • 18 Dec 2020
  • Keeping Windows (and PowerShell) Running

    Depending on your Windows PC energy settings, your machine may go into standby or hibernate after some time even though you might be still running a lengthy script.

    One way to ensure that Windows keeps running while your script is busy is to use the “presentation mode”. There is a tool you can use to enable and disable it. In PowerShell, run this:

     
    PS> presentationsettings
     

    This opens a window where you…

    • 16 Dec 2020
  • Reading Event Logs (Part 4)

    In the previous tip we encouraged you to deprecate the Get-EventLog cmdlet and instead start using Get-WinEvent – because the latter is more powerful, and because the former is no longer supported in PowerShell 7.

    Querying events via Get-WinEvent requires a hash table as you have seen in the previous examples. The following command, for example, returns a list of installed updates:

    Get-WinEvent -FilterHashtable
    • 14 Dec 2020
  • Reading Event Logs (Part 3)

    In the previous tip we encouraged you to deprecate the Get-EventLog cmdlet and instead start using Get-WinEvent – because the latter is more powerful, and because the former is no longer supported in PowerShell 7.

    One of the advantages of Get-WinEvent over Get-EventLog is its ability to read all Windows event logs, not just the classic event logs. To find out the names of these additional event logs, try this:

    • 10 Dec 2020
  • Reading Event Logs (Part 2)

    In the previous tip we encouraged you to deprecate the Get-EventLog cmdlet and instead start using Get-WinEvent – because the latter is more powerful, and because the former is no longer supported in PowerShell 7.

    Let’s practice once more how to translate a Get-EventLog statement to Get-WinEvent. Here is the old one-liner that I’d like to translate. It returns all errors and warnings from the System event log that…

    • 8 Dec 2020
  • Reading Event Logs (Part 1)

    In Windows, there are a number of event logs like “System” and “Application”, and in Windows PowerShell, it is simple to retrieve event entries from these logs using Get-EventLog. This one-liner returns the latest five error events from your System event log:

     
    PS> Get-EventLog -LogName System -EntryType Error -Newest 5 | Out-GridView 
     

    In PowerShell 7 and better, the cmdlet Get-EventLog no…

    • 4 Dec 2020
  • Reading Last Logged-On User and Other Registry Values

    Reading some registry values with PowerShell is typically a snap: simply use Get-ItemProperty. This snippet of code reads the Windows operating system details, for example:

    $Path = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion"
    
    Get-ItemProperty -Path $Path |
    Select-Object -Property ProductName, CurrentBuild, ReleaseId, UBR
    

    The result looks like this:

     
    ProductName    CurrentBuild ReleaseId UBR
    -----…
    • 2 Dec 2020
  • Constant Functions

    In PowerShell, you can write-protect functions. When you do, a function cannot be changed, overwritten or removed anymore during a running PowerShell session. While there may be no apparent use case for this, here is the technique:

    $code = 
    {
        param
        (
            [string]
            [Parameter(Mandatory)]
            $SomeParameter
        )
        
        "I have received $SomeParameter and could now process it..."
    }
    
    $…
    • 30 Nov 2020
  • Suppressing Errors

    With cmdlets, suppressing errors seems easy: simply add the –ErrorAction Ignore parameter.

    However, it turns out that this doesn’t suppress all errors. It only suppresses errors that the cmdlet chose to handle. Especially security-related exceptions still show.

    If you want to suppress all errors, you can pipe exceptions to null by appending „2>$null“:

     
    PS> Get-Service foobar 2>$null
     …
    • 26 Nov 2020
  • Finding PowerShell Host Arguments and Executable

    PowerShell hosts may be launched with arguments, i.e. you may run powershell.exe or pwsh.exe with arguments like –NoProfile, or submit paths to scripts to execute.

    From within the shell, you can always view the command that launched this shell, including additional arguments:

    $exe, $parameters = [System.Environment]::GetCommandLineArgs()
    "EXE: $exe"
    "Args: $parameters"
    

    When you launch powershell…

    • 24 Nov 2020
  • Managing Installed Modules (Part 2)

    Whenever you install new modules via Install-Module or update existing modules via Update-Module, new module versions are installed side-by-side.

    If you always work with the latest versions of modules and do not need to access a specific older version, you might want to find outdated modules and remove them:

    # get all installed modules as a hash table
    # each key holds all versions of a given module
    $list = Get-Instal…
    • 20 Nov 2020
  • Managing Installed Modules (Part 1)

    When you install new PowerShell modules via Install-Module, PowerShell remembers the install location. So it is easy to get a list of modules you installed via Install-Module:

     
    PS> Get-InstalledModule
    
    Version Name                       Repository Description                                               
    ------- ----                       ---------- -----------                                               
    2.7.1.9…
    • 18 Nov 2020
  • Repairing PowerShell Gallery Access

    The PowerShell Gallery (www.powershellgallery.com) is a perfect place to look for new PowerShell commands. With Install-Module, you can easily download and install new PowerShell modules.

    However, sometimes things fail, and there are two primary reasons why.

    Occasionally, the original PowerShellGet module shipping with Windows 10 is outdated. You then get exceptions complaining about missing or wrong parameters.

    To solve…

    • 16 Nov 2020
  • Creating Icons

    In the previous tip we showed how you can fine-tune „Windows Terminal“ and add new entries to the list of launchable applications. If you want to add icons for these entries, you need appropriate icon files.

    Here is some PowerShell code that extracts icons from executables. You can use the generated ICO-files in Windows Terminal and elsewhere.

    # create output folder
    $destination = "c:\icons"
    mkd…
    • 12 Nov 2020