PowerShell is a powerful scripting language for Windows. It’s an easy-to-learn, yet extremely versatile programming language that can be used to automate many common tasks and create some really cool software solutions. If you’re curious about PowerShell, check out these five examples of how it can help make your life easier!
The “powershell script example with parameters” is a PowerShell script that can be used to inspire you to get scripting. This script will give 5 examples of how it can be used.
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
With the first try statement, you’re creating the FTP script file using the Out-File cmdlet. If the try statement fails, the errors will be caught by the catch statement following. The script will then be terminated using the $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
Notice that you’re creating the FTP script file via the Out-File cmdlet with the first try statement. If the try statement failed, the catch statement below would catch the errors. Then the $($_.Exception.Message) property followed by an exit 1 will end the script, displaying the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create a try block and fill it with whatever code you like. try ## Using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/), create the FTP script file. If Out-File produces an FTP script, it then calls ftp.exe to run the script file. @Script = $Script “username and password for localhost BINARY CD/DVD/DVD/DVD/DVD/DVD/DVD/ GET remote.file from C:folder BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ “-ASCII ftp -s encoding: folderftp.txt C:folderftp.txt catch ## If any code within the try block returns a hard-terminating error at any point, PowerShell will redirect the code to the catch block, which writes to the console ## and terminates the PowerShell console with a 1 exit code. exit 1 finally Write-Host “Error: $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
With the first try statement, you’re creating the FTP script file using the Out-File cmdlet. If the try statement fails, the errors will be caught by the catch statement following. The script will then be terminated using the $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
Notice that you’re creating the FTP script file via the Out-File cmdlet with the first try statement. If the try statement failed, the catch statement below would catch the errors. Then the $($_.Exception.Message) property followed by an exit 1 will end the script, displaying the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, an error message (
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
With the first try statement, you’re creating the FTP script file using the Out-File cmdlet. If the try statement fails, the errors will be caught by the catch statement following. The script will then be terminated using the $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
Notice that you’re creating the FTP script file via the Out-File cmdlet with the first try statement. If the try statement failed, the catch statement below would catch the errors. Then the $($_.Exception.Message) property followed by an exit 1 will end the script, displaying the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create a try block and fill it with whatever code you like. try ## Using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/), create the FTP script file. If Out-File produces an FTP script, it then calls ftp.exe to run the script file. @Script = $Script “username and password for localhost BINARY CD/DVD/DVD/DVD/DVD/DVD/DVD/ GET remote.file from C:folder BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ “-ASCII ftp -s encoding: folderftp.txt C:folderftp.txt catch ## If any code within the try block returns a hard-terminating error at any point, PowerShell will redirect the code to the catch block, which writes to the console ## and terminates the PowerShell console with a 1 exit code. exit 1 finally Write-Host “Error: $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
With the first try statement, you’re creating the FTP script file using the Out-File cmdlet. If the try statement fails, the errors will be caught by the catch statement following. The script will then be terminated using the $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
Notice that you’re creating the FTP script file via the Out-File cmdlet with the first try statement. If the try statement failed, the catch statement below would catch the errors. Then the $($_.Exception.Message) property followed by an exit 1 will end the script, displaying the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) property followed by an exit 1, showing the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message)” ## Remove the FTP script file regardless of whether the catch block caught an exception. Remove-Item -Path “C:folderftp.txt” Remove-Item -Path “C:folderftp.txt” ## Exit the PowerShell session with an exit code of 0 exit 0 when the code within the try/catch/finally blocks completes (error or not).
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) property followed by an exit 1, showing the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create a try block and fill it with whatever code you like. try ## Using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/), create the FTP script file. If Out-File produces an FTP script, it then calls ftp.exe to run the script file. @Script = $Script “username and password for localhost BINARY CD/DVD/DVD/DVD/DVD/DVD/DVD/ GET remote.file from C:folder BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ “-ASCII ftp -s encoding: folderftp.txt C:folderftp.txt catch ## If any code within the try block returns a hard-terminating error at any point, PowerShell will redirect the code to the catch block, which writes to the console ## and terminates the PowerShell console with a 1 exit code. exit 1 finally Write-Host “Error: $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
With the first try statement, you’re creating the FTP script file using the Out-File cmdlet. If the try statement fails, the errors will be caught by the catch statement following. The script will then be terminated using the $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
Notice that you’re creating the FTP script file via the Out-File cmdlet with the first try statement. If the try statement failed, the catch statement below would catch the errors. Then the $($_.Exception.Message) property followed by an exit 1 will end the script, displaying the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) property followed by an exit 1, showing the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message)” ## Remove the FTP script file regardless of whether the catch block caught an exception. Remove-Item -Path “C:folderftp.txt” Remove-Item -Path “C:folderftp.txt” ## Exit the PowerShell session with an exit code of 0 exit 0 when the code within the try/catch/finally blocks completes (error or not).
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) will be shown, detailing what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) property followed by an exit 1, showing the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, an error message (
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
With the first try statement, you’re creating the FTP script file using the Out-File cmdlet. If the try statement fails, the errors will be caught by the catch statement following. The script will then be terminated using the $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
Notice that you’re creating the FTP script file via the Out-File cmdlet with the first try statement. If the try statement failed, the catch statement below would catch the errors. Then the $($_.Exception.Message) property followed by an exit 1 will end the script, displaying the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create a try block and fill it with whatever code you like. try ## Using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/), create the FTP script file. If Out-File produces an FTP script, it then calls ftp.exe to run the script file. @Script = $Script “username and password for localhost BINARY CD/DVD/DVD/DVD/DVD/DVD/DVD/ GET remote.file from C:folder BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ “-ASCII ftp -s encoding: folderftp.txt C:folderftp.txt catch ## If any code within the try block returns a hard-terminating error at any point, PowerShell will redirect the code to the catch block, which writes to the console ## and terminates the PowerShell console with a 1 exit code. exit 1 finally Write-Host “Error: $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
With the first try statement, you’re creating the FTP script file using the Out-File cmdlet. If the try statement fails, the errors will be caught by the catch statement following. The script will then be terminated using the $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
Notice that you’re creating the FTP script file via the Out-File cmdlet with the first try statement. If the try statement failed, the catch statement below would catch the errors. Then the $($_.Exception.Message) property followed by an exit 1 will end the script, displaying the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) property followed by an exit 1, showing the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message)” ## Remove the FTP script file regardless of whether the catch block caught an exception. Remove-Item -Path “C:folderftp.txt” Remove-Item -Path “C:folderftp.txt” ## Exit the PowerShell session with an exit code of 0 exit 0 when the code within the try/catch/finally blocks completes (error or not).
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) property followed by an exit 1, showing the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create a try block and fill it with whatever code you like. try ## Using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/), create the FTP script file. If Out-File produces an FTP script, it then calls ftp.exe to run the script file. @Script = $Script “username and password for localhost BINARY CD/DVD/DVD/DVD/DVD/DVD/DVD/ GET remote.file from C:folder BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ “-ASCII ftp -s encoding: folderftp.txt C:folderftp.txt catch ## If any code within the try block returns a hard-terminating error at any point, PowerShell will redirect the code to the catch block, which writes to the console ## and terminates the PowerShell console with a 1 exit code. exit 1 finally Write-Host “Error: $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
With the first try statement, you’re creating the FTP script file using the Out-File cmdlet. If the try statement fails, the errors will be caught by the catch statement following. The script will then be terminated using the $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
Notice that you’re creating the FTP script file via the Out-File cmdlet with the first try statement. If the try statement failed, the catch statement below would catch the errors. Then the $($_.Exception.Message) property followed by an exit 1 will end the script, displaying the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) property followed by an exit 1, showing the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message)” ## Remove the FTP script file regardless of whether the catch block caught an exception. Remove-Item -Path “C:folderftp.txt” Remove-Item -Path “C:folderftp.txt” ## Exit the PowerShell session with an exit code of 0 exit 0 when the code within the try/catch/finally blocks completes (error or not).
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) will be shown, detailing what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message)” ## Remove the FTP script file regardless of whether the catch block caught an exception. Remove-Item -Path “C:folderftp.txt” Remove-Item -Path “C:folderftp.txt” ## Exit the PowerShell session with an exit code of 0 exit 0 when the code within the try/catch/finally blocks completes (error or not).
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, an error message (
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
With the first try statement, you’re creating the FTP script file using the Out-File cmdlet. If the try statement fails, the errors will be caught by the catch statement following. The script will then be terminated using the $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
Notice that you’re creating the FTP script file via the Out-File cmdlet with the first try statement. If the try statement failed, the catch statement below would catch the errors. Then the $($_.Exception.Message) property followed by an exit 1 will end the script, displaying the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create a try block and fill it with whatever code you like. try ## Using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/), create the FTP script file. If Out-File produces an FTP script, it then calls ftp.exe to run the script file. @Script = $Script “username and password for localhost BINARY CD/DVD/DVD/DVD/DVD/DVD/DVD/ GET remote.file from C:folder BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ “-ASCII ftp -s encoding: folderftp.txt C:folderftp.txt catch ## If any code within the try block returns a hard-terminating error at any point, PowerShell will redirect the code to the catch block, which writes to the console ## and terminates the PowerShell console with a 1 exit code. exit 1 finally Write-Host “Error: $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
With the first try statement, you’re creating the FTP script file using the Out-File cmdlet. If the try statement fails, the errors will be caught by the catch statement following. The script will then be terminated using the $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
Notice that you’re creating the FTP script file via the Out-File cmdlet with the first try statement. If the try statement failed, the catch statement below would catch the errors. Then the $($_.Exception.Message) property followed by an exit 1 will end the script, displaying the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) property followed by an exit 1, showing the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message)” ## Remove the FTP script file regardless of whether the catch block caught an exception. Remove-Item -Path “C:folderftp.txt” Remove-Item -Path “C:folderftp.txt” ## Exit the PowerShell session with an exit code of 0 exit 0 when the code within the try/catch/finally blocks completes (error or not).
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) property followed by an exit 1, showing the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create a try block and fill it with whatever code you like. try ## Using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/), create the FTP script file. If Out-File produces an FTP script, it then calls ftp.exe to run the script file. @Script = $Script “username and password for localhost BINARY CD/DVD/DVD/DVD/DVD/DVD/DVD/ GET remote.file from C:folder BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ “-ASCII ftp -s encoding: folderftp.txt C:folderftp.txt catch ## If any code within the try block returns a hard-terminating error at any point, PowerShell will redirect the code to the catch block, which writes to the console ## and terminates the PowerShell console with a 1 exit code. exit 1 finally Write-Host “Error: $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
With the first try statement, you’re creating the FTP script file using the Out-File cmdlet. If the try statement fails, the errors will be caught by the catch statement following. The script will then be terminated using the $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
Notice that you’re creating the FTP script file via the Out-File cmdlet with the first try statement. If the try statement failed, the catch statement below would catch the errors. Then the $($_.Exception.Message) property followed by an exit 1 will end the script, displaying the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) property followed by an exit 1, showing the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message)” ## Remove the FTP script file regardless of whether the catch block caught an exception. Remove-Item -Path “C:folderftp.txt” Remove-Item -Path “C:folderftp.txt” ## Exit the PowerShell session with an exit code of 0 exit 0 when the code within the try/catch/finally blocks completes (error or not).
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) will be shown, detailing what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) property followed by an exit 1, showing the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create a try block and fill it with whatever code you like. try ## Using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/), create the FTP script file. If Out-File produces an FTP script, it then calls ftp.exe to run the script file. @Script = $Script “username and password for localhost BINARY CD/DVD/DVD/DVD/DVD/DVD/DVD/ GET remote.file from C:folder BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ “-ASCII ftp -s encoding: folderftp.txt C:folderftp.txt catch ## If any code within the try block returns a hard-terminating error at any point, PowerShell will redirect the code to the catch block, which writes to the console ## and terminates the PowerShell console with a 1 exit code. exit 1 finally Write-Host “Error: $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
With the first try statement, you’re creating the FTP script file using the Out-File cmdlet. If the try statement fails, the errors will be caught by the catch statement following. The script will then be terminated using the $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
Notice that you’re creating the FTP script file via the Out-File cmdlet with the first try statement. If the try statement failed, the catch statement below would catch the errors. Then the $($_.Exception.Message) property followed by an exit 1 will end the script, displaying the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, an error message (
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
With the first try statement, you’re creating the FTP script file using the Out-File cmdlet. If the try statement fails, the errors will be caught by the catch statement following. The script will then be terminated using the $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
Notice that you’re creating the FTP script file via the Out-File cmdlet with the first try statement. If the try statement failed, the catch statement below would catch the errors. Then the $($_.Exception.Message) property followed by an exit 1 will end the script, displaying the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create a try block and fill it with whatever code you like. try ## Using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/), create the FTP script file. If Out-File produces an FTP script, it then calls ftp.exe to run the script file. @Script = $Script “username and password for localhost BINARY CD/DVD/DVD/DVD/DVD/DVD/DVD/ GET remote.file from C:folder BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ “-ASCII ftp -s encoding: folderftp.txt C:folderftp.txt catch ## If any code within the try block returns a hard-terminating error at any point, PowerShell will redirect the code to the catch block, which writes to the console ## and terminates the PowerShell console with a 1 exit code. exit 1 finally Write-Host “Error: $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
With the first try statement, you’re creating the FTP script file using the Out-File cmdlet. If the try statement fails, the errors will be caught by the catch statement following. The script will then be terminated using the $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
Notice that you’re creating the FTP script file via the Out-File cmdlet with the first try statement. If the try statement failed, the catch statement below would catch the errors. Then the $($_.Exception.Message) property followed by an exit 1 will end the script, displaying the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) property followed by an exit 1, showing the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message)” ## Remove the FTP script file regardless of whether the catch block caught an exception. Remove-Item -Path “C:folderftp.txt” Remove-Item -Path “C:folderftp.txt” ## Exit the PowerShell session with an exit code of 0 exit 0 when the code within the try/catch/finally blocks completes (error or not).
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) property followed by an exit 1, showing the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create a try block and fill it with whatever code you like. try ## Using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/), create the FTP script file. If Out-File produces an FTP script, it then calls ftp.exe to run the script file. @Script = $Script “username and password for localhost BINARY CD/DVD/DVD/DVD/DVD/DVD/DVD/ GET remote.file from C:folder BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ “-ASCII ftp -s encoding: folderftp.txt C:folderftp.txt catch ## If any code within the try block returns a hard-terminating error at any point, PowerShell will redirect the code to the catch block, which writes to the console ## and terminates the PowerShell console with a 1 exit code. exit 1 finally Write-Host “Error: $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
With the first try statement, you’re creating the FTP script file using the Out-File cmdlet. If the try statement fails, the errors will be caught by the catch statement following. The script will then be terminated using the $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
Notice that you’re creating the FTP script file via the Out-File cmdlet with the first try statement. If the try statement failed, the catch statement below would catch the errors. Then the $($_.Exception.Message) property followed by an exit 1 will end the script, displaying the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) property followed by an exit 1, showing the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message)” ## Remove the FTP script file regardless of whether the catch block caught an exception. Remove-Item -Path “C:folderftp.txt” Remove-Item -Path “C:folderftp.txt” ## Exit the PowerShell session with an exit code of 0 exit 0 when the code within the try/catch/finally blocks completes (error or not).
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) will be shown, detailing what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) property followed by an exit 1, showing the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, an error message (
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
With the first try statement, you’re creating the FTP script file using the Out-File cmdlet. If the try statement fails, the errors will be caught by the catch statement following. The script will then be terminated using the $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
Notice that you’re creating the FTP script file via the Out-File cmdlet with the first try statement. If the try statement failed, the catch statement below would catch the errors. Then the $($_.Exception.Message) property followed by an exit 1 will end the script, displaying the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create a try block and fill it with whatever code you like. try ## Using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/), create the FTP script file. If Out-File produces an FTP script, it then calls ftp.exe to run the script file. @Script = $Script “username and password for localhost BINARY CD/DVD/DVD/DVD/DVD/DVD/DVD/ GET remote.file from C:folder BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ “-ASCII ftp -s encoding: folderftp.txt C:folderftp.txt catch ## If any code within the try block returns a hard-terminating error at any point, PowerShell will redirect the code to the catch block, which writes to the console ## and terminates the PowerShell console with a 1 exit code. exit 1 finally Write-Host “Error: $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
With the first try statement, you’re creating the FTP script file using the Out-File cmdlet. If the try statement fails, the errors will be caught by the catch statement following. The script will then be terminated using the $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
Notice that you’re creating the FTP script file via the Out-File cmdlet with the first try statement. If the try statement failed, the catch statement below would catch the errors. Then the $($_.Exception.Message) property followed by an exit 1 will end the script, displaying the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) property followed by an exit 1, showing the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message)” ## Remove the FTP script file regardless of whether the catch block caught an exception. Remove-Item -Path “C:folderftp.txt” Remove-Item -Path “C:folderftp.txt” ## Exit the PowerShell session with an exit code of 0 exit 0 when the code within the try/catch/finally blocks completes (error or not).
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) property followed by an exit 1, showing the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create a try block and fill it with whatever code you like. try ## Using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/), create the FTP script file. If Out-File produces an FTP script, it then calls ftp.exe to run the script file. @Script = $Script “username and password for localhost BINARY CD/DVD/DVD/DVD/DVD/DVD/DVD/ GET remote.file from C:folder BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ “-ASCII ftp -s encoding: folderftp.txt C:folderftp.txt catch ## If any code within the try block returns a hard-terminating error at any point, PowerShell will redirect the code to the catch block, which writes to the console ## and terminates the PowerShell console with a 1 exit code. exit 1 finally Write-Host “Error: $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
With the first try statement, you’re creating the FTP script file using the Out-File cmdlet. If the try statement fails, the errors will be caught by the catch statement following. The script will then be terminated using the $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
Notice that you’re creating the FTP script file via the Out-File cmdlet with the first try statement. If the try statement failed, the catch statement below would catch the errors. Then the $($_.Exception.Message) property followed by an exit 1 will end the script, displaying the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) property followed by an exit 1, showing the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message)” ## Remove the FTP script file regardless of whether the catch block caught an exception. Remove-Item -Path “C:folderftp.txt” Remove-Item -Path “C:folderftp.txt” ## Exit the PowerShell session with an exit code of 0 exit 0 when the code within the try/catch/finally blocks completes (error or not).
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) will be shown, detailing what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message)” ## Remove the FTP script file regardless of whether the catch block caught an exception. Remove-Item -Path “C:folderftp.txt” Remove-Item -Path “C:folderftp.txt” ## Exit the PowerShell session with an exit code of 0 exit 0 when the code within the try/catch/finally blocks completes (error or not).
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, an error message (
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
With the first try statement, you’re creating the FTP script file using the Out-File cmdlet. If the try statement fails, the errors will be caught by the catch statement following. The script will then be terminated using the $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
Notice that you’re creating the FTP script file via the Out-File cmdlet with the first try statement. If the try statement failed, the catch statement below would catch the errors. Then the $($_.Exception.Message) property followed by an exit 1 will end the script, displaying the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create a try block and fill it with whatever code you like. try ## Using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/), create the FTP script file. If Out-File produces an FTP script, it then calls ftp.exe to run the script file. @Script = $Script “username and password for localhost BINARY CD/DVD/DVD/DVD/DVD/DVD/DVD/ GET remote.file from C:folder BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ “-ASCII ftp -s encoding: folderftp.txt C:folderftp.txt catch ## If any code within the try block returns a hard-terminating error at any point, PowerShell will redirect the code to the catch block, which writes to the console ## and terminates the PowerShell console with a 1 exit code. exit 1 finally Write-Host “Error: $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
With the first try statement, you’re creating the FTP script file using the Out-File cmdlet. If the try statement fails, the errors will be caught by the catch statement following. The script will then be terminated using the $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
Notice that you’re creating the FTP script file via the Out-File cmdlet with the first try statement. If the try statement failed, the catch statement below would catch the errors. Then the $($_.Exception.Message) property followed by an exit 1 will end the script, displaying the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) property followed by an exit 1, showing the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message)” ## Remove the FTP script file regardless of whether the catch block caught an exception. Remove-Item -Path “C:folderftp.txt” Remove-Item -Path “C:folderftp.txt” ## Exit the PowerShell session with an exit code of 0 exit 0 when the code within the try/catch/finally blocks completes (error or not).
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) property followed by an exit 1, showing the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create a try block and fill it with whatever code you like. try ## Using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/), create the FTP script file. If Out-File produces an FTP script, it then calls ftp.exe to run the script file. @Script = $Script “username and password for localhost BINARY CD/DVD/DVD/DVD/DVD/DVD/DVD/ GET remote.file from C:folder BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ $Script | Out-File “C:Folderftp.txt” BYE “@ “-ASCII ftp -s encoding: folderftp.txt C:folderftp.txt catch ## If any code within the try block returns a hard-terminating error at any point, PowerShell will redirect the code to the catch block, which writes to the console ## and terminates the PowerShell console with a 1 exit code. exit 1 finally Write-Host “Error: $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
With the first try statement, you’re creating the FTP script file using the Out-File cmdlet. If the try statement fails, the errors will be caught by the catch statement following. The script will then be terminated using the $(
PowerShell is a powerful scripting language that can automate almost any task, and it’s not only for system administrators. But what if you don’t realize you don’t know what you don’t know? In such case, this collection of PowerShell script examples will assist you in getting started with PowerShell scripting.
Prerequisites
This will be a hands-on presentation in this course. If you want to follow along, make sure you have the following items on hand:
- This lesson works with any version of Windows 10, however we’ll be using Windows 10 Enterprise, build 19043.
- Version 5.1 or higher of Windows PowerShell will work, however this guide utilizes PowerShell 7.1, and you should always use the most recent version of PowerShell available.
- An editor with the PowerShell extension, such as PowerShell ISE or Visual Studio Code.
Creating and Changing Registry Values and Keys
Each program and operating system on your Windows computer is registered in the Windows Registry, which is a central area. Values and keys make up the Windows Registry, with keys serving as containers for the values.
Many built-in commands in PowerShell can help you create, update, and edit registry keys and values.
How to Completely Edit the Windows Registry Offline
Because the Windows Registry is a vital part of the operating system, make sure you back it up before making any changes.
Three distinct PowerShell commands are shown below to alter the registry. Let’s have a look at how each of these PowerShell cmdlets works in practice.
- Creates new registry keys using New-Item.
- Creates new registry values using New-ItemProperty.
- Changes registry key values using Set-ItemProperty.
The following example script creates a list of registry keys and checks to see whether each one exists. If that’s the case, the registry values within are updated. If this is not the case, it generates the keys and then adds new registry values inside them.
The script below disables registry settings linked to Transport Layer Security as a result of its output (TLS 1.0).
## An array of three registry key paths is defined. $tls10 = ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’, ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’, ## Verifies that all of the registry keys in the array are present. $tls10check = ($tls10 | Test-Path) $tls10check = ($tls10 | Test-Path) $tls10check = $false -notcontains If ($tls10check -eq $True) all of the registry keys exist, ## Sets the value of four DWORD registry keys to either 0 or 1. Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1 Set-ItemProperty -Path’Set-ItemProperty -Path ‘ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘ Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ else Set-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL ## If at least one of the registry keys is missing, ## skips the confirmation and creates the missing registry keys (Force) HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server -Force New-Item HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client -Force New-Item ## Sets the value of four separate DWORD registry variables to either 0 or 1. HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘Enabled’ HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘DisabledByDefault’ -value ‘1’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server’ -name ‘ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client’ -name ‘Enabled’ -value ‘0’ -Type ‘DWORD’ New-ItemProperty -Path ‘HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTL
How to Start a Windows Service (If Not Running)
Let’s move on to controlling Windows services when you’ve finished modifying the registry.
How to Use PowerShell to Manage Windows Services
You can see an excellent example of conducting comparison logic followed by an action in the PowerShell script below. When this script is launched, it will get the EventLog service’s status. If the Status is not Running, it will start the service and output some messages to the console.
If the service has already begun, it will inform you and take no further action.
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
## Create a variable to hold the service name. $ServiceName = ‘EventLog’ ## Get a service object from Windows by reading the service. If the server is not running (ne), if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.Status -ne ‘Running’) if ($ServiceInfo.S ## Write to the console that the service isn’t running Write-Host ‘Service isn’t started, starting service’ ## Update the $ServiceInfo object to reflect the new status using Start-Service -Name $ServiceName. $ServiceInfo.Refresh() Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host $ServiceInfo.Status else Write-Host ## If the Status isn’t Running, write ‘The service is already running’ to the terminal Write-Host ‘The service is already running.’
The service was launched successfully.
Where Can I Find CIM/WMI Classes?
CIM is a useful information store in Windows, and PowerShell may query it by default. You can get a lot of useful information out of CIM by using a mix of CIM cmdlets.
Run Get-Command -Name *Cim* to locate all CIM-related PowerShell cmdlets.
How to Work with WMI in PowerShell is a related article.
CIM data is divided into classes. Windows information is organized into CIM classes. Perhaps you were seeking for hardware information and noticed that the CIM class had a System variant in its name. You may use the Get-CimClass cmdlet to identify all classes that meet a certain pattern.
On a PowerShell command prompt, supply the ClassName argument with the precise class name or search pattern to get one or more CIM classes using the Get-CimClass cmdlet. You may use a wildcard (*) if you don’t know the whole class name. The command to locate all CIM classes matching the pattern Win32 *System is shown below.
Get-CimClass -ClassName Win32 *System; Get-CimClass -ClassName Win32 *System; Get-CimClass
Classes in CIM, sorted by name.
Computer Information Querying WMI
Once you’ve located the CIM class you want to query, PowerShell now offers a new cmdlet called Get-CimInstance that you can use to get information from it.
Another wonderful PowerShell example script can be found below, this time showcasing a real-world situation of accessing CIM. This example creates a CSV file with a few chosen attributes obtained by querying the Win32 OperatingSystem CIM class on two distant PCs at the same time.
After you’ve found your desired -ClassName, you may want to narrow down the results by using commas to separate the property names.
## On both the serv1 and serv2 machines, query the Win32 OperatingSystem CIM instance. Limit the output to to a few chosen properties using Get-CimInstance -ClassName Win32 OperatingSystem -ComputerName Serv1,Serv2 |’ BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion |’Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion | ‘ Export-CSV C:FoldersComputers.csv -NoTypeInformation -Encoding UTF8 -Verbose each CIM instance object to a CSV file named C:FoldersComputers.csv
When the script is finished, check in the C:Folder directory for a CSV file named Computers.csv that looks like this:
19042,Multiprocessor Free,18,0,0 BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion Multiprocessor Free,18,0,0,0,0,0,0,0,0,0,0,0,0,
Putting Applications Together
Now that you know how to obtain computer data, you can utilize it to determine whether or not those machines are compatible with certain programs.
Manually installing software on a single computer is possible, but when you have a large number of systems to install software on, the work quickly becomes unmanageable. To assist, you may write a PowerShell script that will discreetly install software (if your program supports it).
Maybe you’re working on a Microsoft Installer (MSI) package and want the program to install quietly. The msiexec.exe program is used to install MSI packages. Although this isn’t a PowerShell command, you can use PowerShell to access it.
Perhaps you have a package.msi MSI in your C:folder directory. To install software quietly, you must first understand which options the installer demands. Run the MSI using the /? switch to see what switches are available. Each accessible parameter should be shown using the /? command, as illustrated below.
A pop-up window appears below, displaying a list of argument options for installing the MSI package.
Arguments for Windows Installer
It’s time to use the msiexec.exe program now that you know the options the installation package requires. You must run msiexec.exe as an external process since it is not a PowerShell command. The Start-Process cmdlet is one of the simplest methods to start processes in PowerShell.
A Better PowerShell Start-Process is Related
In this example, you’ll need to utilize two options from the Start-Process: Name and Wait. In the example below, Start-Process uses the Name argument to invoke the msiexec.exe tool and then waits (Wait) for the process to complete before returning control to the console.
Because msiexec.exe requires a few arguments to install software quietly, the example used the ArgumentList to give each parameter required by msiexec.exe.
## Run msiexec.exe with the /i parameter to signal installation, ## the path to the MSI, /q to install quietly, and the location of the log file (/le) to report error messages. Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q /le “C:Folderpackage.log”‘ Start-Process -Name’msiexec.exe’ -Wait -ArgumentList ‘/i “C:Folderpackage.msi” /q
Using a Try, Catch, and Finally Statement to Handle Errors
To wrap off this PowerShell script example article, let’s talk about error handling, which you can (and should) apply to every PowerShell script. Error handling “catch” unforeseen errors in your script, making it more robust and capable of running without delays.
Error handling is a broad subject that might fill an entire book, but for now, let’s focus on the fundamentals: the try, catch, and finally statements. Try/catch blocks are a kind of code that PowerShell “monitors” for mistakes or exceptions that are hard to handle.
If code within a try/catch block throws a hard-terminating exception, it will be “caught” by a block and particular code will be performed against it. PowerShell will execute the finally block after the script has completed, either by throwing an exception or successfully finishing.
The script in the example below produces a File Transfer Protocol (FTP) script file that connects to an FTP server, tries to upload a file to an FTP server, and then deletes the FTP script file after the upload is complete.
You’ll see in the example the “functional” code has been wrapped in a try, catch and finally block. For example, if the Out-File cmdlet returns a hard-terminating error, PowerShell will catch that error and return Error: <the error/exception message> and then exit with a code of 1.
Following the successful creation of the FTP script file, the script tries to launch the ftp.exe tool, which executes the instructions contained inside the FTP script file. If _that_ happens,
Notice that you’re creating the FTP script file via the Out-File cmdlet with the first try statement. If the try statement failed, the catch statement below would catch the errors. Then the $($_.Exception.Message) property followed by an exit 1 will end the script, displaying the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) property followed by an exit 1, showing the error status.
If the first try statement succeeds, the created FTP script will be executed by the next try statement. You will notice log output with the successful connection to the FTP server and file download when the FTP script runs successfully.
The finally line will then execute, regardless of the outcomes of the try and catch statements, and delete the FTP script file.
## Create the try block and create any code inside. try { ## Create the FTP script file using a here string (https://devblogs.microsoft.com/scripting/powertip-use-here-strings-with-powershell/) ## If Out-File creates the FTP script, it then invokes ftp.exe to execute ## the script file. $Script = @” open localhost username password BINARY CD remotefolder LCD C:folder GET remote.file BYE “@ $Script | Out-File “C:Folderftp.txt” -Encoding ASCII ftp -s:C:folderftp.txt } catch { ## If, at any time, for any code inside of the try block, returns a hard-terminating error ## PowerShell will divert the code to the catch block which writes to the console ## and exits the PowerShell console with a 1 exit code. Write-Host “Error: $($_.Exception.Message)” exit 1 } finally { ## Regardless if the catch block caught an exception, remove the FTP script file Remove-Item -Path “C:folderftp.txt” } ## When the code inside of the try/catch/finally blocks completes (error or not), ## exit the PowerShell session with an exit code of 0 exit 0
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message)” ## Remove the FTP script file regardless of whether the catch block caught an exception. Remove-Item -Path “C:folderftp.txt” Remove-Item -Path “C:folderftp.txt” ## Exit the PowerShell session with an exit code of 0 exit 0 when the code within the try/catch/finally blocks completes (error or not).
The FTP script was successfully ran, as seen below.
Output from an FTP script.
If an exception is caught anywhere inside the try block, you’ll see an error message ($_.Exception.Message) indicating what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
.Exception.Message) will be shown, detailing what went wrong.
Running FTP Script File Error
Conclusion
You should now have a better idea of what PowerShell can do thanks to these PowerShell script samples. This course just scratches the surface of what PowerShell can achieve, so use it as a starting point for your research.
What do you believe these script examples can do to help you enhance your workflow? Whatever your response is, don’t wait to begin honing your scripting talents!
PowerShell is a command-line tool that allows users to create scripts. It’s an incredibly powerful scripting language and can be used for everything from automating tasks, to creating complex workflows. These 5 PowerShell Script Examples will inspire you to get started with PowerShell today. Reference: awesome powershell scripts.
Frequently Asked Questions
How do you write a simple PowerShell script?
A: A PowerShell script consists of a set of commands, usually written in text files with the .ps1 extension. Each command starts on its own line and must be followed by an equal sign ( = ) and then further instructions that make up the command.
How do I write a good PowerShell script?
A: A good PowerShell script will have a clear purpose, be straightforward and easy to follow, make use of available resources in the correct way.
What scripting language does PowerShell use?
A: PowerShell uses a scripting language called Microsoft Scripting Host.
Related Tags
- sample powershell scripts for automation
- powershell script example github
- cool powershell examples
- useful powershell scripts for windows 10
- simple powershell script to print hello world