Summary: Learn how to handle naming conflicts for Windows PowerShell cmdlets.
Hey, Scripting Guy! My Windows PowerShell installation is completely hosted on my laptop. In fact, I tried to uninstall and reinstall Windows PowerShell, but that did not work. I really do not want to have to pave my laptop. I download this module from the Internet. It works really well, but the issue is that one of the cmdlets replaced one of the standard cmdlets on my computer. I really need to be able to use the standard cmdlet, and I do not know what to do. Help!
—DV
Hello DV,
Microsoft Scripting Guy, Ed Wilson, is here. This morning I am sitting at my desk sipping a cup of English Breakfast tea with a bit of licorice root, peppermint herb, spearmint herb, and a cinnamon stick. It is quite refreshing, and delightful—especially because my arms feel like they are made from rubber. I just got back from the gym. (It is difficult to replace years of bad habits with a few weekly sessions at the gym, but it is also import to get started—and that is what I am doing.)
PowerShell cmdlet naming conflicts
Windows PowerShell is powerful and easy-to-use. It makes a lot of decisions for me. For example, if I import a module that has a cmdlet with the same name as an existing cmdlet, Windows PowerShell will use the new cmdlet. For example, let's say that I import a module named Process. It has a function named Get-Process. When I type Get-Process, I get the results from that function. This is shown here:
From this display, I see that I am not getting the normal output from the Get-Process cmdlet that I have used since Windows PowerShell 1.0 came out. This is disappointing. So I use the Get-Command cmdlet to see what is going on. Here are the results:
PS C:\> Get-Command -Module Process
CommandType Name ModuleName
----------- ---- ----------
Function Get-Process Process
It seems that Get-Process has been replaced by a function with the same name. It is from a module named Process.
I can unload that module by using the Remove-Module cmdlet as shown here:
Remove-Module Process
Note Using Remove-Module only unloads the module from memory. It does not actually delete the module, nor does
it remove it from disk.
Now if I use the Get-Process cmdlet, I see the standard output. This is shown here:
But what if I want the commands that are available from the Processmodule? How can I have access to those commands, and also access the standard Get-Process cmdlet? There are actually two ways to coexist...
Two ways to coexist
The first way to coexist (but by no means the easiest) is to reference the cmdlet by its complete name. This is the name of the module, separated by a backslash, and then the cmdlet name. To determine the cmdlet’s module, use the Get-Command cmdlet. Here is an example:
PS C:\> Get-Command Get-Process | ft -AutoSize
CommandType Name ModuleName
----------- ---- ----------
Cmdlet Get-Process Microsoft.PowerShell.Management
I see that the Get-Process cmdlet is in the Microsoft.PowerShell.Management module, so this is what I will need to type.
I import the Processmodule, check to ensure that the Get-Process cmdlet is overwritten, and then specify the complete name. It works:
PS C:\> Import-Module Process
PS C:\> Get-Process | select -Last 1
splwow64.exe
PS C:\> Microsoft.PowerShell.Management\Get-Process | select -Last 1
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
1630 142 112116 154792 530 10.41 7044 WWAHost
Note Tab expansion does not work for module names when you are specifying the complete name. So it is helpful to
copy the module name to the Clipboard when looking it up via Get-Command.
The second way to coexist is to specify a command prefix when you import the module. This will add a couple of letters to the noun name; therefore, it avoids the naming conflict. Here is an example:
First I import the module, and specify the prefix. Then I use Get-Command to see the cmdlet name, and I use the new cmdlet name (Get-edProcess) to retrieve a single process name. This is shown here:
PS C:\> Import-Module Process -Prefix ed
PS C:\> Get-Command -Module process
CommandType Name ModuleName
----------- ---- ----------
Function Get-edProcess Process
PS C:\> Get-edProcess | select -Last 1
splwow64.exe
Now I can use the standard cmdlet with the standard cmdlet name. Here, I retrieve a single process object:
PS C:\> Get-Process | select -Last 1
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
1630 142 112116 154304 530 10.41 7044 WWAHost
DV, that is all there is to handling Windows PowerShell naming conflicts. Join me tomorrow when I will talk about the Windows PowerShell Summit in Amsterdam.
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