413 lines
13 KiB
C#
413 lines
13 KiB
C#
// <copyright file="GetProcessSample05.cs" company="Microsoft Corporation">
|
|
// Copyright (c) 2009 Microsoft Corporation. All rights reserved.
|
|
// </copyright>
|
|
// DISCLAIMER OF WARRANTY: The software is licensed “as-is.” You
|
|
// bear the risk of using it. Microsoft gives no express warranties,
|
|
// guarantees or conditions. You may have additional consumer rights
|
|
// under your local laws which this agreement cannot change. To the extent
|
|
// permitted under your local laws, Microsoft excludes the implied warranties
|
|
// of merchantability, fitness for a particular purpose and non-infringement.
|
|
|
|
namespace Microsoft.Samples.PowerShell.Commands
|
|
{
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Management.Automation; // Windows PowerShell namespace.
|
|
using System.Security.Permissions;
|
|
using Win32Exception = System.ComponentModel.Win32Exception;
|
|
#region GetProcCommand
|
|
|
|
/// <summary>
|
|
/// This class implements the get-proc cmdlet.
|
|
/// </summary>
|
|
[Cmdlet(VerbsCommon.Get, "Proc",
|
|
DefaultParameterSetName = "ProcessName")]
|
|
public class GetProcCommand : PSCmdlet
|
|
{
|
|
#region Fields
|
|
/// <summary>
|
|
/// The names of the processes to act on.
|
|
/// </summary>
|
|
private string[] processNames;
|
|
|
|
/// <summary>
|
|
/// The identifiers of the processes to act on.
|
|
/// </summary>
|
|
private int[] processIds;
|
|
|
|
/// <summary>
|
|
/// The process objects to act on.
|
|
/// </summary>
|
|
private Process[] inputObjects;
|
|
|
|
#endregion Fields
|
|
|
|
#region Parameters
|
|
|
|
/// <summary>
|
|
/// Gets or sets the list of process names on
|
|
/// which the Get-Proc cmdlet will work.
|
|
/// </summary>
|
|
[Parameter(
|
|
Position = 0,
|
|
ParameterSetName = "ProcessName",
|
|
ValueFromPipeline = true,
|
|
ValueFromPipelineByPropertyName = true)]
|
|
[ValidateNotNullOrEmpty]
|
|
public string[] Name
|
|
{
|
|
get { return this.processNames; }
|
|
set { this.processNames = value; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the list of process identifiers on
|
|
/// which the Get-Proc cmdlet will work.
|
|
/// </summary>
|
|
[Parameter(
|
|
ParameterSetName = "Id",
|
|
Mandatory = true,
|
|
ValueFromPipeline = true,
|
|
ValueFromPipelineByPropertyName = true,
|
|
HelpMessage = "The unique id of the process to get.")]
|
|
public int[] Id
|
|
{
|
|
get { return this.processIds; }
|
|
set { this.processIds = value; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets Process objects directly. If the input is a
|
|
/// stream of [collection of] Process objects, the cmdlet bypasses the
|
|
/// ProcessName and Id parameters and reads the Process objects
|
|
/// directly. This allows the cmdlet to deal with processes that have
|
|
/// wildcard characters in their name.
|
|
/// <value>Process objects</value>
|
|
/// </summary>
|
|
[Parameter(
|
|
ParameterSetName = "InputObject",
|
|
Mandatory = true,
|
|
ValueFromPipeline = true)]
|
|
public Process[] Input
|
|
{
|
|
get { return this.inputObjects; }
|
|
set { this.inputObjects = value; }
|
|
}
|
|
|
|
#endregion Parameters
|
|
|
|
#region Cmdlet Overrides
|
|
|
|
/// <summary>
|
|
/// The ProcessRecord method calls the Process.GetProcesses
|
|
/// method to retrieve the processes. Then, the WriteObject
|
|
/// method writes the associated processes to the pipeline.
|
|
/// </summary>
|
|
protected override void ProcessRecord()
|
|
{
|
|
List<Process> matchingProcesses;
|
|
|
|
WriteDebug("Obtaining the list of matching process objects.");
|
|
|
|
switch (ParameterSetName)
|
|
{
|
|
case "Id":
|
|
matchingProcesses = this.GetMatchingProcessesById();
|
|
break;
|
|
case "ProcessName":
|
|
matchingProcesses = this.GetMatchingProcessesByName();
|
|
break;
|
|
case "InputObject":
|
|
matchingProcesses = this.GetProcessesByInput();
|
|
break;
|
|
default:
|
|
ThrowTerminatingError(
|
|
new ErrorRecord(
|
|
new ArgumentException("Bad ParameterSetName"),
|
|
"UnableToAccessProcessList",
|
|
ErrorCategory.InvalidOperation,
|
|
null));
|
|
return;
|
|
} // switch (ParameterSetName)
|
|
|
|
WriteDebug("Outputting the matching process objects.");
|
|
|
|
matchingProcesses.Sort(ProcessComparison);
|
|
|
|
foreach (Process process in matchingProcesses)
|
|
{
|
|
WriteObject(process);
|
|
}
|
|
} // ProcessRecord
|
|
|
|
#endregion Overrides
|
|
|
|
#region protected Methods and Data
|
|
|
|
/// <summary>
|
|
/// Retrieves the list of all processes matching the ProcessName
|
|
/// parameter and generates a nonterminating error for each
|
|
/// specified process name which is not found even though the name
|
|
/// contains no wildcards.
|
|
/// </summary>
|
|
/// <returns>The matching processes.</returns>
|
|
[EnvironmentPermissionAttribute(
|
|
SecurityAction.LinkDemand,
|
|
Unrestricted = true)]
|
|
private List<Process> GetMatchingProcessesByName()
|
|
{
|
|
new EnvironmentPermission(
|
|
PermissionState.Unrestricted).Assert();
|
|
|
|
List<Process> allProcesses =
|
|
new List<Process>(Process.GetProcesses());
|
|
|
|
// The keys dictionary is used for rapid lookup of
|
|
// processes that are already in the matchingProcesses list.
|
|
Dictionary<int, byte> keys = new Dictionary<int, byte>();
|
|
|
|
List<Process> matchingProcesses = new List<Process>();
|
|
|
|
if (null == this.processNames)
|
|
{
|
|
matchingProcesses.AddRange(allProcesses);
|
|
}
|
|
else
|
|
{
|
|
foreach (string pattern in this.processNames)
|
|
{
|
|
WriteVerbose("Finding matches for process name \""
|
|
+ pattern + "\".");
|
|
|
|
// WildCard serach on the available processes
|
|
WildcardPattern wildcard =
|
|
new WildcardPattern(
|
|
pattern,
|
|
WildcardOptions.IgnoreCase);
|
|
|
|
bool found = false;
|
|
|
|
foreach (Process process in allProcesses)
|
|
{
|
|
if (!keys.ContainsKey(process.Id))
|
|
{
|
|
string processName = SafeGetProcessName(process);
|
|
|
|
// Remove the process from the allProcesses list
|
|
// so that it is not tested again.
|
|
if (processName.Length == 0)
|
|
{
|
|
allProcesses.Remove(process);
|
|
}
|
|
|
|
// Perform a wildcard search on this particular
|
|
// process name and check whether it matches the
|
|
// pattern specified.
|
|
if (!wildcard.IsMatch(processName))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
WriteDebug("Found matching process id "
|
|
+ process.Id + ".");
|
|
|
|
// A match is found.
|
|
found = true;
|
|
|
|
// Store the process identifier so that the same process
|
|
// is not added twice.
|
|
keys.Add(process.Id, 0);
|
|
|
|
// Add the process to the processes list.
|
|
matchingProcesses.Add(process);
|
|
}
|
|
} // foreach (Process...
|
|
|
|
if (!found &&
|
|
!WildcardPattern.ContainsWildcardCharacters(pattern))
|
|
{
|
|
WriteError(new ErrorRecord(
|
|
new ArgumentException("Cannot find process name "
|
|
+ "\"" + pattern + "\"."),
|
|
"ProcessNameNotFound",
|
|
ErrorCategory.ObjectNotFound,
|
|
pattern));
|
|
}
|
|
} // foreach (string...
|
|
} // if (null...
|
|
|
|
return matchingProcesses;
|
|
} // GetMatchingProcessesByName
|
|
|
|
/// <summary>
|
|
/// Returns the name of a process. If an error occurs, a blank
|
|
/// string is returned.
|
|
/// </summary>
|
|
/// <param name="process">The process whose name is
|
|
/// returned.</param>
|
|
/// <returns>The name of the process.</returns>
|
|
[EnvironmentPermissionAttribute(
|
|
SecurityAction.LinkDemand, Unrestricted = true)]
|
|
protected static string SafeGetProcessName(Process process)
|
|
{
|
|
new EnvironmentPermission(PermissionState.Unrestricted).Assert();
|
|
string name = String.Empty;
|
|
|
|
if (process != null)
|
|
{
|
|
try
|
|
{
|
|
return process.ProcessName;
|
|
}
|
|
catch (Win32Exception)
|
|
{
|
|
}
|
|
catch (InvalidOperationException)
|
|
{
|
|
}
|
|
}
|
|
|
|
return name;
|
|
} // SafeGetProcessName
|
|
|
|
#endregion Cmdlet Overrides
|
|
|
|
#region Private Methods
|
|
|
|
/// <summary>
|
|
/// Function to sort by process name first, and then by
|
|
/// the process identifier.
|
|
/// </summary>
|
|
/// <param name="x">First process object.</param>
|
|
/// <param name="y">Second process object.</param>
|
|
/// <returns>
|
|
/// Returns less than zero if x is less than y,
|
|
/// greater than 0 if x is greater than y, and 0 if x == y.
|
|
/// </returns>
|
|
private static int ProcessComparison(Process x, Process y)
|
|
{
|
|
int diff = String.Compare(
|
|
SafeGetProcessName(x),
|
|
SafeGetProcessName(y),
|
|
StringComparison.CurrentCultureIgnoreCase);
|
|
|
|
if (0 != diff)
|
|
{
|
|
return diff;
|
|
}
|
|
else
|
|
{
|
|
return x.Id.CompareTo(y.Id);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieves the list of all processes matching the Id
|
|
/// parameter and generates a nonterminating error for
|
|
/// each specified process identofier which is not found.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// An array of processes that match the given identifier.
|
|
/// </returns>
|
|
[EnvironmentPermissionAttribute(
|
|
SecurityAction.LinkDemand,
|
|
Unrestricted = true)]
|
|
private List<Process> GetMatchingProcessesById()
|
|
{
|
|
new EnvironmentPermission(
|
|
PermissionState.Unrestricted).Assert();
|
|
|
|
List<Process> matchingProcesses = new List<Process>();
|
|
|
|
if (null != this.processIds)
|
|
{
|
|
// The keys dictionary is used for rapid lookup of the
|
|
// processes already in the matchingProcesses list.
|
|
Dictionary<int, byte> keys = new Dictionary<int, byte>();
|
|
|
|
foreach (int processId in this.processIds)
|
|
{
|
|
WriteVerbose("Finding match for process id "
|
|
+ processId + ".");
|
|
|
|
if (!keys.ContainsKey(processId))
|
|
{
|
|
Process process;
|
|
try
|
|
{
|
|
process = Process.GetProcessById(processId);
|
|
}
|
|
catch (ArgumentException ex)
|
|
{
|
|
WriteError(new ErrorRecord(
|
|
ex,
|
|
"ProcessIdNotFound",
|
|
ErrorCategory.ObjectNotFound,
|
|
processId));
|
|
continue;
|
|
}
|
|
|
|
WriteDebug("Found matching process.");
|
|
|
|
matchingProcesses.Add(process);
|
|
keys.Add(processId, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
return matchingProcesses;
|
|
} // GetMatchingProcessesById
|
|
|
|
/// <summary>
|
|
/// Retrieves the list of all processes matching the InputObject
|
|
/// parameter.
|
|
/// </summary>
|
|
/// <returns>The matching processes.</returns>
|
|
[EnvironmentPermissionAttribute(
|
|
SecurityAction.LinkDemand,
|
|
Unrestricted = true)]
|
|
private List<Process> GetProcessesByInput()
|
|
{
|
|
new EnvironmentPermission(
|
|
PermissionState.Unrestricted).Assert();
|
|
|
|
List<Process> matchingProcesses = new List<Process>();
|
|
|
|
if (null != this.Input)
|
|
{
|
|
// The keys dictionary is used for rapid lookup of the
|
|
// processes already in the matchingProcesses list.
|
|
Dictionary<int, byte> keys = new Dictionary<int, byte>();
|
|
|
|
foreach (Process process in this.Input)
|
|
{
|
|
WriteVerbose("Refreshing process object.");
|
|
|
|
if (!keys.ContainsKey(process.Id))
|
|
{
|
|
try
|
|
{
|
|
process.Refresh();
|
|
}
|
|
catch (Win32Exception)
|
|
{
|
|
}
|
|
catch (InvalidOperationException)
|
|
{
|
|
}
|
|
|
|
matchingProcesses.Add(process);
|
|
}
|
|
}
|
|
}
|
|
|
|
return matchingProcesses;
|
|
} // GetProcessesByInput
|
|
#endregion Private Methods
|
|
} // End GetProcCommand class.
|
|
|
|
#endregion GetProcCommand
|
|
}
|
|
|