2

スプレッドシートを開き、いくつかの値を読み取り、シートを閉じるコードがあります。複数のファイルに対してこれを行う必要があります。私が抱えている問題は、Excel アプリケーション インスタンスが終了していないことです。そのため、いくつかのファイルに対してプロセスを実行すると、いくつかの Excel.exe プロセスが実行されてしまいます。Excelを閉じる方法はありますか?

    static void ParseFile(string file)
    {
        try
        {
            System.Console.WriteLine("parsing:" + file);
            Excel.Application excel = new Excel.Application();
            Excel.Workbook wb = excel.Workbooks.Open(file);
            Excel.Worksheet ws = wb.Worksheets[1];
            for (int i = 2; i < 27; i++)
            {
                log(ws.Cells[i, 1].Text);
            }
            wb.Close(false);                
            excel.Quit();
            excel = null;
            ws = null;
            wb = null;
        }
        catch (Exception ex)
        {
            log(ex.Message);
        }
    }

------2012 年 12 月 11 日更新--------Excel インスタンスを開いたままにします-------

static void ParseFile(string file)
    {
        try
        {
            log("parsing:" + file);
            Excel.Application excel = new Excel.Application();
            Excel.Workbook wb = excel.Workbooks.Open(file);
            Excel.Worksheet ws = wb.Worksheets[1];
    //do some stuff here
            wb.Close(false);
            excel.Quit();
            GC.Collect();
            GC.WaitForPendingFinalizers();
            Marshal.FinalReleaseComObject(ws);
            Marshal.FinalReleaseComObject(wb);
            Marshal.FinalReleaseComObject(excel);                
            excel = null;
            ws = null;
            wb = null;
            System.GC.Collect();
        }
        catch (Exception ex)
        {
            log(ex.Message);
        }            
    }
4

4 に答える 4

3
  1. Marshal.FinalReleaseComObject()リソースを解放するために使用します

  2. 複数のファイルを次々に読み取る場合、パフォーマンスに関しては、Excelアプリケーションを一度だけ開いたり閉じたりして、開いたり閉じたりするアプリケーション部分を別の関数に移動する方がはるかに優れています。

リファクタリングされたコード:

static Excel.Application OpenExcel(){
    Excel.Application excel = null;
    try{
        excel = new Excel.Application();
        return excel;
    }
    catch(Exception ex){
        log(ex.Message);
        return null;
    }
}

static void ParseFile(string file)
{
    try
    {
        System.Console.WriteLine("parsing:" + file);            
        Excel.Workbook wb = excel.Workbooks.Open(file);
        Excel.Worksheet ws = wb.Worksheets[1];
        for (int i = 2; i < 27; i++)
        {
            log(ws.Cells[i, 1].Text);
        }
        wb.Close(false);    
    }
    catch (Exception ex)
    {
        log(ex.Message);
    }
    finally{
        Marshal.FinalReleaseComObject(ws);
        Marshal.FinalReleaseComObject(wb);
        ws = null;
        wb = null;
    }
}

static void CloseExcel(Excel.Application excel){
    try{
        excel.Quit();
    }
    catch(Exception ex){
        log(ex.Message);
    }
    finally{
        Marshal.FinalReleaseComObject(excel);
        excel = null;
    }
}

使用法:

Excel.Application excel = OpenExcel();
if(excel != null){
    // Parse files in a loop
    ParseFile("fileName");

    // Close excel after parsing all files
    CloseExcel(excel);
}
于 2012-11-21T17:11:54.677 に答える
2

プロセスを強制終了しましたが、それが唯一の機能でした。

    [DllImport("user32.dll")]
    private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

    /// <summary> Tries to find and kill process by hWnd to the main window of the process.</summary>
    /// <param name="hWnd">Handle to the main window of the process.</param>
    /// <returns>True if process was found and killed. False if process was not found by hWnd or if it could not be killed.</returns>
    public static bool TryKillProcessByMainWindowHwnd(int hWnd)
    {
        uint processID;
        GetWindowThreadProcessId((IntPtr)hWnd, out processID);
        if (processID == 0) return false;
        try
        {
            Process.GetProcessById((int)processID).Kill();
        }
        catch (ArgumentException)
        {
            return false;
        }
        catch (Exception ex)
        {
            return false;
        }            
        return true;
    }

    static void ParseFile(string file)
    {
        try
        {
            log("parsing:" + file);
            Excel.Application excel = new Excel.Application();
            Excel.Workbook wb = excel.Workbooks.Open(file);
            Excel.Worksheet ws = wb.Worksheets[1];
            //do some stuff here
            wb.Close(false);
            int hWnd = excel.Application.Hwnd;
            excel.Quit();
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            GC.WaitForPendingFinalizers();
            Marshal.FinalReleaseComObject(ws);
            Marshal.FinalReleaseComObject(wb);
            Marshal.FinalReleaseComObject(excel);                
            excel = null;
            ws = null;
            wb = null;
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            GC.WaitForPendingFinalizers();
            TryKillProcessByMainWindowHwnd(hWnd);
        }
        catch (Exception ex)
        {
            log(ex.Message);
        }            
    }
于 2012-12-11T15:41:21.237 に答える