如何从正在运行的对象中获取进程ID?
Dim xlApp As Object = CreateObject("Excel.Application")
Run Code Online (Sandbox Code Playgroud)
我需要使用后期绑定,因为我无法保证我将获得哪个版本,因此使用Microsoft.Office.Interop.Excel将无法正常工作.
'do some work with xlApp
xlApp.Quit
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp)
xlApp = nothing
Run Code Online (Sandbox Code Playgroud)
此时Excel仍在后台运行.我熟悉使用变量的所有建议并释放它们然后使用:System.Runtime.InteropServices.Marshal.ReleaseComObject(o).这不能可靠地工作.我正在做的工作非常复杂.我使用多个文件用于每个循环等.无法在Excel中释放所有资源.我需要一个更好的选择.
我想Process.Kill在Excel 上使用,但我不知道如何从xlApp对象获取进程.我不想杀死所有Excel进程,因为用户可能打开了工作簿.
我尝试使用Dim xProc As Process = Process.Start(ExcelPath)然后使用xProc.Kill()有时工作除了使用XLApp = GetObject("Book1").Application或XLApp = GetObject("", "Excel.Application")如果用户已经打开Excel窗口使用正确的Excel对象有点棘手.我需要一个更好的选择.
我不能使用GetActiveObject或BindToMoniker获取Excel对象,因为它们仅在使用早期绑定时才能工作.例如Microsoft.Office.Interop.Excel
如何从正在运行的对象中获取进程ID?
编辑:其实我真的不想对如何让Excel很好地退出进行重新考虑.许多其他问题都解决了这个问题 在这里和这里我只想杀死它; 干净,准确,直接.我想要杀死我开始的确切过程而不是其他过程.
其实没关系;我想到了。这是一个非常干净,针对性强的解决方案,它会终止已启动的确切过程。它不会干扰用户可能已打开的任何其他进程或文件。以我的经验,在关闭文件并退出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
Run Code Online (Sandbox Code Playgroud)
一旦意识到可以从Excel中获取窗口句柄,则只需要该函数即可从窗口句柄获取进程ID。因此,GetWindowThreadProcessId如果有人知道vb.net的获取方式,我将不胜感激。
使用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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
25109 次 |
| 最近记录: |