Zohar Posted April 9, 2009 Share Posted April 9, 2009 (edited) I am using Run("some application.exe") and getting a PID, and then I need to get a Process Handle from that PID, so I can use some APIs that require a ProcessHandle... Edited April 11, 2009 by Zohar Link to comment Share on other sites More sharing options...
ProgAndy Posted April 9, 2009 Share Posted April 9, 2009 look at _WinAPI_OpenProcess *GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes Link to comment Share on other sites More sharing options...
Zohar Posted April 9, 2009 Author Share Posted April 9, 2009 (edited) oh..What I wanted to do, is to use _WinAPI_WaitForInputIdle() in order to know when an Application that I Run(), has finished loading.But if it requires OpenProcess, CloseProcess, and all that mess, then maybe I'll skip it :]Too bad AutoIt doesn't have function that gives a similar functionality to _WinAPI_WaitForInputIdle(). Edited April 9, 2009 by Zohar Link to comment Share on other sites More sharing options...
FreeFry Posted April 9, 2009 Share Posted April 9, 2009 (edited) As ProgAndy said, use _WinAPI_OpenProcess to get a handle to the process, then use DllCall to call the WaitForInputIdle function inside user32.dll. It's quite easy Nvm. that.there's _WinAPI_WaitForInputIdle Edited April 10, 2009 by FreeFry Link to comment Share on other sites More sharing options...
Zohar Posted April 10, 2009 Author Share Posted April 10, 2009 (edited) really?OK, here's my attempt:#Include <WinAPI.au3> Local Const $PROCESS_ALL_ACCESS =0x1F0FFF Local $PID =Run("SOME SLOW LOADING APPLICATION") Local $Process_Handle =_WinAPI_OpenProcess($PROCESS_ALL_ACCESS,1,$PID) _WinAPI_WaitForInputIdle($Process_Handle) Beep(400,100)Unfortunately it's not waiting.The beep is played immediately after the application is launched, and not after it finishes loading itself :/(as if the _WinAPI_WaitForInputIdle($Process_Handle) line is not there at all)Anyone has done that before? Edited April 10, 2009 by Zohar Link to comment Share on other sites More sharing options...
Authenticity Posted April 10, 2009 Share Posted April 10, 2009 Use The _WinAPI_CreateProcess function before calling _WinAPI_WaitForInputIdle. You'll have to give up using Run doing so. Link to comment Share on other sites More sharing options...
Zohar Posted April 10, 2009 Author Share Posted April 10, 2009 Use The _WinAPI_CreateProcess function before calling _WinAPI_WaitForInputIdle. You'll have to give up using Run doing so.but why?OpenProcess() exists so it will be used.There should be a way to do it using Run()+OpenProcess(). Link to comment Share on other sites More sharing options...
Authenticity Posted April 10, 2009 Share Posted April 10, 2009 Did you test it? I'm not Microsoft developer but I guess it's not mentioned in OpenProcess but in CreateProcess for a good reason, even though Microsoft's documentation is considerably poor. Link to comment Share on other sites More sharing options...
Zohar Posted April 10, 2009 Author Share Posted April 10, 2009 (edited) wellsince it has been many times that you told people "it's impossible", and it turned out that "it is possible",then allow me to say thanks but no:)If anyone here has an idea, please write.If I need to replace OpenProcess() with something else, it's cool,As long as the Run() can stay.basically, it means that I need a different way to get a ProcessHandle from a PID, than what I currently have. Edited April 10, 2009 by Zohar Link to comment Share on other sites More sharing options...
Authenticity Posted April 10, 2009 Share Posted April 10, 2009 Try this and tell me what you think: #include <WinAPI.au3> Dim $sProcess = 'C:\Program Files\Windows Media Player\wmplayer.exe' Dim $hProcess Dim $tPI = DllStructCreate($tagPROCESS_INFORMATION), $pPI = DllStructGetPtr($tPI) Dim $tSI = DllStructCreate($tagSTARTUPINFO), $pSI = DllStructGetPtr($tSI) DllStructSetData($tSI, 'Size', DllStructGetSize($tSI)) Dim $iSuccess = _WinAPI_CreateProcess('', $sProcess, 0, 0, False, 0, 0, 0, $pSI, $pPI) If Not $iSuccess Then MsgBox(0x10, 'Error!', 'Could not create the process!!!') Else _WinAPI_CloseHandle(DllStructGetData($tPI, 'hThread')) $hProcess = DllStructGetData($tPI, 'hProcess') _WinAPI_WaitForInputIdle($hProcess) MsgBox(0x40, 'Success!', 'process initialization has completed!!!') EndIf $tPI = 0 $tSI = 0 Hope you got the wmplayer.exe ;] P.S. I'm not trying to get people down. Believe me. Link to comment Share on other sites More sharing options...
Zohar Posted April 10, 2009 Author Share Posted April 10, 2009 (edited) Authenticity:1)I know you're not trying to get people down,but you must know that your way of thinking which is "I don't know, then it's impossible" is basically wrong.(you do that often, and it's not good.. If you don't know, someone else might know,and when yous upply a "it's impossible" answer, the person who asks might give up)2)Specifically here:Thank you again for trying to help me, but as I said this(CreateProcess()) is not the direction I wish to go.I am looking for a way that will work, without using CreateProcess(),a way that will get a PID,and will be able to Wait for the Process to be Idle.3)Unfortunately, the code you write here, with CreateProcess() is not working.It immediately shows the messagebox, which is the same problem that my original code that uses Run() suffers from. Edited April 10, 2009 by Zohar Link to comment Share on other sites More sharing options...
FreeFry Posted April 10, 2009 Share Posted April 10, 2009 Try this(I'm not 100% sure if it actually works in the way you need it to): #include <WinAPI.au3> #include <Constants.au3> Dim $iPID = Run("calc.exe") Dim $hProcess = _WinAPI_OpenProcess($PROCESS_ALL_ACCESS, 0, $iPID, False) _WinAPI_WaitForInputIdle($hProcess, 5500) MsgBox(0, "Ready", "Process is now ready for use. :)") Link to comment Share on other sites More sharing options...
Zohar Posted April 11, 2009 Author Share Posted April 11, 2009 Hello FreeFry Thank you very much for your help.I tested it, and it too, is not waiting till the process has finished loading..Is it just me?Or maybe my expectation from WaitForInputIdle() is incorrect?What I expect from WaitForInputIdle(), is to wait until the program has finished loading,that means, it has gone past the part that consumes the most CPU in the beginning, it has created its window, etc.Simply put, "It's ready".Isn't that what WaitForInputIdle() should do?And if yes, why all 3 attempts(mine, authenticity's, and freefry's) do not achieve it? Link to comment Share on other sites More sharing options...
trancexx Posted April 11, 2009 Share Posted April 11, 2009 I would say it works as meant.Thing is _WinAPI_WaitForInputIdle is written so it returns true for original 0 and false for anything else. This why, for example you cannot see that WAIT_TIMEOUT is returned for some situations.#include <WinAPI.au3> #include <Constants.au3> Global $iPID = Run('"' & @ProgramFilesDir & '\Internet Explorer\iexplore.exe"') Global $hProcess = _WinAPI_OpenProcess($PROCESS_ALL_ACCESS, 0, $iPID, False) Global $a = TimerInit() Global $aCall = DllCall("user32.dll", "dword", "WaitForInputIdle", "hwnd", $hProcess, "dword", 30) ; RETURN VALUES ARE: ; All_OK = 0 ; WAIT_TIMEOUT = 258 ; WAIT_FAILED = -1 ConsoleWrite("Return value: " & $aCall[0] & @CRLF & "Elapsed time: " & TimerDiff($a) & " ms" & @CRLF)Likely your expectations are incorrect.p.s. Authenticity's code is nice. ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
Zohar Posted April 11, 2009 Author Share Posted April 11, 2009 (edited) Hello trancexx mmm when I say "it's working/not working", I am not talking about the Return Value, I am talking about the Behavior that results from the Wait method. So I think I did not fully understand what you mean. If the return value satisfies you, but you did not see any wait, then where would you use this function(WaitForInputIdle())? Edited April 11, 2009 by Zohar Link to comment Share on other sites More sharing options...
Authenticity Posted April 11, 2009 Share Posted April 11, 2009 (edited) Try calling twice for _WinAPI_WaitForInputIdle(), worked on Microsoft Visual C++ while loading previous opened project, using one call returns as fast as the environment is ready and another call returns when the project is fully loaded. If you can explain the load procedure it may help.Edit: Or if the mouse cursor is changed while the process is loaded you can do like this:_WinAPI_WaitForInputIdle($hProc) Do Sleep(500) Until MouseGetCursor() <> 15 Edited April 11, 2009 by Authenticity Link to comment Share on other sites More sharing options...
Zohar Posted April 11, 2009 Author Share Posted April 11, 2009 HiI tried calling twice, and unfortunately I did not succeed.I tried adding a Sleep(1000) between the two Wait calls, and did not succeed..I even changed the sleep to 4000(the total time for the application+datafile is 15secs), and that too did not succeed.Is that WaitForInputIdle() function supposed to work? maybe the application I try it on is not "good"?Regarding the MouseCursor,I must say this is definitely a clever and creative idea.It works good for applications where the application first shows the window, and only then loads the data file.But, there are many applications that do not display themselves until "everything is ready" and loaded, and there the MouseCursor won't give us a clue.I must admit it's quite disappointing that WaitForInputIdle() is not performing as the developer needs.. Link to comment Share on other sites More sharing options...
Authenticity Posted April 11, 2009 Share Posted April 11, 2009 Well, use AutoIt Window Info or WinSpy and get a class name that can help you to uniquely identify the window and loop until the window exists and visible and then try the aforementioned. Something like this: #include <Constants.au3> #include <WinAPI.au3> #include <WindowsConstants.au3> Dim $hWin While 1 $hWin = WinGetHandle('[CLASS:Unique]') If $hWin And BitAND(_WinAPI_GetWindowLong($hWin, $GWL_STYLE), $WS_VISIBLE) Then ExitLoop Sleep(500) WEnd Link to comment Share on other sites More sharing options...
Zohar Posted April 11, 2009 Author Share Posted April 11, 2009 yeah I use those workarounds. thanks.note that you can use WinGetState() to check if it's visible.Altho, that will not tell when the window has finished loading, coz sometimes the window has a listview that loads items.There's a trick for that too: we can check if the ListView(or whatever control) exists, and check the Number of Items it has.That's what I do now, when I need it to wait for a window.But I thought to make the code better If the WaitForInputIdle() function had worked..I wonder if anyone managed to make it work nicely 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