it-swarm.com.ru

Закрытие приложения Excel в C # после доступа к данным

Я пишу приложение на C #, которое открывает файл шаблона 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, такие как этот вопрос и этот , и тестовые ответы, но он не работает.

67
Javad Yousefi

Попробуй это: 

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

При закрытии рабочей книги у вас есть три необязательных параметра:

Workbook.close SaveChanges, filename, routeworkbook 

Workbook.Close(false) или если вы выполняете позднюю привязку, иногда проще использовать ноль Workbook.Close(0) Именно так я и сделал, когда автоматизировал закрытие книг. 

Кроме того, я пошел и посмотрел документацию для него, и нашел его здесь: Excel Workbook Close

Спасибо, 

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

попробуйте это ... это сработало для меня ... вы должны выпустить этот объект приложения xl, чтобы остановить процесс.

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

Убить 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
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

Я сталкивался с теми же проблемами и пытался решить их многими способами, но это не сработало .... Наконец, я нашел свой путь. Некоторая ссылка введите описание ссылки здесь

Надеюсь, мой код может помочь кому-то в будущем. Я потратил более двух дней, чтобы решить эту проблему .... Ниже приведен мой Код: 

//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 { }
             }
         }

Закрывает последние 10 сек процесс с именем "Excel"

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
Md. Alim Ul Karim

Используйте переменную для каждого объекта 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

Мы можем закрыть приложение Excel при преобразовании xls в xlsx, используя следующий код . Когда мы выполняем такую ​​задачу, приложение Excel запускается в диспетчере задач, мы должны закрыть это приложение Excel, работающее в фоновом режиме. Interop является компонентом Com, для выпуска компонента com мы использовали Marshal.FinalReleaseComObject.

 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