Leaderboard
Popular Content
Showing content with the highest reputation on 05/20/2023 in all areas
-
Hi! Nice example of the XY-Problem! What the Problem is: What the User think the Problem is: No, you are lying to yourself! The MAIN problem is that the app is crashing....you need to fix THIS! You don't have to solve problems, you have to eliminate problems!2 points
-
For what it's worth, I tend to agree with @AndyG. Identifying and fixing the root cause of an issue is almost always better than time spent patching or working around the issue. If you fix (or at least mitigate) the issue, then you hopefully don't have to waste time dealing with it again and again or risk it causing additional problems. I have found WMI much more reliable in getting process info than some of the WinAPI UDF's that use Win32 API's. I haven't dug into why, but when using the WinAPI UDF's, WMI returns some information that the WinAPI UDF's do not. Here's a quick script that displays selected process info (including CPU time) for all running processes: #AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w 5 -w 6 -d #include <Constants.au3> #include <WinAPILocale.au3> #include <Array.au3> list_process_info() ;========================================================================== Func list_process_info() ;========================================================================== Enum $PROCESS_PID, $PROCESS_NAME, $PROCESS_EXE_PATH, $PROCESS_CPU_TIME, $PROCESS_COLS Local $aProcesses[0][$PROCESS_COLS] Local $oComError = ObjEvent("AutoIt.Error", "com_error_handler"), _ $oProcesses = "" Local $sTotalCpuTime = "" With ObjGet("winmgmts:") ;Get list of currently running processes $oProcesses = .ExecQuery("SELECT Handle, Name, ExecutablePath, KernelModeTime, UserModeTime FROM Win32_Process") ;If no processes found, then return with message If $oProcesses.Count = 0 Then Return MsgBox($MB_ICONWARNING, "Warning", "No processes found.") If @error Then Return MsgBox($MB_ICONERROR, "WMI ExecQuery Error", $oComError.Description) ;For each process For $oProcess in $oProcesses With $oProcess ;Calculate total cpu time duration and convert to hh:mm:ss $sTotalCpuTime = _WinAPI_GetDurationFormat($LOCALE_USER_DEFAULT, .KernelModeTime + .UserModeTime, "hh:mm:ss") ;Add process info to the array _ArrayAdd($aProcesses, .Handle & "|" & .Name & "|" & .ExecutablePath & "|" & $sTotalCpuTime) EndWith Next EndWith ;Display process info _ArraySort($aProcesses, 1, 0, 0, $PROCESS_CPU_TIME) ;Sort by cpu time in descending order _ArrayDisplay($aProcesses, "List of processes", "", 0, Default, "PID|NAME|PATH|CPU TIME") EndFunc ;========================================================================== Func com_error_handler($oError) ;========================================================================== #forceref $oError Return ; Return so @error can be trapped by the calling function EndFunc Resulting array:1 point
-
Find out CPU (used) Time of processes.
Jemboy reacted to mistersquirrle for a topic
Well I thought that it wasn't too hard, however it appears that on my system the normal function of _WinAPI_GetProcessTimes doesn't cut it. I needed to open the process myself (likely with debug enabled) to reliably get CPU time information. Check out this script: ;~ #RequireAdmin ;~ #AutoIt3Wrapper_UseX64=y #include <WinAPI.au3> #include <ProcessConstants.au3> Global $iNanoSecondsToMilliSeconds = 10000 Global $sProcessName = 'explorer.exe' Global $iProcessId = ProcessExists($sProcessName) If $iProcessId = 0 Or @error Then ConsoleWrite('Process does not exist, or error: ' & @error & @CRLF) Exit EndIf ;~ Global $aProcessTimes = _WinAPI_GetProcessTimes() Global $ghProcess = _WinAPI_OpenProcess($PROCESS_QUERY_LIMITED_INFORMATION, 0, $iProcessId, True) Global $aProcessTimes = __WinAPI_GetProcessTimes($ghProcess) If @error Then ConsoleWrite('Unable to get process times: ' & @error & ', ' & _WinAPI_GetLastError() & ', Msg: ' & _WinAPI_GetLastErrorMessage() & @CRLF) Exit EndIf ;~ For $i = 0 To UBound($aProcessTimes) - 1 ;~ ConsoleWrite('Index: ' & $i & ', type: ' & VarGetType($aProcessTimes[$i]) & ', string data: ' & String($aProcessTimes[$i]) & ', int data: ' & Int($aProcessTimes[$i]) & @CRLF) ;~ Next ConsoleWrite('Process ID: ' & $iProcessId & ', name: ' & $sProcessName & ' times: ' & @CRLF) ConsoleWrite(@TAB & 'Kernel mode: ' & __MillisecondToTimestamp(($aProcessTimes[1] / $iNanoSecondsToMilliSeconds)) & ' (' & $aProcessTimes[1] & ')' & @CRLF) ConsoleWrite(@TAB & ' User mode: ' & __MillisecondToTimestamp(($aProcessTimes[2] / $iNanoSecondsToMilliSeconds)) & ' (' & $aProcessTimes[2] & ')' & @CRLF) ConsoleWrite(@TAB & ' Total: ' & __MillisecondToTimestamp((($aProcessTimes[1] + $aProcessTimes[2]) / $iNanoSecondsToMilliSeconds)) & @CRLF) Exit Func __MillisecondToTimestamp($iMs, $bSeconds = False, $bColonSeparator = True) Local $sTimestamp If $bSeconds Then $iMs *= 1000 $iMs = Int($iMs, 0) ; Auto Int ; Convert the milliseconds to days, hours, minutes, and seconds $iDays = (($iMs >= 86400000) ? Int($iMs / 86400000) : 0) $iHours = Int(Mod($iMs, 86400000) / 3600000) $iMinutes = Int(Mod($iMs, 3600000) / 60000) $iSeconds = Int(Mod($iMs, 60000) / 1000) ; Format the timestamp as [DD ]hh:mm:ss.zzz ; Not using StringFormat here because it's considerably slower when you do it 10K+ times, so probably doesn't matter at all for this $sTimestamp = _ ($iDays > 0 ? String($iDays) & (($bColonSeparator) ? ' ' : 'd') : '') & _ StringRight('0' & String($iHours), 2) & (($bColonSeparator) ? ':' : 'h') & _ StringRight('0' & String($iMinutes), 2) & (($bColonSeparator) ? ':' : 'm') & _ StringRight('0' & String($iSeconds), 2) & _ ((Not $bSeconds) ? _ (($bColonSeparator) ? '.' : 's') & StringRight('00' & String($iMs), 3) & (($bColonSeparator) ? '' : 'ms') : _ (($bColonSeparator) ? '' : 's')) Return $sTimestamp EndFunc ;==>__MillisecondToTimestamp Func __WinAPI_GetProcessTimes($hProcess) ;~ If Not $iPID Then $iPID = @AutoItPID ;~ Local $hProcess = DllCall('kernel32.dll', 'handle', 'OpenProcess', 'dword', ((_WinAPI_GetVersion() < 6.0) ? 0x00000400 : 0x00001000), _ ;~ 'bool', 0, 'dword', $iPID) ;~ If @error Or Not $hProcess[0] Then Return SetError(@error + 20, @extended, 0) Local $tFILETIME = DllStructCreate($tagFILETIME) Local $aCall = DllCall('kernel32.dll', 'bool', 'GetProcessTimes', 'handle', $hProcess, 'struct*', $tFILETIME, 'uint64*', 0, _ 'uint64*', 0, 'uint64*', 0) If __CheckErrorCloseHandle($aCall, $hProcess) Then Return SetError(@error, @extended, 0) Local $aRet[3] $aRet[0] = $tFILETIME $aRet[1] = $aCall[4] $aRet[2] = $aCall[5] Return $aRet EndFunc ;==>__WinAPI_GetProcessTimes It did require a bit of tweaking, as since I mentioned using the default UDF function wasn't working on my system, with or without running as admin. Here's the output for explorer.exe: Process ID: 29536, name: explorer.exe times: Kernel mode: 01:10:35.937 (42359375000) User mode: 00:17:03.328 (10233281250) Total: 01:27:39.265 Sidenote, I am planning on releasing a UDF that makes getting some process information like CPU time very easy and fast. I'm not sure when I'm going to post it, but keep an eye out if interested.1 point -
Attempt to obtain CMD results fails
argumentum reacted to Mbee for a topic
Thanks for your reply, @argumentum! But I just now solved the problem. I went into Control Panel -> Programs and Features -> Turn Windows features on or off -> Services for NFS. All the options were already checked down through all levels, so I unchecked them all, rebooted, and then re-enabled them all. Afterwards, "ShowMount.exe" and the other NFS client tools were all where they should have been all along: In @SystemDir. Don't know how that got messed up, but everything is working fine now. I'm going to add some code in my script to check for the presence of the necessary NFS Client tools in Windows\System32 first, and if they're not there, I'm going to advise the user to do the same thing. Actually, I'm going to ensure that they're either running Windows 10 Pro (don't know about 11, don't have it on any of my boxes) or otherwise have the Client for NFS (NfsClnt) installed. That last is because I've read of tricks that allow you to install the NFS Client on a non-Pro, Non-Enterprise edition of Windows 10. Many, many thanks to all of you for your time and knowledge!1 point -
He also provide Bans.1 point
-
Keypress simulation with WinAPI functions directly
argumentum reacted to TheXman for a topic
The example below works in 32 bit and 64 bit environments. INPUT is a struct that contains a union. Since the original post only asked about keyboard input, I did not include what the MOUSEINPUT and HARDWAREINPUT unions would look like. There are alignment issues that have to be taken into account when running 32 bit or 64 bit. The example shows one way of handling it. #AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w 5 -w 6 -d ;~ #AutoIt3Wrapper_UseX64=N #include <Constants.au3> #include <Array.au3> #include <WinAPIDiag.au3> Enum Step *2 _ $KEYEVENTF_EXTENDEDKEY = 1, _ $KEYEVENTF_KEYUP, _ $KEYEVENTF_UNICODE, _ $KEYEVENTF_SCANCODE Const $INPUT_KEYBOARD = 1 Const $VK_SHIFT = 0x10 Const $VK_A = 0x41 Const $tagKeyInput = _ "dword type;" & _ (@AutoItX64 ? "byte alignment_pad[4];" : "") & _ "struct;" & _ " word wVk;" & _ " word wScan;" & _ " dword dwFlags;" & _ " dword time;" & _ " ulong_ptr dwExtraInfo;" & _ " byte reserved[8];" & _ "endstruct;" example() Func example() #cs ========================================================= Using the SendInput win32 API, this example sends "AbC" to the last active notepad instance (if it exists). Note: "A" is sent by using virtual key code and "C" is sent using a scan code. It was done just to show the 2 different ways of sending keyboard input. #ce ========================================================= Local $tKeyInput, _ $tInputArray Local $aResult Local $iNumberOfInputs = 8 ;Create a struct to get size $tKeyInput = DllStructCreate($tagKeyInput) ;Create an inputs array buffer $tInputArray = DllStructCreate(StringFormat("byte bytes[%i];", DllStructGetSize($tKeyInput) * $iNumberOfInputs)) ;Load input array[0] $tKeyInput = DllStructCreate($tagKeyInput, DllStructGetPtr($tInputArray) + (0 * DllStructGetSize($tKeyInput))) $tKeyInput.type = $INPUT_KEYBOARD $tKeyInput.wVk = $VK_SHIFT ;Load input array[1] $tKeyInput = DllStructCreate($tagKeyInput, DllStructGetPtr($tInputArray) + (1 * DllStructGetSize($tKeyInput))) $tKeyInput.type = $INPUT_KEYBOARD $tKeyInput.wVk = $VK_A ;Load input array[2] $tKeyInput = DllStructCreate($tagKeyInput, DllStructGetPtr($tInputArray) + (2 * DllStructGetSize($tKeyInput))) $tKeyInput.type = $INPUT_KEYBOARD $tKeyInput.wvk = $VK_A $tKeyInput.dwFlags = $KEYEVENTF_KEYUP ;Load input array[3] $tKeyInput = DllStructCreate($tagKeyInput, DllStructGetPtr($tInputArray) + (3 * DllStructGetSize($tKeyInput))) $tKeyInput.type = $INPUT_KEYBOARD $tKeyInput.wVk = $VK_SHIFT $tKeyInput.dwFlags = $KEYEVENTF_KEYUP ;Load input array[4] $tKeyInput = DllStructCreate($tagKeyInput, DllStructGetPtr($tInputArray) + (4 * DllStructGetSize($tKeyInput))) $tKeyInput.type = $INPUT_KEYBOARD $tKeyInput.wScan = AscW("b") $tKeyInput.dwFlags = $KEYEVENTF_UNICODE ;Load input array[5] $tKeyInput = DllStructCreate($tagKeyInput, DllStructGetPtr($tInputArray) + (5 * DllStructGetSize($tKeyInput))) $tKeyInput.type = $INPUT_KEYBOARD $tKeyInput.wScan = AscW("b") $tKeyInput.dwFlags = $KEYEVENTF_UNICODE + $KEYEVENTF_KEYUP ;Load input array[6] $tKeyInput = DllStructCreate($tagKeyInput, DllStructGetPtr($tInputArray) + (6 * DllStructGetSize($tKeyInput))) $tKeyInput.type = $INPUT_KEYBOARD $tKeyInput.wScan = AscW("C") $tKeyInput.dwFlags = $KEYEVENTF_UNICODE ;Load input array[7] $tKeyInput = DllStructCreate($tagKeyInput, DllStructGetPtr($tInputArray) + (7 * DllStructGetSize($tKeyInput))) $tKeyInput.type = $INPUT_KEYBOARD $tKeyInput.wScan = AscW("C") $tKeyInput.dwFlags = $KEYEVENTF_UNICODE + $KEYEVENTF_KEYUP ;Activate notepad window If Not WinActivate("[CLASS:Notepad]") Then Exit MsgBox($MB_ICONERROR, "WinActivate Error", "Notepad window not found.") ;Send input $aResult = DllCall('user32.dll', 'uint', 'SendInput', _ 'uint' , $iNumberOfInputs, _ 'struct*', $tInputArray, _ 'int' , DllStructGetSize($tKeyInput)) If $aResult[0] = 0 Then MsgBox(0, "GetLastError", _WinAPI_GetLastErrorMessage()) EndFunc1 point