Use PowerShell
The Shell Is Calling
The Shell Is Calling
Mar 2nd
In my Exploring the .NET Framework series, I introduced the System.Net.Mail.MailMessage class. Being able to create a MailMessage object is all well and good, but if you can’t send it, it’s really not helpful.
To send an email from PowerShell using the .NET Framework, you can use the System.Net.Mail.SMTPClient class.
First, you need to create your MailMessage
PS C:\scripts\PowerShell> $message = New-Object System.Net.Mail.MailMessage –ArgumentList steve@usepowershell.com, nobody@adomain.com, 'This is a test', "I’m going to send an email via PowerShell"
If you need to add an attachment, you can add one with the System.Net.Mail.Attachment class.
To create the attachment, we’ll create an use an overload of the Attachment class that allows us to specify a filename and a MIME type (the MIME types are available in several enumerations: System.Net.Mime.MediaTypeNames.Application, System.Net.Mime.MediaTypeNames.Image, and System.Net.Mime.MediaTypeNames.Text – I’ve had a bit of trouble accessing those enumerations via PowerShell, but you can specify the name of the enumeration value in a string).
PS C:\scripts\PowerShell> $attachment = New-Object System.Net.Mail.Attachment –ArgumentList 'c:\docs\test.xls’, ‘Application/Octet’ PS C:\scripts\PowerShell> $message.Attachments.Add($attachment)
After we have our email and optional attachment, we’ll create the SMTP client and have it configured to use the SMTP server of our choice.
The constructor of the SMTPClient class that we will use is
SmtpClient(
String host,
)
PS C:\scripts\PowerShell> $smtp = New-Object System.Net.Mail.SMTPClient –ArgumentList 10.10.10.15
All that is left is sending our email..
PS C:\scripts\PowerShell> $smtp.Send($message)
Have fun!
NOTE:
There is a shortcut to creating the MailMessage object like we did.. there is an overload of Send where you can pass in four strings (from, to, subject, and message). The SMTPClient handles the creation of the MailMessage in the background.
A faster method would be
PS C:\scripts\PowerShell> $smtp = New-Object System.Net.Mail.SMTPClient –ArgumentList 10.10.10.15
PS C:\scripts\PowerShell> $smtp.Send('steve@usepowershell.com', 'nobody@adomain.com', 'This is a test', "I'm going to send an email via PowerShell")
Mar 2nd
In part 2(a & b) of this series, we talked about methods and looked at ways to view their overloads, or ways to call them. We also looked at the objects returned from a method call. In this post, we are going to explore a special kind of method called the constructor.
A constructor is a method whose job is to create the object that you want to work with. When I created the Ping object
PS C:\scripts\PowerShell> $ping = New-Object System.Net.NetworkInformation.Ping
the New-Object cmdlet calls the constructor for Ping.
Like other methods, constructors can require parameters and can have multiple overloads.
Let’s look at System.Net.Mail.MailMessage, which is a object that represents an email message.
The MailMessage constructor contains several overloads. The first method listed is MailMessage(), which is the default constructor. This method does not require any arguments and returns an empty MailMessage object. In PowerShell, we would call this method via New-Object, just like with Ping class.
MailMessage()
PS C:\scripts\PowerShell> $message = New-Object System.Net.Mail.MailMessage
The first overload requires two MailAddress objects, the first of which is the “from” address and the second is the “to” address.
MailMessage(
MailAddress from,
MailAddress to,
)
Creating an object in PowerShell from a constructor that requires parameters can be done in two ways. The first is to use the method call notation.
PS C:\scripts\PowerShell> $message = New-Object System.Net.Mail.MailMessage($MailFrom, $MailTo)
The second is to use the ArgumentList parameter.
PS C:\scripts\PowerShell> $message = New-Object System.Net.Mail.MailMessage –ArgumentList $MailFrom, $MailTo
If you happen to have MailAddress objects floating around, this might work for you. A more common scenario would be to use the next overload, which takes two strings.
MailMessage(
String from,
String to,
)
This overload requires two strings, one for the “to” and one for the “from” address.
The final overload for MailMessage is
MailMessage(
String from,
String to,
String subject,
String body,
)
This overload allows you to pass in four strings and get back basic MailMessage object that is ready to be sent.
Wouldn’t it be great to have a function, where we could provide a type name and get a listing of all the constructors, right from the command line (not needing to go to the MSDN documentation every time). Jeffrey Snover has beaten me to the punch and provided a function to find the constructors, appropriately called Get-Constructor. Add that function to the your toolbox, and exploring the .NET Framework becomes a lot easier.
Next up, we’ll look at static methods. Static methods are methods that can be called without having to create a instance of an object.
One particular type of static method that we’ll dig in to is the factory method, which is another way to create instances of objects.
Feb 19th
Continuing from where I left off last week, we were created an instance of the System.Net.NetworkInformation.Ping class and looked at the different ways (overloads) that we can call the Send method. Now that we’ve seen how we can create Ping objects, let’s take advantage of options for creating some custom ping packets and examine the return object.
PS C:\> $encoder = new-object System.Text.ASCIIEncoding
PS C:\> $bytes = $encoder.Getbytes(‘Hello From Steve’)
PS C:\> $response = $ping.Send(‘google.com’, 100, $bytes)
Let’s take a look at the response we get back.
PS C:\> $response | Get-Member
TypeName: System.Net.NetworkInformation.PingReply
Name MemberType Definition
—- ———- ———-
Equals Method System.Boolean Equals(Object obj)
GetHashCode Method System.Int32 GetHashCode()
GetType Method System.Type GetType()
get_Address Method System.Net.IPAddress get_Address()
get_Buffer Method System.Byte[] get_Buffer()
get_Options Method System.Net.NetworkInformation.PingOptions…
get_RoundtripTime Method System.Int64 get_RoundtripTime()
get_Status Method System.Net.NetworkInformation.IPStatus ge…
ToString Method System.String ToString()
Address Property System.Net.IPAddress Address {get;}
Buffer Property System.Byte[] Buffer {get;}
Options Property System.Net.NetworkInformation.PingOptions…
RoundtripTime Property System.Int64 RoundtripTime {get;}
Status Property System.Net.NetworkInformation.IPStatus St…
BufferSize ScriptProperty System.Object BufferSize {get=$this.Buffe…
OptionsString ScriptProperty System.Object OptionsString {get=’TTL={0}…
Get-Member shows us that this is a PingReply object in the System.Net.NetworkInformation namespace.
Looking at the PingReply object that was returned, we have several methods that look strangely similar to the properties, but with a “get_” prefixed to it. When you see a method that matches a Property, but has “get_” or “set_”, that is a method exposed by the .NET Framework that provides the functionality for the properties. When you access the Buffer property, you are actually calling the get_Buffer method. Properties are, for the most part, easier to work with and you can effectively ignore those methods. Properties also contain a clue in their description, if you look at the end of the Buffer property’s description, you see “{get;}” which indicates that there is a way to retrieve that property. Properties can also show “{set;}” which indicates that you can update that property.
In PowerShell V2 CTP3 those “getters” and “setters” (as those methods are commonly called) are hidden by default. If you are running CTP3 and want to see the “getters” and “setters”, you can call Get-Member with the Force parameter.
PS C:\> $response | Get-Member –Force
Back to the properties of our return object. The properties names are pretty self-explanatory, but to confirm we got back the “special” packet we crafted, let’s take a look at the Buffer property and convert that back to text.
PS C:\> $encoder.GetString($response.buffer)
Hello From Steve
Now for the meat of the response, the RoundtripTime and Status. I commonly use the Roundtrip time to watch for latency on my network, and since it is exposed so nicely, it is easy to log.
PS C:\> $response.RoundtripTime
74
And of course, we are interested in the Status.
PS C:\> $response.Status
Success
Now, we can see from the Get-Member return above, that Status is not just a string that says, “Success”, it is a IPStatus enumeration (more on enumerations coming up, but long story short, there are a number of predefined values that an IPStatus object can hold)(also found in the System.Net.NetworkInformation namespace).
I’m normally checking the IPStatus for a Success value like
PS C:\> $success = [System.Net.NetworkInformation.IPStatus]::Success
PS C:\> $response.status -eq $success
True
I could compare the string results, but then I’m stepping back to parsing text results. By using the IPStatus enumeration values, I can get be reasonably sure that my value are correct and I don’t have any text matching issues.
In the next post in this series, we’ll take a look at a special type of method, the constructor.
Feb 11th
Last week, I defined a number of terms that we’ll be exposed to as we delve into how and why PowerShell is an object oriented shell and how to use it to explore .NET Framework which it is built upon.
Now, let’s take a look at how some of these terms surface themselves in PowerShell.
One of the most common tasks you might encounter is needing to ping a computer. There is ping.exe, which works and has been a common guest in my console sessions for years. You can also get ping information via WMI which provides you with some interesting information.
PS C:\scripts\PowerShell> Get-WmiObject Win32_PingStatus -filter “Address=’google.com’”
My preference is to use a class from the .NET Framework called Ping. Ping lives in the System.Net.NetworkInformation namespace.
To access this in PowerShell, I’ll create an instance of the class and refer to it with a variable, $ping.
PS C:\scripts\PowerShell> $ping = New-Object System.Net.NetworkInformation.Ping
By typing the method name without the parenthesis immediately after it, PowerShell will give us information about the method.
PS C:\scripts\PowerShell> $ping.send
MemberType : Method
OverloadDefinitions : {System.Net.NetworkInformation.PingReply Send(String ho
stNameOrAddress), System.Net.NetworkInformation.PingRep
ly Send(String hostNameOrAddress, Int32 timeout), Syste
m.Net.NetworkInformation.PingReply Send(IPAddress addre
ss), System.Net.NetworkInformation.PingReply Send(IPAdd
ress address, Int32 timeout)…}
TypeNameOfValue : System.Management.Automation.PSMethod
Value : System.Net.NetworkInformation.PingReply Send(String hos
tNameOrAddress), System.Net.NetworkInformation.PingRepl
y Send(String hostNameOrAddress, Int32 timeout), System
.Net.NetworkInformation.PingReply Send(IPAddress addres
s), System.Net.NetworkInformation.PingReply Send(IPAddr
ess address, Int32 timeout), System.Net.NetworkInformat
ion.PingReply Send(String hostNameOrAddress, Int32 time
out, Byte[] buffer), System.Net.NetworkInformation.Ping
Reply Send(IPAddress address, Int32 timeout, Byte[] buf
fer), System.Net.NetworkInformation.PingReply Send(Stri
ng hostNameOrAddress, Int32 timeout, Byte[] buffer, Pin
gOptions options), System.Net.NetworkInformation.PingRe
ply Send(IPAddress address, Int32 timeout, Byte[] buffe
r, PingOptions options)
Name : Send
IsInstance : True
What I am most interested in is the Overload Definitions, which is the explanation of how I can use this method.
PS C:\scripts\PowerShell> $ping.send.overloaddefinitions
System.Net.NetworkInformation.PingReply Send(String hostNameOrAddress)
System.Net.NetworkInformation.PingReply Send(String hostNameOrAddress, Int32 timeout)
System.Net.NetworkInformation.PingReply Send(IPAddress address)
System.Net.NetworkInformation.PingReply Send(IPAddress address, Int32 timeout)
System.Net.NetworkInformation.PingReply Send(String hostNameOrAddress, Int32 timeout, Byte[] buffer)
System.Net.NetworkInformation.PingReply Send(IPAddress address, Int32 timeout, Byte[] buffer)
System.Net.NetworkInformation.PingReply Send(String hostNameOrAddress, Int32 timeout, Byte[] buffer, PingOptions options)
System.Net.NetworkInformation.PingReply Send(IPAddress address, Int32 timeout, Byte[] buffer, PingOptions options)
As we can see from the above output $ping.Send has several different ways that we can call it and it also shows the object that we will get in return, an object of the type System.Net.NetworkInformation.PingReply.
The first overload for $ping.Send is to supply it an object of the type String (remember, in PowerShell, even text is an object) which represents the hostname or IP address of the host we wish to ping.
PS C:\scripts\PowerShell> $ping.send(‘google.com’)
Status : Success
Address : 74.125.45.100
RoundtripTime : 29 ms
BufferSize : 32
Options : TTL=243, DontFragment=False
Here, we called $ping.Send with a argument of the String ‘google.com’ and received back an object of the type PingReply. We can see the textual representation of it’s properties. In my next post, we’ll dig into the return object a bit more and see how we can use its properties to our advantage.
We still have a number of other ways that we can call $ping.Send. Our second option is to provide a String describing the hostname or IP address (as before), but also allows us to specify a timeout by providing an Int32. (Just a quick note, if you specify a really low timeout value, the reply still may be received. It is more of an option to provide a longer than normal, five seconds, timeout period.)
We also see overloads that take an object of the IPAddress type to describe the target of the Ping.
Now, things get a bit more interesting. The next argument we see is of the type Byte[], which means an Array of Byte objects. The quick explanation of an Array is a collection of objects (not 100 percent accurate, but sufficient for right now). This allows us to specify exactly what data will be sent with the ICMP echo message.
The final argument is to supply an object of the PingOptions type. This allows us to specify an Int32 as the TTL (Time To Live) and a Boolean as Don’t Fragment option.
I’m starting to run a bit long here, so I’m going to continue walking through this example in my next post. We’ll create an object of type Ping with some custom options and then dig in to the object that is returned.