데이터 액세스 후 C #에서 Excel 응용 프로그램 프로세스 닫기
읽기 / 쓰기 작업을 위해 Excel 템플릿 파일을 여는 응용 프로그램을 C #으로 작성하고 있습니다. 사용자가 응용 프로그램을 닫을 때 Excel 파일을 저장하지 않고 Excel 응용 프로그램 프로세스를 닫고 싶습니다. 앱을 여러 번 실행 한 후 내 작업 관리자를 참조하십시오.
이 코드를 사용하여 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;
이 질문 및 this 와 같은 스택 오버플로에서 유사한 질문을보고 답변을 테스트하지만 작동하지 않습니다.
이 시도:
excelBook.Close(0);
excelApp.Quit();
통합 문서를 닫을 때 세 가지 선택적 매개 변수가 있습니다.
Workbook.close SaveChanges, filename, routeworkbook
Workbook.Close(false)
또는 후기 바인딩을 수행하는 경우 0을 사용하는 것이 더 쉬울 때도 있습니다. Workbook.Close(0)
이것이 통합 문서 닫기를 자동화 할 때 수행 한 방법입니다.
또한 문서를 찾아 보았는데 여기에서 찾았습니다. Excel 통합 문서 닫기
감사,
xlBook.Save();
xlBook.Close(true);
xlApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
이것을 시도하십시오 .. 그것은 나를 위해 일했습니다 ... 프로세스를 중지하려면 해당 xl 응용 프로그램 개체를 해제해야합니다.
참고 : https://stackoverflow.com/a/17367570/132599
다음과 같은 이중 점 호출 표현식을 사용하지 마십시오.
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 {}
무언가가 잘못되어도 모든 것이 풀리도록하기 위해 이것을 a 로 감싼다 (무엇이 잘못 될 수 있는가?).
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);
}
이것을 생각하면 프로세스가 종료됩니다.
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
Excel을 죽이는 것이 항상 쉬운 것은 아닙니다. 이 기사를 참조하십시오 : Excel을 죽이는 50 가지 방법
이 기사는 Excel을 멋지게 종료하는 방법에 대한 Microsoft ( MS Knowlege Base Article ) 의 최고의 조언을 취하지 만 필요한 경우 프로세스를 종료하여 확인합니다. 두 번째 낙하산을 좋아합니다.
열려있는 통합 문서를 모두 닫고 응용 프로그램을 종료 한 다음 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
excelBook.Close (); excelApp.Quit (); 코드의 끝을 추가하면 충분할 수 있습니다. 내 코드에서 작동 중입니다.
나는 같은 문제를 만났고 그것을 해결하기 위해 많은 방법을 시도했지만 작동하지 않습니다. 마침내, 나는 내 방식으로 발견했습니다. 일부 참조는 여기에 링크 설명을 입력
내 코드가 누군가의 미래를 도울 수 있기를 바랍니다. 나는 그것을 해결하기 위해 이틀 이상을 보냈다. 아래는 내 코드입니다.
//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();
}
}
}
자신의 COM
객체로 프로세스를 죽일 수 있습니다.
dll 가져 오기 코드 아래 어딘가에 추가
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowThreadProcessId(IntPtr hwnd, ref int lpdwProcessId);
그리고 사용
if (excelApp != null)
{
int excelProcessId = -1;
GetWindowThreadProcessId(new IntPtr(excelApp.Hwnd), ref excelProcessId);
Process ExcelProc = Process.GetProcessById(excelProcessId);
if (ExcelProc != null)
{
ExcelProc.Kill();
}
}
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 { }
}
}
이름이 "Excel"인 마지막 10 초 프로세스를 닫습니다.
모든 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 { }
}
}
다른 솔루션을 기반으로합니다. 나는 이것을 사용했다 :
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 엑셀 objecto입니다
각 Excel 개체에 대해 변수를 사용하고 반복해야합니다 Marshal.ReleaseComObject >0
. 루프가 없으면 Excel 프로세스는 여전히 활성 상태로 유지됩니다.
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);
}
}
다음 코드를 사용하여 xls를 xlsx로 변환하는 동안 Excel 응용 프로그램을 닫을 수 있습니다. 이런 종류의 작업을 수행하면 작업 관리자에서 Excel 응용 프로그램이 실행되고 있으므로 백그라운드에서 실행중인이 Excel을 닫아야합니다. Interop은 우리가 Marshal.FinalReleaseComObject를 사용한 com 구성 요소를 해제하기위한 Com 구성 요소입니다.
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);
}
대부분의 방법이 작동하지만 Excel 프로세스는 응용 프로그램을 닫을 때까지 항상 유지됩니다.
같은 스레드에서 다시 한 번 실행할 수 없으면 Excel 프로세스를 종료하면 이유를 알 수 없습니다.
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는 정확한 프로세스 ID를 찾습니다 .... 그것을 죽인 후 .... 즐기십시오 !!!
'Program Tip' 카테고리의 다른 글
버튼을 클릭하면 열리는 새 브라우저 창으로 전환하는 방법은 무엇입니까? (0) | 2020.10.14 |
---|---|
Nexus 4가 MTP를 통해 파일을 표시하지 않음 (0) | 2020.10.14 |
다른 함수 안에 함수를 정의 할 수없는 이유는 무엇입니까? (0) | 2020.10.14 |
C enum의 값 대신 텍스트 인쇄 (0) | 2020.10.14 |
Android에서 스타일 가능 속성 선언 (0) | 2020.10.14 |