Solved

How to activate another process from c++

Posted on 2011-02-21
29
1,195 Views
Last Modified: 2012-05-11
I am trying to write a Windows forms application in C++ using Microsoft Visual C++.

At some point I need to activate a different process, and the problem is to find the windows handle of the other process.   I know the name of the executable from which it comes, and also have a DLL of my own installed so could in principle pass the handle over somehow.

The method I was proposing to use involved using EnumWindowsProc to iterate the windows until I find the one with the right executable name, then use SetActiveWindow to activate it.

The key lines of code are:

static BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam) {
... my code to find the window
}
...
Enum Windows(EnumWindowsProc,0)

This generates 2 errors - the first one says "calling convention of _stdcall ignored; _clrcall used instead"

and the second says

"Cannot convert parameter 1 &c &c - address of function yields _clrcall calling convention &c &c"

The problem is that when I try to set the compiler options to use _stdcall, the rest of the Windows Forms application generates numerous errors - it seems that it requires the _clrcall to work.

Any thought on either how to get this to work, or alteratively a different method of attaining my object.
0
Comment
Question by:DavidRMason
  • 14
  • 7
  • 6
  • +2
29 Comments
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 34943174
Is this C++ .NET?
0
 

Author Comment

by:DavidRMason
ID: 34943196
No
0
 

Author Comment

by:DavidRMason
ID: 34943223
By the way, I have made some progress while awaiting a response - by calling SetActiveWindow from the process that wants itself restored I have no compiler errors (as this process doesn't need Windows forms so can be compiled using _stdcall)  - but it still doesn't work - the process I want to activate flashes in the taskbar but doesn't activate as if I clicked the title bar which is what I want.

I've tried adding in

AttachThreadInput(GetCurrentThreadId(),GetWindowThreadProcessId(myWindowHandle,NULL),true)

but to no effect.
0
 
LVL 74

Assisted Solution

by:käµfm³d 👽
käµfm³d   👽 earned 50 total points
ID: 34943305
I don't mean to press the issue, but _clrcall implies managed code, which implies .NET. I agree that EnumWindows should be what you need, but I am curious why you're getting that particular error message....   curiouser and curiouser...
0
 

Author Comment

by:DavidRMason
ID: 34943406
I may be using .NET without being aware - how would I know?
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 34943415
What version of VS are you using?
0
 

Author Comment

by:DavidRMason
ID: 34943505
Microsoft Visual Studio C++ 2010 Express
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 34943627
Do you remember what project type you selected from the template list?
0
 

Author Comment

by:DavidRMason
ID: 34943722
Windows Forms Application
0
 
LVL 32

Expert Comment

by:sarabande
ID: 34943738
windows forms means always managed code (or CLR or .NET).

i don't know how to write the callback for EnumWindowProc in managed code. doing it with __stdcall would mean a mixed assembly (mixed managed and unmanaged code) what could work in a separate dll. but that all seems too complex for me.

Instead of EnumWindows you could call FindWindow or a loop with GetWindow/GetNextWindow what isn't as safe as EnumWindows but that shouldn't matter for your case.

if you found the window handle you could post a private message to that handle and have an event handler for that message on the other side.

the SetActiveWindow cannot work from a different process cause it only can called for windows belonging to the calling thread's message queue.

Sara





0
 

Author Comment

by:DavidRMason
ID: 34943826
Actually EnumWindows isn't the only problem - even with the handle, how can I activate the window?  

From the Windows Forms applications SetActiveWindow doesn't work as it also requires _stdcall, and calling it from the process I want to activate doesn't work either for the reasons cited in Sara's last paragraph.

Catch22?

0
 
LVL 32

Assisted Solution

by:sarabande
sarabande earned 217 total points
ID: 34944292
you can call SetForegroundWindow(hwnd). as far as i know it can be called by any thread.

Sara
0
 

Author Comment

by:DavidRMason
ID: 34944413
If I SetForegroundWindow(hwnd) from the process I want to activate it sits flashing in the toolbar, but doesn't activate until it's clicked

SetForegroundWindow(hwnd) doesn't compile if called from the Windows Forms process

Still catch22...
0
 
LVL 11

Accepted Solution

by:
DeepuAbrahamK earned 117 total points
ID: 34944976
HWND WINAPI FindWindow(
  __in_opt  LPCTSTR lpClassName,
  __in_opt  LPCTSTR lpWindowName
);

Why didn't you try FindWindow()?

http://msdn.microsoft.com/en-us/library/ms633499%28v=vs.85%29.aspx

Have a look at this link:
http://www.codeproject.com/KB/dialog/FindWindow.aspx
0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 

Author Comment

by:DavidRMason
ID: 34945121
FindWIndow would be another way of doing it, but it suffers from the same problem regarding calling method.

In any case even if I have the handle, how do I make use of it, given problems above on using SetActiveWindow or SetForegroundWindow

The fundamental issue is to find a calling sequence that will work from a Windows Forms application, where apparently _stdcall calling method isn't available (unless someone has a workaround for this).


0
 
LVL 32

Expert Comment

by:sarabande
ID: 34945176
in the window activated you may call

    ShowWindow(SW_RESTORE);

to get from icon state to normal state.

You could do that as a response to the WM_ACTIVATE message and LOWORD(wParam) == WA_ACTIVE.

Sara
0
 

Author Comment

by:DavidRMason
ID: 34945420
I've just tried that - it compiles fine, but still the same problem that the icon in the toolbar flashes, but the window doesn't activate until you click it.

By the way the syntax I had to use to compile was

ShowWindow(myWindowHandle, SW_RESTORE);

0
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 34945452
Have you considered SetForegroundWindow?
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 34945456
Disregard. I missed your above comment  = )
0
 
LVL 32

Expert Comment

by:sarabande
ID: 34945705
what is the myWindowHandle? it needs to be main window like dialog window or main frame.

Sara
0
 

Author Comment

by:DavidRMason
ID: 34945822
The code to set myWindowHandle is:

HWND myWindowHandle;
myWindowHandle=GetActiveWindow();

(executed when the window I want to activate was indeed active - hence avoiding the original problem with EnumWindows or FindWindow)

When I later execute SetForegroundWindow(myWindowHandle) then the icon in the task bar relating to the window I want to activate does indeed start to flash, which presumably means I really do have the correct handle.

David



0
 
LVL 32

Expert Comment

by:sarabande
ID: 34949319
the icon in the taskbar "is" your active window. you would need to restore from icon to normal window after you reognized being activated for example by handling WM_ACTIVATE_APP message.

Sara
0
 

Author Comment

by:DavidRMason
ID: 34949351
Sara - good idea -  unfortunately I don't have access to the Windows message queue in the app I want to activate, as I only have access to the source of a DLL (unless you have a way of getting at the queue from within a DLL not exposed to any windows callbacks that you can explain to me).

Another route that occurred to me overnight was to create a library with mixed _stdcall and _clrcall calling sequences explicitly entered, and include the library at link time.  

David
0
 
LVL 30

Assisted Solution

by:Zoppo
Zoppo earned 116 total points
ID: 34949495
Hi DavidRMason,

there are many reasons where Windows doesn't allow a process to move a window to foreground and activate it - here's a excerpt of MSDN article about SetForegroundWindow (http://msdn.microsoft.com/en-us/library/ms633539%28v=vs.85%29.aspx):

Remarks

The system restricts which processes can set the foreground window. A process can set the foreground window only if one of the following conditions is true:

    * The process is the foreground process.
    * The process was started by the foreground process.
    * The process received the last input event.
    * There is no foreground process.
    * The foreground process is being debugged.
    * The foreground is not locked (see LockSetForegroundWindow).
    * The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
    * No menus are active.

An application cannot force a window to the foreground while the user is working with another window. Instead, Foreground and Background Windows will activate the window (see SetActiveWindow) and call the function to notify the user.

A process that can set the foreground window can enable another process to set the foreground window by calling the AllowSetForegroundWindow function. The process specified by dwProcessId loses the ability to set the foreground window the next time the user generates input, unless the input is directed at that process, or the next time a process calls AllowSetForegroundWindow, unless that process is specified.


If setting a window to be the foreground window fails due to any of these reasons Windows does exactly what you describe: It doesn't show the window but let's the taskbar icon blink to inform the user a window tried to get active.

I don't think there's a workaround to force your window getting activated in foreground.

ZOPPO
0
 
LVL 32

Expert Comment

by:sarabande
ID: 34949677
if you are in a dll of the process you need to recover you could install a hook to the message queue and handle it in the dll.

Sara
0
 

Author Comment

by:DavidRMason
ID: 34950043
Sara - Can you point me to an explanation of how to do this?

David
0
 
LVL 32

Assisted Solution

by:sarabande
sarabande earned 217 total points
ID: 34950203
is the dll managed code or unmanaged (normal) ?

for unmanaged you would call once in your dllmain or other init function

 hook = SetWindowsHookEx(WH_GETMESSAGE, yourMsgProc);

where hook is a global HHOOK handle. yourMsgProc is a callback function you have to provide in the dll.

LRESULT CALLBACK YourMsgProc(
  int code,       // hook code
  WPARAM wParam,  // removal flag
  LPARAM lParam   // address of structure with message
)
{
    MSG * pmsg = (MSG*)lParam;
    if (pmsg->message == WM_ACTIVATE_APP)
       ShowWindow(GetActiveWindow(), SW_RESTORE);
   
    if (code < 0)
       return CallNextHookEx(code, wParam, lParam);
}

note, the code above is not tested and probably not complete. i've seen such hooks in existing software but never made one myself.

Sara
0
 

Author Closing Comment

by:DavidRMason
ID: 34950539
Thanks again to all
0
 

Author Comment

by:DavidRMason
ID: 34950578
Final solution as follows:

- much easier to activate from the calling program due to complexities of usurping control (see Zoppo comment above)

- to avoid the problems with declaration of _stdcall function use FindWindow - I had tried this, amongst numerous other approaches, but when I looked more closely at why it didn't work, it was only that at link time it couldn't find the relevant object file - by including user32.lib this problem is resolved

The final working code reads:

void myActivate()
{
  HWND myWindowHandle=FindWindow(NULL,TEXT("my window name"));
 if (myWindowHandle!=NULL)
 {
    AttachThreadInput(GetWindowThreadProcessId(myWindowHandle,NULL),
                                   GetCurrentThreadProcessId(), true);
   SetForegroundWindow(myWindowHandle);
 }
}
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

If you have done a reformat of your hard drive and proceeded to do a successful Windows XP installation, you may notice that a choice between two operating systems when you start up the machine. Here is how to get rid of this: Click Start Clic…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

759 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now