A while ago I wrote my disappointment about Powershell and trying to pick up the syntax. I’ve scripted for years with WSH / VBS, ASP, ASP.NET, VB.NET and some C#. I was used to Visual Studio and the rich debugging support. Coming from a web developer background along with writing console apps, I was used to tools that allowed me to set a breakpoint, run the code and see all the variables, and hopefully no errors (one can dream right!). When it came to scripting, I’ve learned through “the school of hard knocks” on debugging. The tool support for WSH was notepad, lots of Trial and Error.
Powershell is a different approach. I recently wrote a powershell script to query all servers and bring back DNS settings via WMI. This was a auditing script to ensure all boxes had the correct DNS settings. DNS is pretty important in AD. ? My attitude has switched honestly about Powershell. Some of the basic things about querying a database, logging the results, and more importantly the errors so I can track them down separately was doable. When you are querying hundreds of devices, it’s critical to know the exceptions. The script below is what I came out with. I tinkered with various ways to log, a Stringbuilder object then write at the end of the script, also logging to a text file as the script ran. That was probably a little too much, but it was a good exercise.
The one thing I really wanted to share was instead of using Notepad and lots of patience. I used Powergui, this was a attitude changer for writing scripts in Powershell. PowerGUI was similar to Visual Studio showing results I could compare. I didn’t use the debugging feature, PowerGUI does have breakpoints, but I didn’t try them yet. Thanks to the Powershell community for making PowerGUI available.
I’ve also been browsing the Powershell newsgroup, they have some great responses. It’s help me get more comfortable with Poweshell syntax. I spend a few minutes a day browsing. I’m learning TONS! Coming from a primarily VB background, the brackets were different. It took me probably 30 minutes to do this script below and 2 hours of messing around once I had the logic.
In the end, the script produced the results I expected and exceptions for me to investigate. I’m going to experiment more with exception handling. Coming from VBS world, which had ON ERROR RESUME NEXT. It wasn’t a lot but was simple to understand. Powershell offers more choices. If you want to have a better handle on Powershell error handling, I found this article http://huddledmasses.org/trap-exception-in-powershell/ to be informative.
# ********************* Global variables *********************
$sb = new-object System.Text.StringBuilder
$sbErrors = new-object System.Text.StringBuilder
# ********************* Defining functions *********************
function GetListOfComputer
{
$cn = new-object system.data.SqlClient.SqlConnection(“Data Source=MyServerName;Password=MyPassword;Persist Security Info=True;User ID=MyUserName;Initial Catalog=MyDatabaseName”);
$ds = new-object “System.Data.DataSet” “dsServerData”
$q = “select ServerName,PrimaryIP from ServersTable”
$da = new-object “System.Data.SqlClient.SqlDataAdapter” ($q, $cn)
$da.Fill($ds)
$dtList = new-object “System.Data.DataTable” “dtServerData”
$dtList = $ds.Tables[0]
$dtList | FOREACH-OBJECT {LogInfo $_.ServerName $_.PrimaryIP}
}
function LogError ([string]$strError)
{
$sbErrors.Append($strError)
}
function LogToFile ([string]$strFileName, [string]$strError)
{
Add-Content $strFileName $strError
}
function LogInfo ([string]$strServerName,[string]$strIPAddress)
{
Write-Host $strServerName + “,” + $strIPAddress
$pingresult = Get-WmiObject win32_pingstatus -Filter “address=’$strIPAddress’”
$error.Clear()
$ErrorActionPreference = “SilentlyContinue”
if($pingresult.statuscode -eq 0)
{
trap [Exception] {continue}
$colItems = get-wmiobject -query “Select * From Win32_NetworkAdapterConfiguration Where IPEnabled = 1” -namespace “rootcimv2” -computername $strIPAddress
foreach ($objItem in $colItems)
{
$strCaption = $objItem.Caption
write-host $strCaption
$strDescription = $objItem.Description
write-host $strDescription
$strMACAddress = $objItem.MACAddress
write-host $strMACAddress
$strDNSServerSearchOrder = $objItem.DNSServerSearchOrder
write-host $strDNSServerSearchOrder
$result = $strServerName + “,” + $strIPAddress + “,” + $strCaption + “,” + $strDescription + “,” + $strDNSServerSearchOrder + “,” + $strMACAddress + “`r”
$sb.Append($result)
LogToFile “a.txt” $result
}
}
else
{
Write-Host “Cannot connect:” + $strServerName + “,” + $strIPAddress
$sbErrors.Append($strServerName + “,” + $strIPAddress + “`r”)
LogToFile “b.txt” $strServerName + “,” + $strIPAddress + “`r”
}
}
# ********************* Get list of Computers and call function to get data *********************
GetListOfComputer
# ********************* Write out data *********************
write-output $sb.ToString() >x.txt
write-output $sbErrors.ToString() >y.txt
Cheers,
Steve