MSDN Magazine - December 2007 - (Page 71) to the following parameters at runtime: Figure 2 Virtual Methods Confirm and WhatIf. Confirm specifies Purpose whether user confirmation is required Method before a cmdlet performs an action that BeginProcessing Provides optional one-time, preprocessing functionality for the cmdlet. modifies the system. True indicates that ProcessRecord Provides record-by-record processing functionality for the cmdlet. It may be called any number of times or not at all, depending on the input of the cmdlet. confirmation is required; false indicates EndProcessing Provides optional one-time, post-processing functionality for the cmdlet. that it’s not required. WhatIf specifies whether a cmdlet StopProcessing Stops processing when the user stops the cmdlet asynchronously, such as by entering the key combination Ctrl+C. should inform the user what changes would have been made if the action were performed but without the action occurring. True indicates that tions, but since I’m wrapping them in ThrowTerminatingError, I’ll the user is informed without the action occurring, False indicates be able to provide a bit more information in case of failure. that the action should occur. In my implementation, I’ll use ProcessRecord to do the work of When SupportsShouldProcess is specified, cmdlets that at- creating new entries for data in isolated storage (see Figure 4). Note tempt to declare these parameters will fail when trying to register the use of the try/catch statements, in order to add more informathe cmdlet. You shouldn’t define these parameters in your cmdlet tion in case an error occurs. In this case I’m using WriteError indirectly. Instead, include SupportsShouldProcess when you use stead of ThrowTerminatingError; this is because I don’t need to the [Cmdlet( )] attribute. stop the pipeline in case of a bad write. Since I opened the isolated storage from within BeginProcessing, Parameter Sets I’ll use the EndProcessing method to close the files. I’m not reading Windows PowerShell uses the concept of parameter sets. This or writing to the isolated storage file in Remove-IsolatedStorageFile; enables you to write a single cmdlet that exposes different sets of therefore, I’ll use EndProcessing to remove the file in that cmdparameters to the user and returns different information based on let. Here’s what the EndProcessing code looks like for the Getthe parameters specified by the user. For example, the Get-EventLog IsolatedStorageData and Set-IsolatedStorageData cmdlets: cmdlet (built into Windows PowerShell) returns different inforprotected override void EndProcessing() mation when the user specifies the List or LogName parameter. { if (sw != null ) { sw.Close(); } When LogName is specified, the cmdlet returns information about if (fs != null ) { fs.Close(); } the events in a given event log. However, when List is specified, the if (isoStore != null ) { isoStore.Close(); } } cmdlet returns information about the log files themselves (not the event information they contain). In this case, List and LogName Figure 3 Using the BeginProcessing Method identify two different parameter sets. When multiple parameter sets are defined, the cmdlet can indiprotected override void BeginProcessing() { cate which parameter set to use if Windows PowerShell doesn’t have try enough information to make that determination. The parameter { if ( ShouldProcess( Name )) set that is used in this case is referred to as the default parameter { set, and is specified using the DefaultParameterSet keyword of the WriteVerbose(“Opening Isolated Storage: “ + Name); isoStore = this.GetMyStore(); CmdletAttribute declaration. Note that I’m not using parameter fs = new IsolatedStorageFileStream( sets in my sample cmdlets. Name, Method Overrides The Cmdlet class provides virtual methods, shown in Figure 2, that can be used to process records. One or more of these methods must be overridden by all derived cmdlet classes. Since my cmdlets deal with files, I’ll use the BeginProcessing method to implement the code used to open the IsolatedStorage files, as shown in Figure 3. There are a couple of things worth noting. First, I’m opening the files in create mode, which is a system change, so I should wrap that code in a ShouldProcess block. That means I will have an opportunity to tell the user what I’m going to do before I actually do it. (This is done when the user uses either Confirm or WhatIf arguments.) Also notice that I am going to catch exceptions and wrap them with ThrowTerminatingError. In this sample, if anything goes wrong, it shouldn’t proceed because the file open will have failed. It’s usually bad form to catch all excep} FileMode.OpenOrCreate|FileMode.Append, FileAccess.Write, isoStore ); sw = new StreamWriter(fs); WriteDebug(“Stream encoding: “ + sw.Encoding); } catch ( Exception e ) { this.closeStreams(); ThrowTerminatingError( new ErrorRecord( e, “OpenIsolatedStorage”, ErrorCategory.NotSpecified, Name ) ); } } Custom Cmdlets december2007 71
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.