Today, we wrap up our final deep dive into Powershell. For the past three weeks, we have been exploring the benefits of inline .NET code in your PowerShell scripts. These posts come from Manning Publications’ new book: PowerShell Deep Dives. Because I know you all are anxious to wrap up this series, here is part 3, .NET class with methods.
Adding methods to your .NET code is a bit more complicated than adding properties. For example, the code in the next listing provides a way to use the .NET MessageBox class in your scripts.
$source = @' #1 using System.Drawing; using System.Windows.Forms; public class Messages { public static System.Windows.Forms.DialogResult OK( #2 ➥ string message, string caption) { return MessageBox.Show(message, caption, ➥ System.Windows.Forms.MessageBoxButtons.OK); } public static System.Windows.Forms.DialogResult YesNo( ➥ string message, string caption) { return MessageBox.Show(message, caption, ➥ System.Windows.Forms.MessageBoxButtons.YesNo); } } '@ Add-Type -TypeDefinition $source -Language CSharpVersion3 #3 ➥ -ReferencedAssemblies System.Drawing, System.Windows.Forms [Messages]::OK('Hello, this is to inform you that you have #4 ➥ a decision to make', 'Information') $yn = [Messages]::YesNo('Do you want to take this further', ➥ 'Decision Time') switch ($yn){ 'Yes' {[Messages]::OK('Well done - this technique may ➥ help you in the future','Decision Made')} 'No' {[Messages]::OK('OK - the technique is here ➥ if you need it','Decision Made')} }
#1 Source code definition
#2 Method definition
#3 Compile code
#4 Use methods
The source code is defined in a here string (#1). The first two lines define other assemblies that you need to reference:
using System.Drawing;
using System.Windows.Forms;
The language is C# again, because that’s what I’m most comfortable with. Other languages are available. The class name is supplied—in this case, Messages. Each method (#2) has its own definition block:
public static System.Windows.Forms.DialogResult OK(
➥ string message, string caption)
{
return MessageBox.Show(message, caption,
➥ System.Windows.Forms.MessageBoxButtons.OK);
}
The public keyword means you can find and use the method. The methods are static, meaning you don’t need to create an object to use them. The return object type is defined; in this case, it’s a System.Windows.Forms.DialogResult object. The method name is OK. Two parameters are defined for the method named message and caption. Each parameter is defined to accept a string.
The working part of the method is as follows:
return MessageBox.Show(message, caption,
➥ System.Windows.Forms.MessageBoxButtons.OK);
This line defines the return information. A call to the MessageBox class invokes the Show() method. The message and caption parameters provide the message to be displayed and the Window caption, respectively. A final parameter defines the style of buttons to be used, in this case a simple OK button. A second method supplies the option of having two buttons: one labeled Yes and one labeled No.
Add-Type is used to compile the code (#3). Notice that the assemblies you want to reference are repeated in the call to Add-Type. If you don’t do this you’ll get a confusing error with a message regarding Drawing not being found.
The class is now ready to use (#4):
[Messages]::OK(‘Hello, this is to inform you that you have
➥ a decision to make’, ‘Information’)
The message is ‘Hello, this is to inform you that you have a decision to make’. The second parameter, ‘Decision Time’, provides the caption for the pop-up window. Click the OK button, and the window disappears. The second method asks for a yes/no choice; the result is returned in the $yn variable. A Switch statement processes the result.
You might ask how to discover the values for the System.Windows.Forms.DialogResult enumeration. You can look them up on MSDN or use the following function:
function Get-Enum { param ( [string]$class ) [enum]::GetNames("$class") | foreach { $exp = "([$class]::$($_)).value__" New-Object -TypeName PSObject -Property @{ Name = $_ Number = Invoke-Expression -Command $exp } } }
The function accepts a .NET class as a parameter and uses the GetNames() method of the System.Enum class to provide the list of named values. Each name has a numeric value associated with it, which can be discovered by using the value__ property. Unfortunately you can’t put the class into a type definition via a variable, so I created a string with the required code. I used string substitution to populate it and then called Invoke-Expression to execute the code.
If you are interested in learning more techniques like this, then check out Manning Publications’ new book: PowerShell Deep Dives!
Note: Links above are affiliated with Amazon.