• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1252
  • Last Modified:

How to activate another process from c++

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
DavidRMason
Asked:
DavidRMason
  • 14
  • 7
  • 6
  • +2
5 Solutions
 
käµfm³d 👽Commented:
Is this C++ .NET?
0
 
DavidRMasonAuthor Commented:
No
0
 
DavidRMasonAuthor Commented:
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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
käµfm³d 👽Commented:
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
 
DavidRMasonAuthor Commented:
I may be using .NET without being aware - how would I know?
0
 
käµfm³d 👽Commented:
What version of VS are you using?
0
 
DavidRMasonAuthor Commented:
Microsoft Visual Studio C++ 2010 Express
0
 
käµfm³d 👽Commented:
Do you remember what project type you selected from the template list?
0
 
DavidRMasonAuthor Commented:
Windows Forms Application
0
 
sarabandeCommented:
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
 
DavidRMasonAuthor Commented:
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
 
sarabandeCommented:
you can call SetForegroundWindow(hwnd). as far as i know it can be called by any thread.

Sara
0
 
DavidRMasonAuthor Commented:
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
 
Deepu AbrahamR & D Engineering ManagerCommented:
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
 
DavidRMasonAuthor Commented:
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
 
sarabandeCommented:
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
 
DavidRMasonAuthor Commented:
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
 
käµfm³d 👽Commented:
Have you considered SetForegroundWindow?
0
 
käµfm³d 👽Commented:
Disregard. I missed your above comment  = )
0
 
sarabandeCommented:
what is the myWindowHandle? it needs to be main window like dialog window or main frame.

Sara
0
 
DavidRMasonAuthor Commented:
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
 
sarabandeCommented:
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
 
DavidRMasonAuthor Commented:
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
 
ZoppoCommented:
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
 
sarabandeCommented:
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
 
DavidRMasonAuthor Commented:
Sara - Can you point me to an explanation of how to do this?

David
0
 
sarabandeCommented:
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
 
DavidRMasonAuthor Commented:
Thanks again to all
0
 
DavidRMasonAuthor Commented:
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

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 14
  • 7
  • 6
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now