Jump to content

SIC2 incl. SIC2GUI Updated 2011-11-23


UEZ
 Share

Recommended Posts

A demonstration how to use pseudo multi processing to speed up collection of information of remote systems:

Normally a script works sequentially, e.g. it checks one system by one. If a systems hangs then whole script hangs, too.

How about to speed up script by using multiple processes?

Let's see my solution for that!

This command line tool S(ystem)I(nformation)C(ollector)2 aka SIC2 is helpful for system admins which need to collect data from their systems in an easy and fast way.

SIC2 is a tool which can do that, particularly with ability of pseudo parallel multiple processes (multi threading).

It connects e.g. via WMI to local and/or remote systems to collect data (see options below).

Here the command line (use it in a CMD box):

Usage: SIC2.exe [-i "<system filename="" list="">"]

[-master -slaves <n>] for multiprocessing mode

[-ver] for version number

[-prio <0-3>] for process prio - standard is 0 (idle)

[<options>]

[-? | /? | -help | /help]] for this page

Options can be:

-os get only information about operating system

-rl get only information about role of system

-sv get only information about running services

If argument [-master -slaves <n>] is not given then sequential

mode will be used automatically!

Output will be written to folder Output where SIC2.exe was started.

Output format is a semicolon separated text file (*.csv).

On each run output files will be overwritten!

<system filename="" list=""> is a text file with the names of the systems in each line.

An example of the command line could be: SIC2.exe -i serverlist.txt -master -slaves 15 -os -rl -sv -prio 1

This will run SIC2.exe which will create 15 sub processes (slaves) which are connecting to the systems given in serverlist.txt.

Of course it makes no sense to select 15 slaves when the list contains less systems!

Currently only 3 modules are implemented. Feel free to upgrade it with more options. See below for a version with more modules!

Benchmark on a terminal server with only 4 users, with gigabit network and SIC2.exe in idle priority:

152 systems, only LAN connection, no WAN.

post-29844-1223671890_thumb.png

WAN benchmark will follow hopefully.

I hope this is tool is helpful for you! But have in mind that this project is still in beta phase and thus maybe buggy!

Some parts also adjusted to my needs and will give no results probably on your systems.

Here the code (early stage with 3 modules only):

#AutoIt3Wrapper_UseX64=n
#AutoIt3Wrapper_Change2CUI=y
#AutoIt3Wrapper_Res_Description=System Information Collector
#AutoIt3Wrapper_Res_Fileversion=2.0.0.0
#AutoIt3Wrapper_Res_Language=1033
#AutoIt3Wrapper_res_requestedExecutionLevel=requireAdministrator
://////=__=
#AutoIt3Wrapper_Run_Obfuscator=n
#AutoIt3Wrapper_Res_SaveSource=n
#AutoIt3Wrapper_UseUpx=n
#AutoIt3Wrapper_Run_After=upx.exe --best --compress-resources=1 "%out%"

#include <array.au3>
#include <date.au3>
#NoTrayIcon
Opt('MustDeclareVars', 1)
Opt("TrayIconHide", 1)
TraySetState(2)

Const $ver = "v2.0"
Const $build = "beta 2008-10-13"
Const $coder = "UEZ"
Const $appname = "SIC2.exe"
If @ScriptName <> $appname Then ;force the scriptname to be SIC2.exe
    FileMove(@ScriptName, @ScriptDir & "" & $appname, 0)
    If @error = 0 Then
        ConsoleWrite(@CRLF & "Error renaming " & @ScriptName & " to SIC2.exe. Terminating..." & @CRLF & @CRLF)
        Exit
    EndIf
EndIf
Global $master, $slaves_threshold, $slaves, $slave
Global $yy, $end, $parameters, $cs, $pid_sum, $errors, $list_end
Global $filepath, $hFile, $aFile
Global $os, $rl, $sv, $system, $timer, $kill_threshold, $prio
Global $colItems, $colItems2, $objItem, $objReg, $objWMIService, $objWMILocator
Global $path = @ScriptDir & "Output"
Dim $ServerArray_tmp[1], $ServerArray[1]

$slaves_threshold = 100 ;max. threads to be created at once
$list_end = False

If $CmdLine[0] = 0 Then Help() ;if no parameter is given call help
Check_CMD_Parameter() ;check paramters

If $master = 1 Then ;if master is set then prepare for master function call
    Build_List()
    Dim $PIDs[$slaves] ;create $PIDs array to save PID of each process
    $yy = 0
    For $yy = 0 To UBound($PIDs) - 1 ;set all PIDs to 0
        $PIDs[$yy] = 0
    Next
EndIf

If $slaves > UBound($ServerArray) Then ;check whether n parameter is more than amount of systems
    ConsoleWrite("Error: more slaves (" & $slaves & ") selected then amount of system(s) (" & UBound($ServerArray) & ") is available!" & @CRLF & @CRLF)
    If UBound($ServerArray) = 1 Then
        $master = 0
        $slave = 0
        ConsoleWrite("But found only 1 system. ")
    Else
        Exit
    EndIf
EndIf

If $master = 1 And $slaves > 1 Then ;if parameter is master then call master function
    ConsoleWrite(@CRLF & "Starting parallel runs!" & @CRLF & @CRLF)
    Master()
ElseIf $master = 0 And $slave = 1 Then ;if parameter is slave then call slave function. Slave function can only be called by master
    Slave()
Else ;start sequential run
    ConsoleWrite(@CRLF & "Starting sequential run!" & @CRLF & @CRLF)
    Sequential_Run()
EndIf

Exit

Func Master() ;master function controll multi threading processes
    Local $x
    Local $EndTime, $dsec, $dhr, $dmin
    Local $StartTime = _NowCalc()
    Local $t = Round(LN($slaves) * 1000, 0)
    $end = UBound($ServerArray) - 1 ;set end of operation to end of server list
    $kill_threshold = 60 ;when all systems has been started wait for process to kill in seconds
    $cs = 0
    Do
        Create_PIDs() ;create processes regarding slaves parameter
        Sleep($t)
        Check_PIDs() ;check whether process is still existing
        ConsoleWrite($cs & "/" & UBound($ServerArray) & " (" & Round($cs / UBound($ServerArray) * 100, 2) & "% / " & _DateDiff('s', $StartTime, _NowCalc()) & " s) system(s) processed. " & @CR)
    Until $pid_sum = 0 ;if PID sum = 0 then all opened processes are closed
    Cleanup_Files()
    $EndTime = _NowCalc()
    $dsec = _DateDiff('s', $StartTime, $EndTime)
    $dmin = Round($dsec / 60, 2)
    $dhr = Round($dsec / 60 / 60, 2)
    ConsoleWrite(@CRLF & @CRLF & @CRLF & "Runtime: " & $dsec & " seconds (" & $dmin & "min / " & $dhr & "h) " & @CRLF & @CRLF)
EndFunc   ;==>Master

Func Slave() ;slave function calls the sub functions depending on given parameters
    Local $function_name = "WMI general connection", $TimeStamp, $err
    Local $filename_error_current = $function_name & "_" & $system & "_error.log"
    Ping($system)
    If @error = 0 Then
        ProcessSetPriority(@AutoItPID, $prio) ;set process for sequential run to idle
        ;http://msdn2.microsoft.com/en-us/library/aa393720.aspx or [url="http://msdn2.microsoft.com/en-us/library/a...257%28VS.85%29.aspx"]http://msdn2.microsoft.com/en-us/library/a...257(VS.85).aspx[/url]
        ;$objWMILocator.ConnectServer(strServer = ".", strNamespace = "", strUser = "", strPassword = "", strLocale = "", strAuthority = "", iSecurityFlags = 0, objwbemNamedValueSet = 0)
        $function_name = "WMI general connection"
        $objWMIService = ObjGet("winmgmts:{impersonationLevel=impersonate}!" & $system & "rootcimv2")
        $err = @error
        If $err = 0 Then
            If $os = 1 Then OS($system)
            If $rl = 1 Then Role($system)
            If $sv = 1 Then Services($system)
        Else
            $TimeStamp = @MDAY & "." & @MON & "." & @YEAR & ";" & @HOUR & ":" & @MIN & ":" & @SEC
            FileWriteLine($path & $filename_error_current, $system & ";" & $TimeStamp & ";" & $appname & ";WMI;Error;WMI error " & $err & " on server & " & $system & ";0;")
        EndIf
    Else
        $TimeStamp = @MDAY & "." & @MON & "." & @YEAR & ";" & @HOUR & ":" & @MIN & ":" & @SEC
        FileWriteLine($path & $filename_error_current, $system & ";" & $TimeStamp & ";" & $appname & ";Unreachable;Error;Cannot ping system " & $system & ";0;")
    EndIf
EndFunc   ;==>Slave

Func Sequential_Run() ;starts getting information from systems one by one
    Local $function_name = "WMI general connection", $TimeStamp
    Local $filename_error_current
    Local $i, $err
    Local $EndTime, $dsec, $dhr, $dmin
    Local $StartTime = _NowCalc()
    Local $end = UBound($ServerArray) - 1
    Local $chk_seq_run
    $chk_seq_run = Run($appname & " -chk_seq_run -pid " & @AutoItPID, "", @SW_HIDE) ;run sub process which checks current process whether it still runs after x seconds -> see function Chk_Seq_Run
    ProcessSetPriority(@AutoItPID, $prio) ;set current process to idle
    $slave = 0
    For $i = 0 To $end
        $system = $ServerArray[$i]
        Ping($system) ;check system whether it is reachable via ping
        If @error = 0 Then
            $filename_error_current = $function_name & "_" & $system & "_error.log"
            $function_name = "WMI general connection"
            $objWMIService = ObjGet("winmgmts:{impersonationLevel=impersonate}!" & $system & "rootcimv2")
            $err = @error
            If $err = 0 Then
                If $os = 1 Then OS($system)
                If $rl = 1 Then Role($system)
                If $sv = 1 Then Services($system)
            Else
                $TimeStamp = @MDAY & "." & @MON & "." & @YEAR & ";" & @HOUR & ":" & @MIN & ":" & @SEC
                FileWriteLine($path & "Errors.csv", $system & ";" & $TimeStamp & ";" & $appname & ";WMI;Error;WMI error " & $err & " on server & " & $system & ";0;")
            EndIf
        Else
            $TimeStamp = @MDAY & "." & @MON & "." & @YEAR & ";" & @HOUR & ":" & @MIN & ":" & @SEC
            FileWriteLine($path & "Errors.csv", $system & ";" & $TimeStamp & ";" & $appname & ";Unreachable;Error;Cannot ping system " & $system & ";0;")
        EndIf
        ConsoleWrite($i + 1 & "/" & ($end + 1) & " (" & Round(($i + 1) / ($end + 1) * 100, 2) & "% / " & _DateDiff('s', $StartTime, _NowCalc()) & " s) system(s) processed: " & $system & " " & @CR) ;output status
    Next
    If ProcessExists($chk_seq_run) Then ProcessClose($chk_seq_run); close sub process if exits
    $EndTime = _NowCalc()
    $dsec = _DateDiff('s', $StartTime, $EndTime)
    $dmin = Round($dsec / 60, 2)
    $dhr = Round($dsec / 60 / 60, 2)
    ConsoleWrite(@CRLF & @CRLF & @CRLF & "Runtime: " & $dsec & " seconds (" & $dmin & "min / " & $dhr & "h) " & @CRLF & @CRLF)
    Exit
EndFunc   ;==>Sequential_Run

Func Chk_Seq_Run($pid) ;started by Sequentiell Run to check whether sequentiell run hangs
    Sleep(1000 * 60 * 60 * 3) ;should wait 3h until SIC2 will be terminated by this sub process
    If ProcessExists($pid) Then
        ConsoleWrite(@CRLF & $appname & " probably hangs! Terminating process (PID): " & $pid & " !!!" & @CRLF)
        ProcessClose($pid)
    EndIf
    Exit
EndFunc   ;==>Chk_Seq_Run

Func Create_PIDs() ;created new processes
    Local $i
    If $list_end = False Then ;do not create any new process when system list end has been reached
        For $i = 0 To (UBound($PIDs) - 1) ;check PIDs array whether value is 0
            If $PIDs[$i] = 0 And $cs <= $end Then ;found process slot to start another instance of program saving PID
                $PIDs[$i] = Run($appname & $parameters & " -prio " & $prio & " -slave -system " & $ServerArray[$cs], "", @SW_HIDE) ;call program with -slave parameter
                ProcessSetPriority($PIDs[$i], $prio) ;set the priority of process to default (idle) (0=idle, 1=below normal, 2=normal, 3=above normal, 4=high, 5=realtime)
                ;ConsoleWrite($cs & ")" & " PID " & $PIDs[$i] & ": " & $appname & $parameters & " -system " & $ServerArray[$cs] & " -slave created" & @CRLF) ;debug info
                $cs += 1 ;increase $cs -> system list pointer (get next system name from array)
                ;Sleep(100)
            EndIf
        Next
        If $cs = UBound($ServerArray) Then
            $list_end = True
            $timer = _NowCalc()
        EndIf
    EndIf
EndFunc   ;==>Create_PIDs

Func Check_PIDs() ;checks whether created PIDs still exist
    Local $j
    $pid_sum = 0
    For $j = 0 To (UBound($PIDs) - 1) ;check PIDs array
        $pid_sum += $PIDs[$j] ;sum all PID numbers
        If ProcessExists($PIDs[$j]) = 0 Then ;if PID doesn't exist anymore then set array to 0 to mark that slot is free for next program call
            ;If $PIDs[$j] > 0 Then ConsoleWrite("PID: " & $PIDs[$j] & " was closed." & @CRLF) ;debug info
            $PIDs[$j] = 0 ;if PID doesn't exist then set Array[$j] = 0
        EndIf
        If $list_end And _DateDiff('s', $timer, _NowCalc()) >= $kill_threshold And $PIDs[$j] <> 0 Then ;when server list end has been reached then check for processes that are still running and kill them
            ConsoleWrite("Process time exceeded - killing PID " & $PIDs[$j] & "! " & @CRLF & @CRLF)
            ProcessClose($PIDs[$j]) ;kill process which is running more than 300 seconds
            $PIDs[$j] = 0 ;set array = 0 to get master process terminated.
        EndIf
    Next
EndFunc   ;==>Check_PIDs

Func LN($x)
    Local $y
    Local $e = 2.71828182845904523536
    $y = Log($x) / Log($e)
    Return $y
EndFunc   ;==>LN


Func Check_CMD_Parameter()
    Local $x
    $master = 0
    $slave = 0
    $slaves = 0
    $os = 0
    $rl = 0
    $sv = 0
    $prio = 0
    $parameters = ""

    If StringLower($CmdLine[1]) = StringLower("-?") Or StringLower($CmdLine[1]) = StringLower("/?") Or StringLower($CmdLine[1]) = StringLower("/help") Or StringLower($CmdLine[1]) = StringLower("-help") Then
        Help()
    EndIf

    If StringLower($CmdLine[1]) = StringLower("-chk_seq_run") And StringLower($CmdLine[2]) = StringLower("-pid") Then
        Chk_Seq_Run($CmdLine[3])
    EndIf

    For $x = 1 To $CmdLine[0]
        If StringLower($CmdLine[$x]) = StringLower("-ver") Then Prog_Ver()
        If StringLower($CmdLine[$x]) = StringLower("-os") Then
            $os = 1
            $parameters &= " -os"
        EndIf
        If StringLower($CmdLine[$x]) = StringLower("-rl") Then
            $rl = 1
            $parameters &= " -rl"
        EndIf
        If StringLower($CmdLine[$x]) = StringLower("-sv") Then
            $sv = 1
            $parameters &= " -sv"
        EndIf
        If StringLower($CmdLine[$x]) = StringLower("-system") Then
            $system = Find_Next_Parameter($x + 1)
        EndIf

        If StringLower($CmdLine[$x]) = StringLower("-master") Then $master = 1
        If StringLower($CmdLine[$x]) = StringLower("-i") Then ;get input parameter to read in system names
            $filepath = Find_Next_Parameter($x + 1)
        EndIf
        If StringLower($CmdLine[$x]) = StringLower("-slaves") Then ;get amount of slaves
            $slaves = Find_Next_Parameter($x + 1)
            If StringIsInt($slaves) = 0 Then
                ConsoleWrite(@CRLF & "Argument for -slaves parameter is not integer!" & @CRLF & @CRLF)
                Exit
            EndIf
            $slave = 1
        EndIf
        If StringLower($CmdLine[$x]) = StringLower("-slave") Then ;only for master call (internal)
            $slave = 1
        EndIf
        If StringLower($CmdLine[$x]) = StringLower("-prio") Then ;get input parameter
            $prio = Find_Next_Parameter($x + 1)
        EndIf
    Next

    If $prio < 0 Or $prio > 3 Then $prio = 0 ;set prio to default (idle) if value is not between 0 and 3

    If $os + $rl + $sv = 0 Then
        ConsoleWrite(@CRLF & "At least one argument is missing!" & @CRLF & @CRLF)
        Exit
    EndIf

    If $master = 1 And $slave = 0 Then
        ConsoleWrite(@CRLF & "Argument -slaves <n> is missing!" & @CRLF & @CRLF)
        Exit
    EndIf

    If $slaves > $slaves_threshold Then
        ConsoleWrite(@CRLF & "<n> from parameter -slaves <n> is over threshold (" & $slaves_threshold & ")!" & @CRLF & @CRLF)
        Exit
    EndIf

    If $master = 1 Then
        If $slaves < 1 Then
            ConsoleWrite(@CRLF & "Parameter -slaves < 1 makes no sense!" & @CRLF & @CRLF)
            Exit
        EndIf
    EndIf

EndFunc   ;==>Check_CMD_Parameter

Func Find_Next_Parameter($StartIndex)
    Local $z, $parameter
    $parameter = ""
    For $z = $StartIndex To $CmdLine[0]
        If StringLeft($CmdLine[$z], 1) <> "-" Then
            If $z = $CmdLine[0] Then
                $parameter = $parameter & $CmdLine[$z]
            Else
                $parameter = $parameter & $CmdLine[$z] & " "
            EndIf
        Else
            ExitLoop
        EndIf
    Next
    ;If StringRight ($parameter, 1) = " " Then $parameter = StringTrimRight ($parameter, 1)
    Return StringStripWS($parameter, 8)
EndFunc   ;==>Find_Next_Parameter

Func Help()
    ConsoleWrite(@CRLF & @CRLF)
    ConsoleWrite("Usage: " & $appname & @TAB & _
            "[-i ""<system filename="" list="">""]" & @CRLF & @TAB & @TAB & _
            "[-master -slaves <n>] for multiprocessing mode" & @CRLF & @TAB & @TAB & _
            "[-ver] for version number" & @CRLF & @TAB & @TAB & _
            "[-prio <0-3>] for process prio - standard is 0 (idle)" & @CRLF & @TAB & @TAB & _
            "[<options>]" & @CRLF & @TAB & @TAB & _
            "[-? | /? | -help | /help]] for this page" & @CRLF & @CRLF)
    ConsoleWrite("Options can be:" & @CRLF & @CRLF)
    ConsoleWrite(@TAB & "-os get only information about operating system" & @CRLF)
    ConsoleWrite(@TAB & "-rl get only information about role of system" & @CRLF)
    ConsoleWrite(@TAB & "-sv get only information about running services" & @CRLF & @CRLF)
    ConsoleWrite("If argument [-master -slaves <n>] is not given then sequentiell" & @CRLF & "mode will be used automatically!" & @CRLF & @CRLF)
    ConsoleWrite("Output will be written to folder Output where " & $appname & " was started." & @CRLF)
    ConsoleWrite("Output format is a semicolon separeted text file (*.csv)." & @CRLF & @CRLF)
    ConsoleWrite("On each run output files will be overwritten!" & @CRLF & @CRLF)
    Exit
EndFunc   ;==>Help

Func Prog_Ver()
    ConsoleWrite(@CRLF & @CRLF & $appname & " " & $ver & " build " & $build & " by " & $coder & "." & @CRLF & @CRLF)
    ConsoleWrite($appname & " stands for S(ystem) I(nformation) C(ollector)." & @CRLF & @CRLF & @CRLF)
    Exit
EndFunc   ;==>Prog_Ver

Func WMIDateStringToDate($dtmDate)
    Return (StringMid($dtmDate, 7, 2) & "." & _
            StringMid($dtmDate, 5, 2) & "." & StringLeft($dtmDate, 4)); _
    ;& " " & StringMid($dtmDate, 9, 2) & ":" & StringMid($dtmDate, 11, 2) & ":" & StringMid($dtmDate, 13, 2))
EndFunc   ;==>WMIDateStringToDate


Func Build_List()
    If FileExists($filepath) = 0 Then
        ConsoleWrite(@CRLF & "Unable to open file: " & $filepath & " !!!" & @CRLF & @CRLF)
        Exit
    EndIf
    ;_FileReadToArray function taken from File.au3 include
    $hFile = FileOpen($filepath, 0) ;open system list
    $aFile = FileRead($hFile, FileGetSize($filepath)) ;read system list to variable
    FileClose($hFile)
    If StringInStr($aFile, @LF) Then ;delete line feed and carriage return characters from string and write it to a temp array
        $ServerArray_tmp = StringSplit(StringStripCR($aFile), @LF)
    ElseIf StringInStr($aFile, @CR) Then ;; @LF does not exist so split on the @CR
        $ServerArray_tmp = StringSplit($aFile, @CR)
    Else ;; unable to split the file
        $ServerArray_tmp[0] = $aFile
    EndIf
    If @error > 0 Then ;terminate program on error
        ConsoleWrite(@CRLF & @CRLF & "Internal error (" & @error & ")! Aborting..." & @CRLF & @CRLF & @CRLF)
        Exit
    EndIf

    If UBound($ServerArray_tmp) - 1 > 0 Then
        $yy = 0
        For $x = 1 To UBound($ServerArray_tmp) - 1 ;cleanup system list - only accept non empty lines
            If $ServerArray_tmp[$x] <> "" And StringIsASCII($ServerArray_tmp[$x]) = 1 Then ;save only ASCII and non empty strings
                ReDim $ServerArray[$yy + 1]
                $ServerArray[$yy] = $ServerArray_tmp[$x]
                $yy += 1
            EndIf
        Next
    Else
        ReDim $ServerArray[1]
        $ServerArray[0] = $ServerArray_tmp[0]
    EndIf
    If FileExists($path & "OS.csv") Then FileDelete($path & "OS.csv")
    FileOpen($path & "OS.csv", 1 + 8)
    FileWrite($path & "OS.csv", "Systemname;OS Version;Service Pack Version;Bit;OS Install Date;EDS GoldDisk version" & @CRLF)

    If FileExists($path & "Role.csv") Then FileDelete($path & "Role.csv")
    FileOpen($path & "Role.csv", 1 + 8)
    FileWrite($path & "Role.csv", "Systemname;Domain;Domain Role;System Startup Options" & @CRLF)

    If FileExists($path & "Services.csv") Then FileDelete($path & "Services.csv")
    FileOpen($path & "Services.csv", 1 + 8)
    FileWrite($path & "Services.csv", "Systemname;Caption;Name;Start Mode;State;Starter Name" & @CRLF)

    If FileExists($path & "Errors.csv") Then FileDelete($path & "Errors.csv")
    FileOpen($path & "Errors.csv", 1 + 8)
    FileWrite($path & "Errors.csv", "Systemname;Date;Time;Application Name;Error Source;Error Level;Error Code" & @CRLF)
EndFunc   ;==>Build_List


Func OS($srv)
    Local $array, $os_info
    Local $function_name = "OS"
    Local $OS_OperatingSystemVer, $OS_OperatingSystemSP, $OS_InstallationDate, $OS_OSArch, $OS_WinDir
    Local $HKLM, $BaseKey, $objReg, $OS_GoldDisk_Ver, $Key, $arrSubKeys, $SubKey
    Local $filename_error_current, $TimeStamp
    Local $filename_o = $function_name & "_" & $srv
    Local $filename_error_current = $function_name & "_" & $srv & "_error.log"
    $HKLM = 0x80000002
    $BaseKey = "SOFTWAREMicrosoftWindows NTCurrentVersionWinlogon"
    $objReg = ObjGet("winmgmts:{impersonationLevel=impersonate}!" & $srv & "rootdefault:StdRegProv")

    If IsObj($objReg) Then
        ;$objReg.EnumKey ($HKLM, $BaseKey, $arrSubKeys)
        $OS_GoldDisk_Ver = ""
        $objReg.GetStringValue($HKLM, $BaseKey, "GoldDiskVersion", $OS_GoldDisk_Ver)
    Else
        $TimeStamp = @MDAY & "." & @MON & "." & @YEAR & ";" & @HOUR & ":" & @MIN & ":" & @SEC
        If $slave = 1 Then
            FileWriteLine($path & $filename_error_current, $srv & ";" & $TimeStamp & ";" & $appname & ";WMI;Error;No WMI objects found for class StdRegProv on system " & $srv & ";0;")
        Else
            FileWriteLine($path & "Errors.csv", $srv & ";" & $TimeStamp & ";" & $appname & ";WMI;Error;No WMI objects found for class StdRegProv on system " & $srv & ";0;")
        EndIf
    EndIf

    $colItems = $objWMIService.ExecQuery("SELECT Name, CSDVersion, InstallDate From Win32_OperatingSystem", "WQL", 0x30)
    $colItems2 = $objWMIService.ExecQuery("SELECT AddressWidth From Win32_Processor", "WQL", 0x30)

    If IsObj($colItems2) Then
        For $objItem In $colItems2
            $OS_OSArch = $objItem.AddressWidth & "-bit"
        Next
    Else
        $TimeStamp = @MDAY & "." & @MON & "." & @YEAR & ";" & @HOUR & ":" & @MIN & ":" & @SEC
        If $slave = 1 Then
            FileWriteLine($path & $filename_error_current, $srv & ";" & $TimeStamp & ";" & $appname & ";WMI;Error;No WMI objects found for class Win32_Processor on system " & $srv & ";0;")
        ElseIf $slave = 0 Then
            FileWriteLine($path & "Errors.csv", $srv & ";" & $TimeStamp & ";" & $appname & ";WMI;Error;No WMI objects found for class Win32_Processor on system " & $srv & ";0;")
        EndIf
    EndIf

    If IsObj($colItems) Then
        For $objItem In $colItems
            $array = StringSplit($objItem.Name, "|", 1)
            $OS_OperatingSystemVer = $array[1]
            $OS_OperatingSystemSP = $objItem.CSDVersion
            $OS_InstallationDate = WMIDateStringToDate($objItem.InstallDate)
        Next
        $os_info = $srv & ";" & $OS_OperatingSystemVer & ";" & $OS_OperatingSystemSP & ";" & $OS_OSArch & ";" & $OS_InstallationDate & ";" & $OS_GoldDisk_Ver & ";"
        If $slave = 1 Then
            FileWriteLine($path & $filename_o & ".os", $os_info & @CRLF)
        ElseIf $slave = 0 Then
            FileWriteLine($path & "OS.csv", $os_info & @CRLF)
        EndIf
    Else
        $TimeStamp = @MDAY & "." & @MON & "." & @YEAR & ";" & @HOUR & ":" & @MIN & ":" & @SEC
        If $slave = 1 Then
            FileWriteLine($path & $filename_error_current, $srv & ";" & $TimeStamp & ";" & $appname & ";WMI;Error;No WMI objects found for class Win32_OperatingSystem on system " & $srv & ";0;")
        ElseIf $slave = 0 Then
            FileWriteLine($path & "Errors.csv", $srv & ";" & $TimeStamp & ";" & $appname & ";WMI;Error;No WMI objects found for class Win32_OperatingSystem on system " & $srv & ";0;")
        EndIf
    EndIf
EndFunc   ;==>OS

Func Role($srv)
    Local $x, $filename_r, $filename_error_current, $TimeStamp, $function_name
    Local $Role_Domain, $Role_DomainRole, $Role_SystemStartupOptions, $Role
    $function_name = "Role"
    $filename_r = $function_name & "_" & $srv
    $filename_error_current = $function_name & "_" & $srv & "_error.log"
    $colItems = $objWMIService.ExecQuery("Select Domain, DomainRole, SystemStartupOptions from Win32_ComputerSystem", "WQL", 0x30)
    If IsObj($colItems) Then
        For $objItem In $colItems
            $Role_DomainRole = $objItem.DomainRole
            $Role_Domain = $objItem.Domain
            Select
                Case $Role_DomainRole = 0
                    $Role_DomainRole = "Standalone Workstation"
                Case $Role_DomainRole = 1
                    $Role_DomainRole = "Member Workstation"
                Case $Role_DomainRole = 2
                    $Role_DomainRole = "Standalone Server"
                Case $Role_DomainRole = 3
                    $Role_DomainRole = "Member Server"
                Case $Role_DomainRole = 4
                    $Role_DomainRole = "Backup Domain Controller"
                Case $Role_DomainRole = 5
                    $Role_DomainRole = "Primary Domain Controller"
            EndSelect
            For $x = 0 To UBound($objItem.SystemStartupOptions) - 1
                $Role_SystemStartupOptions &= $objItem.SystemStartupOptions($x) & ", "
            Next
        Next
        $Role = $srv & ";" & $Role_Domain & ";" & $Role_DomainRole & ";" & $Role_SystemStartupOptions & ";"
        If $slave = 1 Then
            FileWriteLine($path & $filename_r & ".rl", $Role)
        ElseIf $slave = 0 Then
            FileWriteLine($path & "Role.csv", $Role)
        EndIf
    Else
        $TimeStamp = @MDAY & "." & @MON & "." & @YEAR & ";" & @HOUR & ":" & @MIN & ":" & @SEC
        If $slave = 1 Then
            FileWriteLine($path & $filename_error_current, $srv & ";" & $TimeStamp & ";" & $appname & ";WMI;Error;No WMI objects found for class Win32_ComputerSystem on system " & $srv & ";0;")
        ElseIf $slave = 0 Then
            FileWriteLine($path & "Errors.csv", $srv & ";" & $TimeStamp & ";" & $appname & ";WMI;Error;No WMI objects found for class Win32_ComputerSystem on system " & $srv & ";0;")
        EndIf
    EndIf
EndFunc   ;==>Role

Func Services($srv)
    Local $function_name = "Services"
    Local $filename_error_current, $TimeStamp, $function_name
    Local $tmp
    Local $Service, $Service_Caption, $Service_Description, $Service_Name, $Service_StartMode, $Service_StartName, $Service_State, $Service_Status
    Local $filename_sv = $function_name & "_" & $srv
    $filename_error_current = $function_name & "_" & $srv & "_error.log"
    $colItems = $objWMIService.ExecQuery("Select Caption, Description, Name, StartMode, StartName, State, Status from Win32_Service", "WQL", 0x30)
    If IsObj($colItems) Then
        For $objItem In $colItems
            $Service_Caption = $objItem.Caption
            $Service_Name = $objItem.Name
            $Service_StartMode = $objItem.StartMode
            $Service_StartName = $objItem.StartName
            $Service_State = $objItem.State
            $Service &= $srv & ";" & $Service_Caption & ";" & $Service_Name & ";" & $Service_StartMode & ";" & $Service_State & ";" & $Service_StartName & ";" & @CRLF
        Next
        If $slave = 1 Then
            FileWriteLine($path & $filename_sv & ".sv", $Service)
        ElseIf $slave = 0 Then
            FileWriteLine($path & "Services.csv", $Service)
        EndIf
    Else
        $TimeStamp = @MDAY & "." & @MON & "." & @YEAR & ";" & @HOUR & ":" & @MIN & ":" & @SEC
        If $slave = 1 Then
            FileWriteLine($path & $filename_error_current, $srv & ";" & $TimeStamp & ";" & $appname & ";WMI;Error;No WMI objects found for class Win32_Service on system " & $srv & ";0;")
        ElseIf $slave = 0 Then
            FileWriteLine($path & "Errors.csv", $srv & ";" & $TimeStamp & ";" & $appname & ";WMI;Error;No WMI objects found for class Win32_Service on system " & $srv & ";0;")
        EndIf
    EndIf
EndFunc   ;==>Services

Func Cleanup_Files() ;merge files which were created with master / slave parameter call
    Dim $arr_role[1], $arr_os[1], $arr_services[1], $arr_error_logs[1]
    Local $search_os, $search_role, $search_services, $search_error_logs, $x, $path, $content
    $path = @ScriptDir & "Output"
    $search_role = FileFindFirstFile($path & "Role_*.rl")
    $search_os = FileFindFirstFile($path & "OS_*.os")
    $search_services = FileFindFirstFile($path & "Services_*.sv")
    $search_error_logs = FileFindFirstFile($path & "*_error.log")

    $x = 0
    FileFindFirstFile($search_os)
    While 1
        ReDim $arr_os[$x + 1]
        $arr_os[$x] = FileFindNextFile($search_os)
        If @error Then ExitLoop
        $x += 1
    WEnd
    FileClose($search_os)

    $x = 0
    FileFindFirstFile($search_role)
    While 1
        ReDim $arr_role[$x + 1]
        $arr_role[$x] = FileFindNextFile($search_role)
        If @error Then ExitLoop
        $x += 1
    WEnd
    FileClose($search_role)

    $x = 0
    FileFindFirstFile($search_services)
    While 1
        ReDim $arr_services[$x + 1]
        $arr_services[$x] = FileFindNextFile($search_services)
        If @error Then ExitLoop
        $x += 1
    WEnd
    FileClose($search_services)

    $x = 0
    FileFindFirstFile($search_error_logs)
    While 1
        ReDim $arr_error_logs[$x + 1]
        $arr_error_logs[$x] = FileFindNextFile($search_error_logs)
        If @error Then ExitLoop
        $x += 1
    WEnd
    FileClose($search_error_logs)

    For $x = 0 To UBound($arr_os) - 1
        $content = FileRead($path & $arr_os[$x])
        If @error = 0 Then
            If $content <> "" Then
                FileWrite($path & "OS.csv", $content)
                FileDelete($path & $arr_os[$x])
            EndIf
        EndIf
    Next
    FileClose($path & "OS.csv")

    For $x = 0 To UBound($arr_role) - 1
        $content = FileRead($path & $arr_role[$x])
        If @error = 0 Then
            If $content <> "" Then
                FileWrite($path & "Role.csv", $content)
                FileDelete($path & $arr_role[$x])
            EndIf
        EndIf
    Next
    FileClose($path & "Role.csv")

    For $x = 0 To UBound($arr_services) - 1
        $content = FileRead($path & $arr_services[$x])
        If @error = 0 Then
            If $content <> "" Then
                FileWrite($path & "Services.csv", $content)
                FileDelete($path & $arr_services[$x])
            EndIf
        EndIf
    Next
    FileClose($path & "Services.csv")

    For $x = 0 To UBound($arr_error_logs) - 1
        $content = FileRead($path & $arr_error_logs[$x])
        If @error = 0 Then
            If $content <> "" Then
                FileWrite($path & "Errors.csv", $content)
                FileDelete($path & $arr_error_logs[$x])
            EndIf
        EndIf
    Next
    FileClose($path & "Errors.csv")
EndFunc   ;==>Cleanup_Files


New Version Below:

You can download source + compiled exes (22 modules) here: SIC2.exe + SIC2.au3 + SIC2GUI.exe

Source code of full version (22 modules) here (build 2012-02-24 beta): SIC2_Src.7z (149 downloads of previous versions)

Use e.g. 7-Zip to extract archive.

SIC2.txt Commandline Parameters:

SIC2 v2.0 build 2010-06-08 beta by UEZ.

Usage: SIC2 <-i (system list filename)>
        [-master] for multi processing mode
        [-slaves <n>] can only be used with -master parameter.
    Default is 20.
        [-prio <0-3>] for process prio - standard is 0 (idle)
        [-silent] no output to CMD
        [-no_folder] doesn't create the output folder.
        [-zip] move Run_YYYY-MM-DD_HHMMSS folder to ZIP archive
        [-shuffle] shuffels system list
        <options> see below!
        [-ver] for version number
        [-? | /? | -help | /help]] for this page

Options can be (at least one option below must be set):

    -all activate all options below
    -di get only information about domain
    -dp get only information about disk partitions
    -el get only information about eventlog
    -ee [d] [id] get only information about eventlog system errors-> slow
    -hd get only information about harddisk
    -hw get only information about hardware
    -ls get only information about local shares
    -lu get only information about local user accounts
    -ms get only information about membership of local administrators group
    -nw get only information about network settings
    -od get only information about optical drive
    -os get only information about operating system
    -pc get only information about patches
    -pf get only information about pagefile
    -ph get only information about PnP hardware problem
    -pt get only information about printer
    -rl get only information about role of system
    -rt get only information about persistent IP4 routing table
    -sv get only information about services
    -sw get only information about installed software
    -tz get only information about timezone
    -vc get only information about video controller

If you set only -ee then all errors of last 7 days will be enumerated!
Otherwise set parameter [d] for days and [id] for event id.

If argument [-master -slaves <n>] is not given then sequential
mode will be used automatically!

Each slave process takes around 6 MB of memory!

System list file for parameter -i may contain only one name or ip address
in each line of the appropriate system.

Output will be written to folder Output where SIC2.exe was started and to a
separate folder named Run_YYYY-MM-DD_HHMMSS.

Output format is a semicolon separeted text file (*.csv) in Ouput's subfolder.


Prio parameter can be from 0-3: Idle, Below Normal, Normal and Above Normal



Examples:

Parallel run:
SIC2.exe -i list.txt -all -zip -master -slaves 25
SIC2.exe -i list.txt -os -nw -hw -master -slaves 15
SIC2.exe -i list.txt -ee 5 7000 -di -sw -od -master -prio 1

Sequential run:
SIC2.exe -i list.txt -all
SIC2.exe -i list.txt -el -pc -tz -ms -od -rt -zip
SIC2.exe -i list.txt -ee 7 -sw -prio 2

If I have more time I will code a GUI for SIC2 because without a GUI many people will not use it!

-> Done! SIC2 GUI download here: SIC2_GUI.7z (10 downloads of previous versions)

Please post any criticism, if you like it or not!

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Sorry, a lot of stupid bugs posted. :P

Above the version with less bugs and post renewed!

UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

  • 1 month later...

I discovered coincidentally that also TrendMicro has a tool with the name SIC. :)

Should I rename my tools, in order to avoid legal problems? :)

Did someone already make such experiences?

Thanks,

UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

  • 2 years later...

Wow, after nearly 3 years a reply! :D

How did you run it? In the CMD line or via the GUI? Is there a Errors.csv file in the output folder? If yes, what is the content?

I need more information otherwise I cannot say what might be wrong!

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Yes, because i'm looking for a script to give me the serial number of the HDD, and there is nothing in the forum...

I execute by the GUi, and with the command line, I have the same problem :

I execute this : SIC2.exe -i list.txt -all

And in the prompt I have : File list.txt is empty!

No csv file.

Link to comment
Share on other sites

What is the content of list.txt? list.txt must contain ip addresses or host names (one per line)!

Further, as far as I can remember there is no option to read the s/n of the HDD but maybe I can add it...

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Try this:

Global $oErrorHandler = ObjEvent("AutoIt.Error", "ObjErrorHandler")

MsgBox(0, "Test", WMI_GetHDDSN("."))

Func WMI_GetHDDSN($host, $usr = "", $pass = "") ;coded by UEZ 2011
    If $host = "." Then $host = "localhost"
    Local $HDD_SN
    Local $ping = Ping($host, 1000)
    If @error Then Return SetError(1, 0, -1)
    Local $objWMILocator = ObjCreate("WbemScripting.SWbemLocator")
    Local $objWMIService = $objWMILocator.ConnectServer($host, "rootcimv2", $usr, $pass, "", "", 128)
    If @error Then Return SetError(2, 0, -1)
    Local $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_DiskDrive WHERE MediaType LIKE '%Fixed%'", "WQL", 0x30)
    If IsObj($colItems) Then
        For $objItem In $colItems
            $HDD_SN &= "Model: " & $objItem.Model & ", S/N: " & WMI_GetHDDSN2(StringMid($objItem.Name, 5), $host, $usr, $pass) & @LF
        Next
    Else
        Return SetError(3, 0, -1)
    EndIf
    Return $HDD_SN
EndFunc

Func WMI_GetHDDSN2($Tag, $host, $usr = "", $pass = "") ;coded by UEZ 2011
    Local $HDD_SN
    Local $objWMILocator = ObjCreate("WbemScripting.SWbemLocator")
    Local $objWMIService = $objWMILocator.ConnectServer($host, "rootcimv2", $usr, $pass, "", "", 128)
    Local $colItems = $objWMIService.ExecQuery("SELECT SerialNumber,Tag FROM Win32_PhysicalMedia WHERE Tag  LIKE '%" & $Tag & "%'", "WQL", 0x30)
    If IsObj($colItems) Then
        For $objItem In $colItems
            ConsoleWrite($objItem.Tag & @LF)
            $HDD_SN = $objItem.SerialNumber
        Next
    Else
        Return SetError(3, 0, -1)
    EndIf
    Return $HDD_SN
EndFunc

Func ObjErrorHandler()
     ConsoleWrite(  "A COM Error has occured!" & @CRLF  & @CRLF & _
                                "err.description is: "    & @TAB & $oErrorHandler.description    & @CRLF & _
                                "err.windescription:"     & @TAB & $oErrorHandler & @CRLF & _
                                "err.number is: "         & @TAB & Hex($oErrorHandler.number, 8)  & @CRLF & _
                                "err.lastdllerror is: "   & @TAB & $oErrorHandler.lastdllerror   & @CRLF & _
                                "err.scriptline is: "     & @TAB & $oErrorHandler.scriptline     & @CRLF & _
                                "err.source is: "         & @TAB & $oErrorHandler.source         & @CRLF & _
                                "err.helpfile is: "       & @TAB & $oErrorHandler.helpfile       & @CRLF & _
                                "err.helpcontext is: "    & @TAB & $oErrorHandler.helpcontext & @CRLF _
                            )
EndFunc

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

I try it on 3 different computers (XP-SP3), the same result, nothing in the msgbox,

A COM Error has occured!

err.description is:

err.windescription:

err.number is: 80041017

err.lastdllerror is: 0

err.scriptline is: 15

err.source is:

err.helpfile is:

err.helpcontext is:

Edited by ricky03
Link to comment
Share on other sites

Local $objWMIService = $objWMILocator.ConnectServer($host, "rootcimv2", $usr, $pass, "", "", "&H80")

This might need to be:

Local $objWMIService = $objWMILocator.ConnectServer($host, "rootcimv2", $usr, $pass, Default, Default, 128)

&H80 is the way VBScript does Hex Numbers, so for AutoIt, it would be 0x80, which is the same number as 128. I've used it with success along with ConnectServer.

Link to comment
Share on other sites

This is what WMI returns!

And what about this?:

Global $oErrorHandler = ObjEvent("AutoIt.Error", "ObjErrorHandler")

MsgBox(0, "Test", WMI_GetHDDSN("."))

Func WMI_GetHDDSN($host, $usr = "", $pass = "") ;coded by UEZ 2011
    If $host = "." Then $host = "localhost"
    Local $HDD_SN
    Local $ping = Ping($host, 1000)
    If @error Then Return SetError(1, 0, -1)
    Local $objWMILocator = ObjCreate("WbemScripting.SWbemLocator")
    Local $objWMIService = $objWMILocator.ConnectServer($host, "rootcimv2", $usr, $pass, "", "", 128)
    If @error Then Return SetError(2, 0, -1)
    Local $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_DiskDrive WHERE MediaType LIKE '%Fixed%'", "WQL", 0x30)
    If IsObj($colItems) Then
        For $objItem In $colItems
            $HDD_SN &= "Model: " & $objItem.Model & ", S/N: " & $objItem.SerialNumber & @LF
        Next
    Else
        Return SetError(3, 0, -1)
    EndIf
    Return $HDD_SN
EndFunc

Func ObjErrorHandler()
     ConsoleWrite(  "A COM Error has occured!" & @CRLF  & @CRLF & _
                                "err.description is: "    & @TAB & $oErrorHandler.description    & @CRLF & _
                                "err.windescription:"     & @TAB & $oErrorHandler & @CRLF & _
                                "err.number is: "         & @TAB & Hex($oErrorHandler.number, 8)  & @CRLF & _
                                "err.lastdllerror is: "   & @TAB & $oErrorHandler.lastdllerror   & @CRLF & _
                                "err.scriptline is: "     & @TAB & $oErrorHandler.scriptline     & @CRLF & _
                                "err.source is: "         & @TAB & $oErrorHandler.source         & @CRLF & _
                                "err.helpfile is: "       & @TAB & $oErrorHandler.helpfile       & @CRLF & _
                                "err.helpcontext is: "    & @TAB & $oErrorHandler.helpcontext & @CRLF _
                            )
EndFunc

On my notebook this function return not the correct value but value is correct from post#10.

Br,

UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Here are :

Model: WDC WD2500SD-01KCC0, S/N:

Model: WDC WD5002ABYS-01B1B0, S/N:

A COM Error has occured!

err.description is:

err.windescription:

err.number is: 80020006

err.lastdllerror is: 0

err.scriptline is: 18

err.source is:

err.helpfile is:

err.helpcontext is:

Link to comment
Share on other sites

WinXP doesn't have the SerialNumber method in Win32_DiskDrive class :D

Br,

UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

I can speak German, Turkish and English but not C/C++ :D

But I can try!

I asume if you want to enumerate only on local PC, not remotely, then the s/n can be read out of a build-in DLL (e.g. kernel32.dll)!

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...