PSS ID Number: 307391
Article Last Modified on 10/27/2002
The information in this article applies to:
- Microsoft Visual C++ .NET (2002)
This article was previously published under Q307391
This article refers to the following Microsoft .NET Framework Class Library namespaces:
- System.Drawing
- System.Windows.Forms
- System.Diagnostics
IN THIS TASK
SUMMARY
In some situations, you may want to determine whether an application is blocked or is still responding. For example, when you are automating Microsoft Internet Explorer, you may want to know whether Internet Explorer has stopped responding.
This article explains how to determine whether an automated instance of Internet Explorer has stopped responding and how to force a quit in Internet Explorer. Although the sample code in this article is written for Internet Explorer and Managed Extensions for Visual C++ .NET, you can use this approach with other applications as well.
The first three sections in this article outline the three important coding concepts that are necessary to accomplish this task. The fourth section demonstrates how to build the sample application.
back to the top
Start the Application
The sample code in this article uses Internet Explorer as the test application. The following code starts Internet Explorer and uses the GetProcessByName method to get a handle to the process:
InternetExplorerClass *Browser; Process *Procs[]; Browser = new InternetExplorerClass(); Browser->Visible = true; Browser->GoHome(); Procs = Process::GetProcessesByName(S"IEXPLORE");
Determine Whether the Application Is Responding
The following code checks the first element in the array procs, which the GetProcessByName method returns, to determine whether the process is responding.
NOTE: This article assumes that only one instance of Internet Explorer is running.
if (Browser) { if (Procs[0]->Responding) MessageBox::Show(S"IEXPLORE is Responding"); else MessageBox::Show(S"IEXPLORE is Not Responding"); } else MessageBox::Show(S"IEXPLORE is Not Running");
Close the Application
The following code demonstrates how to close the application. If the application is still responsive, you can use the CloseMainWindow method of the Process class to close it. If the application is not responsive, you must call the Kill method. Use the try-catch block to handle the exception that is thrown if the process does not exist.
try { if (Procs[0]->Responding) Procs[0]->CloseMainWindow(); else Procs[0]->Kill(); //Destroy object reference and array. CleanUp(); } catch (...) { MessageBox::Show(S"Could Not Find the IEXPLORE Process"); }
Build the Sample Project
About the Sample
The sample project in this article consists of a form that contains the following three buttons:
- Start Internet Explorer: Uses Automation to start an instance of Internet Explorer.
- Check Internet Explorer: Tests to see if the browser is responding.
- Close Internet Explorer: Closes the browser.
If you want to give this code a thorough test and know of a Web page that will cause the browser to stop responding, browse to that page after you open the browser. Then, click Check Internet Explorer and Close Internet Explorer. Allow a few moments after you click these buttons; the response is not immediate when the browser is unresponsive. back to the top
Steps to Build the Sample
- Start a new Managed C++ application called "Example" in Visual C++ .NET.
- Unlike C# and Visual Basic .NET, there is no Add Reference dialog box for Managed C++ projects. You need to manually add a reference to Shdocvw.dll to automate Internet Explorer.
See the "COM References" section in the following article for details:310674 HOW TO: Add References to a Managed Visual C++ Project
- In the Solution Explorer window, double-click Example.cpp.
Replace all of the code in Example.cpp with the following:
#include "stdafx.h" #using <mscorlib.dll> #using <System.Dll> #using <System.Drawing.Dll> #using <System.Windows.Forms.Dll> #using <Interop.Shdocvw.Dll> using namespace System; using namespace System::Drawing; using namespace System::Windows::Forms; using namespace System::Diagnostics; using namespace Interop::Shdocvw; namespace AppStoppedResponding_mc { public __gc class Form1 : public Form { private: Button *btnStart; Button *btnCheck; Button *btnClose; InternetExplorerClass *Browser; protected: Process *Procs[]; public: Form1() { InitializeComponent(); } private: void InitializeComponent() { btnCheck = new Button(); btnStart = new Button(); btnClose = new Button(); SuspendLayout(); // // btnCheck // btnCheck->Location = Point(66, 122); btnCheck->Name = S"btnCheck"; btnCheck->Size = System::Drawing::Size(152, 23); btnCheck->TabIndex = 1; btnCheck->Text = S"Check Internet Explorer"; btnCheck->Click += new System::EventHandler(this, btnCheck_Click); // // btnStart // btnStart->Location = Point(66, 74); btnStart->Name = S"btnStart"; btnStart->Size = System::Drawing::Size(152, 23); btnStart->TabIndex = 0; btnStart->Text = S"Start Internet Explorer"; btnStart->Click += new System::EventHandler(this, btnStart_Click); // // btnClose // btnClose->Location = Point(66, 170); btnClose->Name = S"btnClose"; btnClose->Size = System::Drawing::Size(152, 23); btnClose->TabIndex = 2; btnClose->Text = S"Close Internet Explorer"; btnClose->Click += new System::EventHandler(this, btnClose_Click); // // Form1 // AutoScaleBaseSize = System::Drawing::Size(5, 13); ClientSize = System::Drawing::Size(292, 266); Control *ControlArray[] = { btnClose, btnCheck, btnStart }; Controls->AddRange(ControlArray); Name = S"Form1"; Text = S"Form1"; Closing += new System::ComponentModel::CancelEventHandler(this, Form1_Closing); ResumeLayout(false); } void btnStart_Click(Object *sender, EventArgs *e) { Browser = new InternetExplorerClass(); Browser->Visible = true; Browser->GoHome(); Procs = Process::GetProcessesByName(S"IEXPLORE"); //Build event delegate to catch browser close event. DWebBrowserEvents2_OnQuitEventHandler *oDelegate; oDelegate = new DWebBrowserEvents2_OnQuitEventHandler(this, &Form1::Browser_OnQuit); Browser->OnQuit += oDelegate; } void btnCheck_Click(Object *sender, EventArgs *e) { if (Browser) { if (Procs[0]->Responding) MessageBox::Show(S"IEXPLORE is Responding"); else MessageBox::Show(S"IEXPLORE is Not Responding"); } else MessageBox::Show(S"IEXPLORE is Not Running"); } void btnClose_Click(Object *sender, EventArgs *e) { CloseBrowser(); } void Form1_Closing(Object *sender, System::ComponentModel::CancelEventArgs *e) { //If the browser is still open, close it when the form closes. if (Browser) CloseBrowser(); } void CloseBrowser() { try { if (Procs[0]->Responding) Procs[0]->CloseMainWindow(); else Procs[0]->Kill(); //Destroy object reference and array. CleanUp(); } catch (...) { MessageBox::Show(S"Could Not Find the IEXPLORE Process"); } } void Browser_OnQuit() { //event delegate - clean up if the browser is closed manually CleanUp(); } void CleanUp() { Browser = 0; Procs = 0; } }; } using namespace AppStoppedResponding_mc; void main() { Form1 *FormInstance = new Form1; Application::Run(FormInstance); }
- Press F5 to build and run the project.
- After Internet Explorer is running, click the buttons on the form to test the code.
REFERENCES
For additional information, click the article numbers below to view the articles in the Microsoft Knowledge Base:
304991 HOW TO: Detect if an Application Has Stopped Responding by Using C#
304990 HOW TO: Detect If an Application Has Stopped Responding by Using Visual Basic .NET
For more general information about Visual C++ .NET, visit the following Microsoft Usenet newsgroup and Microsoft Web site:
Additional query words: hang, try...catch...finally
Keywords: kbDSupport kbhowto kbHOWTOmaster kbNewsgroupLink KB307391
Technology: kbAudDeveloper kbVCNET kbVCsearch