• Using Solid Alternatives for $MyInvocation

    Lines like $MyInvocation.MyCommand.Definition can be useful to determine the folder in which the current script is stored, i.e. to access other resources located in the same folder.

    However, ever since PowerShell 3, there have been easy alternatives to find out the current script name and/or the path to the folder that contains the current script. Run the following code to test for yourself:

    $MyInvocation.MyCommand.D…
    • 10 Dec 2018
  • Finding Open Firewall Ports

    Here is a piece of PowerShell code that connects to the local firewall and dumps the open firewall ports:

    $firewall = New-object -ComObject HNetCfg.FwPolicy2
    $firewall.Rules |  Where-Object {$_.Action -eq 0} | 
        Select-Object Name, ApplicationName,LocalPorts
    

    The result may look similar to this:

     
    Name           ApplicationName                                         LocalPorts
    ----           ---------------      …
    • 7 Dec 2018
  • Executing Code with a Timeout (Part 2)

    In the previous tip we implemented a timeout using PowerShell background jobs so you could set a maximum time some code was allowed to run before it raised an exception.

    Here is a more lightweight alternative that uses in-process threads rather than out-of-process executables:

    function Invoke-CodeWithTimeout
    {
        param
        (
            [Parameter(Mandatory)]
            [ScriptBlock]
            $Code,
    
            [int]
            $…
    • 6 Dec 2018
  • Executing Code with a Timeout (Part 1)

    If you’d like to make sure some code won’t execute forever, you can use background jobs to implement a timeout. Here is a sample function:

    function Invoke-CodeWithTimeout
    {
        param
        (
            [Parameter(Mandatory)]
            [ScriptBlock]
            $Code,
    
            [int]
            $Timeout = 5
    
        )
    
        $j = Start-Job -ScriptBlock $Code
        $completed = Wait-Job $j -Timeout $Timeout
        if ($completed -eq
    • 5 Dec 2018
  • Code-Signing Mini-Series (Part 5: Auditing Signatures)

    Once a PowerShell script carries a digital signature, you can easily find out who signed the script, and more importantly, whether the script is still untampered. In the previous parts of this series, you learned how to create digital certificates, and how to apply new code-signing signatures to PowerShell files. Now let’s see how you can validate scripts.

    # this is the path to the scripts you'd like to examine…
    • 4 Dec 2018
  • Code-Signing Mini-Series (Part 4: Code-Signing PowerShell Files)

    Before you give away a PowerShell script to others, it is a good idea to digitally sign it. A signature acts like a “wrapper” for your script and helps others identify who originally wrote the script and whether the script is still in original condition or was tampered with.

    To sign PowerShell scripts you need a digital code-signing certificate. In the previous tips we explained how you can create one, and…

    • 3 Dec 2018
  • Code-Signing Mini-Series (Part 3: Reading Certificates from Personal Store)

    Certificates can be installed permanently by loading them into Windows certificate store. PowerShell can access this store via its cert: drive. The following line dumps all your personal certificates:

     
    PS C:\> Get-ChildItem -Path Cert:\CurrentUser\my
    
    
       PSParentPath: Microsoft.PowerShell.Security\Certificate::CurrentUser\my
    
    Thumbprint                                Subject                              
    ----------…
    • 30 Nov 2018
  • Code-Signing Mini-Series (Part 2: Reading Certificates from PFX Files)

    In the previous tip we created new code-signing test certificates both as pfx file and located in your certificate store. Today, you’ll see how you can load these (or any other certificates you got from other sources) into PowerShell.

    To load a certificate from a pfx file, use Get-PfxCertificate:

    $Path = "$home\desktop\tobias.pfx"
    $cert = Get-PfxCertificate -FilePath $Path 
    
    $cert | Select-Object -Pro…
    • 29 Nov 2018
  • Code-Signing Mini-Series (Part 1: Creating Certs)

    To play with digital signatures, and discover how you can sign scripts and modules, you first need a code-signing certificate. If you can’t get one from your corporate IT, PowerShell can create one for you (provided you are using Windows 10 or Server 2016).

    We wrapped the details in an easy-to-use function called New-CodeSigningCert which can create new code-signing certs in your personal certificate store, or also…

    • 28 Nov 2018
  • Converting SecureString to Clear Text

    Secure string content cannot be easily viewed:

    $password = Read-Host -Prompt 'Your password' -AsSecureString
    
     
    PS C:\> $password
    System.Security.SecureString 
     

    However, if you are the one who asked for the secure string in the first place, you can easily convert it back into plain text with this clever trick:

    $txt = [PSCredential]::new("X", $Password).GetNetworkCredential().Password
    $txt
    

    Essentially…

    • 27 Nov 2018
  • Using Catalog Files

    Catalog file support (.cat) is new in PowerShell 5.1. Cat files basically are file lists with hash values. You can use them to ensure that a given file structure is unchanged.

    Here is a simple example. It takes a folder (make sure it exists, or else rename it) and creates a cat file for the entire folder content. Note that this involves creating a hash value for each file in the folder, so keep an eye on a reasonable…

    • 26 Nov 2018
  • Making Error Records More Readable

    Whenever PowerShell encounters an error, it emits an Error Record with detailed information about the problem. Unfortunately, these objects are a bit cryptic and won’t show all of their information by default. To get to the beef, a function like the below is of invaluable help:

    function ConvertFrom-ErrorRecord
    {
      param
      (
        # we receive either a legit error record...
        [Management.Automation.ErrorRecord[]…
    • 23 Nov 2018
  • Creating Write-Protected Functions

    PowerShell functions by default can be overridden anytime, and you can also remove them using Remove-Item:

    function Test-Lifespan
    {
      "Hello!"
    }
    
    Test-Lifespan
    
    Remove-Item -Path function:Test-Lifespan
    
    Test-Lifespan
    

    For security-relevant functions, you might want to create functions in a way that makes them immune against overwriting. Here is how:

    $FuncName = 'Test-ConstantFunc'
    $Expression = {
      
    • 22 Nov 2018
  • $FormatEnumerationLimit Scoping Issues

    As shown in the previous tip, the secret $FormatEnumerationLimit variable determines how many array elements are shown in output before the output is truncated. Here is an example illustrating the difference again:

    $default = $FormatEnumerationLimit
    
    Get-Process | Select-Object -Property Name, Threads -First 5 | Out-Default
    $FormatEnumerationLimit = 1
    Get-Process | Select-Object -Property Name, Threads -First 5 | Out…
    • 21 Nov 2018
  • Displaying Array Members in Output

    When you output objects that have arrays in their properties, only 4 array elements are displayed, then an ellipsis truncates the rest:

     
    PS C:\> Get-Process | Select-Object -Property Name, Threads -First 6
    
    Name       Threads                    
    ----       -------                    
    acrotray   {3160}                     
    AERTSr64   {1952, 1968, 1972, 8188}   
    AGSService {1980, 1988, 1992, 2000...}
    armsvc     {1920,…
    • 20 Nov 2018
  • Find All Files Two Levels Deep

    Yet another file system task: list all *.log files in a folder structure, but only to a maximum depth of 2 folder structures:

    Get-ChildItem -Path c:\windows -Filter *.log -Recurse -Depth 2 -File -Force -ErrorAction SilentlyContinue |
      Select-Object -ExpandProperty FullName
    

    Fortunately, PowerShell 5 added the helpful -Depth parameter to Get-ChildItem.

    Twitter This Tip! ReTweet this Tip!

    • 19 Nov 2018
  • Deleting All Subfolders Below A Given Level

    Here is another file system task that sounds worse than it actually is. Let’s say you need to remove all folders below a given level in a folder structure. Here is how:

    # Task:
    
    # remove all folders one level below the given path
    Get-ChildItem -Path "c:\sample\*\" -Directory -Recurse | 
        # remove -WhatIf to actually delete
        # ATTENTION: test thoroughly before doing this!
        # you may want to add…
    • 16 Nov 2018
  • Deleting All Files from a Folder Structure

    Sometimes tasks sound worse than they actually are. Let’s say you need to clear a folder structure and remove all files, leaving empty folders. Let’s further assume there are files on a whitelist that should not be deleted. With PowerShell, that’s easy to accomplish:

    # Task:
    # remove all files from a folder structure, but keep all folders,
    # and keep all files on a whitelist
    
    $Path = "c:\sample"…
    • 15 Nov 2018
  • Adding RSS Ticker to PowerShell Title Bar

    A new PowerShell background thread can do things for you in the background, for example updating your PowerShell window title bar with new news feeds every five seconds.

    First, let’s look at how to get to the news feed items:

    $RSSFeedUrl = 'https://www.technologyreview.com/stories.rss'
    $xml = Invoke-RestMethod -Uri $RSSFeedUrl
    $xml | ForEach-Object {
        "{0} {1}" -f $_.title, $_.description
    }
    • 14 Nov 2018
  • Invoke-WebRequest vs. Invoke-RestMethod

    Invoke-WebRequest simply downloads the content from any web site. It is then your job to read the content and make sense of it. In the previous tip we explained how you can download PowerShell code, and execute it:

    $url = "http://bit.ly/e0Mw9w"
    $page = Invoke-WebRequest -Uri $url
    $code = $page.Content
    $sb = [ScriptBlock]::Create($code)
    & $sb
    

    (note: Run above code in a PowerShell console. When run from an…

    • 13 Nov 2018
  • Downloading PowerShell Code

    In the previous tip we explained how Invoke-WebRequest can be used to download the raw HTML content for any web page. This can also be used to transport PowerShell code. Invoke-WebRequest downloads anything a web server serves, so the below example downloads a PowerShell script:

    $url = "http://bit.ly/e0Mw9w"
    $page = Invoke-WebRequest -Uri $url
    $code = $page.Content
    $code | Out-GridView
    

    Once you are confident…

    • 12 Nov 2018
  • Hiding Progress Bars

    Sometimes, cmdlets automatically display a progress bar. Here is an example of such a progress bar:

    $url = "http://www.powertheshell.com/reference/wmireference/root/cimv2/"
    $page = Invoke-WebRequest -URI $url
    

    Invoke-WebRequest retrieves the raw content for a web page, and if retrieving the content takes a while, a progress bar is shown.

    Whenever you run a cmdlet that shows a progress bar, you can hide the progress…

    • 9 Nov 2018
  • Analyzing Web Page Content

    PowerShell comes with a built-in web client which can retrieve HTML content for you. For a simple web page analysis, use the -UseBasicParsing parameter. This gets you the raw HTML content as well as, for example, a list of all embedded links and images:

    $url = "http://powershellmagazine.com"
    $page = Invoke-WebRequest -URI $url -UseBasicParsing
    
    $page.Content | Out-GridView -Title Content
    $page.Links | Select…
    • 8 Nov 2018
  • Adding Extra Safety Net

    If you are writing PowerShell functions, and you know a particular function has the potential to cause a lot of harm, there is an easy way of adding an extra safety net. Below are two functions, one without safety net, and one with a safety net:

    function NoSafety
    {
        param
        (
            [Parameter(Mandatory)]
            $Something
        )
        "HARM DONE with $Something!"
    }
    
    function Safety
    {
        # step 1: add …
    • 7 Nov 2018
  • Hiding Common Parameters

    In our last tip we explained how you can hide parameters from IntelliSense. This has a cool side effect that we’d like to point you to today!

    PowerShell supports two different types of functions: simple functions and advanced functions. A simple function just exposes the parameters you define. An advanced function also adds all the common parameters. Here are two sample functions:

    function Simple
    {
        param
      
    • 6 Nov 2018