July 31st, 2013

PowerShell Get-Command Cmdlet Returns Only One Instance

Doctor Scripto
Scripter

Summary: Microsoft Scripting Guy, Ed Wilson, shows how to configure Windows PowerShell to return more than one instance of a command.

Hey, Scripting Guy! Question Hey, Scripting Guy! I have a problem. I recently upgraded to Windows 8, and now it seems that the Get-Command cmdlet does not work properly. In the past, I have used Get-Command as a replacement for Where.exe in that it is great at finding commands I need. But now in Windows 8, the Get-Command cmdlet only returns a single instance. What gives?

—MC

Hey, Scripting Guy! Answer Hello MC,

Microsoft Scripting Guy, Ed Wilson, is here. Tomorrow we have the Windows PowerShell User Group meeting at the Charlotte, North Carolina Microsoft office. If you are in town, and do not have anything going on around 6:30 P.M., stop by. It will be loads of fun, and I can promise you will learn at least one new thing.

Using Get-Command to find commands

MC, I know it may sound strange, but I also use Get-Command to find commands. It is great at doing that. It finds Windows commands that are in my path, and it is much faster than opening Windows Explorer, and telling it to search.

For example, if I want to know if a command is available, I use Get-Command to find it for me. This is how I learned that there were two notepad.exe programs available. But when I run Get-Command in Windows 8, I am greeted with the following:

Image of command output

Hmm…Did we get rid of one of the Notepads in Windows 8? I don’t know, do I? It also makes me suspect that perhaps something is going on with Get-Command.

Force additional discovery in Get-Command

In Windows PowerShell 3.0, we made a change to Get-Command. When it finds a command, it returns. This is done for performance reasons, and results in faster searches. But if I am particularly interested in additional instances, I can force Get-Command to keep working. To do this, I specify a value for the TotalCount parameter. The value for TotalCount is the maximum value. So if I tell it to look for 10 instances of Notepad, it will keep trying. Of course, I only have two copies, so I am safe. Here is the command I use:

Get-Command notepad -TotalCount 10

The command and its associated output are shown here:

Image of command output

But where are these programs located?

To find where the programs reside, I need a bit more information. To find the additional information, I pipe the results to the Format-List cmdlet and choose all of the properties as shown here:

Get-Command notepad | Format-List *

The following image shows the command and the output associated with the command.

Image of command output

The path to the executable is in the Path property (no surprise, right?). Therefore, all I need to do is to select the path. I do this in the following command, and I can find where both Notepads reside.

PS C:\> Get-Command notepad -TotalCount 5 | Select-Object name, path

 

Name                                       Path

—-                                       —-

notepad.exe                                C:\Windows\SYSTEM32\notepad.exe

notepad.exe                                C:\Windows\notepad.exe

Using the Path property

Now that I know about the Path property and the way Get-Command returns the first application it finds in the search path, I might be interested in the way the commands returns. To do this, I look at the Path variable from the $env drive. I can see that first Windows\System32 is searched, and then the Windows directory. This is shown here:

PS C:\> ($env:Path -split ‘;’)[0..1]

C:\Windows\SYSTEM32

C:\Windows

Armed with this information I can see that the Notepad from Windows\System32 returns first (I actually saw this earlier). Therefore, the application highest in the search path returns when I do not specify TotalCount.

So, now I can use the Path property from Get-Command, and I know what it will do. So if I want to look at the byte encoding of Notepad, I can use the Get-Command cmdlet to return the path to the application. I can supply that to the Get-Content cmdlet Path parameter, and I can specify Encoding Byte. I store this in the $bytes variable, and print out the first four bytes. This is shown here:

PS C:\> $bytes = Get-Content -Path (Get-Command notepad).path -Encoding Byte

PS C:\> $bytes[0..3]

77

90

144

0

MC, that is all there is to using the Get-Command cmdlet to find commands. Join me tomorrow when I will talk about more cool Windows PowerShell stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

Author

The "Scripting Guys" is a historical title passed from scripter to scripter. The current revision has morphed into our good friend Doctor Scripto who has been with us since the very beginning.

0 comments

Discussion are closed.