Microsoft KB Archive/307391

From BetaArchive Wiki

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");
                

back to the top

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");
                

back to the top

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");
}
                

back to the top

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

  1. Start a new Managed C++ application called "Example" in Visual C++ .NET.
  2. 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

    NOTE: The sample code in step 4 of this section assumes that you followed the instructions in the preceding article to generate an interop assembly named Interop.Shdocvw.dll. It also assumes that you have copied this file into both the project directory and the output directory.
  3. In the Solution Explorer window, double-click Example.cpp.
  4. 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);
    }
                        
  5. Press F5 to build and run the project.
  6. After Internet Explorer is running, click the buttons on the form to test the code.

back to the top

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:

back to the top



Additional query words: hang, try...catch...finally

Keywords: kbDSupport kbhowto kbHOWTOmaster kbNewsgroupLink KB307391
Technology: kbAudDeveloper kbVCNET kbVCsearch