LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

WinAPI Some Instances of the same application

hi all,

a everyday thing: I want to look over the WIN-OS before starting an application if there are other instances of this application are running. If other instances are found, I try to delete them. I wrote some lines of code (attached) using the matching (???) WinAPI-functions but it doesnt run ? the running instances (e.g. having a special String in the window-title) are found but they do not do anything if I send "DestroyMessage(iWindowHandle)". Any hints or help ?

best regards

Simon
0 Kudos
Message 1 of 10
(4,778 Views)
I'm not able to give a response on WinApi calls, but if your application is written in CVI you should take a look at CheckForDuplicateAppInstance: it is possible that this function saves you some headace, even if its functionality is way less specialized than your requirements.


Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 2 of 10
(4,773 Views)

Hey Simon - 

 

When I try your code, GetLastError following DestroyWindow returns error 5, which is "Access is denied".  That is because DestroyWindow can only be called from the thread that created the window.  To see how to cleanly shut down a process, check out this Microsoft KB.

 

NickB

National Instruments 

0 Kudos
Message 3 of 10
(4,760 Views)
hi nick,

right, my error was to enum the windows, but I have to enum the applications ?

thanks and best regards

Simon
0 Kudos
Message 4 of 10
(4,756 Views)

Simon - 

 

No - you are right to use EnumWindows, you need to get a reference to the application you want to shut down somehow.  However, instead of telling the application to shut down with DestroyWindow, you should instead use something like PostMessage to send a WM_CLOSE message to the window.  

 

Once the message has been posted, you can wait on the handle returned from OpenProcess  (using the process id returned from GetWindowThreadProcessId) with WaitForSingleObject.  If you timeout, you know that the application you tried to close did not respond to the WM_CLOSE message, and you can then call TerminateProcess on that process.

 

This is all laid out very clearly in the KB I linked to in my previous post.

 

NickB

National Instruments 

0 Kudos
Message 5 of 10
(4,750 Views)
hi nick,

sorry for my bad "speeking windows", I tried to walk the KB, but it doesnt work:

1. I tried to call all the toplevel windows to call a callback -ok
2. I compared the title with another string in order to select some windows -ok
3. I got the processID of the thread these windows are owned -ok
4. I tried to open the process - not possible ???

the sample code is also attached

best regards

Simon


/*=============================================================*/
/*!

\brief UIR_killOtherRunningInstances

\param Kills all the running programs having a title
starting with the sTitleBegin

*/
/*=============================================================*/
void UIR_killOtherRunningInstances()
{
//Call the handles of all the TopLevel-Windows to the Callback-Fct
EnumWindows(UIR_callBack,0);
}

/*=============================================================*/
/*!

\brief UIR_callBack

\param The CB called by EnumWindows()

*/
/*=============================================================*/
BOOL CALLBACK UIR_callBack(HWND iWinHandle,LPARAM iParam)
{
HWND iTest=iWinHandle;
HANDLE hProcess;
DWORD dwRet,dwPID;

char title[MAX_PATHNAME_LEN];

//Reading the title of the Window calls back
//If the Window starts with MPEPIP_TITLEBEGIN_STRING remove
GetWindowText(iWinHandle,title,sizeof(title));
char* pResult=strstr(title,MPEPIP_TITLEBEGIN_STRING);

if(pResult && pResult==title)
{
//Dont remove yourself
int iThisWinHandle;
GetPanelAttribute(iPanelHandle,ATTR_SYSTEM_WINDOW_HANDLE,&iThisWinHandle);
if((HWND) iThisWinHandle != iWinHandle)
{
//Get the ThreadProcess of this Window
dwPID=GetWindowThreadProcessId(iWinHandle, NULL);

//If we cant open the process with process-terminate-rights
//then we give up immedialtely
hProcess=OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE, FALSE,dwPID);
if(hProcess==NULL) return TRUE;

//Post WM_CLOSE to all the windows whose PID matches to the process
EnumWindows((WNDENUMPROC)TerminateAppEnum, (LPARAM) dwPID);

//Wait, if it signals - great. If it times out kill the process
unsigned long dwTimeOut=200;

if(WaitForSingleObject(hProcess, dwTimeOut!=WAIT_OBJECT_0))
dwRet=TerminateProcess(hProcess,0);

CloseHandle(hProcess);
}
}
return TRUE;
}


BOOL CALLBACK TerminateAppEnum(HWND hwnd, LPARAM lParam)
{
DWORD dwID;

GetWindowThreadProcessId(hwnd,&dwID);
if(dwID==(DWORD)lParam)
{
PostMessage(hwnd,WM_CLOSE,0,0);
}
return TRUE;
}
0 Kudos
Message 6 of 10
(4,739 Views)

hey Simon -

 

I'm not sure what you mean when you say you are unable to open the process.  What error do you get?  What does GetLastError return?  Could you not have permission to open it with terminate rights?

 

Also - You have a misplaced parentheses in your WaitForSingleObject call - the closing paren should be before the '!=WAIT_OBJECT_0' 

 

NickB

National Instruments 

0 Kudos
Message 7 of 10
(4,708 Views)
hi nick,

sorry for the paran-mistake, but I cant find the really error. to make it clearly, I packed all in a 20-lines-CVI-project. it opens two instances of "notepad" and tries to kill these two instances. the OpenProcess()-fct brings back an NULL-pointer and GetLastError() a 87, what means "wrong parameter".

thanks and best regards

Simon
0 Kudos
Message 8 of 10
(4,691 Views)

Hey Simon -

 

Turns out it was a simple mistake I should have caught the last time I looked.  In your UIR_Callback function, you are calling GetWindowThreadProcessId, but are assigning the return value to your dwPID variable.  The return value of GetWindowThreadProcessId is the thread ID for the window, and not the process ID, which is required by OpenProcess.  The call should instead look like it does in your TerminateAppEnum call:

 

GetWindowThreadProcessId(iWinHandle,&dwID);

 

Once you make this change, I think you should see the program work as expected.

 

NickB

National Instruments 

Message 9 of 10
(4,675 Views)
hi nick,

that was it - thank you.

best regards

Simon
0 Kudos
Message 10 of 10
(4,670 Views)