How to get the process identifier from the created "Excel.Application" object?

How to get the process identifier from a running object?

Dim xlApp As Object = CreateObject("Excel.Application") 

I need to use the latest binding because I cannot guarantee which version I will get, so using Microsoft.Office.Interop.Excel will not work.

 'do some work with xlApp xlApp.Quit System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp) xlApp = nothing 

At this point, Excel is still running in the background. I got acquainted with all the recommendations for using variables and their release, and then use: System.Runtime.InteropServices.Marshal.ReleaseComObject(o) . This does not work reliably. The work that I do is very difficult. I use for each cycle, etc., using multiple files. Unable to release all resources in Excel. I need a better option.

I would like to use Process.Kill in Excel, but I don't know how to get this process from an xlApp object. I do not want to kill all Excel processes, because the user may have a workbook open.

I tried using Dim xProc As Process = Process.Start(ExcelPath) and then using xProc.Kill() This works sometimes, except it is a little difficult to get the correct Excel object using XLApp = GetObject("Book1").Application or XLApp = GetObject("", "Excel.Application") if the user already has Excel windows. I need a better option.

I cannot use GetActiveObject or BindToMoniker to get an Excel object, because they only work with work when using early binding. For example. Microsoft.Office.Interop.Excel

How to get the process ID from a running object?

Edit: Actually, I am not interested in rethinking how to get Excel to exit well. This was discussed by many other questions. here and here I just want to kill him; clean, accurate and direct. I want to kill the exact process that I started, and no one else.

+4
excel
Jul 20 '13 at 5:42 on
source share
4 answers

It doesn't really matter; I understood. This is a very clean, precisely targeted solution that kills the exact process that was started. It does not interfere with any other process or file that the user can open. In my experience, killing a process after closing files and exiting Excel is the fastest and easiest way to deal with Excel. Here is a knowledge base article describing the problem and a solution recommended by Microsoft.

Please note that this solution does NOT kill Excel. It only kills the empty shell of the process if any pointers have not been correctly deleted. Excel itself actually stops when we call xlApp.quit() . This can be confirmed by trying to attach the running Excel application, which will fail because Excel is not running at all.

Many people do not recommend killing the process; See How to properly clean Excel interaction objects and Understanding garbage collection in .net

On the other hand, many people do not recommend using GC.Collect. See What's Wrong About Using GC.Collect ()?

Be sure to Close all open books, Close the application, Release the xlApp object. Finally, check if the process is alive, and if so, kill it.

 Private Declare Auto Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hwnd As IntPtr, _ ByRef lpdwProcessId As Integer) As Integer Sub testKill() 'start the application Dim xlApp As Object = CreateObject("Excel.Application") 'do some work with Excel 'close any open files 'get the window handle Dim xlHWND As Integer = xlApp.hwnd 'this will have the process ID after call to GetWindowThreadProcessId Dim ProcIdXL As Integer = 0 'get the process ID GetWindowThreadProcessId(xlHWND, ProcIdXL) 'get the process Dim xproc As Process = Process.GetProcessById(ProcIdXL) 'Quit Excel xlApp.quit() 'Release System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp) 'set to nothing xlApp = Nothing 'kill it with glee If Not xproc.HasExited Then xproc.Kill() End If End Sub 

As soon as I realized that I can get the window handle from Excel, I just need a function to get the process ID from the window handle. Therefore, GetWindowThreadProcessId If someone knows the vb.net way to get this, I would be grateful.

+2
Jul 20 '13 at 6:36
source share

Using Marshal.ReleaseComObject () or killing the Excel.exe process are ugly, error prone, and unnecessary tape tools for this problem. And ultimately very harmful, this question shows what might happen. The correct way to do this is to call GC.Collect (), but read this answer to see why this does not work when debugging your program.

The workaround is simple, you just need to make sure that you call GC.Collect () in a different way. This ensures that references to Excel objects are no longer included. Thus, the rough outline of a program that does this correctly will be:

 Sub Main() DoOfficeStuff() GC.Collect() GC.WaitForPendingFinalizers() '' Excel.exe will now be gone '' Do more work ''... End Sub Sub DoOfficeStuff() Dim xlApp As Object = CreateObject("Excel.Application") '' etc.. End Sub 
+6
Jul 21 '13 at 0:51
source share
 Public Declare Function GetWindowThreadProcessId Lib "user32" _ (ByVal hwnd As Long, _ ByRef lpdwProcessId As Long) As Long Function KillProcess(hwnd As Long) Dim CurrentForegroundThreadID As Long Dim strComputer As String Dim objWMIService Dim colProcessList Dim objProcess Dim ProcIdXL As Long ProcIdXL = 0 CurrentForegroundThreadID = GetWindowThreadProcessId(hwnd, ProcIdXL) strComputer = "." Set objWMIService = GetObject _ ("winmgmts:\\" & strComputer & "\root\cimv2") Set colProcessList = objWMIService.ExecQuery _ ("Select * from Win32_Process Where ProcessID =" & ProcIdXL) For Each objProcess In colProcessList objProcess.Terminate Next End Function KillProcess (ExcelApplication.hwnd) 
+1
Nov 19 '15 at 10:29
source share

To use C #:

  [DllImport("user32.dll")] private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); uint iProcessId = 0; //Get the process ID of excel so we can kill it later. GetWindowThreadProcessId((IntPtr)ExcelObj.Hwnd, out iProcessId); try { Process pProcess = Process.GetProcessById((int)iProcessId); pProcess.Kill(); } catch (System.Exception) { //just ignore any failure. } 
0
May 15 '14 at 21:36
source share



All Articles