Sign in to follow this  
Followers 0
joseLB

run, runwait, etc. - suggestion on hwnd

16 posts in this topic

Today I started a program with RUN(...). The only parameter ($cmdline) was the program name. After that, normally you need to wait for the program to "start", or, in my case, I needed to call _ScreenCapture_CaptureWnd. Title, class, hwnd, etc. where not avaiable.

Most of the control functions need a title, a class, or hwnd, etc. Most functions DO NOT use PID.

I solved my problem with a script from BRETT and monoceres that converts PID to hWND, at PID -> Window Handle (hWND) conversion

My suggestion: RUN, RUNWAIT, etc., to have one more last parameter.

-> Default=0, returns just PID as today.

-> Value=1, returns an array with some parameters (including hwind), something like WinList(), but including PID also.

-> Value=2, returns an array, something like WinGetPos(), but including PID and hwnd.

-> .....

Regards

Jose

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

It is not possible to get the windows from a PID. Possibly there is a way, but it is a secret of M$.

It is possible to get the PID from a window, so the workaround is, to loop all windows and check which process they belong to.

Edited by ProgAndy

*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

Share this post


Link to post
Share on other sites

It is not possible to get the windows from a PID. Possibly there is a way, but it is a secret of M$.

It is possible to get the PID from a window, so the workaround is, to loop all windows and check which process they belong to.

That's Brett solution, as follows. But is hard to believe that If I'm starting a process, I can't have all information about it, as for example WinList and other does...

Func _GetHwndFromPID($PID)
    $hWnd = 0
    $stPID = DllStructCreate("int")
    Do
        $winlist2 = WinList()
        For $i = 1 To $winlist2[0][0]
            If $winlist2[$i][0] <> "" Then
                DllCall("user32.dll", "int", "GetWindowThreadProcessId", "hwnd", $winlist2[$i][1], "ptr", DllStructGetPtr($stPID))
                If DllStructGetData($stPID, 1) = $PID Then
                    $hWnd = $winlist2[$i][1]
                    ExitLoop
                EndIf
            EndIf
        Next
        Sleep(100)
    Until $hWnd <> 0
    Return $hWnd
EndFunc;==>_GetHwndFromPID

Share this post


Link to post
Share on other sites

If you don't believe it, just search MSDN and google. I found no other solution or API function to do that. Windows stores those things, but you have to use the known APIs.

WinList / EnumWindows lists all windows

WinGetProcess / GetWindowThreadProcessId fetches PID from HWND

Run / CreateProcess just returns PID there is no Window Handle, since a process can have none, one or multiple windows.


*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

Share this post


Link to post
Share on other sites

That's Brett solution, as follows. But is hard to believe that If I'm starting a process, I can't have all information about it, as for example WinList and other does...

That's actually a common mistake. But in reality, what you just described would be a "do all" function. A "do all" function would be bad for everyone, because it would be limiting them. You can't take functionality away from premade functions, you can only extend functionality. So instead, we split up the functions in a way so that you may use them to build your own "do all" function exactly as how you would like it.

Knowing this, you could write your own function that would:

1) Start the process using function parameters

2) Find all the window handles that are being opened for that process and gather some other information you would like

3) Put all that information in an array and use it as the return handle to your function.

Once you've done that, you'll also understand some of the more technically challenging things about writing such a function. Such as, once a process is created it doesn't always instantly create it's Windows.

Good luck.

Share this post


Link to post
Share on other sites

Manadar said it best. It's not going to happen natively. That's why we made a scripting language, not a language where every function can do every single thing every single user wants right out of the box.

Share this post


Link to post
Share on other sites

I'm not really sure how practical this is (or even how "workable" it is). You can setup a windows shell hook. In your hook procedure, check for "HSHELL_WINDOWCREATED", then call GetWindowThreadProcessId to check if the Process ID of the window is the same as the process ID returned by Run.

There was a callback UDF floating around the forum a while ago - it may come in handy if you use this method.

http://msdn.microsoft.com/en-us/library/ms644990.aspx - SetWindowsHookEx

http://msdn.microsoft.com/en-us/library/ms644991(VS.85).aspx - ShellProc

http://msdn.microsoft.com/en-us/library/ms633522(VS.85).aspx - GetWindowThreadProcessId

Share this post


Link to post
Share on other sites

Shell hooks require being inside a DLL.

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

Shell hooks require being inside a DLL.

Ah... I forgot about that. Edited by cppman

Share this post


Link to post
Share on other sites

WH_SHELL can be set either as thread or global. Setting it on a out-of-process thread or on all threads (global) requires a DLL so it can be loaded into the address space of those processes. Setting it on an in-process thread seems rather useless as the only notifications you will get will revolve around you but not other windows (I haven't tested this).

Share this post


Link to post
Share on other sites

Today I started a program with RUN(...). The only parameter ($cmdline) was the program name. After that, normally you need to wait for the program to "start", or, in my case, I needed to call _ScreenCapture_CaptureWnd. Title, class, hwnd, etc. where not avaiable.

Most of the control functions need a title, a class, or hwnd, etc. Most functions DO NOT use PID.

I solved my problem with a script from BRETT and monoceres that converts PID to hWND, at PID -> Window Handle (hWND) conversion

My suggestion: RUN, RUNWAIT, etc., to have one more last parameter.

-> Default=0, returns just PID as today.

-> Value=1, returns an array with some parameters (including hwind), something like WinList(), but including PID also.

-> Value=2, returns an array, something like WinGetPos(), but including PID and hwnd.

-> .....

Regards

Jose

Here my two cents:

CODE
#include <array.au3>

$iPid = Run("notepad.exe")

Sleep(100) ; allow notepad to create window

$aArray = _WinGetInfoByProcess($iPid, 1)

_ArrayDisplay($aArray, "by Pid, only visible windows")

$aArray = _WinGetInfoByProcess("notepad.exe", -1)

_ArrayDisplay($aArray, "by Name, all windows")

$aArray = _WinGetInfoByProcess("notepad.exe", 0)

_ArrayDisplay($aArray, "by Name, only invisible windows")

$aArray = _WinGetInfoByProcess("notepad.exe", 1)

_ArrayDisplay($aArray, "by Name, only visible windows")

$hHandle = _WinGetInfoByProcess("notepad.exe") ; default is $nShow = 2

ControlSend($hHandle, "", "", "{alt}{right 2}{down 2}{enter}")

Sleep(300 * ControlSend("[active]", "", "", "{tab 2}{BS}72{enter}")) ; allow window to change

ControlSend("[active]", "", "", "{enter} Hello World.")

Func _WinGetInfoByProcess($vProcess, $nShow = 2)

;

;===============================================================================

;

; Function Name: _WinGetInfoByProcess

; Description:: Get Window Handle of Process

; Parameter(s): $vProcess = Processname(e.g. "Notepad.exe") or Processnumber(e.g. 4711 )

; $nShow = -1 "All (Visble or not)"

; $nShow = 0 "Not Visible Only"

; $nShow = 1 "Visible Only"

; $nShow = 2 "Return handle of newest window " (Default)

; Requirement(s): none

; Return Value(s):

; @extended = returns number of entries in the array

; @error = 0 AND $nShow = 2 (default) returns handle of newest window

; @error = 0 returns array with processinfos

; n = 1 to @extended

; Array[n][0] shows windows title.

; Array[n][1] shows windows handle.

; Array[n][2] shows windows Pid.

; @error = 1 Process not found.

; @error = 2 Window not found.

; Author(s): Bee

; inspired by Smoke_N's script _WinGetHandleByPID()

; but to handle more than one process with the same name

; and to return handle of newest window ($nShow = 2).

; tested versions: Autoit 3.3.0.0

;

;===============================================================================

;

If Not ProcessExists($vProcess) Then Return SetError(1, 0, 0) ; no matching process

Local $iWinList, $aWinList = WinList()

Local $iResult, $aResult[uBound($aWinList)][3]

Local $iProcessList, $aProcessList = ProcessList($vProcess)

If $aProcessList[0][0] = 0 Then Local $aProcessList[2][2] = [[1, 0],["", $vProcess]]

For $iWinList = 1 To $aWinList[0][0]

For $iProcessList = 1 To $aProcessList[0][0]

If WinGetProcess($aWinList[$iWinList][1]) = $aProcessList[$iProcessList][1] Then

If $nShow > -1 And Not $nShow = (2 = BitAND(WinGetState($aWinList[$iWinList][1]), 2)) Then ContinueLoop

$iResult += 1

$aResult[$iResult][0] = $aWinList[$iWinList][0]

$aResult[$iResult][1] = $aWinList[$iWinList][1]

$aResult[$iResult][2] = $aProcessList[$iProcessList][1]

EndIf

Next

Next

If $iResult = 0 Then Return SetError(2, 0, 0) ; no window found

ReDim $aResult[$iResult + 1][3]

$aResult[0][0] = $iResult

If $nShow = 2 Then Return SetError(0, $iResult, $aResult[1][1])

Return SetError(0, $iResult, $aResult)

EndFunc ;==>_WinGetInfoByProcess

Just execute it and see what happens. :)

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

TinyBoy, you aren't affecting Jos. I'm the one cleaning up your mess at the moment but don't get your hopes up that you are really affecting me all that much. It's rather amusing at this point, actually. So thank you for being a form of entertainment.

However, to answer your question, yes, I am satisfied even if Jos isn't. You've admitted you were going to attack us and now we have logs proving that you did indeed attack us. I'm sure your ISP will be quite interested in seeing these new logs where you DoS our issue tracker. I bet they would be interested in that PM you sent to the staff, too. It should go along quite nicely with the previous information we already sent them. Feel free to continue your actions. The more evidence of your behavior we get the better.

Oh, and if you wish to speak to Jos or any of us for that matter then use #771. Have fun. Toodles.

Edited by Valik
Removed a word that shouldn't have been there.

Share this post


Link to post
Share on other sites

Oh, and if you wish to speak to Jos or any of us for that matter then use #771. Have fun. Toodles.

Yeah, I'll have fun.

But speaking by #771 is not possible, since you 'banned' the IP's of my old proxy 'Kabel Deutschland' and no access to TRAC was possible. Error 403

So I changed my proxy and used another userid to communicate in this topic.

I have enough proxies around the world. ;-)

Like this one.

My real ISP is difficult to expose.

And again: Please reinstate banned users: Tinyboy and JellyFish666

Thanks

Tinyboy :)

Share this post


Link to post
Share on other sites

Yeah, I'll have fun.

But speaking by #771 is not possible, since you 'banned' the IP's of my old proxy 'Kabel Deutschland' and no access to TRAC was possible. Error 403

So I changed my proxy and used another userid to communicate in this topic.

I have enough proxies around the world. ;-)

Like this one.

My real ISP is difficult to expose.

And again: Please reinstate banned users: Tinyboy and JellyFish666

Thanks

Tinyboy :)

So let me summarize this and you can confirm if I'm correct.

  • For no personal reason at all you decide to "teach" me a lesson and attack our issue tracker.
  • You are banned for your behavior in attacking our issue tracker (as well as banned for having multiple accounts)
  • Unhappy at being banned you now try to use your attacks as leverage to get us to cave in to your demands.
  • You stop the attacks for some reason.
  • You come onto the forum again and are promptly banned.
  • In retaliation you go back to threatening us and demanding accounts be unbanned.
So does that about sum up your behavior?

May I ask you a serious question? What is wrong with you. You go out of your way to attack somebody and then threaten to attack them further when they retaliate. Does that not strike you as incredibly stupid on your part? You can't honestly expect us to actually give in to your demands. So what is it you expect? Do you enjoy making me take 15 seconds to run a script to clean up after you? Do you enjoy causing me to learn useful things to combat you? It seems like whatever goal you have in mind you are having an inverse effect. You aren't really affecting anybody you are aiming at unless you're aiming at innocent people. I can't tell you the number of legitimate tickets that have been blocked because of measures put in place to keep you out. Is that your goal? To stop legitimate users of this site from being able to use the site? You really aren't affecting the staff myself or Jos, the two people you have issue with.

Know this: Your demands will never be met. You can stop asking now. We will never unban those accounts. You will never be knowingly allowed on this website again. Neither will be the idiot that was banned at your expense. Right now there is a reason I'm not banning you but that reason will soon expire and you will once again have your account banned. All future accounts will be banned. All tickets created by you will be automatically deleted. You may continue to attack this community all you want but know that you hurt yourself and you hurt a lot of innocent people far more than you ever hurt us. You don't hurt us at all, actually. You hurt the community. You make their life difficult. Is that your goal?

Share this post


Link to post
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
Sign in to follow this  
Followers 0