데이터 액세스 후 C #에서 Excel 응용 프로그램 프로세스 닫기


88

읽기 / 쓰기 작업을 위해 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 와 같은 스택 오버플로에서 유사한 질문을보고 답변을 테스트하지만 작동하지 않습니다.


Excel과 Word는 매우 느리고 우연히 만난 것과 같은 많은 단점이 있습니다. 파일은 일부 XML 및 기타 콘텐츠가 포함 된 zip 파일입니다. 문서를 열 수있는 Open XML SDK (또는 최신 버전)도 있습니다. 이러한 코드는 Office를 로컬에 설치하지 않아도 작동합니다. Excel을 사용하지 않는 것을 고려하십시오
Sten Petrov

답변:


97

이 시도:

excelBook.Close(0); 
excelApp.Quit();

통합 문서를 닫을 때 세 가지 선택적 매개 변수가 있습니다.

Workbook.close SaveChanges, filename, routeworkbook 

Workbook.Close(false)또는 후기 바인딩을 수행하는 경우 0을 사용하는 것이 더 쉬울 때가 Workbook.Close(0) 있습니다. 통합 문서 닫기를 자동화 할 때 이렇게했습니다.

또한 문서를 찾아서 여기에서 찾았습니다. Excel 통합 문서 닫기

감사,


감사합니다 친애하는 마이클, 그것은 작품이 제대로 : excelBook.Close (0)
자바드 Yousefi

안녕 여러분, 읽기를 위해 엑셀 파일을 열 때 작동하지 않습니다. 다음은 코드입니다. var excelApp = new Application (); var workBooks = excelApp.Workbooks.Open @ "c : \ temp \ myexcel.xlsx"); workBooks.Close (0); excelApp.Quit ();
user1131926 aug

나는 applicationClass를 사용 ... 그리고 난 개체를 처리하기 위해 위의 코드를 사용하지만 ... 일을 못해 한
Singaravelan

3
이 모든 답변으로 많은 시도가 실패한 후이 솔루션 을 사용하여 열었던 프로세스 ID를 가져와 직접 종료했습니다.
UndeadBob

@Singaravelan : David Clarke의 대답을 확인 했습니까?
The Anh Nguyen

22
xlBook.Save();
xlBook.Close(true);
xlApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);

이것을 시도하십시오 .. 그것은 나를 위해 일했습니다 ... 프로세스를 중지하려면 해당 xl 응용 프로그램 개체를 해제해야합니다.


14

참고 : 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);
}

2
이것은 나를 위해 일했으며 변수에 통합 문서를 할당하여 지울 수 있습니다. 또한 한 가지 관찰은 웹 응용 프로그램과 콘솔 응용 프로그램에서 Excel 앱을 지우는 데 정확히 동일한 코드가 있다는 것입니다. 이중 점 제거 업데이트 이전의 코드는 콘솔 앱에서 제대로 작동했지만 웹 앱에서 실행할 때 EXCEL.EXE를 지우지 않았습니다. 왜 그들이 다르게 행동했는지 잘 모르겠지만 이중 점 참조를 제거하면 웹 앱에서 수정되었습니다.
IronHide 2015 년

나를 위해 일하고 있습니다. comobject를 해제하려면 관련된 모든 객체를 해제해야한다고 생각합니다. SolidWorks 프로그램에 대해서도 같은 문제가있었습니다.
Gs.

1
통합 문서를 닫고 Excel 응용 프로그램을 종료하고 이중 점 호출을 피하고 생성 된 모든 COM 개체를 해제합니다. 그것은 나를 위해 일했습니다. 생명을 구하는 대답. 감사.
Sinan ILYAS

13

이것을 생각하면 프로세스가 종료됩니다.

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 파일을 닫습니다. 'excelBook.Close'를 사용할 때 Excel 저장 대화 상자가 나타나고 원하지 않습니다. (
Javad Yousefi

1
나는 그것이 도움이되기를 바랍니다, 그것을 편집하고 코드로 대화 상자를 대체 할 코드에서 다른 이름으로 저장을 할 수있는 라인을 추가 :.
모리스 미아오에게

1
방금 열린 Excel 프로세스에 대한 초기 검사와 함께 이것을 사용하고 ID를 목록에 저장했습니다. 그런 다음 새 Excel 프로세스를 만들고 편집을 수행하고 ID 목록에 포함되지 않은 Excel 프로세스를 닫았습니다.
182764125216

작업 관리자에서 Excel을 해제하는 올바른 방법이 아닙니다. WorkBOok과 같이 씬 ​​뒤에서 생성 된 오브젝트를 포함하여 생성 된 모든 오브젝트를 해제해야합니다.
ehh

이렇게하면 실행중인 모든 Excel 프로세스를 종료 할 수 있습니다. 문제는 동시에 Excel을 사용하는 다른 사용자 나 응용 프로그램이있을 수 있다는 것입니다. 당신이 이것을 할 의향이 있는지 명심하십시오.
Sinan ILYAS

6

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

이것은 나를 위해 일한 유일한 솔루션이었습니다. 감사.
Jon 투표

2

나는 같은 문제를 만났고 그것을 해결하기 위해 많은 방법을 시도했지만 작동하지 않습니다. 마침내, 나는 내 방식으로 발견했습니다. 일부 참조는 여기에 링크 설명을 입력

내 코드가 누군가의 미래를 도울 수 있기를 바랍니다. 나는 그것을 해결하기 위해 이틀 이상을 보냈다. 아래는 내 코드입니다.

//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();
                    }        
                }
            }

1

excelBook.Close (); excelApp.Quit (); 코드의 끝을 추가하면 충분할 수 있습니다. 내 코드에서 작동 중입니다.


내가 대화 상자가 나타납니다 저장, 사용, 내가 원하지 않는 경우 예,하지만 :( 표시
자바드 Yousefi

1

자신의 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();
                }
            }

1

나는 루프 Marshal.ReleaseComObject내에 있고 Garbage Collection으로While 끝내는 것이 중요하다는 것을 알았습니다 .

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();
}

0
         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 초 프로세스를 닫습니다.


0

다른 솔루션을 기반으로합니다. 나는 이것을 사용했다 :

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입니다


0

각 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);
        }
}

0

다음 코드를 사용하여 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);
   }

0

대부분의 방법은 작동하지만 Excel 프로세스는 응용 프로그램을 닫을 때까지 항상 유지됩니다.

같은 스레드에서 다시 한 번 실행할 수 없으면 Excel 프로세스를 종료하면 이유를 알 수 없습니다.


0

모든 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 { }
    }
}

이것은 또한 VS 환경 외부에 열려있는 모든 합법적 인 Excel 인스턴스를 종료합니다. 즉, 실제 엑셀 앱에서 다른 엑셀 워크 시트를 열었다 고 가정 해 보겠습니다. 코드도이를 죽입니다.
Mark

업데이트 해주셔서 감사합니다.
. 메릴랜드 Alim에 UL 카림

0
workbook.Close(0);
excelApp.Quit();

나를 위해 일했습니다.


-1
        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를 찾는다.


-1
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();
    }
}

이 코드가 문제를 해결할 수 있지만 문제를 해결하는 방법과 이유에 대한 설명포함 하여 게시물의 품질을 향상시키는 데 실제로 도움이되며 아마도 더 많은 찬성 투표를 받게됩니다. 지금 질문하는 사람뿐만 아니라 미래에 독자를 위해 질문에 답하고 있다는 것을 기억하십시오. 제발 편집 설명을 추가하고, 제한 및 가정이 적용 무엇의 표시를 제공하는 답변을.
Dave
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.