// // Copyright (c) 2006 Microsoft Corporation. All rights reserved. // // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. // using System; using System.Diagnostics; using System.Collections; using Win32Exception = System.ComponentModel.Win32Exception; using System.Management.Automation; // Windows PowerShell namespace using System.Globalization; // This sample shows how to implement a PassThru parameter that indicates that // the user wants the cmdlet to return an object, and how to request // user feedback by calls to the ShouldProcess and ShouldContinue methods. // // To test this cmdlet, create a module folder that has the same name as // this assembly (StopProcesssample01), save the assembly in the module folder, and then run the // following command: // import-module stopprocesssample01 namespace Microsoft.Samples.PowerShell.Commands { #region StopProcCommand /// /// This class implements the stop-proc cmdlet. /// [Cmdlet(VerbsLifecycle.Stop, "Proc", SupportsShouldProcess = true)] public class StopProcCommand : Cmdlet { #region Parameters /// /// This parameter provides the list of process names on /// which the Stop-Proc cmdlet will work. /// [Parameter( Position = 0, Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true )] public string[] Name { get { return processNames; } set { processNames = value; } } private string[] processNames; /// /// This parameter overrides the ShouldContinue call to force /// the cmdlet to stop its operation. This parameter should always /// be used with caution. /// [Parameter] public SwitchParameter Force { get { return force; } set { force = value; } } private bool force; /// /// This parameter indicates that the cmdlet should return /// an object to the pipeline after the processing has been /// completed. /// [Parameter] public SwitchParameter PassThru { get { return passThru; } set { passThru = value; } } private bool passThru; #endregion Parameters #region Cmdlet Overrides /// /// The ProcessRecord method does the following for each of the /// requested process names: /// 1) Check that the process is not a critical process. /// 2) Attempt to stop that process. /// If no process is requested then nothing occurs. /// protected override void ProcessRecord() { foreach (string name in processNames) { // For every process name passed to the cmdlet, get the associated // processes. // Write a nonterminating error for failure to retrieve // a process. Process[] processes; try { processes = Process.GetProcessesByName(name); } catch (InvalidOperationException ioe) { WriteError(new ErrorRecord(ioe,"UnableToAccessProcessByName", ErrorCategory.InvalidOperation, name)); continue; } // Try to stop the processes that have been retrieved. foreach (Process process in processes) { string processName; try { processName = process.ProcessName; } catch (Win32Exception e) { WriteError(new ErrorRecord(e, "ProcessNameNotFound", ErrorCategory.ReadError, process)); continue; } // Confirm the operation with the user first. // This is always false if the WhatIf parameter is set. if (!ShouldProcess(string.Format(CultureInfo.CurrentCulture,"{0} ({1})", processName, process.Id))) { continue; } // Make sure that the user really wants to stop a critical // process that culd possibly stop the computer. bool criticalProcess = criticalProcessNames.Contains(processName.ToLower(CultureInfo.CurrentCulture)); if (criticalProcess &&!force) { string message = String.Format (CultureInfo.CurrentCulture, "The process \"{0}\" is a critical process and should not be stopped. Are you sure you wish to stop the process?", processName); // It is possible that the ProcessRecord method is called // multiple times when objects are recieved as inputs from // the pipeline. So to retain YesToAll and NoToAll input that // the user may enter across mutilple calls to this function, // they are stored as private members of the cmdlet. if (!ShouldContinue(message, "Warning!", ref yesToAll, ref noToAll)) { continue; } } // if (cricicalProcess... // Stop the named process. try { process.Kill(); } catch (Exception e) { if ((e is Win32Exception) || (e is SystemException) || (e is InvalidOperationException)) { // This process could not be stopped so write // a nonterminating error. WriteError(new ErrorRecord(e, "CouldNotStopProcess", ErrorCategory.CloseError, process)); continue; } // if ((e is... else throw; } // catch // If the PassThru parameter is // specified, return the terminated process. if (passThru) { WriteObject(process); } } // foreach (Process... } // foreach (string... } // ProcessRecord #endregion Cmdlet Overrides #region Private Data private bool yesToAll, noToAll; /// /// Partial list of critical processes that should not be /// stopped. Lower case is used for case insensitive matching. /// private ArrayList criticalProcessNames = new ArrayList( new string[] { "system", "winlogon", "spoolsv" } ); #endregion Private Data } // StopProcCommand #endregion StopProcCommand }