Thursday, June 10, 2010

Automating Domain Controller Diagnostics, Version 2.0

I posted a portion of this some time ago, but this week I received the fourth inquiry about the full version, so I guess it’s time to post it.  Here goes…

Create a shared folder on each domain controller named "Data$" and assign permissions to only the "Domain Admins" security group.  Remove all others from the permissions set.

Install the Support Tools and latest versions of DCDIAG.exe, NETDIAG.exe, and REPADMIN.exe on each domain controller.  Make SURE they are the same versions on all of them.

Create a share named "Scripts$" on a central domain member server.  Assign permissions to allow "Domain Controllers" security group to have Read permissions.  Assign "Domain Admins" to have full control permissions.

Create a share named "Logs$" on a central domain member server (can be the same member server as the one above).  Assign permissions to allow "Domain Controllers" security group to have Change permissions (read/write/modify/delete).  Assign "Domain Admins" group full control.

Put the script below into the "Scripts$" share.

On each domain controller, create a scheduled task to run the script from the "Scripts$" UNC path at a chosen interval (daily, weekly, monthly, quarterly, whatever) using the local "SYSTEM" account.  The "SYSTEM" account operates in the context of the computer (the domain controller on which it is executed) and therefore becomes a member of the "Domain Controllers" group when it attempts to access remote resources (across the LAN/WAN).

When the scheduled task executes the script, it should dump the output files into the local "Data$ share.  Another script will be posted soon which crawls through the collected files to produce a summary report of how your domain controllers are doing (with respect to the diagnostics reports for each).

Option Explicit
'**************************************************************
' Filename: dc_diagnostics.vbs
' Author: David Stein
' Date: 11/19/07
' Purpose: Run and Report Diagnostics on Domain Controllers

'**************************************************************
' copyright: free for derivative use without any warranties
' provided, explicit or implicit, provided that the above info
' with author name is included (provide attribution)

'**************************************************************
Const DebugMode = True
Const collectionFolder = "\\memberserver\logs$\"
Const alertList = "EMAIL_ADDRESS@mydomain.local"
Const alertFrom = "IT REPORTS <donotreply@MYDOMAIN.LOCAL>"
Const mailServer = "mail.mydomain.local"
Const localShare = "Data$"

Const bRunDCDIAG = True
Const bRunNETDIAG = True
Const bRunREPADMIN = True
Const DeleteTempFiles = False
Const SendAlerts = True
Const SendOnErrorsOnly = True

Const bVerbose = False

'--------------------------------------------------------------
' declare variables
'--------------------------------------------------------------

Dim objShell, objFSO, strServerName, strServerData
Dim strMonthNum, strDayNum, strYear
Dim datestamp, dcDiagReport, netDiagReport, repAdminReport
Dim statlog, errorCount
errorCount = 0

'--------------------------------------------------------------
' diagnostics status display
'--------------------------------------------------------------

Sub DebugPrint(code, strval)
If DebugMode Then
wscript.echo Now & vbTab & code & vbTab & strval
End If
End Sub

'--------------------------------------------------------------
' run DCDIAG report
'--------------------------------------------------------------

Sub RunDCDiag()
Dim cmdstr
cmdstr = "%comspec% /c dcdiag >" & dcDiagReport
DebugPrint "info", "" & cmdstr
objShell.Run cmdstr, 1, True
DebugPrint "info", "dcdiag process completed."
End Sub

'--------------------------------------------------------------
' run NETDIAG report
'--------------------------------------------------------------

Sub RunNetDiag()
Dim cmdstr
cmdstr = "%comspec% /c netdiag >" & netDiagReport
DebugPrint "info", "" & cmdstr
objShell.Run cmdstr, 1, True
DebugPrint "info", "netdiag process completed."
End Sub

'--------------------------------------------------------------
' run REPADMIN /SHOWREPS report
'--------------------------------------------------------------

Sub RunRepAdmin()
Dim cmdstr
cmdstr = "%comspec% /c repadmin /showreps >" & repAdminReport
DebugPrint "info", "" & cmdstr
objShell.Run cmdstr, 1, True
DebugPrint "info", "repadmin process completed."
End Sub

'--------------------------------------------------------------
' upload report files to remote collection point
'--------------------------------------------------------------

Sub CollectReports()
DebugPrint "info", "uploading reports to remote collection point..."

If bRunDCDIAG Then
If objFSO.FileExists(dcDiagReport) Then
DebugPrint "info", "uploading dcdiag report to collection point..."
'debugprint "*** " & dcDiagReport
objFSO.CopyFile dcDiagReport, collectionFolder, True
If DeleteTempFiles = True Then
DebugPrint "info", "deleting local dcdiag report file..."
objFSO.DeleteFile dcDiagReport
End If
DebugPrint "info", "dcdiag report uploaded successfully."
DebugPrint "info", "collection-point: " & collectionFolder
statlog = statlog & vbCRLF & "dcdiag report uploaded successfully."
Else
statlog = statlog & vbCRLF & "error: dcdiag report failure!"
DebugPrint "error", "dcdiag report file not found."
errorCount = errorCount + 1
End If
End If

If bRunNETDIAG Then
If objFSO.FileExists(netDiagReport) Then
DebugPrint "info", "uploading netdiag report to collection point..."
objFSO.CopyFile netDiagReport, collectionFolder, True
If DeleteTempFiles = True Then
DebugPrint "info", "deleting local netdiag report file..."
objFSO.DeleteFile netDiagReport
End If
DebugPrint "info", "netdiag report uploaded successfully."
DebugPrint "info", "collection-point: " & collectionFolder
statlog = statlog & vbCRLF & "netdiag report uploaded successfully."
Else
statlog = statlog & vbCRLF & "error: netdiag report failure!"
DebugPrint "error", "netdiag report file not found."
errorCount = errorCount + 1
End If
End If

If bRunREPADMIN Then
If objFSO.FileExists(repAdminReport) Then
DebugPrint "info", "uploading repadmin report to collection point..."
objFSO.CopyFile repAdminReport, collectionFolder, True
If DeleteTempFiles = True Then
DebugPrint "info", "deleting local repadmin report file..."
objFSO.DeleteFile repAdminReport
End If
DebugPrint "info", "repadmin report uploaded successfully."
DebugPrint "info", "collection-point: " & collectionFolder
statlog = statlog & vbCRLF & "repadmin report uploaded successfully."
Else
statlog = statlog & vbCRLF & "error: repadmin report failure!"
DebugPrint "error", "repadmin report file not found."
errorCount = errorCount + 1
End If
End If
End Sub

'--------------------------------------------------------------
' send email
'--------------------------------------------------------------

Sub SendMail(sTo, sFrom, sSubject, sBody, sFormat)
Dim objMessage
Set objMessage = CreateObject("CDO.Message")
objMessage.Subject = sSubject
objMessage.Sender = sFrom
objMessage.To = sTo
If sFormat = "TEXT" Then
objMessage.TextBody = sBody
Else
objMessage.HTMLBody = sBody
End If
objMessage.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
objMessage.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/smtpserver") = mailServer
objMessage.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
objMessage.Configuration.Fields.Update
objMessage.Send
Set objMessage = Nothing
DebugPrint "info", "(sendmail) message sent to " & sTo
End Sub

'--------------------------------------------------------------
' function: return padded string using parameters
' arg: strval (string - value being padded)
' arg: intLen (integer - string length to meet)
' arg: sChar (string - value to append or prefix to string)
' arg: sSide (string - side of string to pad, "L" or "R")
'--------------------------------------------------------------

Function PadString(strval, intLen, sChar, sSide)
Dim retval
retval = Trim(strval)
Do While Len(retval) < intLen
If Ucase(sSide) = "L" Then
retval = sChar & retval
Else
retval = retval & sChar
End If
Loop
PadString = retval
End Function

'--------------------------------------------------------------
' main subroutine
'--------------------------------------------------------------

Sub Main()
Dim msgSub, msgBody
Set objShell = Wscript.CreateObject("Wscript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")

strServerName = objShell.ExpandEnvironmentStrings("%computername%")
strServerData = "\\" & strServerName & "\" & localShare & "\"

statlog = ""

strMonthNum = DatePart("m", Now)
If Len(strMonthNum) = 1 Then
strMonthNum = "0" & strMonthNum
End If

strDayNum = DatePart("d", Now)
If Len(strDayNum) = 1 Then
strDayNum = "0" & strDayNum
End If

strYear = DatePart("yyyy", Now)
datestamp = strMonthNum & strDayNum & Right(strYear,2)

DebugPrint "info", "datestamp = " & datestamp
DebugPrint "info", "servername = " & strServerName

If bRunDCDIAG Then
dcDiagReport = strServerData & strServerName & "_dcdiag.txt"
RunDCDiag()
End If

If bRunNETDIAG Then
netDiagReport = strServerData & strServerName & "_netdiag.txt"
RunNetDiag()
End If

If bRunREPADMIN Then
repAdminReport = strServerData & strServerName & "_repadmin.txt"
RunRepAdmin()
End If

CollectReports()

If SendAlerts = True Then
If SendOnErrorsOnly = True Then
' send alert only when errors occur...

If errorCount > 0 Then
msgSub = "DC Status Check: ERROR - " & strServerName
msgBody = "DC Status Check: ERROR - " & strServerName & vbCRLF & _
"------------------------------" & vbCRLF & _
"One or more diagnostic reports could not" & vbCRLF & _
"be generated or collected from " & strServerName & vbCRLF & _
"------------------------------"
SendMail alertList, alertFrom, msgSub, msgBody, "TEXT"
End If
Else
' send alert for any status, not just errors...

msgsub = "DC Status Check: SUCCESS - " & strServerName
If bVerbose Then
msgbody = strServerName & " Diagnostics Process Report" & vbCRLF & _
"----------------------------" & vbCRLF & _
"Diagnostics reports have been processed on this " & _
"domain controller with the following results. " & _
"Reports have been uploaded to the central collection " & _
"point for further processing." & vbCRLF & _
"----------------------------" & vbCRLF & statlog
Else
msgbody = strServerName & " Diagnostics Process Report" & vbCRLF & _
"----------------------------" & vbCRLF & _
"Diagnostics reports were uploaded successfully."
End If
SendMail alertList, alertFrom, msgSub, msgBody, "TEXT"
End If
End If

Set objFSO = Nothing
Set objShell = Nothing
End Sub

'--------------------------------------------------------------

Call Main()

wscript.Quit

No comments:

Post a Comment