• Managing Shortcut Files (Part 3)

    In the previous tip we created new shortcut files, and you have seen how the CreateShortcut() method provides methods to control almost any detail of a shortcut. Here’s the code again that creates a PowerShell shortcut on your Desktop:

    $path = [Environment]::GetFolderPath('Desktop') | Join-Path -ChildPath 'myLink.lnk'
    $scut = (New-Object -ComObject WScript.Shell).CreateShortcut($path)
    $scut.Targ…
    • 28 Jul 2021
  • Managing Shortcut Files (Part 2)

    In the previous tip we created new shortcut files, and you have seen how the CreateShortcut() method provides methods to control almost any detail of a shortcut. Here’s the code again that creates a PowerShell shortcut on your Desktop:

    $path = [Environment]::GetFolderPath('Desktop') | Join-Path -ChildPath 'myLink.lnk'
    $scut = (New-Object -ComObject WScript.Shell).CreateShortcut($path)
    $scut.Targ…
    • 26 Jul 2021
  • Managing Shortcut Files (Part 1)

    PowerShell creates new LNK files and edits existing ones with the help of an old COM object.

    Let’s first find all LNK files anywhere in your start menu:

    [Environment]::GetFolderPath('StartMenu') | Get-ChildItem -Filter *.lnk -Recurse   
    

    You get back all LNK files found anywhere in your start menu.

    Next, let’s read them all and find out their targets and hidden keyboard shortcuts (if any):

    [Enviro…
    • 22 Jul 2021
  • Unlock Additional PowerShell Modules in Windows 10

    Windows 10 comes with a number of PowerShell modules that you can use to control Server functionality - like WSUS Update Management which is only one example of many.

    In earlier Windows 10 builds, these PowerShell modules were part of so-called RSAT tools (Remote Server Administration Tools), a separate download. In recent builds, you already own the RSAT tools (all commands in this tip require elevated privileges):

    • 20 Jul 2021
  • Enabling ActiveDirectory Module

    Windows 10 ships with the ActiveDirectory PowerShell module – it may just not be enabled yet. If you would like to use PowerShell cmdlets for AD management – i.e. Get-ADUser – simply run the following code with full Administrator privileges:

    #requires -RunAsAdmin
    
    $element = Get-WindowsCapability -Online -Name "Rsat.ActiveDirectory.DS*" 
    Add-WindowsCapability -Name $element.Name -Online
    

    Once…

    • 16 Jul 2021
  • Forensic Event Log Analysis (Part 2)

    In the previous tip we looked at Get-EventLog to do a forensic analysis and find search-related errors in the Application log. Get-EventLog is simple to use yet it is slow and deprecated. While it is perfectly OK to use Get-EventLog on Windows PowerShell, you might want to switch to Get-WinEvent instead. It’s faster and runs on PowerShell 7, too.

    Let’s quickly translate Get-EventLog to Get-WinEvent for the forensic…

    • 14 Jul 2021
  • Forensic Event Log Analysis (Part 1)

    Event logs log almost any aspect of Windows so if something goes wrong or stops working as expected, it is a good idea to include event log forensic strategies into your troubleshooting.

    For example, some users reported that their Windows “Instant Search” stopped finding newer Email items. Why would the indexing service no longer update with Outlook?

    That’s when reading event logs can become very important…

    • 12 Jul 2021
  • Trivia Facts for Birthday Parties

    Let’s assume you are invited to the 37th birthday of a friend. What can you put on the birthday card? Try this:

     
    PS> Invoke-RestMethod -Uri http://numbersapi.com/37 -UseBasicParsing
    37 is the number of plays William Shakespeare is thought to have written (counting Henry IV as three parts).  
     

    Just replace the number in the URL to whatever number you need facts for. This is a great example of how easy it is…

    • 8 Jul 2021
  • Splitting without Losing

    When you split texts, you typically lose the splitting character. That’s why the backslash in this example is lost:

     
    PS> 'c:\test\file.txt' -split '\\'
    c:
    test
    file.txt   
     

    IMPORTANT: Note that the -split operator expects a regular expression. If you want to split at backslashes, since a backslash is a special character in regex, you need to escape it. The following call tells you what you need…

    • 6 Jul 2021
  • Sorting Tricks (Part 4)

    In the previous tip we showed that Sort-Object accepts property names, hash tables or plain script blocks to sort things, and we used script blocks to control the sort algorithms, and sort string information by date and time, not alphanumerical.

    In this final example, let’s use this to sort IPv4 addresses. By default, Sort-Object treats them as plain text and uses alphanumeric sorting:

     
    PS> '10.12.11.1', '298.12…
    • 2 Jul 2021
  • Sorting Tricks (Part 3)

    In the previous tip we showed that Sort-Object accepts property names, hash tables or plain script blocks to sort things. Let’s check out why submitting script blocks to Sort-Object can be a good idea.

    Let’s assume you have a bunch of string data that represents dates, and you’d like to sort them:

     
    PS> 'May 12, 2020', 'Feb 1, 1999', 'June 12, 2021' | Sort-Object
    
    Feb 1, 1999
    June 12, 2021
    May 12, 2020…
    • 30 Jun 2021
  • Sorting Tricks (Part 2)

    In the previous tip we showed how Sort-Object can sort multiple properties, and how you can use hash tables to control sort direction individually per property. Hash tables can do a lot more, though.

    For example, the hash table key “Expression” can be a script block, and this script block is then executed for each item that you want to sort. The result of the script block determines the sort order.

    That’s…

    • 28 Jun 2021
  • Sorting Tricks (Part 1)

    Sort-Object is your cmdlet to sort things: simply specify the property you like to sort, and Sort-Object covers the rest, including picking the correct sort algorithm based on the property data type:

     
    Get-Service | Sort-Object -Property DisplayName -Descending 
     
    1. A lesser-known fact is that Sort-Object also accepts hash tables which gives you more control. For example, you can easily sort multiple properties like this…
    • 24 Jun 2021
  • Hashing Text

    PowerShell comes with Get-FileHash which reads a file and calculates a unique hash value. That’s great to test whether files have identical content. However, there is no way to hash plain texts.

    Of course, you could write the text you want to hash to a file, then use Get-FileHash.

    A better way is a largely unknown feature of Get-FileHash. Instead of submitting a path to a file, you can also submit a so called “MemoryStream…

    • 22 Jun 2021
  • Identifying Windows Version (Part 3)

    In the previous tip we illustrated that accessing the WinRT class AnalyticsInfo seems to be the only supported way to read the current Windows 10 version. Rather than using asynchronous methods like in the previous example, to get just the current Windows 10 version, here is a simpler way:

    # get raw Windows version
    [int64]$rawVersion = 
      [Windows.System.Profile.AnalyticsInfo,Windows.System.Profile,ContentType=Window…
    • 18 Jun 2021
  • Identifying Windows Version (Part 2)

    In the previous tip we reported that ReleaseId is deprecated and can no longer be used to correctly identify the current Windows 10 version. Instead, DisplayVersion should be used:

     
    PS> (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion').DisplayVersion
    20H2  
     

    However, DisplayVersion, too, is not a dependable way of determining the current Windows 10 version as its purpose originally…

    • 16 Jun 2021
  • Identifying Windows Version (Part 1)

    The current Windows version can be read easily from the Windows Registry:

     
    PS> Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' | Select-Object -Property ReleaseId, DisplayVersion
    
    ReleaseId DisplayVersion
    --------- --------------
    2009      20H2   
     

    Be aware though that the information shown in ReleaseId is deprecated. New Windows 10 builds use the DisplayVersion property instead…

    • 14 Jun 2021
  • Original Windows 10 Product Key

    There are tons of PowerShell scripts floating around pretending they can decode the original Windows 10 product key. Most of these scripts use outdated algorithms that no longer work in Windows 10.

    Here is a much simpler way to retrieve your original Windows 10 product key:

    Get-CimInstance -ClassName SoftwareLicensingService | 
      Select-Object -ExpandProperty OA3xOriginalProductKey
    

    If the command does not yield any return…

    • 10 Jun 2021
  • Evaluating Event Log Data (Part 3)

    In the previous tip we looked at Get-WinEvent and how you can use calculated properties to directly access the “Properties” attached to each event rather than having to text-parse the event message.

    For example, below code produced a list of installed updates by pulling out the names of installed updates from the array found in “Properties”:

    $software = @{
        Name = 'Software'
        Exp…
    • 8 Jun 2021
  • Evaluating Event Log Data (Part 2)

    In the previous tip we looked at Get-WinEvent and how you can use a hash table to specify your query. The previous tip used below code to list all events written by the Windows Update Client using the event ID 19, across all event log files:

    Get-WinEvent -FilterHashTable @{
        ID=19
        ProviderName='Microsoft-Windows-WindowsUpdateClient'
    } | Select-Object -Property TimeCreated, Message
    

    The result was a list…

    • 4 Jun 2021
  • Evaluating Event Log Data (Part 1)

    Event logs contain hugely useful information about almost any aspect of your Windows system. When using the deprecated Get-EventLog cmdlet, however, only a fraction of this information is accessible because this cmdlet can only access the older classic logs. That’s why the cmdlet was removed from PowerShell 7 altogether.

    In PowerShell 3, a faster and more powerful replacement cmdlet was added: Get-WinEvent. This…

    • 2 Jun 2021
  • Parsing Raw Data and Log Files (Part 2)

    In the previous tip we explained that most log files can be treated as CSV files and read by Import-Csv. All you need to do is tell Import-Csv where your log file differs from standard CSV, and for example define a different delimiter or supply missing headers.

    One log file format however is hard to parse: fixed-width columns. In this case, there is no single delimiter character to use. Instead, the data uses fixed width…

    • 31 May 2021
  • Parsing Raw Data and Log Files (Part 1)

    Most raw log files come in tabular form: even though they may not be full-featured CSV format, they typically have columns and some sort of delimiter, and sometimes even a header.

    Here is an example taken from an IIS log. When you look around, plenty of log files organize their data fundamentally in a tabular way like this:

    #Software: Microsoft Internet Information Services 10.0
    #Version: 1.0
    #Date: 2018-02-02 00:03:04…
    • 27 May 2021
  • Repairing CSV Exports (Part 2)

    In the previous tip we pinpointed a general problem when converting objects to CSV: any property containing an array will display the array data type instead of the array content. Here is an example:

     
    PS> Get-Service | Select-Object -Property Name, DependentServices, RequiredServices | ConvertTo-Csv
    
    #TYPE Selected.System.ServiceProcess.ServiceController
    "Name","DependentServices","RequiredServices"
    "AarSvc_e1277","System…
    • 25 May 2021
  • Repairing CSV Exports (Part 1)

    When you convert data to CSV you may discover a pretty disturbing phenomenon: some properties no longer display the original data. Here is an example:

     
    PS> Get-Service | Select-Object -Property Name, DependentServices, RequiredServices | ConvertTo-Csv
    
    #TYPE Selected.System.ServiceProcess.ServiceController
    "Name","DependentServices","RequiredServices"
    "AarSvc_e1277","System.ServiceProcess.ServiceController[]","System…
    • 21 May 2021