MSDN Magazine - December 2007 - (Page 72) Figure 4 Using ProcessRecord in Set-IsolatedStorageData protected override void ProcessRecord() { try { // Remember ShouldProcess may not have opened the file if(sw != null ) { WriteVerbose(“Setting “ + Key + “ = “ + Value); sw.WriteLine(Key + “=” + Value); } } catch ( Exception e ) { WriteError( new ErrorRecord( e, “SetIsolatedStorageValue”, ErrorCategory.NotSpecified, Name ) ); } } member, I need to do a little reflection because this information isn’t surfaced as part of the IsolatedStorage information. So the implementation of the object that I’ll use for the results will look like what’s shown in Figure 5. Again, remember that in order to provide consistency across all cmdlets, Windows PowerShell cmdlets return objects into a pipeline rather than text to a stream. WriteObject is what the cmdlet uses to emit the results. After retrieving the data from the IsolatedStorage file, I convert that to an instance of an IsolatedStorageData type and use WriteObject to emit those results into the pipeline. Reporting Error Conditions When running code, there will be times when things just don’t do what you want and some sort of error occurs. Windows PowerShell has some fairly sophisticated behaviors for these circumstances and its error-reporting capabilities allow for very fine-grained control over what happens. Sometimes when an error occurs, it’s not catastrophic. For example, if you want to remove thousands of files in a directory, failing to remove one or two of those files won’t invalidate all the other file deletions. These are non-terminating errors—that is, it’s still an error, but it’s not an error that will result in you having to stop whatever you’re doing. You can continue to remove the files that are removable. However, there are operations that you can’t recover from. Suppose you need to create a temporary file to hold on to some data that you’ll use later. If you can’t create and use the temporary file, there’s no point in proceeding with the rest of the operation because the data you’ll need won’t be available. This qualifies as a TerminatingError. In Windows PowerShell, two different cmdlet methods—WriteError and ThrowTerminatingError—allow you to make this distinction. WriteError is used whenever there’s some sort of exceptional circumstance in the execution of your cmdlet that isn’t fatal to the overall operation of the cmdlet. The method takes as an argument an instance of an ErrorRecord, which allows you to include more than just the exception (the cause of the error). Figure 5 Object Used for the Results public class IsolatedStorageData { public string Key; // The Key public string Value; // The Value public string FullName; // The path to the storage public override string ToString() { return Value; } public IsolatedStorageData( string _key, string _value, IsolatedStorageFileStream _fs ) { Key = _key; Value = _value; FullName = _fs.GetType() . GetField(“m_FullPath”, BindingFlags.Instance|BindingFlags.NonPublic ) . GetValue(_fs).ToString(); } } The code in Remove-IsolatedStorageFile is a bit trickier. In this cmdlet, I delete the file itself using the appropriate methods from the IsolatedStorage object: if(ShouldProcess(“Remove Isolated Storage”)) { WriteVerbose(“Deleting Isolated Storage: “ + Name); isoStore = this.GetMyStore(); isoStore.DeleteFile(Name); } Notice that I’m using ShouldProcess again. Since I’m making a change to the system, I need to notify the user of what I’m about to do, should they want this information. Emitting Results Windows PowerShell is all about results, but you have to find a balance in the way you provide those results. The balance involves making sure you return as much information as you can without causing too much impact on the performance (such as by using too much memory, taking too long to execute, and so on). Since I’ll be saving text to a file, I could just return the text all by itself. While this would be OK, I want to demonstrate something better, so I will provide the key and the value. When I was first learning about IsolatedStorage, I noticed that it’s pretty tough to find the actual file being used for the storage, so I want to include that information in my results. This will make the results more useful. By returning the key, value, and the path to the data, my object looks like this: public class IsolatedStorageData { public string Key; // The Key public string Value; // The Value public string FullName; // The path to the storage } I also have to consider what sort of string the object’s ToString method should return. By default, most .NET objects return just the name of the type—this isn’t very useful. So I’ll have the ToString method return the Value rather than the name of the type. In order to get the value of the actual filename for the FullName 72 msdnmagazine Custom Cmdlets
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.