Link to home
Start Free TrialLog in
Avatar of OAC Technology
OAC TechnologyFlag for United States of America

asked on

Improper shutdown detection and running chkdsk automatically

Hi all,

We're trying to fabricate a way to have Windows run a chkdsk scan on boot if the volume comes up dirty (wasn't shutdown properly), but I'm having a rough time coming up with some solutions.  I've tracked down how to find the status of the dirty bit in event viewer and the command prompt, but I don't know what to do with the information from there.  If it helps, the computers are on a Server 2008 domain.

Thanks!
Avatar of RobSampson
RobSampson
Flag of Australia image

Hi, I haven't tested it, but this WMI code (VBScript) should execute a ChkDsk on the C Drive of a remote PC.

Regards,

Rob.

strComputer = "."
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set objDisk = objWMIService.Get("Win32_LogicalDisk.DeviceID='C'")
' This method should add an entry to the following key
'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\BootExecute
'The script will add
'autochk autochk /r \??\C:
errReturn = objDisk.ChkDsk(True, False, False, False, True, True)

Open in new window

following this article, you don't need to do anyything if the dirty flag is set :
http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/fsutil_dirty.mspx?mfr=true
Check disk will run automatically if the system HDD has bad sector and not cleanly shutdown.

http://support.microsoft.com/kb/152404

http://support.microsoft.com/kb/831426

One easy way to determine if a drive letter is marked as dirty and will require auto chkkdsk on boot is to run the command fsutil dirty query C:

http://www.raymond.cc/blog/disable-or-stop-auto-chkdsk-during-windows-startup/
Jaihunt - that's what my post just said...
Avatar of OAC Technology

ASKER

Thanks for all the input so far.

Is there any way to prohibit user action to stop that chkdsk on boot?  We have the feeling that our end-users keep skipping it when they turn their machines on in the morning and getting some kind of report (even if it's a .bat making a .txt in a network directory somewhere) that would be ideal.

Thanks again!
i would not do that; instead, run a diagnostic on the drive, to be sure if it is ok or not.
When Windows boots up and finds bad sectors, it will always run chkdsk

Hardware diagnostic CD    UBCD
 i suggest the UBCD  to run some diags first - to be sure about the basics
go to the download page, scroll down to the mirror section, and  click on a mirror to start the download
Download the UBCD and make the cd   <<==on a WORKING PC, and boot the problem PC from it
Here 2 links, one to the general site, and a direct link to the download

since the downloaded file is an ISO file, you need to use an ISO burning tool
if you don't have that software, install cdburnerXP : http://cdburnerxp.se/

If you want also the Ram tested - run memtest86+ at least 1 full pass,  - you should have NO errors!
 
For disk Diagnostics run the disk diag for your disk brand (eg seagate diag for seagate drive)  from the HDD section -  long or advanced diag !  (runs at least for30 minutes)

http://www.ultimatebootcd.com/                        ultimate boot cd
http://www.ultimatebootcd.com/download.html             download page
Sounds good!

What is also important here is remote monitoring of whether a computer hasn't shut down properly.  That's the last thing we need here and then we're set.

Thanks again!
If you want to check remotely, you can search the Application event log for events with a source of WININIT and an Event ID of 1001.  This will be the ChkDsk report, and will tell you whether the user cancelled it or not.

Regards

Rob.
Thanks, Rob!

Any way of checking for that event ID via a script of some kind?  I want to automate this as much as possible.
You can try this VBS code.  Save the code into GetChkDskEvents.vbs, and create a text file called "Systems.txt" that has some computer names in it.  Run the script, and then check Results.csv for any events it finds.

It will pull events that are written to the event log since 12am on the day you run it.

Regards,

Rob.

Const intForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objInputFile = objFSO.OpenTextFile("Systems.txt", intForReading, False)

strEventDetails = """Computer"",""Event Type"",""Event Source"",""Event Code"",""Event Message"",""Date and Time"""

strTimeBias = Get_CurrentTimeZone_Of_Computer(".")

' Get events only since midnight today
strDate = Year(Now) & Right("0" & Month(Now), 2) & Right("0" & Day(Now), 2) & "000000.000000" & "+" & strTimeBias

While Not objInputFile.AtEndOfStream
	strComputer = objInputFile.ReadLine
	boolPingResult = Ping(strComputer)
	If boolPingResult = True Then
		On Error Resume Next
		Set objWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
		If Err.Number = 0 Then
			On Error GoTo 0
		
			' Event Types: 1 = Error ; 2 = Warning ; 3 = Information ; 4 = Security audit success ; 5 = Security audit failure 
			Set colLoggedEvents = objWMI.ExecQuery _
			("SELECT EventType, SourceName, EventCode, Message, TimeWritten FROM Win32_NTLogEvent WHERE " &_
				"LogFile = 'Application' AND SourceName='Wininit' AND EventCode = 1001 AND TimeWritten >= '" & _
							strDate & "'", "WQL", _
		                                         wbemFlagReturnImmediately + wbemFlagForwardOnly)
		
			For Each objEvent in colLoggedEvents
				If Err.Number = 0 Then
					On Error GoTo 0
		
					strDate = Left(objEvent.TimeWritten,8)
					strDate = Right(strDate, 2) & "-" & Mid(strDate, 5, 2) & "-" & Left(strDate, 4)
					dteDate = CDate(strDate)
					strTime = Mid(objEvent.TimeWritten, 9, 6)
					strTime = Left(strTime, 2) & ":" & Mid(strTime, 3, 2) & ":" & Right(strTime, 2)
					dteTime = CDate(strTime)
		
					strEventType = objEvent.EventType
					Select Case strEventType
						Case 1
							strEventType = "Error"
						Case 2
							strEventType = "Warning"
						Case 3
							strEventType = "Information"
						Case 4
							strEventType = "Audit Success"
						Case 5
							strEventType = "Audit Failure"
						Case Else
							strEventType = "CODE " & objEvent.EventType & " = " & objEvent.Type
					End Select
					
					strEventDetails = strEventDetails & VbCrLf & """" & strComputer & """,""" & strEventType & """,""" & objEvent.SourceName & """,""" & objEvent.EventCode & """,""" & objEvent.Message & """,""" & dteDate & " " & dteTime & """"
				Else
					Err.Clear
					On Error GoTo 0
					strEventDetails = strEventDetails & VbCrLf & "Could not retrieve events from " & strComputer
				End If
				Exit For
			Next
		Else
			Err.Clear
			On Error GoTo 0
			strEventDetails = strEventDetails & VbCrLf & "Could not connect to " & strComputer
		End If
	Else
		strEventDetails = strEventDetails & VbCrLf & "Could not ping " & strComputer
	End If
Wend
objInputFile.Close
Set objInputFile = Nothing
Set objOutputFile = objFSO.CreateTextFile("Results.csv", True)
objOutputFile.Write strEventDetails
objOutputFile.Close
Set objOutputFile = Nothing

MsgBox "Done"

Function Ping(strComputer)
	Dim objShell, boolCode
	Set objShell = CreateObject("WScript.Shell")
	boolCode = objShell.Run("Ping -n 1 -w 300 " & strComputer, 0, True)
	If boolCode = 0 Then
		Ping = True
	Else
		Ping = False
	End If
End Function

Function Get_CurrentTimeZone_Of_Computer(byval strComputerName)

	Dim objWMIService, colLogFiles, objLogFile, intTotal, colItems, objItem, strCurrentTimeZone
	Const wbemFlagReturnImmediately = &h10
	Const wbemFlagForwardOnly = &h20
	Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
	        strComputerName & "\root\cimv2")			

	Set colItems = objWMIService.ExecQuery("Select CurrentTimeZone from Win32_OperatingSystem",,48)

	On Error Resume Next
	For Each objItem in colItems
		If Err.Number = 0 Then
			On Error GoTo 0
			strCurrentTimeZone = objItem.CurrentTimeZone
			Exit For
		Else
			MsgBox "Unknown Error during Time Bias for " & strComputer & "." & vbCrLf & "Error Number: " & _
				Err.Number & vbCrLf & "Error Description: " & Err.Description, vbOKOnly, "Unknown Error"
			Err.Clear
			On Error GoTo 0
			Exit For
		End If
	Next
	On Error GoTo 0

	Get_CurrentTimeZone_Of_Computer = strCurrentTimeZone
	
End Function

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of OAC Technology
OAC Technology
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
We decided that running the chkdsk once per week was enough, and we didn't want to interrupt users' work during the day.