Windows Server 2019 – Working within PowerShell

Install PHP on CentOS 8

The first step to doing real work with PowerShell is getting comfortable interfacing with the platform, and becoming familiar with the daily routines of working from this command line, rather than relying on your mouse pointer. Here, we will explore some of the most common ways that I have seen server administrators make use of PowerShell in order to enhance their daily workload.

Launching PowerShell

Pretty simple—the first thing we need to do is get PowerShell opened up to start using it. The PowerShell console is installed by default in all recent versions of Windows, so you can run it from the Start menu, pin it to the Desktop, or access it in any way that you normally open any application.

Since I tend to prefer using my keyboard for everything, the way that I normally open PowerShell is to hold down the WinKey and press R in order to open a Run prompt, type the word powershell, and press Enter:

As you can see, since I am logged into an administrative account on my server, my PowerShell prompt has been opened with elevated permissions. This is visible in the fact that the word Administrator is listed in the top toolbar of the PowerShell window. It is important to note that, just like Command Prompt, you can open a PowerShell prompt with either regular user permissions, or elevated Administrator privileges. It is generally safer to work from within a regular PowerShell session that does not have elevated rights, unless the task that you are trying to accomplish requires those extra permissions.

Another quick and easy way to open PowerShell on any newer Windows platform is by right-clicking on the Start button and selecting it right from the quick-tasks list that is presented. As you can see in the following screenshot, I have right-clicked on the Start button of one of my new Server 2019 boxes and can choose from here to open PowerShell, or even an elevated (administrative) PowerShell prompt:

If you right-click on your Start button and do not find options for PowerShell, but rather for opening Command Prompt, do not be dismayed. This is a configurable option; you are able to show either Command Prompt or PowerShell options in the quick admin tasks menu. If you right-click on your Taskbar and select Taskbar settings, you will find an option that is called Replace Command Prompt with Windows PowerShell in the menu when I right-click the start button or press Windows key+X. Toggling this option will swing your quick admin menu back and forth between the two command-line interfaces.

You also have the option of entering into a PowerShell prompt from inside an existing Command Prompt window. Normally, when you are working from Command Prompt, you cannot make use of any PowerShell cmdlets. Let’s go ahead and give this a shot. Open an administrative Command Prompt window, and try to type in the name of one of the cmdlets we mentioned earlier. Perhaps type Get-NetIPAddress to show us what IP addresses reside on this system. Whoops—that failed because Command Prompt doesn’t recognize the Get-NetIPAddress cmdlet.

Now type powershell and press Enter. Instead of opening a separate PowerShell window, your prompt changes but the application window itself remains the same. You have now entered the PowerShell shell from inside the black Command Prompt window, and you can start utilizing cmdlets as you wish. Running Get-NetIPAddress again now produces some information:

You can move from PowerShell mode back to regular Command Prompt mode by typing exit.

Default Execution Policy

When you are working with the PowerShell command-line interface directly, you can simply open up PowerShell, start typing cmdlets, and start getting work done. However, one of the big advantages of using PowerShell comes when you start playing around with creating, saving, and running scripts. If you open up PowerShell, create a script, and then try to run it, you will sometimes find that it fails with a big messy error message, such as this one:

This shouldn’t happen on a fresh instance of Windows Server 2019, but could if you have any GPOs being applied to your new server or if you are using a different operating system and are trying to run some PowerShell scripts; you might find yourself stuck at one of these error messages right out of the gate. While the nature of some versions of Windows to block the running of scripts by default is a security enhancement, it can be a nuisance to work around when you are trying to get something done. Thankfully, if you do encounter this problem, the resolution is easy: you simply need to adjust the Default Execution Policy (DEP) inside PowerShell, so that it allows the execution of scripts to happen properly.

This is not a simple ON/OFF switch. There are five different levels within the DEP, and it is important to understand each one so that you can set your DEP accordingly, based on the security that you want in place on your servers. Here are descriptions of each level, in order of most to least secure.

Restricted

The Restricted policy allows commands and cmdlets to be run, but stops the running of scripts altogether.

AllSigned

This requires that any script being run needs to be signed by a trusted publisher. When set to AllSigned, even scripts that you write yourself will have to be put through that validation process and signed before they will be allowed to run.

RemoteSigned

RemoteSigned is the default policy in Windows Server 2019. For scripts that have been downloaded from the internet, it requires that these scripts are signed with a digital signature from a publisher that you trust. However, if you choose to create your own scripts, it will allow these local scripts to run without requiring that digital signature.

Unrestricted

Scripts are allowed to run, signed or unsigned. You do still receive a warning prompt when running scripts that have been downloaded from the internet.

The Bypass mode

In Bypass mode, nothing is blocked and no warnings are given when you run scripts. In other words, you’re on your own.

Sometimes a single execution policy doesn’t meet all of your needs, depending on how you utilize PowerShell scripts. DEPs can be further enhanced by setting an Execution Policy Scope that allows you to set different execution policies to different aspects of the system. For example, the three scopes that you can manipulate are Process, CurrentUser, and LocalMachine. By default, the DEP affects LocalMachine so that any scripts running adhere to the DEP. But if you need to modify this behavior so that different DEPs are set for the CurrentUser or even an individual Process, you have the ability to do that.

If you are unsure about the current status of your DEP or suspect that someone may have changed it, you can easily view the currently assigned execution policy with a simple cmdlet called Get-ExecutionPolicy. As you can see in the following image, mine is set to Restricted, which explains my earlier error message when I tried running a script:

Once you have decided on the level of DEP that you want on your server or workstation, you can set it accordingly with a quick cmdlet. For example, since this is a test lab and I want scripts to be able to run, and I am not really concerned about security since I am isolated, I am going to change mine to Unrestricted. Here is my command for doing just that:

Set-ExecutionPolicy Unrestricted  

Remember, right now we are running PowerShell on this local system (I happen to be logged into my WEB3 server), so the only execution policy I am setting is the local one for my WEB3 system. If I wanted to change this setting globally, or for a group of machines at the same time, I could utilize Group Policy for that change. The location inside Group Policy for configuring PowerShell script execution policy is  Computer Configuration | Policies | Administrative Templates | Windows Components | Windows PowerShell | Turn on script execution.

Using the Tab key

Before we get started navigating inside PowerShell, there is one important thing I want to point out: get used to pressing the Tab key when you are inside the PowerShell prompt! If you type the first few letters of any command or cmdlet, and then press Tab, the remainder of the cmdlet name will be automatically populated on the screen.

If we type get-co and then press Tab, the prompt automatically populates the full Get-Command cmdlet. Since there are multiple cmdlets that started with get-co, if you press Tab numerous times you can see that it cycles through all of the available cmdlets that start with those letters.

Tab also works with file and folder names. For example, I downloaded a hotfix that needs to be installed onto a server. I want to launch this hotfix using the PowerShell prompt that I already have open, but I don’t want to spend an entire minute or more trying to type out the huge filename of this hotfix. I have already navigated to the folder where my hotfix resides, and now if I simply type the first few letters of the filename and press the Tab key, PowerShell will populate the remainder of the filename. From there, all we need to do is press Enter to launch that installer:

Useful cmdlets for daily tasks

When I started incorporating PowerShell into my daily workflow, I found it useful to keep a list of commonly-used commands and cmdlets handy. Until you get to the point where they become memorized and second nature, if you don’t have a quick and easy way to recall those commands, chances are you aren’t going to use them and will revert to the old method of configuring your servers. Here is a list of some of the items I use regularly when I’m building servers. Some are traditional commands that would also work from a Command Prompt, and some are cmdlets, but they are all useful when working inside a PowerShell window:

  • Get-Command: This is useful for finding additional commands or cmdlets that you may want to run or research.
  • Get-Command -Name *example* : Enhances the usefulness of Get-Command by adding the -Name switch to the end of it, so that you can filter results to whatever types of cmdlets you are searching for.
  • GC: This is simply a short alias for Get-Command. I only wanted to point this one out because some of the PowerShell cmdlets have aliases, such as gcm, that allow you to launch these commonly-used cmdlets with fewer keystrokes.
  • Get-Alias: Since we just mentioned the GCM alias for Get-Command, you may be wondering what other aliases are available inside PowerShell. To see a complete list, simply plug in the Get-Alias cmdlet.
  • Rename-Computer: This allows you to set a new hostname for the server.
  • Add-Computer: Use the Add-Computer cmdlet to join servers or computers to a domain.
  • Hostname: This displays the name of the system you are currently working on. I use hostname all the time to make sure that I really am working on the server that I think I am. Have you ever rebooted the wrong server? I have. By running a quick hostname command, you can get peace of mind that the function you are about to perform is really happening on the correct system.
  • $env:computername: This presents you with the hostname of the system you are working on, but I’m calling it out to show that PowerShell can easily tap into your environment variables in order to pull out information. The simpler hostname command is useful when you are logged into a local system and are simply trying to verify its name, but the ability to pull information from a variable, such as $env:computername, will be much more useful when creating scripts or trying to perform a function against a remote system.
  • Logoff: The name is self-explanatory, Logoff just logs you out of the system. Rather than trying to find the Sign out function by clicking around inside your server’s Start menu, you can throw a quick Logoff command into either a Command Prompt or a PowerShell window, and it will immediately log you off that session. I use this one all the time when closing out RDP connections.

Both shutdown or Restart-Computer are useful for shutting down or restarting a server. On my own computer, these commands are most commonly preceded by the hostname command. When rebooting a server, you want to take special care that you restart the correct machine, so I find it best to open a PowerShell prompt, do a quick hostname check, and then run a restart command from that same prompt. This ensures that I am restarting the server that was returned in the hostname output.

shutdown /r /t 0

If you run a simple shutdown command, the system will shut down in one minute. I’m not sure why this is the default, as I have never found any IT administrator who actually wanted to wait that extra minute before shutting down their system. Instead, it is more efficient to set a time limit before that shutdown commences. In the preceding command, I have told the shutdown command that I want to restart instead of shutting down, that is what /r does; I have also told it to wait zero seconds before performing this restart. This way, it happens immediately; I don’t have to wait for that default 60 seconds.

Query user or quser

Often most useful in RDS environments, the quser command will display all of the users that are currently logged into a server, including statistics about whether they are logged in locally or remotely, and how long their session has been active:

quser /computer:WEB1

Using quser in combination with the /computer switch allows you to see the currently-logged-in users on a remote system. This way, you can remain logged into a single server in your RDS farm, but check on the user sessions for all of your systems without having to log into them. You could even write a script that runs this command against each of your session host servers, and outputs the data to a file. This output could then be run on a schedule, and used as a reporting mechanism for keeping track of which users were logged into which RDS session host servers at any given time.

Install-WindowsFeature

Use PowerShell to simplify the installation of roles and features onto your servers.

New-NetIPAddress -InterfaceIndex 12 -IPAddress 10.10.10.40 -PrefixLength 24 -DefaultGateway 10.10.10.1

Use New-NetIPAddress to assign IP addresses to your NICs. Keep in mind that the information in the preceding cmdlet is clearly example data, and needs to be replaced with your own information.

Set-DnsClientServerAddress -InterfaceIndex 12 -ServerAddresses 10.10.10.2,10.10.10.3

Often used in combination with New-NetIPAddress, use this to set the DNS server addresses in your NIC properties.

Using Get-Help

How many hundreds of times have you used the /? switch in Command Prompt to pull some extra information about a command that you want to run? The extra information provided by this help function can sometimes mean the difference between a command being useful, or completely useless. PowerShell cmdlets have a similar function, but you cannot simply /? at the end of a PowerShell cmdlet because a space following a cmdlet in PowerShell indicates that you are about to specify a parameter to be used with that cmdlet. For example, if we try to use /? with the Restart-Computer cmdlet in order to find more information about how to use Restart-Computer, it will fail to recognize the question mark as a valid parameter, and our output is as follows:

Instead, there is an even more powerful help function inside PowerShell. Get-Help is a cmdlet itself, and like any cmdlet, we need to use information following the cmdlet in order to specify and pull the information that we are looking for. So instead of using Get-Help at the end of a command, like we used to do with the question mark, we use it as its own entity.

Running Get-Help by itself only gives us more information about the Get-Help command, which may be useful to look over, but right now we are more interested in finding out how we can use Get-Help to give us additional information for a cmdlet we want to run, such as the Restart-Computer function. What we need to do is use Get-Help as a cmdlet, and then specify the other cmdlet as a parameter to pass to Get-Help, by placing a space between them:

Get-Help Restart-Computer  

The information provided by Get-Help is very comprehensive; in some cases, it has all of the same information that you can find on TechNet. Make sure to start utilizing Get-Help to further your knowledge of any cmdlet in PowerShell!

Formatting the output

When searching for information in PowerShell, I often encounter the case where so much information is provided to me that it’s difficult to sort through. Are you trying to find useful cmdlets from Get-Command, or maybe track down a particular alias with Get-Alias? The output from these cmdlets can be staggeringly long. While we have discussed some parameters you can use to whittle down this output, such as specifying particular -Name parameters, there are a couple of formatting parameters that can also be appended to cmdlets, in order to modify the data output.

Format-Table

The purpose of Format-Table is pretty simple: it takes the data output from a command and puts it into a table format. This generally makes the information much easier to read and work with. Let’s look at an example. We have used Get-NetIPAddress a couple of times, but, let’s be honest, its output is a little messy. Running the cmdlet by itself on my virtual server, which only has a single NIC assigned to it, results in four pages of data inside my PowerShell window, with all kinds of informational fields that are either empty or not important to finding the IP addresses assigned to my server:

If we simply add Format-Table to the end of my Get-NetIPAddress cmdlet, the generated data is much easier on the eyes, while still giving me the important information that I am really looking for: the IP addresses being used on the system:

Get-NetIPAddress | Format-Table 

Some of you may be familiar with a cmdlet called Select-Object, which can perform the same functions as Format-Table. While Select-Object seems to be the more widely-known cmdlet, in my experience, it is actually less powerful than Format-Table, and so I suggest you spend some time playing around with the one we have discussed here.

Format-List

Similar to the way that Format-Table works, you can utilize Format-List to display command output as a list of properties. Let’s give it a quick try. We already know that Get-Command gives us the available cmdlets within PowerShell, and by default, it gives them to us in a table format.

If we wanted to view that output in a list instead, with more information being provided about each cmdlet, we could tell Get-Command to output its data in list format, with the following command:

Get-Command | Format-List

This results in a tremendously long output of information, so long in fact that my PowerShell window had a problem displaying it all. Maybe we need to whittle that info down a little bit by narrowing our focus. Let’s search for all of the cmdlets that include the word Restart while displaying them in list format:

Get-Command -Name *Restart* | Format-List

Comments are closed.