web-dev-qa-db-ja.com

データアクセス後にC#でExcelアプリケーションプロセスを閉じる

読み取り/書き込み操作のためにExcelテンプレートファイルを開くC#でアプリケーションを作成しています。ユーザーがアプリケーションを閉じると、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;

this questionthis などのstackoverflowで同様の質問が表示され、回答をテストしますが、機能しません。

75
Javad Yousefi

これを試して:

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

ワークブックを閉じるとき、次の3つのオプションパラメータがあります。

Workbook.close SaveChanges, filename, routeworkbook 

Workbook.Close(false)または遅延バインディングを実行している場合、ゼロを使用する方が簡単な場合がありますWorkbook.Close(0)これは、ブックのクローズを自動化するときに実行した方法です。

また、私は行って、そのドキュメントを調べて、ここで見つけました: Excel Workbook Close

おかげで、

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

これを試してください..それは私のために働いた...あなたはそのxlアプリケーションオブジェクトをリリースしてプロセスを停止する必要があります。

20
Sameera R.

これを考えて、それはプロセスを殺します:

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
10
Morris Miao

参照: 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 {}でラップして、何かがうまくいかなくてもすべてがリリースされるようにします(何がうまくいかない可能性がありますか)。

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);
}
10
David Clarke

Excelを強制終了するのは必ずしも簡単ではありません。この記事を参照してください: Excelを終了する50の方法

この記事では、Microsoftからの最善のアドバイス( MS Knowlege Base Article )を使用して、Excelを正常に終了する方法について説明しますが、必要に応じてプロセスを強制終了することでも確認します。 2番目のパラシュートが好きです。

開いているワークブックをすべて閉じ、アプリケーションを終了して、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
4
D_Bester

独自のCOMオブジェクトExcel pidでプロセスを強制終了できます

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
Alican Kuklaci

私は同じ問題に出会い、それを解決するために多くの方法を試しましたが、うまくいきません。最後に、私は自分の方法で見つけました。参照 リンクの説明をここに入力

私のコードが将来の誰かを助けることを願っています。私はそれを解決するために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
Kenneth Wong

excelBook.Close(); excelApp.Quit();コードの終わりを追加すれば、それで十分かもしれません。それは私のコードに取り組んでいます

1
user2605046

ほとんどのメソッドは機能しますが、Excelプロセスは常にアプリケーションを閉じるまで残ります。

Excelプロセスを一度強制終了すると、同じスレッドで再度実行できなくなります。理由はわかりません。

0
Atanas Atanasov
         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
xrhstos

別のソリューションに基づいています。私はこれを使用しています:

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:これは私のアプリケーション相互運用Excelオブジェクトです

0
merryrppin

すべての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 { }
    }
}
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
user10170010

次のコードを使用して、xlsをxlsxに変換しながらExcelアプリケーションを閉じることができます。この種のタスクを実行し、Excelアプリケーションがタスクマネージャーで実行されている場合、バックグラウンドで実行されているこのExcelを閉じる必要があります。 InteropはComコンポーネントであり、Marshal.FinalReleaseComObjectを使用して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
Sumant Singh