vb.net 无法杀死excel进程

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19224099/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 15:23:17  来源:igfitidea点击:

Unable to kill excel processes

vb.netvisual-studio-2010excelprocess

提问by Gutanoth

I am using the followiwing code to do some copying and pasting with excel files:

我正在使用以下代码对 excel 文件进行一些复制和粘贴:

Imports Excel = Microsoft.Office.Interop.Excel
Imports System.IO
Imports System.Runtime.InteropServices

Private Sub btnCombine_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCombine.Click

    Dim xlAppSource As New Excel.Application
    Dim xlAppTarget As New Excel.Application
    Dim xlWbSource As Excel.Workbook
    Dim xlWbTarget As Excel.Workbook
    Dim xlsheetSource As Excel.Worksheet
    Dim xlsheetTarget As Excel.Worksheet
    Dim xlRangeSource As Excel.Range
    Dim xlRangeTarget As Excel.Range

    Dim Progress As Integer = 0
    pbrProgress.Minimum = 0
    pbrProgress.Maximum = amountOfFiles

    btnCombine.Enabled = False
    btnSelect.Enabled = False
    pbrProgress.Visible = True

    getSaveLocation()
    MakeExcelFile()

    'loop through all excel files to get the required data
    For i = 0 To amountOfFiles - 1


        Dim CurrentFile As String = strFileNames(i)
        Dim IntAmountOfRows As Integer = amountOfRows(CurrentFile)
        Dim intStartOfEmptyRow As Integer = amountOfRows(SummaryLocation)

        xlAppSource.DisplayAlerts = False
        xlAppTarget.DisplayAlerts = False

        'Set current workbook
        xlWbSource = xlAppSource.Workbooks.Open(CurrentFile)
        xlWbTarget = xlAppTarget.Workbooks.Open(SummaryLocation)

        'set current worksheet
        xlsheetSource = xlWbSource.ActiveSheet
        xlsheetTarget = xlWbTarget.ActiveSheet

        'copy range of data from source to target file
        xlRangeSource = xlsheetSource.Range("A2:k" & IntAmountOfRows)
        xlRangeSource.Copy()

        xlRangeTarget = xlsheetTarget.Range("A" & intStartOfEmptyRow)
        xlRangeTarget.PasteSpecial(Excel.XlPasteType.xlPasteValues)

        'save summary file before closing
        xlsheetTarget.SaveAs(SummaryLocation)

        'updating progress bar
        Progress = Progress + 1
        pbrProgress.Value = Progress

    Next

    'close excel
    xlWbSource.Close(True)
    xlWbTarget.Close(True)
    xlAppSource.Quit()
    xlAppTarget.Quit()

    xlAppSource.DisplayAlerts = True
    xlAppTarget.DisplayAlerts = True


    'Cleanup
    Marshal.ReleaseComObject(xlAppSource)
    Marshal.ReleaseComObject(xlAppTarget)
    Marshal.ReleaseComObject(xlWbSource)
    Marshal.ReleaseComObject(xlWbTarget)
    Marshal.ReleaseComObject(xlsheetSource)
    Marshal.ReleaseComObject(xlsheettarget)
    Marshal.ReleaseComObject(xlRangeSource)
    Marshal.ReleaseComObject(xlRangeTarget)

    xlAppSource = Nothing
    xlAppTarget = Nothing
    xlWbSource = Nothing
    xlWbTarget = Nothing
    xlsheetSource = Nothing
    xlsheetTarget = Nothing
    xlRangeSource = Nothing
    xlRangeTarget = Nothing

    MsgBox("Samenvoegen compleet")

    init()

End Sub

I have tried every solution given on SO:

我已经尝试了 SO 上给出的所有解决方案:

  • Never use 2 points on a line
  • I have tried using marshall.ReleaseComObject
  • I have tried setting the objects to "Nothing"
  • 切勿在一条线上使用 2 个点
  • 我曾尝试使用 marshall.ReleaseComObject
  • 我尝试将对象设置为“无”

However, everytime I run the application, there will be 10-20 excel processes still running.

但是,每次运行该应用程序时,都会有 10-20 个 excel 进程仍在运行。

回答by

Option Explicit

Sub Main()

    Dim xlApp As Excel.Application
    Set xlApp = New Excel.Application

    xlApp.Visible = False
    xlApp.DisplayAlerts = False

    Dim xlWb As Workbook
    Set xlWb = xlApp.Workbooks.Open("C:\...\path")

    Dim xlSht As Worksheet
    Set xlSht = xlWb.Sheets(1)

    xlSht.Range("A1") = "message from " & ThisWorkbook.FullName

    xlWb.Saved = True
    xlWb.Save
    xlWb.Close

    xlApp.Quit

End Sub

Works for me every single time and does not leave any Excel processes hanging in the task manager.

每次都对我有用,并且不会在任务管理器中留下任何挂起的 Excel 进程。

Note:if your code breaks at some point and you do not handle the already opened objects properly then they will just hang in the processes tab in the Task Manager. If you haven't implemented error handling in your code then start here.

注意:如果您的代码在某个时候中断,并且您没有正确处理已经打开的对象,那么它们只会挂在任务管理器的进程选项卡中。如果您尚未在代码中实现错误处理,请从此处开始。

just consider this as alternative

只考虑这个作为替代

Option Explicit

Sub Main()

    On Error GoTo ErrHandler
    Dim xlApp As Excel.Application
    Set xlApp = New Excel.Application

    xlApp.Visible = False
    xlApp.DisplayAlerts = False

    Dim xlWb As Workbook
    Set xlWb = xlApp.Workbooks.Open("C:\...\path")

    Dim xlSht As Worksheet
    Set xlSht = xlWb.Sheets(1)

    xlSht.Range("A1") = "message from " & ThisWorkbook.FullName

    xlWb.Saved = True
    xlWb.Save
    xlWb.Close

    xlApp.Quit
    Exit Sub

ErrHandler:
    xlWb.Saved = True
    xlWb.Save
    xlWb.Close

    xlApp.Quit
End Sub

回答by coder

The Interop Marshal release doesn't always work because Excel XP and lower suck at releasing. I had to use your loop, but replace the Process.Close() and Process.Quit() with Process.Kill(). Works like a charm. Just be careful that you want ALL versions of excel.exe to be killed, because they will.

The Interop Marshal release doesn't always work because Excel XP and lower suck at releasing. I had to use your loop, but replace the Process.Close() and Process.Quit() with Process.Kill(). Works like a charm. Just be careful that you want ALL versions of excel.exe to be killed, because they will.

I use this:

我用这个:

Workbook.Save()
Workbook.Close()
Application.Quit()

System.Runtime.InteropServices.Marshal.ReleaseComObject(Application)

Worksheet = Nothing
Workbook = Nothing
Application = Nothing

Dim proc As System.Diagnostics.Process

For Each proc In System.Diagnostics.Process.GetProcessesByName("EXCEL")
proc.Kill()
Next

回答by Daniel Gee

When you do anything with the Excel Interop, it creates a new process.

当您使用 Excel Interop 执行任何操作时,它会创建一个新进程。

The problem with killing all Excel processes is that you may kill a process that you are working with. You can kill all processes which have been running for a certain length of time (i.e. from a certain timestamp) with:

终止所有 Excel 进程的问题在于您可能会终止正在使用的进程。您可以使用以下命令杀死所有运行了一定时间(即从某个时间戳开始)的进程:

Dim proc As System.Diagnostics.Process
Dim info As ManagementObject
Dim search As New ManagementObjectSearcher("SELECT ProcessId FROM Win32_process WHERE caption = 'Excel'")
For Each info In search.Get()

    'The string will give you the time that the process started
    'You can then subtract that from the current time to see if you want to kill the process
    Dim TheString As String = info.GetText(TextFormat.Mof).ToString

    'Kill the process according to its ID
    proc = System.Diagnostics.Process.GetProcessById(Mid$(TheString, _
                                                    (Len(TheString) - 8), 4))
    proc.CloseMainWindow()
    proc.Refresh()
    If proc.HasExited Then GoTo NoKill
    proc.Kill()
NoKill:
Next

You'll need to add:

您需要添加:

Imports System.Management

and add the reference for the 'System.Management' to your project.

并将“System.Management”的引用添加到您的项目中。

回答by Rob

You can obtain the process ID from the Excel.Application hwnd and use that to kill the process safely.

您可以从 Excel.Application hwnd 获取进程 ID 并使用它来安全地终止进程。