Piszę aplikację w C #, która otwiera plik szablonu programu Excel do operacji odczytu / zapisu. Chcę, gdy użytkownik zamyka aplikację, proces aplikacji Excel został zamknięty, bez zapisywania pliku Excela. Zobacz mojego Menedżera zadań po wielu uruchomieniach aplikacji.
Używam tego kodu, aby otworzyć plik Excela:
public Excel.Application excelApp = new Excel.Application();
public Excel.Workbook excelBook;
excelBook = excelApp.Workbooks.Add(@"C:/pape.xltx");
a do dostępu do danych używam tego kodu:
Excel.Worksheet excelSheet = (Worksheet)(excelBook.Worksheets[1]);
excelSheet.DisplayRightToLeft = true;
Range rng;
rng = excelSheet.get_Range("C2");
rng.Value2 = txtName.Text;
Widzę podobne pytania w przepełnieniu stosu, takie jak to i to , i testuję odpowiedzi, ale to nie działa.
c#
excel
visual-studio-2012
excel-interop
kill-process
Javad Yousefi
źródło
źródło
Odpowiedzi:
Spróbuj tego:
excelBook.Close(0); excelApp.Quit();
Zamykając zeszyt ćwiczeń, masz trzy opcjonalne parametry:
Workbook.Close(false)
lub jeśli wykonujesz późne wiązanie, czasami łatwiej jest użyć zera.Workbook.Close(0)
Tak właśnie zrobiłem podczas automatyzacji zamykania skoroszytów.Poszedłem też do dokumentacji i znalazłem ją tutaj: Skoroszyt programu Excel Zamknij
Dzięki,
źródło
xlBook.Save(); xlBook.Close(true); xlApp.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
spróbuj tego ... zadziałało dla mnie ... powinieneś zwolnić ten obiekt aplikacji xl, aby zatrzymać proces.
źródło
Ref: https://stackoverflow.com/a/17367570/132599
To rozwiązało problem. Twój kod staje się:
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;
A potem wypuść wszystkie te obiekty:
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);
Owijam to,
try {} finally {}
aby upewnić się, że wszystko zostanie zwolnione, nawet jeśli coś pójdzie nie tak (co może się nie udać?) Nppublic 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); }
źródło
Pomyśl o tym, to zabija proces:
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 { } } }
Czy próbowałeś po prostu normalnie go zamknąć?
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
źródło
Zabicie Excela nie zawsze jest łatwe; zobacz ten artykuł: 50 sposobów na zabicie programu Excel
W tym artykule zawarto najlepsze rady firmy Microsoft ( artykuł bazy wiedzy MS Knowlege ), jak sprawić, by program Excel ładnie zakończył pracę, ale także upewnia się o tym, zabijając proces, jeśli to konieczne. Lubię mieć drugi spadochron.
Zamknij wszystkie otwarte skoroszyty, zamknij aplikację i zwolnij obiekt xlApp. Na koniec sprawdź, czy proces nadal żyje, a jeśli tak, zakończ go.
W tym artykule upewniono się również, że nie zabijamy wszystkich procesów programu Excel, a tylko dokładnie ten proces, który został uruchomiony.
Zobacz także Pobierz proces z uchwytu okna
Oto kod, którego używam: (działa za każdym razem)
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
źródło
Spotkałem te same problemy i wypróbowałem wiele metod, aby je rozwiązać, ale nie działa. Wreszcie znalazłem przy okazji. Niektóre odniesienia wprowadź tutaj opis linku
Mam nadzieję, że mój kod pomoże komuś w przyszłości. Na rozwiązanie tego problemu spędziłem ponad dwa dni. Poniżej mój kod:
//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(); } } }
źródło
excelBook.Close (); excelApp.Quit (); dodaj koniec kodu, może wystarczyć. działa na moim kodzie
źródło
Możesz zabić proces za pomocą własnego
COM
obiektu Excel piddodaj gdzieś poniżej kodu importu dll
[DllImport("user32.dll", SetLastError = true)] private static extern int GetWindowThreadProcessId(IntPtr hwnd, ref int lpdwProcessId);
I użyć
if (excelApp != null) { int excelProcessId = -1; GetWindowThreadProcessId(new IntPtr(excelApp.Hwnd), ref excelProcessId); Process ExcelProc = Process.GetProcessById(excelProcessId); if (ExcelProc != null) { ExcelProc.Kill(); } }
źródło
I odkryli, że ważne jest, aby mieć
Marshal.ReleaseComObject
wWhile
pętli i zakończyć Garbage Collection .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(); }
źródło
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 { } } }
Zamyka ostatnie 10 sekund proces o nazwie „Excel”
źródło
Właściwy sposób na zamknięcie wszystkich procesów programu 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 { } } }
źródło
Oparty na innych rozwiązaniach. Użyłem tego:
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 { } } }
Korzystanie z „MainWindowHandle” w celu zidentyfikowania procesu i zamknięcia go.
excelObj: To jest mój obiekt Excel Application Interop
źródło
Użyj zmiennej dla każdego obiektu programu Excel i musi zostać zapętlona
Marshal.ReleaseComObject >0
. Bez pętli proces Excela nadal pozostaje aktywny.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); } }
źródło
Możemy zamknąć aplikację Excel podczas konwersji xls do xlsx za pomocą następującego kodu. Kiedy wykonujemy tego rodzaju zadanie, aplikacja Excel działa w menedżerze zadań, powinniśmy zamknąć ten program Excel, który działa w tle. Interop jest składnikiem Com, aby zwolnić składnik com użyliśmy 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); }
źródło
Większość metod działa, ale proces excela pozostaje zawsze do zamknięcia aplikacji.
Kiedy zabijamy proces Excela, nie można go wykonać ponownie w tym samym wątku - nie wiem dlaczego.
źródło
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;
to GetWindowThreadProcessId znajduje poprawny identyfikator procesu o excell .... Po jego zabiciu .... Ciesz się !!!
źródło
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(); } }
źródło