How to use Visual C++ to close another application

For a Microsoft Visual Basic .NET version of this article, see
305602 .

For a Microsoft Visual C# .NET version of this article, see
305603 .

IN THIS TASK


Summary

This article describes how to close another application from within your application. This article also describes how to close a specific instance of another application, such as Notepad, if more than one instance of the application is running.

back to the top

Declare Variables

You must define several variables. Because these variables are used in multiple methods, define them outside any procedure so that they remain in scope.

The first variable is an array to hold the process objects that the GetProcessByName method returns. In this code, "procName" is a String variable that is used to hold the name of the process:
private:
Process *processes[];
static String *procName = S"Notepad";
back to the top

Obtain a List of Application Instances

The following code for the BuildList function is called each time a new instance of Notepad is created. This example stores the process information in a ListView control. The code to populate the ListView control is included only for consistency with the complete example that follows.

The most important part of this code is the call to the GetProcessByName method of the Process class. This method returns an array of Process object pointers, which can be iterated over by using a For loop.
ListViewItem *itemAdd ; 
ListView1->Items->Clear();
processes = Process::GetProcessesByName(procName);
for (int i = 0; i < processes->Length; i++)
{
itemAdd = ListView1->Items->Add(processes[i]->MainWindowTitle);
itemAdd->SubItems->Add(processes[i]->Id.ToString());
}
back to the top

Close a Specific Instance of an Application

When you have multiple instances of an application running, if you want to close one instance, you must differentiate between those processes. This example uses the Id property to differentiate between the processes. The Id property and the MainWindowTitle property are stored in the ListView control.

This code gets the item that is currently selected in the ListView control, obtains a reference to the process by using the GetProcessById method of the Process class, and then closes that process by calling the CloseMainWindow method. Note that you cannot rebuild the list before the process has exited fully because the WaitForExit method of the Process class prevents this.
try
{
ListViewItem *lvi = ListView1->SelectedItems->get_Item(0);
ListViewItem::ListViewSubItem *lvsi = lvi->SubItems->get_Item(1);
int procID = System::Convert::ToInt32(lvsi->Text);
Process *tempProc=Process::GetProcessById(procID);
tempProc->CloseMainWindow();
tempProc->WaitForExit();
BuildList();
}
catch(...)
{
MessageBox::Show(S"Select a process in the ListView.");
}
back to the top

Close All Instances of an Application

To close all instances of a particular application, walk the array that the GetProcessByName method returns, and then call the CloseMainWindow method on each process object.
try
{
for (int i = 0; i < processes->Length; i++)
{
processes[i]->CloseMainWindow();
}

ListView1->Items->Clear();
}
catch (System::NullReferenceException *)
{
MessageBox::Show("No instances of Notepad running.");
}
back to the top

Step-by-Step Example

  1. Create a new Managed C++ Application in Microsoft Visual Studio .NET or Microsoft Visual Studio 2005. To do this, follow these steps:
    1. Start Visual Studio .NET or Visual Studio 2005.
    2. On the File menu, point to
      New, and then click Project.
    3. In the New Project dialog box, click
      Visual C++ Projects under Project Types, and then click Managed C++ Application for Visual Studio .NET 2002, click Console Application (.NET) for Visual Studio .NET 2003, or click CLR Console Application for Visual Studio 2005 under
      Templates.
    4. Type a file name in the Name box.
  2. In Solution Explorer, open the project .cpp file.
  3. Replace the code in the Code window with the following:
    #include "stdafx.h"
    #include <windows.h>
    #ifdef MessageBox
    #undef MessageBox
    #endif

    #using <mscorlib.dll>
    #using "System.Dll"
    #using "System.Windows.Forms.Dll"
    #using "System.Drawing.Dll"

    using namespace System;
    using namespace System::Drawing;
    using namespace System::Collections;
    using namespace System::ComponentModel;
    using namespace System::Windows::Forms;
    using namespace System::Diagnostics;

    namespace CloseApplication_mc
    {
    public __gc class Form1 : public Form
    {
    protected:
    Button *btnCloseAll;
    ColumnHeader *ColumnHeader2;
    ColumnHeader *ColumnHeader1;
    Button *btnLaunch1;
    ListView *ListView1;
    Button *btnClose1;

    private:
    Process *processes[];
    static String *procName = S"Notepad";
    static String *specialFolder = Environment::GetFolderPath(Environment::SpecialFolder::System);

    public:
    Form1()
    {
    InitForm();
    }

    protected:
    void Dispose( bool disposing )
    {
    Form::Dispose(disposing);
    }

    private:
    void InitForm()
    {
    btnClose1 = new Button();
    ColumnHeader2 = new ColumnHeader();
    ColumnHeader1 = new ColumnHeader();
    btnCloseAll = new Button();
    btnLaunch1 = new Button();
    ListView1 = new ListView();
    SuspendLayout();

    //
    // btnClose1
    //
    btnClose1->Location = Point(160, 176);
    btnClose1->Name = S"btnClose1";
    btnClose1->Size = System::Drawing::Size(112, 32);
    btnClose1->TabIndex = 4;
    btnClose1->Text = S"Close Selected Process";
    btnClose1->Click += new System::EventHandler(this, btnClose1_Click);
    Controls->Add(btnClose1);

    //
    // btnCloseAll
    //
    btnCloseAll->Location = Point(160, 216);
    btnCloseAll->Name = S"btnCloseAll";
    btnCloseAll->Size = System::Drawing::Size(112, 32);
    btnCloseAll->TabIndex = 3;
    btnCloseAll->Text = S"Close All Processes";
    btnCloseAll->Click += new System::EventHandler(this, btnCloseAll_Click);
    Controls->Add(btnCloseAll);

    //
    // btnLaunch1
    //
    btnLaunch1->Location = Point(32, 176);
    btnLaunch1->Name = S"btnLaunch1";
    btnLaunch1->Size = System::Drawing::Size(112, 72);
    btnLaunch1->TabIndex = 1;
    btnLaunch1->Text = S"Start Notepad";
    btnLaunch1->Click += new System::EventHandler(this, btnLaunch1_Click);
    Controls->Add(btnLaunch1);

    //
    // ColumnHeader2
    //
    ColumnHeader2->Text = S"Process ID";
    ColumnHeader2->Width = 85;

    //
    // ColumnHeader1
    //
    ColumnHeader1->Text = S"Window Title";
    ColumnHeader1->Width = 160;

    //
    // ListView1
    //
    ListView1->Columns->Add(ColumnHeader1);
    ListView1->Columns->Add(ColumnHeader2);
    ListView1->Location = Point(22, 8);
    ListView1->MultiSelect = false;
    ListView1->Name = S"ListView1";
    ListView1->Size = System::Drawing::Size(250, 152);
    ListView1->TabIndex = 7;
    ListView1->View = View::Details;
    Controls->Add(ListView1);

    //
    // Form1
    //
    AutoScaleBaseSize = System::Drawing::Size(5, 13);
    ClientSize = System::Drawing::Size(292, 266);
    Name = S"Form1";
    Text = S"Process Example";
    Closing += new System::ComponentModel::CancelEventHandler(this, closing);
    Load += new System::EventHandler(this, Form1_Load);
    ResumeLayout(false);
    }

    void BuildList()
    {
    ListViewItem *itemAdd ;
    ListView1->Items->Clear();
    processes = Process::GetProcessesByName(procName);
    for (int i = 0; i < processes->Length; i++)
    {
    itemAdd = ListView1->Items->Add(processes[i]->MainWindowTitle);
    itemAdd->SubItems->Add(processes[i]->Id.ToString());
    }
    }

    void btnLaunch1_Click(Object *sender, EventArgs *e)
    {
    ProcessStartInfo *p = new ProcessStartInfo();
    p->FileName = String::Concat(specialFolder, S"\\eula.txt");
    p->WindowStyle = ProcessWindowStyle::Minimized ;
    Process *proc = Process::Start(p);
    proc->WaitForInputIdle();
    BuildList();
    }

    void Form1_Load(Object *sender, EventArgs *e)
    {
    }

    void btnClose1_Click(Object *sender, EventArgs *e)
    {
    try
    {
    ListViewItem *lvi = ListView1->SelectedItems->get_Item(0);
    ListViewItem::ListViewSubItem *lvsi = lvi->SubItems->get_Item(1);
    int procID = System::Convert::ToInt32(lvsi->Text);
    Process *tempProc=Process::GetProcessById(procID);
    tempProc->CloseMainWindow();
    tempProc->WaitForExit();
    BuildList();
    }
    catch(...)
    {
    MessageBox::Show(S"Select a process in the ListView before clicking this button.");
    }
    }

    void btnCloseAll_Click(Object *sender, EventArgs *e)
    {
    if (processes != 0)
    {
    for (int i = 0; i < processes->Length; i++)
    {
    processes[i]->CloseMainWindow();
    }

    ListView1->Items->Clear();
    }
    }

    void closing(Object *sender, System::ComponentModel::CancelEventArgs *e)
    {
    btnCloseAll_Click(this,e);
    }
    };
    }

    using namespace CloseApplication_mc;

    int APIENTRY WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPTSTR lpCmdLine,
    int nCmdShow)
    {
    Form1 *FormInstance = new Form1;
    Application::Run(FormInstance);

    return 0;
    }
  4. Build and then run the application.
  5. Click Start Notepad one or more times.
  6. Click an instance of Notepad in the
    ListView box, and then click Close Process. This closes the specific instance of Notepad that you selected. You can also click Close All Processes to close all the instances of Notepad that are running.
Note This article uses the Id property of the Process class to differentiate between instances of the application. The Id property is good for this task because all process IDs are unique. You can use the WindowHandle property of a Process object to get the same results. Although you can use other properties, they are less suitable for this task. If you do not know the process ID, or if you have the handle of the main window, you can also use the MainWindowTitle property to help identify the correct instance. However, because the MainWindowTitle property may not be unique, you cannot guarantee that you are referring to the correct window.

back to the top

References

For more information, see the "Process Class" page on the following Microsoft Developer Network (MSDN) Web site:
back to the top
Proprietăți

ID articol: 307395 - Ultima examinare: 3 ian. 2006 - Revizie: 1

Feedback