Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I stop Excel processes from running in the background after a PowerShell script?

No matter what I try, Excel 2013 continues to run in the background on Windows 10 no matter what commands I throw at the end of my PowerShell script. I've tried adding all suggestions I've found to the end of my script and the only Excel object I open continues to remain open. Here is what I have at the end of my script. Any other suggestions?

## Quit Excel and Terminate Excel Application process:
$xlsxwb.quit
$xlsxobj.Quit

[System.Runtime.Interopservices.Marshal]::ReleaseComObject($xlsxobj)
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($xlsxwb)
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($xlsxSh1)
Start-Sleep 1
'Excel processes: {0}' -f @(Get-Process excel -ea 0).Count
like image 286
mtb2434 Avatar asked Aug 19 '16 17:08

mtb2434


3 Answers

I ran into the same problem and tried various solutions without success. I got closer when I started releasing all of the COM objects I saved as variables, not just the ones for the workbook, worksheet, and Excel application.

For example, take the following example code:

$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $False
$Workbook = $Excel.Workbooks.Open("C:\Temp\test.xlsx")
$Worksheet = $Workbook.Worksheets.Item(1)
$UsedRange = $Worksheet.UsedRange
$Range = $Worksheet.Range("A1:B10")
$Workbook.Close()
$Excel.Quit()
[void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($Range)
[void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($UsedRange)
[void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($Worksheet)
[void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($Workbook)
[void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel)
[GC]::Collect()

If you were to take out just one of the ReleaseComObject statements, the Excel process would remain open. In my code I release all the ones like ranges, tables, etc. first and then I do the worksheet, workbook, and finally the Excel application itself. Then because that only seemed to work like 90% of the time, I added the garbage collection command at the end and finally had a solution that seems to work every time without having to kill the process.

Note: My system is Windows 8.1 with PowerShell v5 and Office 2013.

like image 196
Jon Dechiro Avatar answered Oct 17 '22 20:10

Jon Dechiro


Here's a simple example below. It will likely require some additional code for more complex procedures.

function _FullQuit {
    while ( $this.Workbooks.Count -gt 0 ) {
        $this.Workbooks.Item(1).Close()
    }
    $this.Quit()
    [System.Runtime.InteropServices.Marshal]::ReleaseComObject($this)
    [System.GC]::Collect()
    [System.GC]::WaitForPendingFinalizers()
}

function New-Excel {
$object = New-Object -ComObject "Excel.Application"
$object | Add-Member -MemberType ScriptMethod -Name FullQuit -Value {_FullQuit}
$object
}

$xl = New-Excel

$wb1 = $xl.Workbooks.Open("C:\Data1.csv")
$wb2 = $xl.Workbooks.Open("C:\Data2.csv")

$xl.FullQuit()
like image 34
annoying_squid Avatar answered Oct 17 '22 20:10

annoying_squid


  1. Create Excel Application.
  2. Make it visible
  3. Get Process Id of the application.
  4. Hide Excel Application.
  5. Stop process my process id. Sample Code

    # Create Excel Application
    $excel = New-Object -comobject Excel.Application
    
    # Make it visiable
    $excel.Visible = $true
    
    # Get Windows handle of the application
    $excelWinHwnd = $excel.Hwnd
    
    # Get Process Id of the application
    $process = Get-Process Excel | Where-Object {$_.MainWindowHandle -eq $excelWinHwnd}
    $excelProcessId = $process.Id
    
    # Hide the application : Run In background 
    $excel.Visible = $false
    
    # Kill/Stop the process by id
    Stop-Process -Id $excelProcessId
    
like image 31
DigviJay Patil Avatar answered Oct 17 '22 20:10

DigviJay Patil