Microsoft KB Archive/305602

From BetaArchive Wiki

Article ID: 305602

Article Last Modified on 3/29/2007



APPLIES TO

  • Microsoft Visual Basic 2005
  • Microsoft Visual Basic .NET 2003 Standard Edition
  • Microsoft Visual Basic .NET 2002 Standard Edition



This article was previously published under Q305602


For a Microsoft Visual C++ .NET version of this article, see 307395.

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

For a Microsoft Visual Basic 6.0 version of this article, see 176391.



IN THIS TASK

SUMMARY

REFERENCES

SUMMARY

This article describes how to close an application from within an application. It 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

Discussion of the Programming Logic

Declare Variables

Several variables need to be defined. Because these variables are used in multiple methods, they should be defined outside of any procedure so that they remain in scope. The proc variable holds a reference to an individual process object, and processes is an array that holds the process objects that are returned by the GetProcessByName method:

Private proc As Process
Private processes() As Process
Private procName As String = "notepad"
                

Obtain a List of Application Instances

The following code comprises a function (called buildList in the sample) that is called each time a new instance of Notepad is created. This sample stores the process information in a ListView control; the code to populate the ListView control is included only for consistency with the complete sample. 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 objects, which can be iterated over by using a For...Each block, as follows:

Dim itemAdd As ListViewItem
ListView1.Items.Clear()

processes = Process.GetProcessesByName(procName)

For Each proc In processes
    itemAdd = ListView1.Items.Add(proc.MainWindowTitle)
    itemAdd.SubItems.Add(proc.Id.ToString)
Next
                

Close a Specific Instance of an Application

When multiple instances of an application are running, and you want to close one instance, you must differentiate between those processes. The following sample uses the Id property of the Process object to tell the processes apart. The Id property and the MainWindowTitle property (another property of the Process object) are stored in the ListView control. The code obtains 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 closes that process by calling the CloseMainWindow method, as follows:

Try
    Dim procID As Integer = _  
     System.Convert.ToInt32(ListView1.SelectedItems(0).SubItems(1).Text)
    Dim tempProc As Process = Process.GetProcessById(procID)
    tempProc.CloseMainWindow()
    tempProc.WaitForExit()
    buildList()
Catch
    MessageBox.Show("Please select a process in the ListView before clicking this button." + _
      " Or the Process may have been closed by somebody.")
    buildList()
End Try
                

Close All Instances of an Application

Closing all instances of a particular application is relatively straightforward. You can walk the array that is returned by the GetProcessByName method and call the CloseMainWindow method on each process object, as follows:

Try
  For Each proc In processes
    proc.CloseMainWindow()
    proc.WaitForExit()
  Next
  buildList()
Catch ex As System.NullReferenceException
  MessageBox.Show("No instances of Notepad running.")      
End Try
                

back to the top

Steps to Build the Sample

  1. Start a new Visual Basic Windows application in Visual Studio .NET or in Visual Studio 2005.
  2. Right-click the default form, Form1.vb, and select View Code.
  3. Replace the code that is in the code window with the following:

    Option Strict On
    Option Explicit On 
    
    Public Class Form1
      Inherits System.Windows.Forms.Form
    
    #Region " Windows Form Designer generated code "
    
      Public Sub New()
        MyBase.New()
    
        'This call is required by the Windows Form Designer.
        InitializeComponent()
    
        'Add any initialization after the InitializeComponent() call.
    
      End Sub
    
      'Form overrides dispose to clean up the component list.
      Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
          If Not (components Is Nothing) Then
            components.Dispose()
          End If
        End If
        MyBase.Dispose(disposing)
      End Sub
      Friend WithEvents btnLaunch1 As System.Windows.Forms.Button
      Friend WithEvents ColumnHeader1 As System.Windows.Forms.ColumnHeader
      Friend WithEvents ColumnHeader2 As System.Windows.Forms.ColumnHeader
      Friend WithEvents ListView1 As System.Windows.Forms.ListView
      Friend WithEvents btnCloseAll As System.Windows.Forms.Button
      Friend WithEvents btnClose1 As System.Windows.Forms.Button
    
      'Required by the Windows Form Designer.
      Private components As System.ComponentModel.Container
    
      'NOTE: The following procedure is required by the Windows Form Designer
      'It can be modified by using the Windows Form Designer.  
      'Do not modify it by using the code editor.
      <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.btnClose1 = New System.Windows.Forms.Button()
        Me.ListView1 = New System.Windows.Forms.ListView()
        Me.ColumnHeader1 = New System.Windows.Forms.ColumnHeader()
        Me.ColumnHeader2 = New System.Windows.Forms.ColumnHeader()
        Me.btnCloseAll = New System.Windows.Forms.Button()
        Me.btnLaunch1 = New System.Windows.Forms.Button()
        Me.SuspendLayout()
        '
        'btnClose1
        '
        Me.btnClose1.Location = New System.Drawing.Point(160, 176)
        Me.btnClose1.Name = "btnClose1"
        Me.btnClose1.Size = New System.Drawing.Size(112, 32)
        Me.btnClose1.TabIndex = 4
        Me.btnClose1.Text = "Close Selected Process"
        '
        'ListView1
        '
        Me.ListView1.Columns.AddRange(New System.Windows.Forms.ColumnHeader() {Me.ColumnHeader1, Me.ColumnHeader2})
        Me.ListView1.Location = New System.Drawing.Point(22, 8)
        Me.ListView1.MultiSelect = False
        Me.ListView1.Name = "ListView1"
        Me.ListView1.Size = New System.Drawing.Size(250, 152)
        Me.ListView1.TabIndex = 7
        Me.ListView1.View = System.Windows.Forms.View.Details
        '
        'ColumnHeader1
        '
        Me.ColumnHeader1.Text = "Window Title"
        Me.ColumnHeader1.Width = 160
        '
        'ColumnHeader2
        '
        Me.ColumnHeader2.Text = "Process ID"
        Me.ColumnHeader2.Width = 85
        '
        'btnCloseAll
        '
        Me.btnCloseAll.Location = New System.Drawing.Point(160, 216)
        Me.btnCloseAll.Name = "btnCloseAll"
        Me.btnCloseAll.Size = New System.Drawing.Size(112, 32)
        Me.btnCloseAll.TabIndex = 3
        Me.btnCloseAll.Text = "Close All Processes"
        '
        'btnLaunch1
        '
        Me.btnLaunch1.Location = New System.Drawing.Point(32, 176)
        Me.btnLaunch1.Name = "btnLaunch1"
        Me.btnLaunch1.Size = New System.Drawing.Size(112, 72)
        Me.btnLaunch1.TabIndex = 1
        Me.btnLaunch1.Text = "Start Notepad"
        '
        'Form1
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(292, 266)
        Me.Controls.AddRange(New System.Windows.Forms.Control() {Me.ListView1, Me.btnClose1, Me.btnCloseAll, Me.btnLaunch1})
        Me.Name = "Form1"
        Me.Text = "Process Example"
        Me.ResumeLayout(False)
    
      End Sub
    
    #End Region
    
      Private procName As String = "notepad"
      Private proc As Process
      Private processes() As Process
      Private specialFolder As String = System.Environment.GetFolderPath(Environment.SpecialFolder.System)
    
      Private Sub buildList()
        'this sub populates the listview control with the instances of 'procName'
        'that are currently running.
        Dim itemAdd As ListViewItem
        ListView1.Items.Clear()
    
        processes = Process.GetProcessesByName(procName)
    
        For Each proc In processes
          itemAdd = ListView1.Items.Add(proc.MainWindowTitle)
          itemAdd.SubItems.Add(proc.Id.ToString)
        Next
    
      End Sub
    
    
      Private Sub btnLaunch1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnLaunch1.Click
        'Launch notepad and open the end user license agreement.
        Dim pInfo As New ProcessStartInfo()
        pInfo.FileName = specialFolder & "\eula.txt"
        pInfo.WindowStyle = ProcessWindowStyle.Minimized
        Dim p As Process = Process.Start(pInfo)
        p.WaitForInputIdle()
        buildList()
      End Sub
    
    
      Private Sub btnClose1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClose1.Click
        'Close one of the instances of notepad based on the selected item in the ListView.
        'There are several ways to identify a process. For example,
        'you can use the mainwindowtitle, windowhandle, or processname, depending  
        'on your needs. The process ID is used here because there may be several
        'windows open with the same title.
        Try
          Dim procID As Integer = System.Convert.ToInt32(ListView1.SelectedItems(0).SubItems(1).Text)
          Dim tempProc As Process = Process.GetProcessById(procID)
          tempProc.CloseMainWindow()
          tempProc.WaitForExit()
          buildList()
        Catch
          MessageBox.Show("Please select a process in the ListView before clicking this button." + _
          " Or the Process may have been closed by somebody.")
          buildList()
        End Try
      End Sub
    
      Private Sub btnCloseAll_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCloseAll.Click
        'Walk the process array and close all processes.
        Try
          For Each proc In processes
            proc.CloseMainWindow()
            proc.WaitForExit()
          Next
          buildList()
        Catch ex As System.NullReferenceException
          MessageBox.Show("No instances of Notepad running.")      
        End Try
      End Sub
    
      Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
        'Make sure that you do not leave any instances running.
        If Not (processes Is Nothing) Then
          If (processes.Length <> 0) Then
            Me.btnCloseAll_Click(Me, e)
          End If
        End If
      End Sub
    
    End Class
                        

    Note You must change the code in Visual Basic 2005. By default, Visual Basic creates two files for the project when you create a Windows Forms project. If the form is named Form1, the two files that represent the form are named Form1.vb and Form1.Designer.vb. You write the code in the Form1.vb file. The Windows Forms Designer writes the code in the Form1.Designer.vb file. The Windows Forms Designer uses the partial keyword to divide the implementation of Form1 into two separate files. This behavior prevents the designer-generated code from being interspersed with your code.

    For more information about the new Visual Basic 2005 language enhancements, visit the following Microsoft Developer Network (MSDN) Web site:

    For more information about partial classes and the Windows Forms Designer, visit the following MSDN Web site:

    Note It is recommended that you collapse the region that is labeled Windows Form Designer generated code.

  4. Run the application.
  5. Click Start Notepad one or more times.
  6. Click an instance of Notepad in the ListView control window and select Close Process. This closes the specific instance of Notepad that you selected. You can also select Close All Processes to close all of the running instances of Notepad.

Notes

This sample uses the Id property of the Process class to differentiate between instances of the application. The Id property is a good candidate for this task because all process IDs are unique. The same is true of the WindowHandle property, so you can also use the WindowHandle property of a Process object to differentiate between instances of the application.

Other properties can also be used, although they are less well-suited to the task. For example, if you do not know the process ID of a specific process or have the handle of the main window, you can use the MainWindowTitle property to help identify the proper instance. The MainWindowTitle property may not be unique, but it can help you to isolate the desired application.

The sample in this article uses a Windows application and employs the CloseMainWindow method to close the application. CloseMainWindow does not work with a non-Windows application. If the application that you are attempting to close does not have a window (for example, a console application), you must use the Kill method to close the application.

back to the top

REFERENCES

For more information, see the following Microsoft Developer Network (MSDN) Web site:

back to the top

Keywords: kbvs2005swept kbvs2005applies kbhowtomaster KB305602