×
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Contact US

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Students Click Here

set EXE on foreground using PID

set EXE on foreground using PID

set EXE on foreground using PID

(OP)
Hi

If I know the PID of another .EXE that's running, how can I bring that .EXE to the foreground to make sure it's visible?

Regards, Gerrit

RE: set EXE on foreground using PID

Gerrit,
You can bring an .EXE to the foreground by using the Win32 API's FindWindow() and SetForeGroundWindow() through Platform invoke. This will set the running .EXE application as the foreground window. The FindWindow() API will search for the window with the given PID and the SetForeGroundWindow() API will set the window as the foreground window.

CODE

* Declare the necessary API functions
DECLARE INTEGER FindWindow IN user32.dll STRING lpClassName, STRING lpWindowName
DECLARE INTEGER SetForegroundWindow IN user32.dll INTEGER hWnd

* Set the PID of the target .EXE application
targetPID = 1234  && Replace with the actual PID of the .EXE process

* Use the FindWindow API function to get the handle of the application's window
windowHandle = FindWindow(0, "")
DO WHILE windowHandle > 0
    IF GetWindowThreadProcessId(windowHandle, @lpdwProcessId) = 0
        * Error getting the process ID, handle it here
        EXIT
    ENDIF

    IF lpdwProcessId = targetPID
        * This is the window we're looking for, bring it to the foreground
        SetForegroundWindow(windowHandle)
        EXIT
    ENDIF

    * Get the next window handle
    windowHandle = GetWindow(windowHandle, GW_HWNDNEXT)
ENDDO 

Best Regards,
Scott
MSc ISM, MIET, MASHRAE, CDCAP, CDCP, CDCS, CDCE, CTDC, CTIA, ATS, ATD

"I try to be nice, but sometimes my mouth doesn't cooperate."

RE: set EXE on foreground using PID

(OP)
Hi Scott,

I get an error: Variable 'LPDWPROCESSID' is not found
It seems something is missing in your code sample.

Regards, Gerrit

RE: set EXE on foreground using PID

The declaration of GetWindowThreadProcessId is missing, also that of GetWindow.

Chriss

RE: set EXE on foreground using PID

Here's something based on https://github.com/VFPX/Win32API/blob/master/sampl..., which lists all child windows of the Windows desktop.
I added the filtering by process ID and concentrated on the Hwnd, not titles, position and size, etc.:

CODE

#Define GW_HWNDLAST 1
#Define GW_HWNDNEXT 2
#Define GW_CHILD 5
Do Declare

Local lnProcessHwnd, lnPID

lnPID = 8120 && for my test, this was _vfp.processid of a second VFP IDE.
lnProcessHwnd = FindProcessWindow(lnPID)
SetForegroundWindow(lnProcessHwnd)

Function FindProcessWindow()
   Lparameters tnTargetPID

   Local lnHDesktop, lnHFirstChild, lnHLastChild, lnVisible, lnPID, lnReturnHwnd, lpdwProcessId 
   lnHDesktop = GetDesktopWindow()
   lnHFirstChild = GetWindow(lnHDesktop, GW_CHILD)
   lnHLastChild = GetWindow(lnHFirstChild, GW_HWNDLAST)
   lnHCurrent = lnHFirstChild
   lpdwProcessId = 0
   Do While .T.
      lnVisible = IsWindowVisible(lnHCurrent)
      If lnVisible=1
         GetWindowThreadProcessId(lnHCurrent, @lpdwProcessId)
         If lpdwProcessId = tnTargetPID
            lnReturnHwnd = lnHCurrent
            Exit
         Endif
      Endif
      If lnHCurrent = lnHLastChild
         lnReturnHwnd = -1
         Exit
      Endif
      lnHCurrent = GetWindow(lnHCurrent, GW_HWNDNEXT)
   Enddo

   Return lnReturnHwnd

Procedure Declare
   Declare Integer GetDesktopWindow In user32
   Declare Integer GetWindow In user32 Integer HWnd, Integer wFlag
   Declare Integer IsWindowVisible In user32 Integer HWnd
   Declare Integer GetWindowThreadProcessId In user32.Dll Integer HWnd, Integer @lpdwProcessId
   Declare Integer SetForegroundWindow In user32.Dll Integer HWnd 

Notice: The overall code sample needs all DLL declaratons, the FindProcessWindow function needs all except SetForegroundWindow, because I designed the function to only return the first Hwnd it finds for the given processid, not to make it the foreground window. That#s done with the result hwnd. Feel free to integrate it, but I thought it's a good functionality usable not only for the goal of setting the foregroundwindow.

Also notice: It's based on the assumption that the first window you find in this enumeration of all desktop windows will be the major window handle for a process, the usual enumeration order goes from parent to child windows, and you start with the top parent window, the desktop itself.

I tested it with the process ID of a second VFP IDE and that worked fine, but that's no proof it always works. Besides quite recent threads that also had the topic of setting foreground windows just of the process itself by a known HWND. And that reveals timing problems, if you start several processes and set one to foreground, the next moment that can change again, especially at the start of Windows. That's another aspect needing caution and understanding about the situation you're in.

Chriss

RE: set EXE on foreground using PID

(OP)
Hi Chriss,

I got it working - at least in my test.prg - making a few changes:

CODE --> foxpro

lnProcessHwnd = FindProcessWindow(lnPID)
	WAIT WINDOW "lnProcessHwnd = " + TRANSFORM(lnProcessHwnd) timeout(1)
	&& SetForegroundWindow(lnProcessHwnd)
	DECLARE INTEGER BringWindowToTop IN Win32API INTEGER lhWnd
	IF lnProcessHwnd#0
		BringWindowToTop(lnProcessHwnd)
	ENDIF 

So far so good, I will now continue to try this in my project.
Thanks a lot!

Regards, Gerrit

RE: set EXE on foreground using PID

(OP)
Hi Chris,

Another update: it's working with my changes now in the project too.
At first it didn't do anything (nothing brought to foreground), but when I commented a few WAIT WINDOW it is now finally working.
I cannot explain this, so I activated a WAIT WINDOW again. And indeed it doesn't bring the window to the foreground.
At least I know what to do now.

Thanks again!

Regards, Gerrit

RE: set EXE on foreground using PID

Quote (Gerrit Broekhuis)

IF lnProcessHwnd#0
Notice if my function does not find a hwnd for the passed in process id I return -1, not 0. Well, maybe you changed that.

From the recent discussion I know SetForegroundWindow is actually the more relevant function for making it the foreground process at the same time of making it the foreground window. BringWindowToTop is of course, simply by name, an alternative. I don't know why it would work better for you, but may it be. Another reason to limit the function to only determine a Hwdn, to make use of it for different things.

I can imagine what happens when you do the wait window. It's not problematic that the wait window exists, but after the timeout of 1 second it will be released again, and that probably causes the parent VFP window to become foreground again, because the wait window is part of the VFP IDE. That also shows how shortlived this status of foreground can be and why it can change.

Chriss

RE: set EXE on foreground using PID

(OP)
Hi Chriss,

I used

CODE --> foxpro

LOCAL lnProcessHwnd
	lnProcessHwnd = FindProcessWindow(lnPID) 

I'm still confused about the WAIT WINDOW commands. After all the PID's don't change.

Regards, Gerrit

RE: set EXE on foreground using PID

Well, in short, any window can play a role in the processs of the Windows OS maintaining a foreground process and window. And wait window is a window, too. Anytime a window is becoming shown, it also becomes foreground. My assumption now is that anytime a window closes, that means Windows also monitors such moments to possibly decide for a new top contender.

I wouldn't bother finding out why. As you know not using a wait window solves the problem, that's the solution. You don't really want to show a hwnD to an end user, do you? You just did that for testing purposes.

Chriss

RE: set EXE on foreground using PID

Is the handle you get bei using

lnProcessHwnd = FindProcessWindow(lnPID)

a different "handle category" than the window handle you get by using FindWindow() ?

Thanks,
Manni

RE: set EXE on foreground using PID

Thank you Chris, so it's a window handle. The reason why I ask is I don't understand the difference when you use the PID to find a window handle or if you find the same window handle by issuing FindWindow() using the window caption.

If it's the same handle in the end, why does SetForegroundWindow() not work in both cases?

Thanks,
Manni

RE: set EXE on foreground using PID

You're perhaps overlooking that the information Gerrit has is the PID and not a title?

The goal is to get a HWnd when you know a PID, a process ID, as per question of Gerrit. That's not a windows title, caption or class name. FindWindow() doesn't offer that. So, no, you don't find a window by a process id directly with FindWindow(). There also isn't another Windows API function that does so directly. Since Scotts solution was incomplete I based mine on the news2news sample I referred to. If you think there's something simpler, feel free to add it. I don't see that you could directly get to a HWnd from a PID somehow and other solutions in C++ or C# you find also use either Enumwindows or other means to iterate all windows and GetWindowThreadProcessId to find out to which process a window hwnd belongs. For example https://stackoverflow.com/questions/11711417/get-h....

What you do with the Hwnd is up to you. I already explained why I thought such a function better returns the Hwnd than directly doing the BringWindowToTop or SetForegroundWindow. The next step could also be sending Windows messages to the Hwnd, for example.

Chriss

RE: set EXE on foreground using PID

Hi Chriss,

no I understood that, but I thought the reason for using the PID instead of window handle to begin with was because for some reason using the window handle to put the window to the foreground wasn't working. Hope this makes sense.

Thanks,
Manni

RE: set EXE on foreground using PID

(OP)
Hi Manni,

I could not use the window title, as multiple instances of the same executable will have similar titles. Therefore I used the PID. I could list the PID’s and pick the ‘oldest’ one, being the first execution of the executable. Just what I needed for my purpose.

I use this to archive e-mails from Outlook into MySQL and I had to be sure no other mail was left unsaved to prevent database / content errors.

Regards, Gerrit

RE: set EXE on foreground using PID

Manni,

well, if you have a hwnd you're at the goal of doing anything with the window as far as your privileges go, i.e. you can do more by being owner of a process.

Gerrit,

I don't know how you pick the oldest pid I just hope you don't pick the lowest, the PIDs are not ascending.
If you work with Outlook isn't the easiest way to automate it by using Outlook.Application?

Chriss

RE: set EXE on foreground using PID

(OP)
Hi Chriss,

I add all win32 processes into a cursor and sort on creationdate. I hope I use the right terms here, I don’t have my office computer with me right now.

I understand very well what you mean and I checked the outcome several times. I get 100% reliable results and checked with various .exe’s to be sure. For example you can open notepad and enter “1” in it’s window. Wait a few seconds, open another notepad and enter “2”. You can add more instances of notepad if you want. If you bring a notepad instance to the foreground using it’s PID, you will immediately see if you get the right notepad.

Regards, Gerrit

RE: set EXE on foreground using PID

Okay, assuming you use WMi to get a list of win32_process classes, they have a creationdate which is a datetime.
https://learn.microsoft.com/de-de/windows/win32/ci...
That will work well to get the oldest process. I don't know why that's relevant for your Outlook mail backup, but you know best.

I just remembered Christoph Wollenhaupt has OLIndex.zip in his downloads: http://www.foxpert.com/downloads.html. it does not look like it's what you need, as its goal is to buid a full text index on all mail items for fast searching. You can skip the part creatng such an index, the first part of the code is to get all mail items from outlook, exactly what you'd need to backup them. In this case they are all read into DBFs.

Chriss

RE: set EXE on foreground using PID

(OP)
Hi Chriss,

Thanks for the link to OLIndex. However it’s not relevant for my project that archives a single e-mail message into a MySQL database and saves the .msg file to disk. The message can then be deleted from Outlook. After all Outlook is not suitable for storing lot’s of mail.

Regards, Gerrit

RE: set EXE on foreground using PID

You can save a single mail even simpler with OLE automation of Outlook.Application. No need to bring a window to top at all. It's up to you to ask a follow up.

The only challenge here is selecting which mail.

Here's a sketch of what to do:

1. Get at the mail items folder:

CODE

#DEFINE olFolderInBox 6
Local loOutlook, loMapiNameSpace, loInbox
loOutlook = CreateObject('Outlook.Application')
loMapiNameSpace = loOutloook.GetNameSpace('MAPI')
loInbox = loMapiNameSpace.GetDefaultFolder(olFolderInbox)
* Now all mail items are in the collection loInbox.Items
* You can spot unread mail items, identify mail items by subject or attachment or whatever criteria you want.
* And a mail item has a SaveAs method, so you can fully automate saving as msg or eml or whatever format you like. 
See FAQ184-3894: Usefull functions with Outlook Automation for many more useful snippets to get something from Outlook, without half automation by activation of a window and then using Sendkeys or such second best automation tricks. Outlook has an automation server to be able to automate it, so make use of it.

Chriss

RE: set EXE on foreground using PID

Thanks, Gerrit and Chriss, I didn't need it yet to find a window by PID, but it's useful to know how it can be done.

Regards,
Manni

RE: set EXE on foreground using PID

(OP)
Hi Chriss,

My application saves the e-mail message into a MySQL database with a table for a lot of message specific fields, like sender, datetime sent, datetime received, subject, txt message, html message, attachments, etc.. Each e-mail is saved for a specific company (or private person) and the .msg file is only kept as a reference, with a link to the file in the database.

Once the e-mail is in my database I have another, larger app, that can search in all fields (including e-mail content), show the e-mail content, attachments, etc.. This works very well and works “easier” than searching in
Exchange Server.

E-mail concerning invoices can be archived for that specific invoice (or order). This is part of creating a good file in case legal steps are required to get an invoice paid.

When the mail is saved like this, the original mail can be deleted from Outlook (or Exchange Server).

Regards, Gerrit

RE: set EXE on foreground using PID

That can all still be achieved, Gerrit.

I'm not telling ou to not use your MYSQL Server solution, I'm just telling you that you can fully automate the process to get from Outlook to there. And this doesn't need to bring a window to top.

I think along these lines, Gerrit: Why do you want to bring a window to top? Because that's helping the user 8perhaps you yourself) to act on this window or you use programmatic keyboard/mouse input to control that window. It could be outlook, it could be a mail of outlook, whatever. Perhaps you can use a tool that integrates into outlook as a plugin, I don't care. But with outlook automation you get at mail items too, and their single properties. So you could pull out anthing about the mail item and save it to MySQL yourself.

Chriss

RE: set EXE on foreground using PID

(OP)
Chriss,

The application we talked about is just 5% of en entire application suite built with VFP, PHP and MySQL (plus some third party components). We store everything that is digital or can be digitized in our database and we do that for nearly all business processes from sales, project management, document management, planning, tasks, procurement, stock, quotations, customers, suppliers, etc., etc..

I don’t tbink I would want to run ODBC connections to MySQL withing Outlook. What we do with the data is more than can be programmed in MS Office. It becomes even more problematic if you have to support everything from Office 2007 onward. I don’t even want to think about this…

I will leave this as it is now, as it has been working fine now for years and we have happy customers.

Regards, Gerrit

RE: set EXE on foreground using PID

Who talked about ODBC from Outlook? When you have a mail item in VFP you can go from there. I think all I'm saying is misunderstood, so let's simply forget it.

Chriss

RE: set EXE on foreground using PID

(OP)
Hi Chriss,

I know what you mean, and that may be usefull for a single user. When working in a company with many Outlook users working with Exchange Server or Exchange Online (O365) there are other needs that go much further than can be accomplished with Outlook.

I know it's going off topic, but one again I thank you very much for your help. You really made my day1

Regards, Gerrit

RE: set EXE on foreground using PID

Gerrit,

you just prove once more your misunderstanding. You said yourself, that you read mails from Outlook and delete them there.

Quote (Gerrit Broekhuis)

I use this to archive e-mails from Outlook into MySQL

Quote (Gerrit Broekhuis)

my project that archives a single e-mail message into a MySQL database and saves the .msg file to disk. The message can then be deleted from Outlook.

You can do exactly that, read a mail and delete it, fully with VFP and without any user interaction and without any visible additional window, by Outlook automation from VFP with VFP code. That's all I'm saying and pointing out.

Chriss

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members! Already a Member? Login


Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close