RogFleming Posted October 29, 2010 Share Posted October 29, 2010 Seems I run into a problem, maybe someone can help. I trying to increase the speed of a WMI query against 1000's of workstations Remote Execute code Calling command $tstoumembers is a large array of workstations For $i = 1 To UBound($tstoumembers,1) -1 _GUICtrlStatusBar_SetText($hStatus, $tstoumembers[$i]&" "&"Complete:"&$i&"/"&$tstoumembers[0], 1) GUICtrlSetData($progress,($i/$tstoumembers[0])*100) If $RandStart = 1 Then RemoteExecute($ScanName, "DTESCAN01",$tstoumembers[$i],$Proc) If $RandStart = 2 Then RemoteExecute($ScanName, "DTESCAN02",$tstoumembers[$i],$Proc) If $RandStart = 3 Then RemoteExecute($ScanName, "DTESCAN03",$tstoumembers[$i],$Proc) If $RandStart = 4 Then RemoteExecute($ScanName, "DTESCAN04",$tstoumembers[$i],$Proc) $RandStart = 0 EndIf $RandStart = $RandStart + 1 Next Func RemoteExecute($ScanName, $strComputer,$sComputerName,$program) Dim $objWMIService, $objProcess Dim $strShell, $objProgram, $strExe, $strInput $strExe = "c:\\dtescan\\"&$ScanName&" "&$sComputerName&" "&$program $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2") $objProcess = $objWMIService.Get("Win32_Process") $objProgram = $objProcess.Methods_("Create").InParameters.SpawnInstance_ $objProgram.CommandLine = $strExe ;Execute the program now at the command line. $strShell = $objWMIService.ExecMethod( "Win32_Process", "Create", $objProgram) EndFunc Remote Scan Engine Code expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_outfile=DTESCANPROC.exe #AutoIt3Wrapper_Change2CUI=y #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <Array.au3> #Include <File.au3> #Include <Date.au3> #include <AD.au3> If $cmdline[0] <> 2 Then MsgBox(4096,"Invalid Command","Useage DTEScanProc.exe Hostname Program") Else $sComputerName = $cmdline[1] $sProcName = $cmdline[2] Endif $sProcLog = "c:\dtescan\"&StringTrimRight($sProcName,4)&".log" #cs McShield Scanner Proc #ce ;$timer = TimerInit() Global $timer TCPStartup() $timer = TimerInit() TCPNameToIP($sComputerName) If @error Then _FileWriteLog($sProcLog,'|'&$sComputerName&'|'&"Remote system has no IP Address from a DNS Query"&'|'&int(TimerDiff($timer)) & " ms") TCPShutdown() Exit Else TCPShutdown() $timer = TimerInit() If Ping($sComputerName,255) = 0 Then _FileWriteLog($sProcLog,'|'&$sComputerName&'|'&"Remote system did not respond to Ping,"&'|'&int(TimerDiff($timer)) & " ms") Exit Else SearchForProc($sComputerName) EndIf EndIf Func SearchForProc($sComputerName) Local $i $timer = TimerInit() $count = 1 Local $arTasks [1] $wbemFlagReturnImmediately = 0x10 $wbemFlagForwardOnly = 0x20 $objWMIService = ObjGet("winmgmts:\\" & $sComputerName & "\root\CIMV2") <---- Fails Here but only when called in this way, works fine locally If @error Then _FileWriteLog($sProcLog,'|'&$sComputerName&'|'&"Remote system did not respond to WMI Query,"&'|'&int(TimerDiff($timer)) & " ms") ;_AD_Close() Exit Else $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_Process", "WQL", _ $wbemFlagReturnImmediately + $wbemFlagForwardOnly) If IsObj($colItems) then Local $Object_Flag = 0 For $objItem In $colItems $Object_Flag = 1 ReDim $arTasks [$count] $arTasks [$count - 1] = $objItem.Caption $count += 1 Next _ArraySort ($artasks) ;_ArrayDisplay($artasks) IF _ArraySearch($artasks,$sProcName) <> -1 Then _FileWriteLog($sProcLog,'|'&$sComputerName&'|'&$sProcName&" process is running"&'|'&int(TimerDiff($timer)) & " ms") Exit Else _FileWriteLog($sProcLog,'|'&$sComputerName&'|'&$sProcName&" was not a running process,"&'|'&int(TimerDiff($timer)) & " ms") Exit EndIf Else _FileWriteLog($sProcLog,'|'&$sComputerName&'|'&"No WMI Objects Found for class: Win32_Process,"&'\'&int(TimerDiff($timer)) & " ms") Exit Endif EndIf EndFunc Link to comment Share on other sites More sharing options...
RogFleming Posted October 30, 2010 Author Share Posted October 30, 2010 Solved! I figured a way around it Break down explanation: Using PsExe.exe to launch wmic.exe on a remote system to start a process on that workstation,the network credentials are preserved. The only remaining issue is to address the the rate in which each scanner sends data to the log file. Previously I just send data to a log statement, but now I think I need to create a log function, which will track logging success, and have a randum backoff timers if the file is unavailable to write to. FYI the "c:\DTESCAN\" directory in the command is on the remote system, You could use PsExec to copy a file to execute instead. Func RemoteExecutePsExec($ScanName, $strComputer,$sComputerName,$proc) Sleep(30) ShellExecute("c:\SysinternalsSuite\PsExec.exe","-d \\"&$strComputer&" "&"-u domain\username -p password wmic /node:"&$strComputer&" "&"PROCESS CALL Create"&" "&"'"&"c:\DTESCAN\"&$ScanName&" "&$sComputerName&" "&$Proc&"'","","Open",@SW_HIDE) Sleep(30) EndFunc Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now