• Hiding Parameters

    In the previous tip we explained how you can dump all the legal values for a PowerShell attribute. Today we’ll take a look at the [Parameter()] attribute and its value DontShow. Take a look at this function:

    function Test-Something
        "You entered: $name…
    • 2 Nov 2018
  • Exploring PowerShell Attribute Values

    As you might know, you can add attributes to variables and parameters to more specifically define them. For example, the line below defines a function with a parameter that accepts only three distinct string values and is mandatory:

    function Test-Attribute
        "Choice: $Choice…
    • 1 Nov 2018
  • Using Dynamic Parameters

    Most PowerShell functions use static parameters. They are defined in a param() block and are always present. A little-known fact is that you can also add dynamic parameters programmatically on the fly. The big advantage of dynamic parameters is that you are completely free as to when they should appear, and what kind of values they should accept. The drawback is that you need to use a lot of low level code to “program…

    • 31 Oct 2018
  • Accessing Website Content

    Typically, it is trivial for PowerShell to retrieve raw HTML website content by using Invoke-WebRequest. A script can then take the HTML content and do whatever it wants with it, for example scrape information from it using regular expressions:

    $url = "www.tagesschau.de"
    $w = Invoke-WebRequest -Uri $url -UseBasicParsing

    However, sometimes a website content is created dynamically using client-side…

    • 30 Oct 2018
  • Accepting Different Parameter Types

    Occasionally, you might want to create a function that accepts different parameter types. Let’s say you want the user to be able to either submit an employee name, or an Active Directory object.

    There is one fixed rule in PowerShell: variables cannot have multiple data types at the same time. Since parameters are variables, a given parameter can only have one distinct type.

    However, you can use parameter sets to…

    • 29 Oct 2018
  • Translating VBScript to PowerShell

    Most old VBS scripts can be easily translated to PowerShell. The key command in VBS is “CreateObject” which lets you access system libraries. PowerShell translates “CreateObject” to “New-Object -ComObject”, yet the object model and member names stay the same:

    This VBS script talks to you when you save it to a text file with “.vbs” extension:

    Set obj = CreateObject("Sapi…

    • 26 Oct 2018
  • Invoking Excel Macros from PowerShell

    PowerShell can invoke Microsoft Excel sheets and start contained macros. While this would work with an invisible Excel application window, it is a wise idea to keep Excel open (as shown below) to spot warning messages that might appear when you try and run security sensitive things like macros:

    # file path to your XLA file with macros
    $FilePath = "c:\test\file.xla"
    # macro name to run
    $Macro = "AddData"…
    • 25 Oct 2018
  • Programmatically listing any Cmdlet or Function Parameters

    Ever wondered how you can list all properties exposed by a function or cmdlet? Here is how:

    Get-Help Get-Service -Parameter * | Select-Object -ExpandProperty name

    Get-Help provides a lot of helpful information and meta data about parameters as well. If you’d like to dump only parameters that support pipeline input, here is how:

    Get-Help Get-Service -Parameter * | 
    Where-Object { $_.pipelineInput.Length -gt 10 
    • 24 Oct 2018
  • Examining Object Properties Programmatically

    Whether you import a CSV list into PowerShell using Import-Csv, or deal with any other type of objects: how can you automatically determine the object properties? Here is a simple approach:

    # take any object, and dump a list of its properties
    Get-Process -Id $pid | 
      Get-Member -MemberType *property | 
      Select-Object -ExpandProperty Name | 

    Why would this be useful? There are many use cases. For example…

    • 23 Oct 2018
  • Accessing Hidden (Private) Member

    Objects and types have members such as methods and properties, but only a fraction is publicly visible and usable. There are numerous hidden (private) members. While it is not wise to use these in production code as they can change without notice with new versions, it is a highly interesting playground for advanced PowerShellers.

    There is a free PowerShell module called ImpliedReflection which makes private members visible…

    • 22 Oct 2018
  • Performance (Part 3): Faster Pipeline Functions

    In previous tips we illustrated how you can improve loops and especially pipeline operations. To transfer this knowledge to functions, take a look at a simple pipeline-aware function which counts the number of piped elements:

    function Count-Stuff
            # pipeline-aware input parameter
            # initialize counter
    • 19 Oct 2018
  • Performance (Part 2): From 2 sec to 200ms

    In the previous tip we added considerable speed to a common script pattern. Now, let’s squeeze out even more performance with a pretty unusual trick. Here is how far we got in the last tip:

    $start = Get-Date
    $bucket = 1..100000 | ForEach-Object {
        "I am adding $_"
    (Get-Date) - $start

    We managed to get down from 6+ minutes to only 46 seconds on PowerShell 5.1 and 1.46 seconds on PowerShell…

    • 18 Oct 2018
  • Performance (Part 1): From 6 min to 2 sec

    Here is a common mistake found in many PowerShell scripts:

    $start = Get-Date
    $bucket = @()
    1..100000 | ForEach-Object {
        $bucket += "I am adding $_"
    (Get-Date) - $start

    In this design, scripts are using an empty array, then employ some sort of loop to add items to the array. When you run it, you’ll notice that it takes forever. In fact, it took more than 6 minutes on our test system and…

    • 17 Oct 2018
  • Keeping Track of Script Execution

    Here is a chunk of code that demonstrates how you can store private settings in the Windows Registry:

    # store settings here
    $Path = "HKCU:\software\powertips\settings"
    # check whether key exists
    $exists = Test-Path -Path $Path
    if ($exists -eq $false)
        # if this is first run, initialize registry key
        $null = New-Item -Path $Path -Force
    # read existing value
    $currentValue = Get-ItemProperty -Path 
    • 16 Oct 2018
  • Retrieving Outlook Calendar Entries

    If you use Outlook to organize your calendar events, here is a useful PowerShell function that connects to Outlook and dumps your calendar entries:

    Function Get-OutlookCalendar
        # load the required .NET types
        Add-Type -AssemblyName 'Microsoft.Office.Interop.Outlook'
        # access Outlook object model
        $outlook = New-Object -ComObject outlook.application
        # connect to the appropriate location…
    • 15 Oct 2018
  • Getting AD Users with Selected First Letters

    How would you query for all AD users with names that start with a “e”-“g”? You shouldn’t use a client-side filter such as Where-Object. One thing you can do is use the -Filter parameter with logical operators such as -and and -or:

    Get-ADUser -filter {(name -lt 'E') -or (name -gt 'G')} |
      Select-Object -ExpandProperty Name

    this example requires the free RSAT tools from Microsoft…

    • 12 Oct 2018
  • Adding New Incrementing Number Column in a Grid View Window

    Maybe you’d like to add a column with incrementing indices to your objects. Try this:

    $startcount = 0
    Get-Service |
      Select-Object -Property @{N='ID#';E={$script:startcount++;$startcount}}, * |

    When you run this chunk of code, you get a list of services in a grid view window, and the first column “ID#” is added with incrementing ID numbers.

    The technique can be used to add arbitrary…

    • 11 Oct 2018
  • Improving Group-Object

    In the previous tip we explained what Group-Object can do for you, and how awesome it is. Unfortunately, Group-Object does not scale well. When you try and group a large number of objects, the cmdlet may take a very long time.

    Here is a line that groups all files in your user profile by size. This could be an important prerequisite when you want to check for duplicate files. While this line will eventually yield results…

    • 10 Oct 2018
  • Discover Group-Object

    Group-Object is an awesome cmdlet: it can easily visualize distributions. Check out the examples below:

    Get-Process | Group-Object -Property Company
    Get-Eventlog -LogName System -EntryType Error | Group-Object -Property Source
    Get-ChildItem -Path c:\windows -File | Group-Object -Property Extension

    Basically, the cmdlet builds groups based on the content of a given property. You can also omit the group, and just look…

    • 9 Oct 2018
  • Automating “Live” Websites

    Occasionally, there is the need to automate tasks on websites that have been opened manually. Maybe you need to log into internal web pages first using some web forms. Provided the website is hosted in Internet Explorer (not Edge or any 3rd-party browser), you can use a COM interface to access the live browser content.

    This can even be valuable for plain “HTML-scraping” when you visit dynamic web pages. A pure WebClient…

    • 8 Oct 2018
  • Installing Printers

    Starting with Windows 8 and Server 2012 R2, these operating systems ship a PowerShell module called PrintManagement. The cmdlets found in this module can be helpful to script printer installations and configuration. Here is a simple chunk of code to get you started:

    $PrinterName = "MyPrint"
    $ShareName = "MyShare"
    $DriverName = 'HP Designjet Z Series PS Class Driver'
    $portname = "${PrinterName…
    • 5 Oct 2018
  • Using CSV to Create Objects

    Sometimes it may be clever to use simple text-based CSV format internally to bulk-create objects, especially if the original data is already text-based and may need just a little reformatting.

    Here is a simple example that takes information and creates a list of custom objects this way:

    $text = 'Name,FirstName,Location
    • 4 Oct 2018
  • Finding Active Directory Group Members Efficiently

    Often, AD Administrators need to find all members of a given AD group, including nested members. Here is a code snippet that frequently surfaces in examples to solve this puzzle:

    $groupname = 'External_Consultants'
    $group = Get-ADGroup -Identity $groupname
    $dn = $group.DistinguishedName
    $all = Get-ADUser -filter {memberof -recursivematch $dn}
    $all | Out-GridView

    (note that you need the free RSAT tools from Microsoft…

    • 3 Oct 2018
  • Using Artificial Intelligence with Azure Cognitive Services

    The cloud these days not only offers virtual machines and storage, but also brand new and exciting services such as the cognitive services. You need an Azure subscription key (which you can get for free on the website mentioned below) if you want to directly access these services. Else, you would need to resort to the free interactive demos found here:


    • 2 Oct 2018
  • Backing Up All Scripts to ZIP

    PowerShell 5 finally includes support for ZIP files, so if you want to backup all of your PowerShell scripts into one ZIP file, here is a one-liner:

    Get-ChildItem -Path $Home -Filter *.ps1 -Recurse -ErrorAction SilentlyContinue |
      Compress-Archive -DestinationPath "$home\desktop\backupAllScripts.zip" -CompressionLevel Optimal

    Note that on Windows 10, all files are passed through your AV engine before they…

    • 1 Oct 2018