Excel exe process id

Here’s an example of how to open an Excel file using Excel-Interop, and properly disposing the instance
(source: google)

    Application ExcelObj = new Application();
    Workbook WB = ExcelObj.Workbooks.Open(fileName,
        0, true, 5, "", "", true, XlPlatform.xlWindows, "t",
        false, false, 0, true, false, false);
    Sheets sheets = WB.Worksheets;
    Worksheet WS = (Worksheet)sheets.get_Item(1);
    Range excelRange = WS.UsedRange;

        ... (DO STUFF?)

        // Get rid of everything - close Excel
        while (Marshal.ReleaseComObject(WB) > 0) { }
        WB = null;
        while (Marshal.ReleaseComObject(sheets) > 0) { }
        sheets = null;
        while (Marshal.ReleaseComObject(WS) > 0) { }
        WS = null;
        while (Marshal.ReleaseComObject(excelRange) > 0) { }
        excelRange = null;
        GC();
        ExcelObj.Quit();
        while (Marshal.ReleaseComObject(ExcelObj) > 0) { }
        ExcelObj = null;
        GC();

    public static void GC()
    {
        System.GC.Collect();
        System.GC.WaitForPendingFinalizers();
        System.GC.Collect();
        System.GC.WaitForPendingFinalizers();
    }

INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Contact US

Thanks. We have received your request and will respond promptly.

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!

  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It’s Free!

*Tek-Tips’s functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Students Click Here

Simple Way to Get Excel.exe Process ID

Simple Way to Get Excel.exe Process ID

(OP)

15 Dec 03 18:52

Hi,

I found a neat little snippit that will let me close any program given the process id, but I need to be able to find out the process id since it’s dynamically generated.

Any ideas?  

Thanks.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Join Tek-Tips® Today!

Join your peers on the Internet’s largest technical computer professional community.
It’s easy to join and it’s free.

Here’s Why Members Love Tek-Tips Forums:

  • Tek-Tips ForumsTalk To Other Members
  • Notification Of Responses To Questions
  • Favorite Forums One Click Access
  • Keyword Search Of All Posts, And More…

Register now while it’s still free!

Already a member? Close this window and log in.

Join Us             Close

Using Marshal.ReleaseComObject() or killing the Excel.exe process are ugly, error prone and unnecessary band-aids for this problem. And highly detrimental in the long run, this question shows what can happen. The proper way to do it is by calling GC.Collect(), but read this answer to understand why this tends to not work when you debug your program.

The workaround is simple, you just need to make sure that you call GC.Collect() in a different method. Which ensures that your Excel object references are no longer in scope. So the rough outline of a program that does this right would 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

Actually never mind; I figured it out. This is a very clean, precisely targeted solution that kills the exact process that was started. It doesn’t interfere with any other process or file that the user might have open. In my experience killing the process after closing files and quitting Excel is the fastest and easiest way to deal with Excel. Here is a knowledge Base article describing the problem and Microsoft’s recommended solution.

Please note that this solution does NOT kill the Excel application. It only kills the empty process shell if any pointers have not been properly disposed. Excel itself DOES actually quit 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 don’t recommend killing the process; See
How to properly clean up Excel interop objects
and Understanding Garbage Collection in .net

On the other hand many people don’t recommend using GC.Collect. See What’s so wrong about using GC.Collect()?

Be sure to Close any open workbooks, Quit the application, Release the xlApp object. Finally check to see if the process is still alive and if so then 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

Once I realized that I could get the window handle from Excel, then I just needed the function to get the process ID from the window handle. Hence GetWindowThreadProcessId If anyone knows a vb.net way to get that I would be grateful.

Hi all,

I am looking for a way to get the Process id (or a handle) of an EXCEL
process created from within my code.

For example when the following code is executed:

Dim EXL As Excel.Application = New Excel.Application

a new instance of EXCEL.EXE is created in the task manager.

I am looking for some code (or ideas) of how to identify this
particular instance of EXCEL.EXE AS IT IS CREATED. I know I can use
something like this:

Dim localByName As Process() = Process.GetProcessesByName(«excel»)

but this code will give me ALL instances of EXCEL processes running on
the computer. I know I can also get the users of the processes but
what if I myself had just say 5 instances of EXCEL already running on
my computer?? How do I identify which is the Process Id of EXCEL
created (opened) by my code??

I’m sure some smart people out there have the answers! Appreciate any
help.

PowaGuy

Nov 21 ’05
#1

Как мне получить идентификатор процесса из запущенного объекта?

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

Мне нужно использовать позднее связывание, потому что я не могу гарантировать, какую версию получу, поэтому использование Microsoft.Office.Interop.Excel не сработает.

'do some work with xlApp

xlApp.Quit
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp)
xlApp = nothing

На данный момент Excel все еще работает в фоновом режиме. Я знаком со всеми рекомендациями по использованию переменных и их выпуску, а затем использую: System.Runtime.InteropServices.Marshal.ReleaseComObject(o). Это не работает надежно. Работа, которую я делаю, очень сложная. Я использую для каждого цикла и т.д., используя несколько файлов. Освободить все ресурсы в Excel невозможно. Мне нужен лучший вариант.

Я хотел бы использовать Process.Kill в Excel, но не знаю, как получить процесс из объекта xlApp. Я не хочу убивать все процессы Excel, потому что у пользователя может быть открыта книга.

Я пробовал использовать Dim xProc As Process = Process.Start(ExcelPath), а затем xProc.Kill(). Иногда это работает, за исключением того, что немного сложно получить правильный объект Excel с помощью XLApp = GetObject("Book1").Application или XLApp = GetObject("", "Excel.Application"), если у пользователя уже открыты окна Excel. Мне нужен лучший вариант.

Я не могу использовать GetActiveObject или BindToMoniker для получения объекта Excel, потому что они работают с работой только при использовании раннего связывания. Например. Microsoft.Office.Interop.Excel

Как мне получить идентификатор процесса из запущенного объекта?

Изменить: на самом деле меня не очень интересует перефразирование того, как заставить Excel красиво выйти. Многие другие вопросы касались этого. здесь и здесь Я просто хочу убить его; чисто, точно и прямо. Я хочу убить именно тот процесс, который я начал, и никакой другой.

6 ответов

Лучший ответ

На самом деле неважно; Я понял. Это очень чистое, точно нацеленное решение, которое убивает точно запущенный процесс. Это не мешает другим процессам или файлам, которые может открыть пользователь. По моему опыту, прекращение процесса после закрытия файлов и выхода из Excel — это самый быстрый и простой способ справиться с Excel. Вот статья базы знаний с описанием проблемы и рекомендуемым решением Microsoft.

Обратите внимание, что это решение НЕ убивает приложение Excel. Он убивает пустую оболочку процесса только в том случае, если какие-либо указатели не были должным образом удалены. Сам Excel действительно закрывается, когда мы вызываем xlApp.quit(). Это можно подтвердить, попытавшись подключить работающее приложение Excel, но это не поможет, потому что Excel вообще не запущен.

Многие не рекомендуют убивать процесс; Видеть Как правильно очистить объекты взаимодействия Excel и Общие сведения о сборке мусора в .NET

С другой стороны, многие люди не рекомендуют использовать GC.Collect. См. Что плохого в использовании GC.Collect ()?

Обязательно закройте все открытые книги, выйдите из приложения, отпустите объект xlApp. Наконец, проверьте, жив ли процесс, и если да, то убейте его.

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

Как только я понял, что могу получить дескриптор окна из Excel, мне просто понадобилась функция для получения идентификатора процесса из дескриптора окна. Следовательно, GetWindowThreadProcessId Если кто-нибудь знает способ получить это на vb.net, я был бы признателен.


9

Community
23 Май 2017 в 12:00

Использование Marshal.ReleaseComObject () или уничтожение процесса Excel.exe некрасиво, подвержено ошибкам и является ненужным средством решения этой проблемы. И очень вредно в долгосрочной перспективе, этот вопрос показывает, что может случиться. Правильный способ сделать это — вызвать GC.Collect (), но прочтите этот ответ, чтобы понять, почему это не так. работать, когда вы отлаживаете свою программу.

Обходной путь прост, вам просто нужно убедиться, что вы вызываете GC.Collect () в другом методе. Это гарантирует, что ваши ссылки на объекты Excel больше не входят в область действия. Итак, приблизительный набросок программы, которая делает это правильно, будет следующим:

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

Community
23 Май 2017 в 12:17

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 & "rootcimv2")
  Set colProcessList = objWMIService.ExecQuery _
    ("Select * from Win32_Process Where ProcessID =" & ProcIdXL)
  For Each objProcess In colProcessList
    objProcess.Terminate
  Next

End Function


KillProcess (ExcelApplication.hwnd)


2

Jakuje
19 Ноя 2015 в 11:13

Для 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

JimMoore
15 Май 2014 в 21:36

Я нашел обходной путь (источник на VB):

Private Declare Auto Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hwnd As IntPtr, ByRef lpdwProcessId As Integer) As Integer

Сначала Marshal.ReleaseComObject () все более детализированные объекты и устанавливают для них значение Nothing.

Переместите окно Excel наверх после закрытия последней книги, а затем подождите 1000 мс (хорошее значение для шансов на работу):

exlBook.Close()
Dim exlProcId As Integer = Nothing
GetWindowThreadProcessId(exlApp.Hwnd, exlProcId)
AppActivate(exlProcId)
Threading.Thread.Sleep(1000)
Marshal.ReleaseComObject(exlBook)
exlBook = Nothing

В конце концов:

exlApp.Quit()
exlApp = Nothing
GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()
GC.WaitForPendingFinalizers()

Я обнаружил это, когда остановил программу после закрытия рабочей книги, затем открыл окно Excel, затем продолжил программу и процесс Excel был закрыт.

С уважением: Торстен, Ганновер, Германия


0

user3756502
30 Дек 2018 в 23:04

Я столкнулся с этой проблемой при разработке автоматического приложения, которое каждый день создает от 50 до 100 книг Excel и отправляет их по электронной почте. Что бы я ни делал, экземпляр Excel зависал в диспетчере задач, иногда даже после GC.WaitForPendingFinalizers ().

Поскольку приложение работает без присмотра, я не могу рисковать, что Excel съест машину, поэтому я объединил все подходы в:

Private Declare Auto Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hwnd As IntPtr, ByRef lpdwProcessId As Integer) As Integer

        Dim XLApp As Excel.Application
        Dim XLHwnd As Integer
        Dim XLProcID As Integer
        Dim XLProc As Process

        XLApp = New Excel.Application

        XLHwnd = XLApp.Hwnd
        GetWindowThreadProcessId(CType(XLHwnd, IntPtr), XLProcID)
        XLProc = Process.GetProcessById(XLProcID)

        DoStuffWithExcel()

        Try
            XLApp.Quit()
            System.Runtime.InteropServices.Marshal.ReleaseComObject(XLApp)
            XLApp = Nothing
            GC.Collect()
            GC.WaitForPendingFinalizers()

            If Not XLProc.HasExited Then
                XLProc.Kill()
            End If
        Catch ex As Exception
            XLApp = Nothing
        Finally
            GC.Collect()
        End Try

Я пытаюсь выйти изящно, но если это не удается, я прекращаю процесс, потому что должен!

Пока что вёл себя ;-)


0

Yowser
7 Мар 2019 в 19:04

Понравилась статья? Поделить с друзьями:
  • Excel documents in google docs
  • Excel exe bad image
  • Excel document to download
  • Excel document personal information
  • Excel exception code 0xc0000005