Estou escrevendo um aplicativo em C # que abre um arquivo de modelo do Excel para operações de leitura / gravação. Eu quero quando o usuário fecha o aplicativo, o processo do aplicativo do Excel foi fechado, sem salvar o arquivo do Excel. Veja meu Gerenciador de Tarefas após várias execuções do aplicativo.
Eu uso este código para abrir o arquivo excel:
public Excel.Application excelApp = new Excel.Application();
public Excel.Workbook excelBook;
excelBook = excelApp.Workbooks.Add(@"C:/pape.xltx");
e para acesso aos dados eu uso este código:
Excel.Worksheet excelSheet = (Worksheet)(excelBook.Worksheets[1]);
excelSheet.DisplayRightToLeft = true;
Range rng;
rng = excelSheet.get_Range("C2");
rng.Value2 = txtName.Text;
Vejo perguntas semelhantes no stackoverflow, como esta pergunta e esta , e teste as respostas, mas não funciona.
c#
excel
visual-studio-2012
excel-interop
kill-process
Javad Yousefi
fonte
fonte
Respostas:
Experimente isto:
excelBook.Close(0); excelApp.Quit();
Ao fechar o caderno de trabalho, você tem três parâmetros opcionais:
Workbook.Close(false)
ou se você estiver fazendo ligação tardia, às vezes é mais fácil usar zero.Workbook.Close(0)
É assim que fiz ao automatizar o fechamento de pastas de trabalho.Também fui e procurei a documentação para ele e o encontrei aqui: Excel Workbook Close
Obrigado,
fonte
xlBook.Save(); xlBook.Close(true); xlApp.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
tente isso .. funcionou para mim ... você deve liberar esse objeto de aplicativo xl para parar o processo.
fonte
Ref: https://stackoverflow.com/a/17367570/132599
Isso resolveu o problema para mim. Seu código se torna:
public Excel.Application excelApp = new Excel.Application(); public Excel.Workbooks workbooks; public Excel.Workbook excelBook; workbooks = excelApp.Workbooks; excelBook = workbooks.Add(@"C:/pape.xltx"); ... Excel.Sheets sheets = excelBook.Worksheets; Excel.Worksheet excelSheet = (Worksheet)(sheets[1]); excelSheet.DisplayRightToLeft = true; Range rng; rng = excelSheet.get_Range("C2"); rng.Value2 = txtName.Text;
E então libere todos esses objetos:
System.Runtime.InteropServices.Marshal.ReleaseComObject(rng); System.Runtime.InteropServices.Marshal.ReleaseComObject(excelSheet); System.Runtime.InteropServices.Marshal.ReleaseComObject(sheets); excelBook .Save(); excelBook .Close(true); System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBook); System.Runtime.InteropServices.Marshal.ReleaseComObject(workbooks); excelApp.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
Eu envolvo isso em um
try {} finally {}
para garantir que tudo seja liberado, mesmo se algo der errado (o que poderia dar errado?).public Excel.Application excelApp = null; public Excel.Workbooks workbooks = null; ... try { excelApp = new Excel.Application(); workbooks = excelApp.Workbooks; ... } finally { ... if (workbooks != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(workbooks); excelApp.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp); }
fonte
Pense nisso, isso mata o processo:
System.Diagnostics.Process[] process=System.Diagnostics.Process.GetProcessesByName("Excel"); foreach (System.Diagnostics.Process p in process) { if (!string.IsNullOrEmpty(p.ProcessName)) { try { p.Kill(); } catch { } } }
Além disso, você tentou apenas fechá-lo normalmente?
myWorkbook.SaveAs(@"C:/pape.xltx", missing, missing, missing, missing, missing, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, missing, missing, missing, missing, missing); excelBook.Close(null, null, null); // close your workbook excelApp.Quit(); // exit excel application excel = null; // set to NULL
fonte
Matar o Excel nem sempre é fácil; veja este artigo: 50 maneiras de matar o Excel
Este artigo segue os melhores conselhos da Microsoft ( artigo da base de conhecimento do MS ) sobre como fazer com que o Excel saia bem, mas também se certifica disso eliminando o processo, se necessário. Gosto de ter um segundo pára-quedas.
Certifique-se de fechar todas as pastas de trabalho abertas, sair do aplicativo e liberar o objeto xlApp. Por fim, verifique se o processo ainda está ativo e, se estiver, elimine-o.
Este artigo também garante que não eliminemos todos os processos do Excel, mas apenas o processo exato que foi iniciado.
Consulte também Obter processo do identificador de janela
Aqui está o código que uso: (funciona sempre)
Sub UsingExcel() 'declare process; will be used later to attach the Excel process Dim XLProc As Process 'call the sub that will do some work with Excel 'calling Excel in a separate routine will ensure that it is 'out of scope when calling GC.Collect 'this works better especially in debug mode DoOfficeWork(XLProc) 'Do garbage collection to release the COM pointers 'http://support.microsoft.com/kb/317109 GC.Collect() GC.WaitForPendingFinalizers() 'I prefer to have two parachutes when dealing with the Excel process 'this is the last answer if garbage collection were to fail If Not XLProc Is Nothing AndAlso Not XLProc.HasExited Then XLProc.Kill() End If End Sub 'http://msdn.microsoft.com/en-us/library/ms633522%28v=vs.85%29.aspx <System.Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True)> _ Private Shared Function GetWindowThreadProcessId(ByVal hWnd As IntPtr, _ ByRef lpdwProcessId As Integer) As Integer End Function Private Sub ExcelWork(ByRef XLProc As Process) 'start the application using late binding Dim xlApp As Object = CreateObject("Excel.Application") 'or use early binding 'Dim xlApp As Microsoft.Office.Interop.Excel '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 XLProc = Process.GetProcessById(ProcIdXL) 'do some work with Excel here using xlApp 'be sure to save and close all workbooks when done 'release all objects used (except xlApp) using NAR(x) 'Quit Excel xlApp.quit() 'Release NAR(xlApp) End Sub Private Sub NAR(ByVal o As Object) 'http://support.microsoft.com/kb/317109 Try While (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0) End While Catch Finally o = Nothing End Try End Sub
fonte
Encontrei os mesmos problemas e tentei vários métodos para resolvê-los, mas não funcionou. Finalmente, encontrei o meu caminho. Alguma referência insira a descrição do link aqui
Espero que meu código possa ajudar alguém no futuro. Passei mais de dois dias para resolvê-lo. Abaixo está o meu código:
//get current in useing excel Process[] excelProcsOld = Process.GetProcessesByName("EXCEL"); Excel.Application myExcelApp = null; Excel.Workbooks excelWorkbookTemplate = null; Excel.Workbook excelWorkbook = null; try{ //DO sth using myExcelApp , excelWorkbookTemplate, excelWorkbook } catch (Exception ex ){ } finally { //Compare the EXCEL ID and Kill it Process[] excelProcsNew = Process.GetProcessesByName("EXCEL"); foreach (Process procNew in excelProcsNew) { int exist = 0; foreach (Process procOld in excelProcsOld) { if (procNew.Id == procOld.Id) { exist++; } } if (exist == 0) { procNew.Kill(); } } }
fonte
excelBook.Close (); excelApp.Quit (); adicionar o final do código, pode ser o suficiente. está funcionando no meu código
fonte
Você pode matar o processo com o seu próprio
COM
objeto excel pidadicione em algum lugar abaixo do código de importação dll
[DllImport("user32.dll", SetLastError = true)] private static extern int GetWindowThreadProcessId(IntPtr hwnd, ref int lpdwProcessId);
E use
if (excelApp != null) { int excelProcessId = -1; GetWindowThreadProcessId(new IntPtr(excelApp.Hwnd), ref excelProcessId); Process ExcelProc = Process.GetProcessById(excelProcessId); if (ExcelProc != null) { ExcelProc.Kill(); } }
fonte
Eu descobri que é importante ter
Marshal.ReleaseComObject
dentro de umWhile
loop E terminar com a Coleta de Lixo .static void Main(string[] args) { Excel.Application xApp = new Excel.Application(); Excel.Workbooks xWbs = xApp.Workbooks; Excel.Workbook xWb = xWbs.Open("file.xlsx"); Console.WriteLine(xWb.Sheets.Count); xWb.Close(); xApp.Quit(); while (Marshal.ReleaseComObject(xWb) != 0); while (Marshal.ReleaseComObject(xWbs) != 0); while (Marshal.ReleaseComObject(xApp) != 0); GC.Collect(); GC.WaitForPendingFinalizers(); }
fonte
wb.Close(); app.Quit(); System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("Excel"); foreach (System.Diagnostics.Process p in process) { if (!string.IsNullOrEmpty(p.ProcessName) && p.StartTime.AddSeconds(+10) > DateTime.Now) { try { p.Kill(); } catch { } } }
Fecha o processo dos últimos 10 segundos com o nome "Excel"
fonte
A maneira certa de fechar todos os processos do Excel
var _excel = new Application(); foreach (Workbook _workbook in _excel.Workbooks) { _workbook.Close(0); } _excel.Quit(); _excel = null; var process = System.Diagnostics.Process.GetProcessesByName("Excel"); foreach (var p in process) { if (!string.IsNullOrEmpty(p.ProcessName)) { try { p.Kill(); } catch { } } }
fonte
Baseado em outras soluções. Eu usei isto:
IntPtr xAsIntPtr = new IntPtr(excelObj.Application.Hwnd); excelObj.ActiveWorkbook.Close(); System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("Excel"); foreach (System.Diagnostics.Process p in process) { if (p.MainWindowHandle == xAsIntPtr) { try { p.Kill(); } catch { } } }
Usando o "MainWindowHandle" para identificar o processo e fechá-lo.
excelObj: Este é o meu aplicativo Interop excel objecto
fonte
Use uma variável para cada objeto do Excel e deve fazer um loop
Marshal.ReleaseComObject >0
. Sem o loop, o processo do Excel ainda permanece ativo.public class test{ private dynamic ExcelObject; protected dynamic ExcelBook; protected dynamic ExcelBooks; protected dynamic ExcelSheet; public void LoadExcel(string FileName) { Type t = Type.GetTypeFromProgID("Excel.Application"); if (t == null) throw new Exception("Excel non installato"); ExcelObject = System.Activator.CreateInstance(t); ExcelObject.Visible = false; ExcelObject.DisplayAlerts = false; ExcelObject.AskToUpdateLinks = false; ExcelBooks = ExcelObject.Workbooks; ExcelBook = ExcelBooks.Open(FileName,0,true); System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application"); ExcelSheet = ExcelBook.Sheets[1]; } private void ReleaseObj(object obj) { try { int i = 0; while( System.Runtime.InteropServices.Marshal.ReleaseComObject(obj) > 0) { i++; if (i > 1000) break; } obj = null; } catch { obj = null; } finally { GC.Collect(); } } public void ChiudiExcel() { System.Threading.Thread.CurrentThread.CurrentCulture = ci; ReleaseObj(ExcelSheet); try { ExcelBook.Close(); } catch { } try { ExcelBooks.Close(); } catch { } ReleaseObj(ExcelBooks); try { ExcelObject.Quit(); } catch { } ReleaseObj(ExcelObject); } }
fonte
Podemos fechar o aplicativo Excel enquanto convertemos xls em xlsx usando o código a seguir. Quando realizamos este tipo de tarefa, o aplicativo Excel está rodando no gerenciador de tarefas, devemos fechar este Excel que está rodando em background. Interop é um componente Com, para liberar o componente com usamos Marshal.FinalReleaseComObject.
private void button1_Click(object sender, EventArgs e) { Excel03to07("D:\\TestExls\\TestExcelApp.XLS"); } private void Excel03to07(string fileName) { string svfileName = Path.ChangeExtension(fileName, ".xlsx"); object oMissing = Type.Missing; var app = new Microsoft.Office.Interop.Excel.Application(); var wb = app.Workbooks.Open(fileName, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing); wb.SaveAs(svfileName, XlFileFormat.xlOpenXMLWorkbook, Type.Missing, Type.Missing, Type.Missing, Type.Missing, XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing); wb.Close(false, Type.Missing, Type.Missing); app.Quit(); GC.Collect(); Marshal.FinalReleaseComObject(wb); Marshal.FinalReleaseComObject(app); }
fonte
A maioria dos métodos funciona, mas o processo do excel sempre fica até o fechamento da aplicação.
Quando mata o processo do Excel uma vez que não pode ser executado mais uma vez no mesmo segmento - não sei por quê.
fonte
GetWindowThreadProcessId((IntPtr)app.Hwnd, out iProcessId); wb.Close(true,Missing.Value,Missing.Value); app.Quit(); System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("Excel"); foreach (System.Diagnostics.Process p in process) { if (p.Id == iProcessId) { try { p.Kill(); } catch { } } } } [DllImport("user32.dll")] private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); uint iProcessId = 0;
este GetWindowThreadProcessId encontra o Id de Processo correto o excell .... Depois de matá-lo .... Divirta-se !!!
fonte
private void releaseObject(object obj) { try { System.Runtime.InteropServices.Marshal.ReleaseComObject(obj); obj = null; } catch (Exception ex) { obj = null; MessageBox.Show("Unable to release the Object " + ex.ToString()); } finally { GC.Collect(); } }
fonte