Page 2 of 2

Posted: Tue Apr 04, 2006 1:15 pm
by Klonk
Yes sorry, at my first try i forgot or did not use the flag #PB_Program_Open. As I used it I was able to kill the program. But killing the problem is not really what I wanted. because I want the started application to close properly (maybe saving some configs).

So

Code: Select all

PostMessage_(FindWindow_(@"notepad", 0), #WM_CLOSE, 0, 0)
looks really good. The only problem is that I do not know the name of the window that is created by the started application. So FindWindow_ would not work as the title might differ from the application name. Is searched an appropriate function on MSDN and the WinAPI help, but both are not very helpful i.e. easy to search if you have no idea where to search...

Just for information: I try to write an application launcher for the USB stick. Or better I released the first version already, but this function would be very handy. (See uStart or µStart on the Showcase at purearea.net)

Posted: Tue Apr 04, 2006 1:24 pm
by ts-soft
have a look at the source of pbosl_process lib by Rings.

Posted: Tue Apr 04, 2006 1:34 pm
by PB
> sorry, at my first try i forgot or did not use the flag #PB_Program_Open

I see. You made me think I was going insane! ;)

Posted: Tue Apr 04, 2006 2:06 pm
by Klonk
Sorry PBOSL did not give what i searched.

On the german forum I found:

Code: Select all

process = RunProgram(...)
terminateprocess_(process,0) 
which looks very good and seems to do what I want.

I just do not get it working:
example code:

Code: Select all

process = RunProgram("c:\winnt\notepad.exe")
Delay(1000)
TerminateProcess_(process,0)
Can anyone tell me whats wrong here? Or is this the wrong approach??

BTW: I'm trying with PB4b9

Posted: Tue Apr 04, 2006 2:39 pm
by PB
This is the only way I know to do it. Not all my own code.

Code: Select all

; RunProgramEx: Retrieves handle of an app's opened window.

Procedure RunProgramEx(filename$,parameter$,directory$,showflag)
  If Left(parameter$,1)<>" " : parameter$=" "+parameter$ : EndIf
  Info.STARTUPINFO : Info\cb=SizeOf(STARTUPINFO) : Info\dwFlags=1
  Info\wShowWindow=showflag : ProcessInfo.PROCESS_INFORMATION
  If CreateProcess_(@filename$,@parameter$,0,0,0,#NORMAL_PRIORITY_CLASS,0,@directory$,@Info,@ProcessInfo)
    ProcessID=ProcessInfo\dwProcessId
    Repeat
      win=FindWindow_(0,0)
      While win<>0
        GetWindowThreadProcessId_(win,@pid.l)
        If pid=ProcessID : WinHandle=win : Break : EndIf
        win=GetWindow_(win,#GW_HWNDNEXT)
      Wend
    Until WinHandle
  EndIf
  ProcedureReturn WinHandle
EndProcedure

app$="c:\windows\notepad.exe" ; Full path needed!
hWnd=RunProgramEx(app$,"",GetPathPart(app$),#SW_SHOW)
Sleep_(2000) ; Give it a couple of seconds to open.
PostMessage_(hWnd,#WM_CLOSE,0,0) ; Now close it.

Posted: Tue Apr 04, 2006 5:05 pm
by Klonk
Thank you very much, this is exactly what I searched for.
Could you please tell me the type of the returned result. Is it long?
I want to store the result in a structured list therefore I need the type.

I tried to understand what it does (to improve my knowledge)
1. Parameters for the program are set
2. Create the process
3. Obtain the ProcessID
4. go throught all open windows and check their processIDs
5. When window with same processID is found return handle to that window

Is that correct?

Posted: Tue Apr 04, 2006 9:59 pm
by PB
The return type is Long, because PureBasic uses longs by default if the user
doesn't set the type. So because it uses just "WinHandle" instead of another
type like "WinHandle.b" etc, it's a long.

Your steps from 1-5 are correct as to how it works, too. :)

@Fred: Would be great if there was a command to do this after using
RunProgram to launch an app. I experimented a bit but couldn't find
a way?

Posted: Wed Apr 05, 2006 7:37 am
by Klonk
PB wrote:The return type is Long, because PureBasic uses longs by default if the user
doesn't set the type. So because it uses just "WinHandle" instead of another
type like "WinHandle.b" etc, it's a long.
A very valuable information, didn't found it in the help. Maybe it would make sense to state with Runprogram etc. that the parameter program is of type long?

I took your code and modified it to get a universal code snippet with least use of API functions (works great BTW:):

Code: Select all

;{ ==========================================================================
;|  EndProgram(processID.l)
;|    Closes the application that was started with RunProgram. In difference
;|    to KillProgram it allows the program to shut down properly and save e.g.
;|    settings. The parameter "processID" is obtained by ProgramID(<result of
;|    RunProgram(app$,option$,path$, #PB_Program_Open)>)
;} ==========================================================================
Procedure EndProgram(processID.l)
;***** End a program started with Runprogram, but give chance to save settings!
  If OpenProcess_(#PROCESS_ALL_ACCESS,0,processID)<>0
    CloseHandle_(processHandle)
    Repeat ;searcht through all windows
      win=FindWindow_(0,0)
      While win<>0
        GetWindowThreadProcessId_(win,@pid.l) ; get processID of found window
        If pid=processID : WinHandle=win : Break : EndIf
        win=GetWindow_(win,#GW_HWNDNEXT)
      Wend
    Until WinHandle
    PostMessage_(WinHandle,#WM_CLOSE,0,0) ; Now close the started application 
  EndIf
EndProcedure

 app$="c:\winnt\notepad.exe" ; Full path needed!
 handle.l=RunProgram(app$,"",GetPathPart(app$),#PB_Program_Open)
id.l = ProgramID(handle)
CloeProgram(handle)
 Sleep_(2000) ; Give it a couple of seconds to open.
 EndProgram(id);End started program
With that I a code snippet that I can store for later use.

BTW is there a database for storing those useful codesnippets? I know there is the codearchive which is updated more or less frequently (IMHO less frequently).

Posted: Wed Apr 05, 2006 11:44 am
by PB
> A very valuable information, didn't found it in the help

In the v3.94 docs, it's under the "DefType" topic:
http://www.purebasic.com/documentation/ ... ftype.html

In the v4.00 docs, it's under the "Define" topic (because DefType is now Define).

@Fred: Maybe the following text from the topic called "Variables, Types
and Operators" should be changed to the following, because that's where
most people would expect to find an explanation of the default type:

OLD:
To declare a variable in PureBasic, simply type its name. You can also
specify the type you want this variable to be. Variables do not need to be
explicitly declared, as they can be used as "variables on-the-fly". The
Define keyword can be used to declare multiple variables in one statement.


NEW:
To declare a variable in PureBasic, simply type its name. You can also
specify the type you want this variable to be, but if you don't specify a
type then it will be of long (.l) type by default.
Variables do not need to
be explicitly declared, as they can be used as "variables on-the-fly". The
Define keyword can be used to declare multiple variables in one statement.

Posted: Wed Apr 05, 2006 9:46 pm
by Klonk
Found a problem in my routine, fixed it above. It seems like when additional program are run the handle delivered by RunProgram differs from the new handle. With ProcessID everything works fine.

Posted: Fri Apr 07, 2006 7:12 pm
by Klonk
Anotehr fix for my routine (added above) Added checking whether the process is still running and only then search for the correct window and send message.

Posted: Fri Apr 07, 2006 7:19 pm
by Klonk
I have a program (maybe there are more) that does not react on WM_CLOSE (don't know why). Anything else I could send???

In my Case it was the program SIREN, a renaming tool that did not react.

Posted: Tue Apr 18, 2006 4:09 pm
by Klonk
Just one addition to the code provided by PB:
Add the following into the While loop:

Code: Select all

delay(100)
I found that on certain circumstances (especially when the system is quite busy) the system seems to hang, i.e. opening other applications or windows is extremly slow. This gives the system time to open or launch applications.

In my case this oftenly happend when booting the computer.

Missing Commands

Posted: Tue Apr 18, 2006 8:38 pm
by laborde
ts-soft wrote:better close the program after kill

Code: Select all

pid = RunProgram("calc.exe", "", "", #PB_Program_Open)
Delay(1000)
KillProgram(pid)
CloseProgram(pid) ; clear Datas
I have PB Version 3.94 and it does not have the commands "KillProgram()" or "CloseProgram()". How do I add these commands. Also "#PB_Program_Open" cannot be found in the constants list.

Posted: Wed Apr 19, 2006 7:02 pm
by Klonk
Well this is a feature of PB4 and works there. As the new version will be officially released soon, please be patient.