Section 5.4. How Variables Relate to the .NET Framework


5.4. How Variables Relate to the .NET Framework

Scattered across the examples we've seen so far have been a number of references to the .NET Framework, which was introduced in Chapter 3. We'll now take some time to look at the deep relationship between MSH and the .NET Framework and several of the ways that it brings additional functionality to the shell.

Given the number of classes available in the Class Library, it's impossible to cover each in turn. We'll look at a few examples that lead the way and illustrate what the tight integration with the .NET Framework allows. An understanding of what is possible will likely become invaluable as you use MSH to approach more tasks that are increasingly complex.

5.4.1. How Do I Do That?

Let's start by reviewing a syntax we've already encountered: square brackets ([ ]). When square brackets are used in a script, they indicate to the shell that the enclosed term is a .NET Framework reference. A reference may be in the form of a fully qualified class (such as [System.Xml.XmlDocument]), a class name within the System namespace (such as [string]), or one of several shortcuts (such as [Xml] and [Regex]).

We've already encountered different variable types (such as int, double, string), and it is no coincidence that each one is based on a .NET class. MSH does its best to automatically infer underlying types when working with data. The type conversion rules follow a predictable pattern. If the value looks like a number, it will be converted to either an int (whole number) or a double (real number), depending on whether a decimal point is present. Anything else must be enclosed in quotation marks and is assumed to be a string:

     MSH D:\MshScripts> $a = 132     # $a is an int     MSH D:\MshScripts> $b = 3.14     # $b is a double     MSH D:\MshScripts> $c = 0x20     # $c is an int with value 32 (decimal)     MSH D:\MshScripts> $d = "99.99"     # $d is a string

Automatic type conversion also happens when operations are performed on variables. In the case of addition, using + on a double and an int will yield a double: in general, MSH will try to preserve as much precision as possible during arithmetic operations:

     MSH D:\MshScripts> $a = 1.2     MSH D:\MshScripts> $b = 3     MSH D:\MshScripts> $c = $a + $b     # $c is a double with value 4.2

At times it's necessary to override these rules by using an explicit cast. Using the square bracket notation before either the variable name or the value, a script can force MSH to convert a value to a suitable type for either the immediate assignment or all future ones:

     MSH D:\MshScripts> $a = [int]3.21     MSH D:\MshScripts> $a           # round 3.21 to an int this time only 3     MSH D:\MshScripts> $a = 5.2     MSH D:\MshScripts> $a     5.2     MSH D:\MshScripts> [int]$b = 1.2   # any future assignments to $b will be                                          rounded     MSH D:\MshScripts> $b     1     MSH D:\MshScripts> $b = 6.9      # since $b is always an int, round up to 7     MSH D:\MshScripts> $b     7     MSH D:\MshScripts> $a = "samplestring"     MSH D:\MshScripts> $b = "samplestring"     : Cannot convert "samplestring" to "System.Int32". Error: "samplestring is not a  valid value for Int32.".     At line:1 char:3     + $b= <<<< "samplestring"

Casting can be used to convert values into any .NET Framework type, not just into the native int, double, and string cases we've seen so far. For example, the boolean type represents a true/false value, and explicit cast to this type will convert a value into one of those states. Many other types can parse a string into a format they are well suited to represent:

     MSH D:\MshScripts> $success = [boolean]1     MSH D:\MshScripts> $success     True     MSH D:\MshScripts> $success = [boolean]0     False     MSH D:\MshScripts> $moonDay = [datetime]"1969-5-20"     MSH D:\MshScripts> $moonDay     Tuesday, May 20, 1969 12:00:00 AM     MSH D:\MshScripts> $newYear = [datetime]"1/1"     MSH D:\MshScripts> $newYear     Saturday, January 01, 2005 12:00:00 AM

We've covered some of this ground before, but this recap sets the scene for what comes next. A new concept that we haven't covered yet is enumeration, which defines a (usually small) set of valid values. A variable is assigned an enumeration value using an explicit cast of a string. Some enumerations allow multiple values (known as flags), which can be specified as a comma-separated list:

     MSH D:\MshScripts> $succ = [System.Security.AccessControl.AuditFlags]"Success"     MSH D:\MshScripts> $both = [System.Security.AccessControl.AuditFlags]"Success,Failure"

All possible values for a given enumeration can be gathered by using the GetNames static method of the Enum class:

     MSH D:\MshScripts> [Enum]::GetNames([System.Security.AccessControl.AuditFlags])     None     Success     Failure

Flags and enumerations are frequently used when calling into .NET Framework methods, as we'll see in the next section.

5.4.2. What Just Happened?

When variables were first covered in Chapter 3, we quickly saw that they store not only values but also some information about their structure. Instead of treating everything as if it were a string, this distinction is what sets MSH apart from cmd.exe and other shells. What we've seen here isn't just a mapping between MSH variable types and .NET Framework types; they are one and the same. A .NET Framework type can be used seamlessly anywhere within the shell.

Although automatic type conversion is designed to go unnoticed, it is helpful to understand the predictable pattern used by the shell when figuring out the type for a variable. For assignment, the shell follows this sequence:

  • If the variable does not have a strict type:

    • If the value is a number without a decimal point (of the form 123 or 0x123, 12e3, 16k, or similar), the variable is an int.

    • If the value is a number with a decimal point (of the form 123.45, 123.0, 12.3e4, or similar), the variable is a double.

    • If the value is contained within quotation marks (single or double), the variable is a string.

    • If none of the above applies, the value is evaluated as a cmdlet, function, or executable program, and its type will vary depending on what is invoked.

  • If the variable already has a type (it was created with explicit type before the variable name):

    • Try to convert the value to the variable's type. If an automatic conversion fails, an error will be displayed.

Automatic type conversion stops short of trying to make too many assumptions because sometimes there is too little information in the assignment or operation for MSH to accurately judge what it should be doing. Explicit casts are used to fill this gap and provide the means for telling the shell exactly which types to use. Some degree of caution is a good idea when casting between different types. While MSH will put a stop to nonsensical operations ([bool]($b*"s")), other conversions are legitimate ([int]$b where $b is a boolean) but may not always have the desired or expected effect. Although it is sometimes possible to just "make it work" by casting one type to another, it's generally a good idea to understand why it wasn't working in the first place.

5.4.3. Where Can I Learn More?

Refer to Chapter 3, where we first discussed variables. The types available in the System namespace are listed on MSDN: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystem.asp.

That's only half the story. Now that you understand that MSH types and .NET Framework types are one and the same, let's look at using this rich set of methods in the Class Library.




Monad Jumpstart
Monad Jumpstart
ISBN: N/A
EAN: N/A
Year: 2005
Pages: 117

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net