• Using Profile Scripts

    Profile scripts work like autostart scripts in PowerShell. They do not need to exist, but if they do, PowerShell executes its content silently during each launch. There are up to four profile scripts, and this line exposes their paths:

     
    PS> $profile | Select-Object -Property *
    
    AllUsersAllHosts       : C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1
    AllUsersCurrentHost    : C:\Windows\System32\WindowsPowerShell…
    • 25 Sep 2020
  • Identifying User Profile

    Be careful when using $env:userprofile or $home to create paths to user files. When a Windows box is set up for OneDrive, the documents folder may have been redirected to a subfolder named “OneDrive”. Here are some examples:

     
    PS> $env:USERPROFILE
    C:\Users\tobia
    
    PS> $HOME
    C:\Users\tobia
    
    PS> $profile
    C:\Users\tobia\OneDrive\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1
    
    PS> 
     …
    • 23 Sep 2020
  • Get Rid of Get-EventLog

    The Get-EventLog cmdlet provides easy access to event log entries in the primary Windows event logs, however it neither can access the many application level event logs, nor is it available at all in PowerShell 7.

    If you ever plan to run your code in PowerShell 7, you should start getting used to its successor: Get-WinEvent. This cmdlet is powerful and supports many parameters. Here is an example that comes close to what…

    • 21 Sep 2020
  • Setting and Clearing Trusted Hosts

    PowerShell remoting maintains a list of trusted IP addresses and/or machine names on the client side (the machine that issues the command and authenticates at the server). This list is important for you because it governs how you can authenticate to remote computers.

    By default, PowerShell supports Kerberos authentication only because it is most secure and authenticates both sides, client and server. It requires an Active…

    • 17 Sep 2020
  • Using PowerShell 7 inside PowerShell ISE

    The PowerShell ISE built into Windows works with Windows PowerShell only and is stuck at PowerShell version 5.1. Typically, when you want to use an editor to write PowerShell 7 code, Visual Studio Code and the PowerShell extension is the way to go.

    Still, you can make PowerShell ISE “talk” to PowerShell 7. It then provides rich IntelliSense for PowerShell 7 and understands all language features that were introduced in…

    • 15 Sep 2020
  • Using $Is* Variables

    In PowerShell 7, there is a new set of variables all starting with “Is”. They help you understand the environment in which your script runs:

     
    PS> Get-Variable -Name is*
    Name                           Value
    ----                           -----
    IsCoreCLR                      True
    IsLinux                        False
    IsMacOS                        False
    IsWindows                      True 
    

    In Windows PowerShell…

    • 11 Sep 2020
  • Enabling and Disabling Realtime Antivirus Protection

    You can use PowerShell to enable and disable real-time antivirus protection provided you are running with full Administrator privileges. Temporarily disabling real-time antivirus protection may occasionally be helpful when there is explicit need to run legit scripts that may otherwise be blocked. Generally, real-time protection is valuable and should only be disabled with good cause.

    To disable real-time protection, run…

    • 9 Sep 2020
  • Identifying Antivirus Engine State

    In the previous tip you learned how you can query WMI to find out the antivirus product present on your Windows machine:

    $info = Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntiVirusProduct
    
    $info
    

    The ProductState property encodes additional pieces of information, telling you whether the AV engine is operational and uses up-to-date signatures. Unfortunately, the information comes as a single number and…

    • 7 Sep 2020
  • Identifying Installed Antivirus Product

    A PowerShell one-liner can help you identify the antivirus product installed on a Windows box:

     
    PS> Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntiVirusProduct 
     

    Add the -ComputerName parameter to query remote systems.

    Note that this line returns only antivirus products that properly registered. The result looks similar to this and provides you with AV product and install location:

     
    displayName  …
    • 3 Sep 2020
  • Deleting Microsoft Teams Cache Data

    If you use Microsoft Teams for video conferencing, you may occasionally want to clean cache files and remove traces which reside in a number of subfolders.

    You can adjust the code from our previous example to do the cleanup for you:

    # the folder that contains the Microsoft Teams data
    $parentFolder = "$env:userprofile\AppData\Roaming\Microsoft\Teams\*"
    # list of subfolders that cache data
    $list = 'application…
    • 1 Sep 2020
  • Deleting Multiple Subfolders

    Occasionally, it may become necessary to delete a set of subfolders within a given folder. Here is a simple chunk of code that deletes the folders from a list of folder names.

    Warning: this code will delete the subfolders listed in $list without further confirmation. If the subfolders do not exit, nothing happens.

    # the folder that contains the subfolders to remove
    # (adjust to your needs)
    $parentFolder = $env:userpr…
    • 28 Aug 2020
  • Managing Autostarts

    To manage auto starting programs on Windows, don’t bother writing extensive scripts. PowerShell can directly open the autostart manager included in task manager which does all you need:

     
    PS C:\> Taskmgr /7 /startup 
     

    This opens a window and lists all auto starting programs, along with their impact on the launch time. To keep any one of these programs from automatically starting, click a program in the list,…

    • 26 Aug 2020
  • Downloading Useful Scripts

    The PowerShell Gallery not only offers public modules with new PowerShell commands but also public scripts. Before you invest time, you may want to investigate if someone else may have created PowerShell code that can do what you want.

    Here is a quick example that illustrates how searching and downloading scripts via the PowerShell Gallery works:

    # create temporary folder
    $destination = Join-Path -Path $env:temp -Chi…
    • 24 Aug 2020
  • Speeding Up PowerShell Remoting

    PowerShell remoting is insanely powerful: with Invoke-Command, you can send arbitrary PowerShell code to one or many remote machines and execute it there in parallel.

    On Windows Servers, PowerShell remoting is typically enabled, so all you need are Administrator privileges. Here is a simple example:

     
    PS> Invoke-Command -ScriptBlock { "I am running on $env:computername!" } -ComputerName server1 -Credenti…
    • 20 Aug 2020
  • Creating PowerShell Functions Dynamically

    New-Item can create new things on any PowerShell drive, including the function: drive that holds all PowerShell functions.

    If you’d like, you can define new functions dynamically inside your code. These new functions would then exist only in the scope where they were defined. To make them script-global, add the script: scope identifier. Here is an example:

    function New-DynamicFunction
    {
       # creates a new function…
    • 18 Aug 2020
  • Validating User Account Passwords (Part 3)

    In the previous parts, we created the Test-Password function that can test user account passwords for both local and remote user accounts.

    In our last part, we’ll add error handling to the Test-Password function so it responds gracefully when the user enters domain that does not exist or is unavailable:

    function Test-Password
    {
       param
       (
          [Parameter(Mandatory)]
          [string]
          $Domain,
    
          [Par…
    • 14 Aug 2020
  • Validating User Account Passwords (Part 2)

    In the previous tip we showed how PowerShell can validate and test user account passwords, however the password was requested in plain text. Let’s change this so that PowerShell masks the password when it is entered.

    You can re-use the strategy used below for any other PowerShell function where you’d like to prompt the user for masked input.

    Here is the function Test-Password:

    function Test-Password
    {
       
    • 12 Aug 2020
  • Validating User Account Passwords (Part 1)

    PowerShell can test user account passwords for you. This works both for local and domain accounts. Here is a sample function called Test-Password:

    function Test-Password
    {
       param
       (
          [Parameter(Mandatory)]
          [string]
          $Domain,
    
          [Parameter(Mandatory)]
          [string]
          $Username,
    
          [Parameter(Mandatory)]
          [string]
          $Password
    
       )
    
       # load assembly for required system commands…
    • 10 Aug 2020
  • Reading 4K-Hash

    Windows operating systems can be uniquely identified by a so-called 4K-Hash: this is a special hash string that is 4000 bytes in size. You can use this hash for example with “Windows Autopilot” to add physical and virtual machines.

    The 4K Hash is just one piece of information required to register Windows machines yet it may be interesting by itself to uniquely identify Windows operating systems for other purposes…

    • 6 Aug 2020
  • Sophisticated Battery Report

    If your laptop battery is going low too soon, or you’d like to investigate related issues, there is a simple way to generate an extensive battery charging report. It shows exactly when your battery was charged, what its capacity is, and how long it took to deplete.

    Here is the code to create a 14-day report:

    $path = "$env:temp/battery_report2.html"
    powercfg /batteryreport /output $Path /duration 14
    Start…
    • 4 Aug 2020
  • Adding PowerShell commands for SharePoint

    The PowerShell Gallery provides easy access to additional PowerShell commands. For example, you can download and install the command extension for SharePoint and use PowerShell to automate your SharePoint sites:

    Install-Module -Name Microsoft.Online.SharePoint.PowerShell -Scope CurrentUser -Force 
    
    # listing all new SharePoint commands
    Get-Command -Module Microsoft.Online.SharePoint.PowerShell
    

    There are many more PowerShell…

    • 31 Jul 2020
  • Adding PowerShell commands for Azure

    To manage and automate your assets in the Azure cloud, you can easily install a free PowerShell module which comes with a wealth of new PowerShell commands:

    if ($PSVersionTable.PSEdition -eq 'Desktop' -and (Get-Module -Name AzureRM -ListAvailable)) {
        Write-Warning 'AzureRM and Az modules installed at the same time is not supported.')
    } else {
        Install-Module -Name Az -AllowClobber -Scope Curren…
    • 29 Jul 2020
  • Showing Wi-Fi SSIDs

    In the previous tip we illustrated how you can dump all Wi-Fi profile names using netsh.exe. Typically, profile names and SSIDs are identical. However, if you are interested in the true Wi-Fi SSID names, you can query these directly by dumping individual profiles and using a wildcard for the profile name:

     
    PS> netsh wlan show profile name="*" key=clear |
     Where-Object { $_ -match "SSID name\s*:\s(.*)$"…
    • 27 Jul 2020
  • Dumping Wi-Fi Passwords

    In the previous tip we used netsh.exe to dump Wi-Fi profiles. Let’s take it a step further and expose the cached passwords:

     # get cleartext password for each profile
     Foreach ($profile in $profiles)
     {
           $password = (@(netsh wlan show profile name="$profile" key=clear) -like '*Key Content*' -split ': ')[-1]
           [PSCustomObject]@{
                 Profile = $profile
                 Pa…
    • 23 Jul 2020
  • Showing Wi-Fi Profiles

    PowerShell is not limited to cmdlets and can run executables. For example, there is no built-in cmdlet to list the existing Wi-Fi profiles, but netsh.exe can provide the information:

     
    PS> netsh wlan show profiles
     

    Use Select-String to identify only output lines that match the pattern (a colon with following text), then use the -split operator to separate the strings at “: “, and get just the profile names by returning…

    • 21 Jul 2020