none
TerminateProcess not working in Windows 7 RRS feed

  • Question

  • Using this code; TerminateProcess works as expected in Windows XP but not in Windows 7 - why?
    HANDLE hProc = OpenProcess(PROCESS_TERMINATE, FALSE, piProcessInfo.dwProcessId);
    BOOL ptmResult = TerminateProcess(hProc, 0);
    CloseHandle(hProc);

    In Windows 7; using the above code:

    OpenProcess succeeds but TerminateProcess always returns 0 and GetLastError returns 00000005 - Access is denied.

    Again in Windows XP; using the above code, TerminateProcess works as expected.

    More Information: The process we're trying to terminate is Microsoft Internet Explorer (version 9). And IE was started using a call to the Windows CreateProcess API.

    Thanks;

    Tech_Net_User
    Wednesday, May 18, 2011 7:47 PM

Answers

All replies

  • Most likely because in XP you are running as an admin, whereas in Windows 7 due to UAC you are not. Have you tried running your app as an administrator?

    Not sure why OpenProcess succeeds though.

    Wednesday, May 18, 2011 8:24 PM
  • Using this code; TerminateProcess works as expected in Windows XP but not in Windows 7 - why?
    HANDLE hProc = OpenProcess(PROCESS_TERMINATE, FALSE, piProcessInfo.dwProcessId);
    BOOL ptmResult = TerminateProcess(hProc, 0);
    CloseHandle(hProc);

    In Windows 7; using the above code:

    OpenProcess succeeds but TerminateProcess always returns 0 and GetLastError returns 00000005 - Access is denied.Again in Windows XP; using the above code, TerminateProcess works as expected.

    If you run your process (that's calling TerminateProcess) elevated,
    does it then work in W7?

    Dave

    Wednesday, May 18, 2011 8:27 PM
  • Hello,

     

    How about when you close the process in Windows Task Manager? Will this do not work again? Did you check the piProcessInfo.dwProcessId is the IE 9 process ID not your application process ID.

     

    In addition, the TerminateProcess initiates termination and returns immediately. It is asynchronous function, when we get the return of it, the process will not be close immediately.

     

    I hope my suggestions can help you to solve this problem.

     

    Best regards,

    Jesse


    Jesse Jiang [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Thursday, May 19, 2011 2:56 AM
    Moderator
  • Jesse Jiang;

    Thanks for responding. Yes, I've double-checked and the process id is the IE 9 process id (not the process id of the "controlling process" - the process trying to close IE 9).

    How about what the other posters are commenting; that the new(er) Windows security model used in both Vista and Windows 7 requires the "controlling process" - the process trying to close IE 9 - must be running elevated (as administrator). Is that a possible cause of this problem?

    If insufficient process elevation is really the reason why TerminateProcess doesn't work in Windows 7 - I'd need guidance on exactly how to elevate the "controlling process" - the process trying to TerminateProcess on IE 9 - because the code issuing the TerminateProcess command is actually a C++ based DLL and I'm assuming the executable in which the DLL is running is the process that would have to be elevated. I know that normally you might simply set the properties of the EXE to: "Run as administrator", but in this case I don't actually own the EXE code (created by a 3rd party) and I don't have control over the installation (or property settings) of the EXE at customer site(s). So is there any way the DLL itself can elevate the process in which it is running to get to the elevation level required for TerminateProcess to succeed?

    Perhaps Another Possible Option: The "controlling process" - the process trying to close IE 9 - is the same process that launched IE 9 to begin with via a call to the Windows API "CreateProcess". Is there anything special I can do when issuing the "CreateProcess" command - perhaps a setting in one of the CreateProcess parameters - that would allow the "controlling process" to sucessfully call TerminateProcess on the process it started?

    Thank you;


    Tech_Net_User
    Thursday, May 19, 2011 1:10 PM
  • First of all, make sure that elevation solves your problem. 

    If so, your best bet is to create a helper .exe with an appropriate manifest to elevate it.  Have your DLL spawn the exe when you need to terminate the process.

    Thursday, May 19, 2011 2:17 PM
  • Hello,

     

    Would you mind letting me know the result of the suggestions? If you need further assistance, feel free to let me know. I will be more than happy to be of assistance.

     

    Best regards,

    Jesse


    Jesse Jiang [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Tuesday, May 24, 2011 3:15 AM
    Moderator
  • Hi Jesse;

    Yea, none of those suggests were the answer. What I've discovered is actually happening:

    • When IE 8 and/or IE 9 is NOT running and CreateProcess launches IE 8 or IE 9, then the dwThreadId and dwProcessId returned to CreateProcess are correct / valid. And these thread and process id values can be used to close the IE 8 / IE 9 process via a WM_CLOSE message or even a TerminateProcess command. However...

     

    • When IE 8 and/or IE 9 is already running and CreateProcess launches another instance of IE 8 / IE 9, then the dwThreadId and dwProcessId return to CreateProcess are NOT correct / valid. And these thread and process id values can NOT be used to close the IE 8 / IE 9 process via a WM_CLOSE message or even a TerminateProcess command.

    So what I struggling with now is to figure out how to programmatically (I'd like to use CreateProcess if possible) launch IE (all version I'm likely to encounter at customer site: 6, 7, 8 or 9) in such a way that I can close IE programmatically at a later time.

    With IE 6 and IE 7 CreateProcess works as expected and I can programmatically close IE as indicated above. But with IE 8 and IE 9, things don't work the same way and I've not found any one at Microsoft (yet) to explain how to accomplish this task.

    Any advice you can provide would be appreciated.

     


    Tech_Net_User
    Friday, June 3, 2011 3:16 PM
  • Hello,

     

    I write some codes as your describe, and I found the same problem, thanks for your good question. I would like you to provide us the sample codes in your project. In my codes, I just found that when I get the HWND of that Internet Explorer, I posted the WM_CLOSE message, but the explorer does not close. Therefore, I think your codes will be help for us to do more research.

     

    #include "stdafx.h"
    #include <Windows.h>
    
    static PROCESS_INFORMATION pi;
    BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lparam)
    {
    	DWORD  ProcId; 
    	DWORD  ThreadId; 
    	ThreadId=GetWindowThreadProcessId(hwnd,&ProcId);
    	printf("process id %d \n",ProcId);
    	if(ProcId==pi.dwProcessId)
    	{
    		 printf( "the iexplore hwnd is found \n");
    		 PostMessage(hwnd,WM_CLOSE,NULL,NULL);
    		 return false;
    	}
    	return true;
    }
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	STARTUPINFO si;
      
    
      ZeroMemory( &si, sizeof(si) );
      si.cb = sizeof(si);
      ZeroMemory( &pi, sizeof(pi) );
    
     /*  if( argc != 2 )
      {
        printf("Usage: %s [cmdline]\n", argv[0]);
        return;
      }*/
    
      // Start the child process. 
      if( !CreateProcess( L"C:\\Program Files\\Internet Explorer\\iexplore.exe",  // No module name (use command line)
        L"www.microsoft.com",    // Command line
        NULL,      // Process handle not inheritable
        NULL,      // Thread handle not inheritable
        TRUE,     // Set handle inheritance to FALSE
        0,       // No creation flags
        NULL,      // Use parent's environment block
        NULL,      // Use parent's starting directory 
        &si,      // Pointer to STARTUPINFO structure
        &pi )      // Pointer to PROCESS_INFORMATION structure
      ) 
      {
        printf( "CreateProcess failed (%d).\n", GetLastError() );
        return 0;
      }
    
      // Wait until child process exits.
      //
    	//WaitForInputIdle(pi.hProcess,INFINITE);
    //	WaitForSingleObject( pi.hProcess, INFINITE );
    	 printf( "CreateProcess success and then post cclose message.\n");
    	 if(!EnumWindows(EnumWindowsProc,(LPARAM)0))
    	 {
    		 printf( "EnumWindows false \n");
    	 }
    	 //GUITHREADINFO gui;
    	 //gui.cbSize = sizeof(GUITHREADINFO);
    	 
    	 //if(!GetGUIThreadInfo(pi.dwThreadId,&gui))
    	 //{
    		// printf( "GetGUIThreadInfo failed (%d).\n", GetLastError() );
    
    	 //}
    	 //if(gui.hwndActive)
    	 //{
    		// PostMessage(gui.hwndActive,WM_CLOSE,NULL,NULL);
    	 //}
    	 //else
    	 //{
    		// printf( "no hwnd can be found");
    	 //}
    	 
      // Close process and thread handles. 
      CloseHandle( pi.hProcess );
      CloseHandle( pi.hThread );
    
    
    	return 0;
    }
    

    Best regards,

    Jesse


    Jesse Jiang [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, June 6, 2011 6:15 AM
    Moderator
  • Hi Jesse Jiang;

    Thanks for posting that sample code and essentially confirming my results.

    The code I'm using is very similar to yours. I'm using CreateProcess to start IExplore.exe and I'm saving off the dwProcessId and dwThreadId returned to CreateProcess. Then later, I'm trying to shutdown IE by passing IE WM_CLOSE messages via the EnumWindowProc callback with dwThreadId and failing that I try using TerminateProcess with dwProcessId.

    Since my original posting on this topic, I've been doing a lot of testing and the issue is more involved that I first thought. The problem with using CreateProcess to launch IExplorer.exe (v8 and v9) has to do with some "special" startup functionality that Microsoft has introduced into the IExplorer.exe startup process.

    Here's the net fallout of this new IE startup functionality:

    • If IE (v8/v9) is NOT already running - your code, shown above, should work as expected. CreateProcess will launch IE and get back a dwThreadId and dwProcessId value that can be used to shutdown IE at a later time.

    However...

    • If IE (v8/v9) is already running - your code, shown above, will not work as expected. CreateProcess will launch another instance of IE but the dwThreadId and dwProcessId returned to CreateProcess cannot be used at a later time to shutdown IE.

    I'm working a similar question on the MSDN "Internet Explorer Extension Development" Forum - "Use CreateProcess to launch IE 9 and get the correct process ID and thread ID for shutting down IE at a later time". On that thread MVP: "Sheng Jiang" suggests using the Windows API: "IELaunchURL" to start IE. That API will return the correct process Id for the "tab" window within IE. But he cautions that the "tab" process Id cannot be used directly to shutdown IE at a later time. The WM_CLOSE message (and TerminateProcess command) must be used against the "frame" process Id. 

    To get the "frame" process Id from the "tab" process Id the MVP suggests: "You can get the parent process id of the tab process by enumerating processes". Unfortunately I havent' gotten a response yet about which specific Windows API should be used to enumerate processes. I'd expect some API that takes the "tab" process Id as an input parameter and returns the "frame" process Id. Otherwise why call IELaunchURL and deal with a "tab" process Id?

    Anyway, if I can get an answer, I'll pass it on. And if you hear anything, please do the same.

    Thanks;


    Tech_Net_User
    Monday, June 6, 2011 1:49 PM
  • I've been thinking about this and there seems to be two major problems.

    First, the reason why it is failing is because there is an existing IE window open. If you successfully managed to find the parent proces and terminate it, what would happen to the rest of the tabs open? Well, obviously they would all get terminated too, so what would happen to data from other sites that the user has open at the time, and would the user want them closed unexpectedly?

    Secondly, TerminateProcess is a bad function to use, using it to just close an IE window. ExitProcess would be the function of choice as terminate would end up with data loss, corruption and possibly other issues. Would you want a program doing this on your system? I certainly wouldn't.


    This is a signature

    Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.
    Visit my (not very good) blog at
    http://ccprogramming.wordpress.com/
    Monday, June 6, 2011 8:56 PM
  • Jesse Jiang;

    Please see my solution posted to thread "Use CreateProcess to launch IE 9 and get the correct process ID and thread ID for shutting down IE at a later time" in the "Internet Explorer Extension Development" thread.

    URL: http://social.msdn.microsoft.com/Forums/en-US/ieextensiondevelopment/thread/803834b2-4f2a-4880-8bfa-7f23ded7252b

     

    Thank you;


    Tech_Net_User
    • Marked as answer by TechNetUser Monday, June 13, 2011 2:41 PM
    Monday, June 13, 2011 2:41 PM
  • Hi TechNetUser,

     

    You did an excellent job, thanks for your sharing the solution.

     

    Best regards,

    Jesse


    Jesse Jiang [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Tuesday, June 14, 2011 5:10 AM
    Moderator