So my cmdlet still isn’t working. This time, I’ve made another “debugging” change to my code, adding this line:
For Each ThisName In _Name
WriteDebug("Attempting to ping " & ThisName)
WriteObject("SELECT StatusCode FROM Win32_PingStatus WHERE Address = '" & ThisName & "'") Dim Query As SelectQuery
Query = New SelectQuery("SELECT StatusCode FROM Win32_PingStatus WHERE Address = '" & ThisName & "'")
As you can see, I’ve just added a line to output my WMI query. This results in the following when I run the cmdlet in PowerShell:
PS C:\> get-content c:\computers.txt | ping-computer
SELECT StatusCode FROM Win32_PingStatus WHERE Address = 'sapienteched'
sapienteched
SELECT StatusCode FROM Win32_PingStatus WHERE Address = 'server2'
server2
SELECT StatusCode FROM Win32_PingStatus WHERE Address = 'localhost'
localhost
SELECT StatusCode FROM Win32_PingStatus WHERE Address = ''
Now I can copy and paste the exact query my code is using into Wbemtest.exe, to test it. I want to try the Server2 query, since I know Server2 should NOT be pingable. When I try it, the query works… but I learn something interesting. The StatusCode property, which is usually 0 for a successful ping, is Null for Server2’s ping. Looking at my code:
If result.GetPropertyValue("StatusCode") = 0 Then
I see my mistake. I’m comparing Null to 0, and anything compared to Null is Null… in other words, this comparison doesn’t equal True or False, ir equals Null… which is messing up the logic in my code. I need to use VB.NET’s IsNothing() function to see if the returned value is null or not. Doing so, I recompile, rerun, etc, and get this:
PS C:\> add-pssnapin primaltoys
PS C:\> get-content c:\computers.txt | ping-computer
sapienteched
localhost
Notice that I’ve removed my debugging code that wrote out the query; this WORKS! This is what I want! Yay! Here’s my final code for the entire cmdlet (BTW, I know this formatting is a little crazy – hang in because at the end of the series I’ll post the project files; I don’t want to do so until I’m DONE, though):
Imports System.Management.Automation
Imports System.Management
<Cmdlet(VerbsDiagnostic.Ping, “Computer”, SupportsShouldProcess:=True)> _Public Class PingComputerCmdInherits Cmdlet
‘<Parameter(Position:=0, Mandatory:=False)> _ ‘Public Property Name() As String ’ Get ’ Return “” ’ End Get ’ Set(ByVal value As String) ’ End Set ‘End Property Private _Name AsString() <Parameter(Position:=0, Mandatory:=False, ValueFromPipeline:=True)> _Public Property Name() AsString()
Get Return _Name
End Get Set(ByVal value AsString()) _Name = valueEnd Set End Property Protected OverridesSub ProcessRecord()
Dim ThisName As StringFor Each ThisName In _Name WriteDebug(“Attempting to ping “ & ThisName)Dim Query As SelectQuery
Query = New SelectQuery(“SELECT StatusCode FROM Win32_PingStatus WHERE Address = ‘” & ThisName & “’”)
Dim Searcher As ManagementObjectSearcher
Searcher = New ManagementObjectSearcher(Query)
Dim result As ManagementObject
For Each result In Searcher.Get
If Not IsNothing(result.GetPropertyValue(“StatusCode”)) Then If result.GetPropertyValue(“StatusCode”) = 0 Then
WriteDebug(“Successful ping of “ & ThisName)
WriteObject(ThisName)
Else
WriteDebug(“Could not ping “ & ThisName)
End IfElse
WriteDebug(“Could not ping “ & ThisName)
End If
NextNextEnd Sub
End Class
But stay tuned… there’s still a bit more to learn. And apologies for the formatting… neither Visual Studio nor the blog software really seem to like one another when it comes to copy/paste… again, I’ll be posting the source code at the end of this series, so just hang in there.