• Redirecting PowerShell Output to GridView

    When you output data in PowerShell, it gets silently piped to Out-Default and ends up as text in the console. By overriding Out-Default, you can change this behavior and for example send all PowerShell output to a grid view window. You can in fact even separate regular output from error messages, and display both in separate windows.

    Here are two functions: Enable-GridOutput and Disable-GridOutput. When you run Enable…

    • 13 May 2019
  • Compare AD User

    Did you ever want to compare the properties of ADUsers? Provided you have installed the RSAT tools, you can read individual AD users with Get-ADUser, but comparing their properties isn’t easy.

    Except when you use below function: it basically splits up AD user properties into individual objects that can be compared using Compare-Object:

    #requires -Version 3.0 -Modules ActiveDirectory
    
    function Compare-User
    {
       
    • 10 May 2019
  • Exporting and Importing Code-Signing Certificates

    In the previous tip we explained how you can create self-signed code-signing certificates in Windows 10 and Server 2016 (and better). Today, let’s take a look at how you can export such certificates to a password protected file, and reuse the certificates on a different machine.

    Let’s assume you have created a new code-signing certificate in your personal certificate store, or there is a code-signing certificate…

    • 9 May 2019
  • Creating Code-Signing Certificates

    Windows 10 and Server 2016 (and better) ship with an enhanced New-SelfSignedCert cmdlet that finally can create code-signing certificates. With code-signing certificates, you can digitally sign PowerShell scripts and use the signature to detect when people tamper with your script content.

    Here is a function that you can use to create a code-signing certificate:

    function New-CodeSigningCert
    {
        param
        (
            [
    • 8 May 2019
  • Using Catalog Files to Maintain Folder Integrity

    If you’d like to make sure a folder content stays untouched, you can use catalog files. A catalog file lists all folder content plus creates hashes for each file in the folder. Here is an example:

    # path to folder to create a catalog file for
    # (make sure it exists and isn't too large)
    $path = "$Home\Desktop"
    # path to catalog file to be created
    $catPath = "$env:temp\myDesktop.cat"
    # create…
    • 7 May 2019
  • Finding PowerShell Named Pipes

    Each PowerShell host running PowerShell 5 or better opens a “named pipe” that you can detect. The code below identifies these named pipes and returns the processes exposing the pipes:

    Get-ChildItem -Path "\\.\pipe\" -Filter '*pshost*' |
    ForEach-Object {
        Get-Process -Id $_.Name.Split('.')[2]
    }
    

    The result may look similar to this:

     
    Handles  NPM(K)    PM(K)      WS(K)     CPU(s…
    • 6 May 2019
  • Finding the Latest PowerShell 6 Download URL

    PowerShell 6 is open-source and maintained in a public repository on GitHub. There are frequent releases. Here is a way how you can find out the download URL for the latest available PowerShell 6 release:

    $AllProtocols = [Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'
    [Net.ServicePointManager]::SecurityProtocol = $AllProtocols 
    
    
    # get the URL for the latest PowerShell 6 release
    $url = "https://github.com/PowerShell…
    • 3 May 2019
  • Finding Latest PowerShell 6 Release (and Download URLs)

    PowerShell 6 is open-source and maintained in a public repository on GitHub. There are frequent releases.

    If you don’t want to dig your way through the GitHub front-end to find the download location for the latest PowerShell 6 release, here is a PowerShell way:

    $AllProtocols = [Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'
    [Net.ServicePointManager]::SecurityProtocol = $AllProtocols 
    
    # get all releases…
    • 2 May 2019
  • Finding Latest PowerShell 6 Release

    PowerShell 6 is open-source, and there are frequently new releases available. You can always visit https://github.com/PowerShell/PowerShell/releases to learn more about these releases.

    From a PowerShell perspective, to automate this step, here is a small script that reads the GitHub release RSS feed, converts the data appropriately, and then dumps the releases with their respective download URLs in descending order:

    • 1 May 2019
  • PowerShell ISE Module Browser

    If you are using the built-in PowerShell ISE, you might find the “Module Browser Add-on” useful. It is fairly old and was published in 2015, however you can easily download and install it from the PowerShell Gallery:

     
    PS C:\> Install-Module ISEModuleBrowserAddOn -Repository PSGallery -Scope CurrentUser 
     

    Once the module is installed, you can load it into PowerShell ISE like this:

     
    PS C:\> Import-Module…
    • 30 Apr 2019
  • Converting SecureString to String

    Sometimes it can make sense to convert a SecureString back to a regular string, for example because you have used the shielded input provided by Read-Host:

    $secret = Read-Host -Prompt 'Enter Keypass' -AsSecureString
    

    This prompts the user to enter secret and now the input is a SecureString:

     
    PS> $secret
    System.Security.SecureString  
     

    To make it plain text again, use the SecureString to create a PSCredential…

    • 29 Apr 2019
  • Real-Time Processing for Language Structures

    In the previous tip we looked at queues and how they can search the entire file system:

    # create a new queue
    $dirs = [System.Collections.Queue]::new()
    
    # add an initial path to the queue
    # any folder path in the queue will later be processed
    $dirs.Enqueue('c:\windows')
    
    # process all elements on the queue until all are taken
    While ($current = $dirs.Dequeue())
    {
        # find subfolders of current folder, and if present…
    • 26 Apr 2019
  • Using a Queue instead of a Recursion

    Rather than calling functions recursively, you may at times want to use a Queue object that you can load with fresh tasks while you are unloading things that you have already processed.

    Lee Holmes has recently posted the below sample which searches an entire filesystem folder tree without recursive calls:

    # create a new queue
    $dirs = [System.Collections.Queue]::new()
    
    # add an initial path to the queue
    # any folder path…
    • 25 Apr 2019
  • Finding Service Privileges

    Get-Service can provide basic information about Windows services but won’t list the required privileges. Here is a small PowerShell function that accepts a service name and returns the service privileges:

    function Get-ServicePrivilege
    {
        
        param
        (
            [Parameter(Mandatory)]
            [string]
            $ServiceName
        )
        
        # find the service
        $Service = @(Get-Service -Name $ServiceName -Erro…
    • 24 Apr 2019
  • Using Variable Breakpoints (Part 2)

    In the previous tip we examined Set-PSBreakpoint to create dynamic variable breakpoints in PowerShell. We showed how a breakpoint can trigger when a variable changes.

    However, what if you want to monitor the change of object properties? Let’s assume you want to monitor the size of an array, and break into the debugger when it grows too large.

    In this scenario, the PowerShell variable never changes. It is the object…

    • 23 Apr 2019
  • Using Variable Breakpoints (Part 1)

    For debugging, variable breakpoints can be of invaluable help. They break into the debugger once a variable changes. If you know that a variable hits a certain value (or a NULL value) when bad things happen, you can make sure the debugger kicks in just then.

    The example below illustrates how to use variable breakpoints. It is best to define them at the top of your script because that way you can use $PSCommandPath to…

    • 22 Apr 2019
  • Hiding Properties in Return Results

    By default, PowerShell shrink-fits most objects and shows only the most important properties by default:

     
    PS C:\> Get-WmiObject -Class Win32_BIOS
    
    
    SMBIOSBIOSVersion : 1.9.0
    Manufacturer      : Dell Inc.
    Name              : 1.9.0
    SerialNumber      : DLGQD72
    Version           : DELL   - 1072009
     

    To see the real information, users would need to use Select-Object and request all information explicitly:

     
    PS C:\> Get…
    • 19 Apr 2019
  • Locking Workstation

    PowerShell can access low-level API functions by using C#-style signatures. This way, API functions are compiled in-memory and added as new types. The example below uses an API function to lock the workstation:

    Function Lock-WorkStation 
    {
        $signature = '[DllImport("user32.dll",SetLastError=true)]
        public static extern bool LockWorkStation();'
        $t = Add-Type -memberDefinition $signature -name api -na…
    • 18 Apr 2019
  • Command Discovery Unleashed (Part 2)

    When you enter a command in PowerShell, the engine triggers three events to actually discover the command you want to execute. This gives you a number of opportunities to intercept and change command discovery. Let’s teach PowerShell to send command output to Out-GridView whenever you add “>>” to a command name!

    Here is the code:

    $ExecutionContext.InvokeCommand.PreCommandLookupAction = {
    param
    • 17 Apr 2019
  • Command Discovery Unleashed (Part 1)

    Whenever you enter a command in PowerShell, a series of events takes place to figure out where the command is located. This starts with a PreCommandLookupAction which you can use to log commands. Have a look at this:

    $ExecutionContext.InvokeCommand.PreCommandLookupAction = {
    param
    (
        [string]
        $Command,
    
        [Management.Automation.CommandLookupEventArgs]
        $Obj
    )
    $whitelist = @(
    'prompt',
    'out-def…
    • 16 Apr 2019
  • Adding Numbers to a String (Part 2)

    In the previous tip we illustrated a number of ways how to safely add variables to string content. Adding variables to double-quoted text can expose yet another issue with automatic variable detection. Have a look:

    # this is the desired output:
    # PowerShell Version is 5.1.17763.316
    
    # this DOES NOT WORK:
    "PowerShell Version is $PSVersionTable.PSVersion"
    

    When you run this code, the output is not what most people…

    • 15 Apr 2019
  • Adding Numbers to a String (Part 1)

    Double-quoted strings can easily expand variables, however this concept is not foolproof:

    $id = 123
    
    # this is the desired output:
    # Number is 123:
    # this DOES NOT WORK:
    "Number is $id:"
    

    As you see in the sample above, when you place variables inside double-quoted text, PowerShell determines automatically where a variable starts and ends. A *** is considered part of the variable. To correct the issue, you need…

    • 12 Apr 2019
  • Get-PSCallStack and Debugging

    In the previous tip we have used Get-PSCallStack to determine the “nest level” of code. Let’s today take a look at how this cmdlet can help during debugging. To illustrate this, save the below code to a script file. It is important that it is in fact is a ps1 file. Execute it in the PowerShell ISE.

    function test1
    {
        test2
    }
    
    function test2
    {
    Wait-Debugger
    Get-Process 
        
    }
    
    test1
    

    test1 is calling…

    • 11 Apr 2019
  • Discovering Nesting Level

    Get-PSCallStack returns a so-called “Call Stack” which – in its simplest form – tells you the nesting depth of your code: there will be a new object added to the stack each time you enter a script block. Have a look:

    function test1
    {
        $callstack = Get-PSCallStack
        $nestLevel = $callstack.Count - 1   
        "TEST1: Nest Level: $nestLevel"    
        test2
    }
    
    function test2
    {
        $cal…
    • 10 Apr 2019
  • Super Simple Random Password Generator

    Here is a super simple approach to create random passwords. The approach makes sure no ambiguous characters are used but does not care about other rules such as a given minimum number of certain characters.

    $Length = 12
    $characters = 'abcdefghkmnprstuvwxyz23456789§$%&?*+#'
    $password = -join ($characters.ToCharArray() | 
    Get-Random -Count $Length) 
    
    $password 
    

    psconf.eu – PowerShell Conference EU 2019…

    • 9 Apr 2019