Learn about Windows PowerShell
Summary: Microsoft Scripting Guy Ed Wilson shows how to use .NET Framework commands inside Windows PowerShell
Hey, Scripting Guy! I understand that Windows PowerShell is built upon the .NET Framework. I also get the idea that some of the Windows PowerShell cmdlets are simply calling things from the .NET Framework in the background. But what good is that to me? Why do I care?
Hello HB, Microsoft Scripting Guy Ed Wilson here.
Yesterday we looked at the fundamental concepts of the .NET Framework, and explored the System.Diagnostics.Process .NET Framework class.
By using the static GetProcesses method, a listing of all the processes and their top properties is obtained. When you call a .NET Framework class, the System part of the namespace can be left off as it is assumed. Therefore, with the System.Diagnostics.Process class, System.Diagnostics is the namespace, and Process is the actual class name. When I leave the System portion off the namespace name the command morphs to the one shown here.
The output from this command is seen in the figure below.
The output shown in this figure is very extensive and provides a useful overview of the way the system is performing. It is so useful the Windows PowerShell team has incorporated it into the Get-Process cmdlet. To use the Get-Process cmdlet you just have to type the command on Windows PowerShell console command line as seen here.
The output from the Get-Process command is shown in the following figure.
The output from the Get-Process cmdlet and the [diagnostics.process]::GetProcesses() are equivalent. The difference is that Get-Process alphabetizes the output by process name and [diagnostics.process]::GetProcesses() does not.
The point of this exercise is to show that Windows PowerShell is a .NET Framework application. You do not have to type [diagnostics.process]::GetProcesses() because that is the essence of Get-Process. In fact, if I pipeline Get-Process to the Get-Member cmdlet, I can see that the System.Diagnostics.Process class is returned by the command. The command to do this is shown here.
Get-Process | Get-Member
As we saw yesterday, there are an awful lot of methods and properties exposed by System.Diagnostics.Process. The output is shown in the figure below.
Using the .NET Framework Process class, from the System.Diagnostics namespace, I can use the static method GetProcessByName. If I am not certain how to use the method, I can pipeline the class to Get-Member, specify I want to see the static method getProcessbyname and output the returned information to the format-list cmdlet. When I do this, the output seen here appears.
PS C:\> [diagnostics.process] | gm -s getProcessesbyname | fl *TypeName : System.Diagnostics.ProcessName : GetProcessesByNameMemberType : MethodDefinition : static System.Diagnostics.Process GetProcessesByName(string processName), static Sys tem.Diagnostics.Process GetProcessesByName(string processName, string machineName)PS C:\>
The output seen earlier tells me that I have to provide either a process name or a process name and a computer name to the method. By using that information, I can return information about the explorer process. This is seen here.
PS C:\> [diagnostics.process]::GetProcessesByName("explorer")Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName------- ------ ----- ----- ----- ------ -- ----------- 1084 80 99332 120468 447 13.90 3620 explorerPS C:\>
We see the same subset of information that was returned by the Get-Process Windows PowerShell cmdlet. We know now, that additional information would be available ... the information such as seen in the previous figure.
Remember back when we were looking at the member information for the GetProcessesByName method? There was an alternative way of calling the method that would accept both a process name and a computer name as parameters. If I wanted to use the process .NET Framework class to retrieve process information from a remote computer back in the Windows PowerShell days, this was the way to do it. (Of course, there was also the Win32_Process WMI class that was available also). To use the process class and specify a computer name, use the syntax seen here (The output is shown under the command).
PS C:\> [diagnostics.process]::GetProcessesByName("explorer", "localhost")Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName------- ------ ----- ----- ----- ------ -- ----------- 1488 96 141128 153208 589 3620 explorer
In Windows PowerShell 2.0 the Get-Process cmdlet was upgraded to accept a computername parameter. This command and associated output is shown here.
PS C:\> Get-Process -Name explorer -ComputerName localhostHandles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName------- ------ ----- ----- ----- ------ -- ----------- 1478 95 140644 152968 587 3620 explorerPS C:\>
By comparing the output from the two previous commands, you can see that the output is virtually the same. This shows that the .NET Framework class GetProcessByName method is behind the name parameter that is used by the Get-Process cmdlet.
Not all the methods and properties exposed through the System.Diagnostics.Process .NET Framework class are exposed through a switch or a parameter of the Get-Process Windows PowerShell cmdlet. This is where knowing a bit about the underlying .NET Framework classes comes into play. For example, if I want to change the processor affinity of a particular process that is running on a computer, all I have to do is to use Get-Process to retrieve the process, and then assign a new value to the ProcessorAffinity property. This is illustrated here where I first launch a new instance of notepad. I then use Get-Process to retrieve the notepad process to make sure it is working correctly. After confirming that it works, I again use the Get-Process Windows PowerShell cmdlet to retrieve the notepad process, and I store it in the $a variable. I then query the ProcessorAffinity property and see that the notepad process has a processor affinity of 3.
PS C:\> notepadPS C:\> Get-Process notepadHandles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName------- ------ ----- ----- ----- ------ -- ----------- 67 7 1524 5416 71 0.03 6236 notepadPS C:\> $a = Get-Process notepadPS C:\> $a.ProcessorAffinity3PS C:\> $a.ProcessorAffinity = 0x0002PS C:\> $a.ProcessorAffinity2
HB, that is all there is to using the .NET Framework Process class. Exploring .NET Framework week will continue tomorrow when we will talk about how to work with the .NET Framework classes.
I invite you to follow me on Twitter or Facebook. If you have any questions, send email to me at firstname.lastname@example.org or post them on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy
.Net Framework Tutorial