View Single Post
 
Old 04-10-2009, 08:13 AM
Mike Rosenblum's Avatar
Mike Rosenblum Mike Rosenblum is offline
Microsoft Excel MVP

Forum Leader
* Guru *
 
Join Date: Jul 2003
Location: New York, NY, USA
Posts: 7,848
Default Closing your Excel.Application - Yet Another Extreme Measure

As a reminder, using Process.Kill() should be a last resort, for if you follow the cleanup procedures properly, Process.Kill() should almost never be necessary. However, just in case ...

Another approach to using Process.Kill(), should you need it, is to use the Application.Hwnd of the Excel.Application instance in order to get the process ID for the running excel application. Then Process.Kill can be called using that process ID. This approach is outlined on StackOverflow here: Killing Excel.EXE on server.

The key to achieving this is by using the GetWindowThreadProcessId Windows API, which can be declared within a class or module as follows:
Code:
' Note: Imports System.Runtime.InteropServices

<DllImport("user32.dll", SetLastError:=True)> _
Private Shared Function GetWindowThreadProcessId(ByVal hwnd As IntPtr, _
                                                 ByRef lpdwProcessId As Integer) As Integer
End Function
Then to call it, you could close down your Excel.Application as follows:
Code:
If xlApp IsNot Nothing Then
    Dim excelProcessId As Integer
    GetWindowThreadProcessId(New IntPtr(xlApp.Hwnd), excelProcessId)

    If excelProcessId > 0 Then
        Dim ExcelProc As Process = Process.GetProcessById(excelProcessId)
        If ExcelProc IsNot Nothing Then ExcelProc.Kill()
    End If
End If
Putting this altogether, the following code for a Form1 class could be used to create an Excel Application instance via the btnStartExcel button and then close it via the btnKillExcel button, which utilizes Process.Kill:

Code:
Imports Excel = Microsoft.Office.Interop.Excel
Imports System.Runtime.InteropServices

Public Class Form1
    <DllImport("user32.dll", SetLastError:=True)> _
    Private Shared Function GetWindowThreadProcessId(ByVal hwnd As IntPtr, _
                                                     ByRef lpdwProcessId As Integer) As Integer
    End Function

    Private xlApp As Excel.Application

    Private Sub btnStartExcel_Click(ByVal sender As System.Object, _
                                    ByVal e As System.EventArgs) Handles btnStartExcel.Click
        xlApp = New Excel.Application
        xlApp.Visible = True
    End Sub

    Private Sub btnKillExcel_Click(ByVal sender As System.Object, _
                                   ByVal e As System.EventArgs) Handles btnKillExcel.Click

        If xlApp IsNot Nothing Then
            Dim excelProcessId As Integer
            GetWindowThreadProcessId(New IntPtr(xlApp.Hwnd), excelProcessId)

            If excelProcessId > 0 Then
                Dim ExcelProc As Process = Process.GetProcessById(excelProcessId)
                If ExcelProc IsNot Nothing Then ExcelProc.Kill()
            End If
        End If
    End Sub
End Class
(See the attached Visual Studio 2008 project, if you'd like to give it a try.)

But remember, using Process.Kill() should be a last resort. If you follow the cleanup procedures properly, using Process.Kill() should almost never be necessary. If you need assistance cleaning up / shutting down your application instance, feel free to post on the .NET Office Automation forum, where we'll be glad to help you out.

-- Mike
Attached Files
File Type: zip AutomationTesterVb.zip (15.7 KB, 294 views)
__________________
My Articles:
| Excel from .NET | Excel RibbonX using VBA | Excel from VB6 | CVErr in .NET | MVP |
Avatar by Lebb

Last edited by Mike Rosenblum; 04-10-2009 at 12:33 PM.
Reply With Quote