Powershell Script, WMI to get DNS settings.

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)

$dtList = new-object “System.Data.DataTable” “dtServerData”
$dtList = $ds.Tables[0]
$dtList | FOREACH-OBJECT {LogInfo $_.ServerName $_.PrimaryIP}

function LogError ([string]$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'”
  $ErrorActionPreference = “SilentlyContinue”
  if($pingresult.statuscode -eq 0)
    trap [Exception] {continue}
    $colItems = get-wmiobject -query “Select * From Win32_NetworkAdapterConfiguration Where IPEnabled = 1” -namespace “root\cimv2” -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”
         LogToFile “a.txt” $result
    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 *********************

# ********************* Write out data *********************
write-output $sb.ToString() >x.txt
write-output $sbErrors.ToString() >y.txt



URLScan 3.0 rtw (release to web) available

I have to give kudo’s to the Microsoft IIS team for updating URLScan to help block automated sql injection attacks.  Especially to Wade Hilmo and Nazim Lala.  They have been very responsive when it came to involving the community (Thanks guys for the w3c logs).  They (I’m sure along with others on the team) showed real passion to help provide a tool to make sites more secure.  URLScan 3.0 can be used on IIS 6 and IIS 7 servers.   With the release of URLScan 3.0, IIS Administrators have the ability to block automated attacks at a global or site level. Here is a link to download the rtw bits.  If you have questions about URLScan 3.0, visit the Security forum @ http://forums.iis.net/1031.aspx 

Personally, I’ve used URLScan 3.0 since the beta was released.  It’s helped block many attacks on the server hosting www.iislogs.com  I’ve had to tweak the sql injection rules a bit so legitmate requests aren’t affected,   Check out my TAG on sql injections for more information.  I wonder if Slashdot can post a article announcing URLScan 3.0 was released to help with attacks originally announced, here is the link.   

I can see the headline.  The IIS team responds with URLScan 3.0 to help with SQL Injections. 




Send email with powershell cmd-let

I’ve been reading the Powershell newsgroup, which is pretty much the authoritative source for community help.  


For those who want to send email, Send-SmtpMail is part of the PowerShell Community Extensions.  Download here:


Getting CDONTS to work on Windows Server 2008 x64

A few questions come up in the forums @ http://forums.iis.net about people moving Classic ASP applications that use CDONTS.  CDONTS was introduced in NT4 and was widely popular.  With the success of ASP applications ‘back in the day’, many used CDONTS to send emails from their application.   Windows Server 2008 x64 introduces a different challenge.  Here is the procedure I used to get CDONTS working.

1) Copy CDONTS.dll from another server to C:\Windows\SysWOW64

2) Run regsvr32 c:\windows\SysWOW64\cdonts.dll

3) Grant the appropriate permissions on C:\inetpub\mailroot\pickup (I granted USERS group Modify permissions).  You could get permission denied if the folder security isn’t adjusted.

4) I’m assuming you have installed the SMTP Service located in Server Manager > Features > SMTP Server option

5) Make sure when you when you install the SMTP service, you enable Relay for localhost > Administrative Tools > Internet Information Services (IIS6) > SMTP Virtual Server > Right click, Properties > Access Tab > Relay button > Add in the option.   Also enable logging for additional troubleshooting. 

‘Enable logging

‘Ensure logging will work on x64

6) Test using code listed below.

Here is the code to run CDONTS webpage.

    Dim strBody
    Dim CDONTSMail
    Set CDONTSMail = CreateObject(“CDONTS.NewMail”)
    CDONTSMail.From= “user@example.com
    CDONTSMail.To= “user@example.com
    CDONTSMail.Subject=”This is a Test email”
    strBody = “Thank you for order from www.iislogs.com.” & vbCrLf
    CDONTSMail.Body= strBody
    set CDONTSMail=nothing

I recommend you use CDOSYS instead of CDONTS, however if you are trying to migrate from NT4, 2000/2003 and don’t want to make code changes, hope this helps. 

PS:I tested this using Network Service as the application pool user, a custom application pool user, IUSR (default anonymous authentication module user) and the Anonymous Authentication module inherit the application pool user as network service and a custom user.  If you are having permissions issues, enable auditing and use process monitor.  

Here is a article that can help with auditing.  http://weblogs.asp.net/steveschofield/archive/2008/03/07/detecting-permission-issues-using-auditing-and-process-monitor.aspx