Закрытие процесса приложений Excel на С# после доступа к данным
Я пишу приложение на С#, которое открывает файл шаблона Excel для операций чтения/записи. Я хочу, чтобы пользователь закрыл приложение, исключительный процесс приложения был закрыт, не сохраняя файл excel. См. Мой диспетчер задач после нескольких запусков приложения.
![enter image description here]()
Я использую этот код для открытия файла excel:
public Excel.Application excelApp = new Excel.Application();
public Excel.Workbook excelBook;
excelBook = excelApp.Workbooks.Add(@"C:/pape.xltx");
и для доступа к данным я использую этот код:
Excel.Worksheet excelSheet = (Worksheet)(excelBook.Worksheets[1]);
excelSheet.DisplayRightToLeft = true;
Range rng;
rng = excelSheet.get_Range("C2");
rng.Value2 = txtName.Text;
Я вижу похожие вопросы в stackoverflow, такие как этот вопрос и этот, и тестируйте ответы, но это не работает.
Ответы
Ответ 1
Попробуйте следующее:
excelBook.Close(0);
excelApp.Quit();
При закрытии рабочей книги у вас есть три необязательных параметра:
Workbook.close SaveChanges, filename, routeworkbook
Workbook.Close(false)
или если вы выполняете позднюю привязку, иногда проще использовать нуль
Workbook.Close(0)
Вот как я это делал при автоматизации закрытия книг.
И я пошел и посмотрел документацию для него, и нашел его здесь:
Закрыть книгу Excel
Спасибо,
Ответ 2
xlBook.Save();
xlBook.Close(true);
xlApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
попробуйте это.. это сработало для меня...
вы должны освободить этот объект приложения xl, чтобы остановить процесс.
Ответ 3
Подумайте об этом, он убивает процесс:
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 { }
}
}
Кроме того, вы пытались просто закрыть его нормально?
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
Ответ 4
Ссылка: fooobar.com/questions/104775/...
Избегайте использования выражений с двумя точками, таких как:
var workbook = excel.Workbooks.Open(/*params*/)
... потому что таким образом вы создаете объекты RCW не только для рабочей книги, но и для рабочих книг, и вы также должны ее выпускать (что невозможно, если ссылка на объект не поддерживается).
Это решило проблему для меня. Ваш код будет выглядеть следующим образом:
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;
И затем отпустите все эти объекты:
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);
Я обертываю это в try {} finally {}
, чтобы гарантировать, что все будет выпущено, даже если что-то пойдет не так (что может пойти не так?), например.
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);
}
Ответ 5
Убийство Excel не всегда легко; см. эту статью: 50 способов убить Excel
В этой статье содержится лучший совет от Microsoft (MS Knowlege Base Article) о том, как заставить Excel прекратить работу, но затем также делает уверенный в этом, убив процесс, если это необходимо. Мне нравится иметь второй парашют.
Обязательно Закройте все открытые книги, Закройте приложение и отпустите объект xlApp. Наконец, проверьте, жив ли процесс, и если да, то убивайте его.
Эта статья также гарантирует, что мы не убиваем все процессы Excel, а только убиваем точный процесс, который был запущен.
См. также Получить процесс из окна управления
Вот код, который я использую: (работает каждый раз)
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
Ответ 6
excelBook.Close();
excelApp.Quit();
добавьте конец кода, этого может быть достаточно. он работает над моим кодом
Ответ 7
Я встретил те же проблемы и попробовал много методов для его решения, но не работает.
Наконец, я нашел его по-моему. Некоторая ссылка введите ссылку здесь
Надеюсь, мой код поможет кому-то в будущем. Мне было потрачено более двух дней, чтобы решить эту проблему.
Ниже мой код:
//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();
}
}
}
Ответ 8
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 { }
}
}
Он закрывает последний 10-секундный процесс с именем "Excel"
Ответ 9
Правильный способ закрыть весь процесс 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 { }
}
}
Ответ 10
На основе других решений. Я использую это:
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 { }
}
}
Используя "MainWindowHandle", чтобы идентифицировать процесс и закрыть его.
excelObj: Это мое приложение Interop excel objecto
Ответ 11
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;
этот GetWindowThreadProcessId находит правильный идентификатор процесса o excell....
После убийства...
Наслаждайтесь этим!!!