Menutup Proses Aplikasi Excel di C # setelah Akses Data

88

Saya sedang menulis aplikasi di C # yang membuka file template Excel untuk operasi baca / tulis. Saya ingin ketika pengguna menutup aplikasi, proses aplikasi excel telah ditutup, tanpa menyimpan file excel. Lihat Task Manager saya setelah beberapa kali menjalankan aplikasi.

masukkan deskripsi gambar di sini

Saya menggunakan kode ini untuk membuka file excel:

public Excel.Application excelApp = new Excel.Application();
public Excel.Workbook excelBook;
excelBook = excelApp.Workbooks.Add(@"C:/pape.xltx");

dan untuk akses data saya menggunakan kode ini:

Excel.Worksheet excelSheet = (Worksheet)(excelBook.Worksheets[1]);
excelSheet.DisplayRightToLeft = true;
Range rng;
rng = excelSheet.get_Range("C2");
rng.Value2 = txtName.Text;

Saya melihat pertanyaan serupa di stackoverflow seperti pertanyaan ini dan ini , dan menguji jawaban, tetapi tidak berhasil.

Javad Yousefi
sumber
Excel dan Word sangat lambat dan hadir dengan banyak keunikan seperti yang Anda temukan. File tersebut adalah file zip dengan beberapa XML dan konten lain di sana. Ada juga Open XML SDK (atau mungkin sesuatu yang lebih baru) yang dapat membuka dokumen. Kode tersebut berfungsi tanpa Office diinstal secara lokal juga. Pertimbangkan untuk tidak menggunakan Excel
Sten Petrov

Jawaban:

97

Coba ini:

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

Saat menutup buku kerja, Anda memiliki tiga parameter opsional:

Workbook.close SaveChanges, filename, routeworkbook 

Workbook.Close(false)atau jika Anda melakukan penjilidan terlambat, terkadang lebih mudah menggunakan nol. Workbook.Close(0) Begitulah cara saya melakukannya saat mengotomatiskan penutupan buku kerja.

Juga saya pergi dan mencari dokumentasi untuk itu, dan menemukannya di sini: Tutup Buku Kerja Excel

Terima kasih,

Michael
sumber
Terima kasih Dear Michael, Ini berfungsi dengan baik: excelBook.Close (0)
Javad Yousefi
Hai Teman-teman, ini tidak berfungsi saat Anda membuka file excel untuk membaca. Berikut ini adalah kode var excelApp = new Application (); var workBooks = excelApp.Workbooks.Open @ "c: \ temp \ myexcel.xlsx"); workBooks.Close (0); excelApp.Quit ();
pengguna1131926
Saya telah menggunakan applicationClass ... dan saya menggunakan kode di atas untuk membuang objek tetapi tidak berfungsi ...
Singaravelan
3
Setelah banyak upaya yang gagal dengan semua jawaban ini, saya menggunakan solusi ini untuk mendapatkan ID proses yang saya buka dan langsung membunuhnya.
UndeadBob
@ Singaravelan: Sudahkah Anda memeriksa jawaban David Clarke?
The Anh Nguyen
22
xlBook.Save();
xlBook.Close(true);
xlApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);

coba ini .. berhasil untuk saya ... Anda harus melepaskan objek aplikasi xl itu untuk menghentikan proses.

Sameera R.
sumber
14

Ref: https://stackoverflow.com/a/17367570/132599

Hindari menggunakan ekspresi pemanggilan titik ganda, seperti ini:

var workbook = excel.Workbooks.Open(/*params*/)

... karena dengan cara ini Anda membuat objek RCW tidak hanya untuk workbook, tetapi juga untuk Workbooks, dan Anda harus merilisnya juga (yang tidak dimungkinkan jika referensi ke objek tidak dipertahankan).

Ini menyelesaikan masalah saya. Kode Anda menjadi:

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;

Dan kemudian lepaskan semua objek itu:

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

Saya membungkus ini try {} finally {}untuk memastikan semuanya dibebaskan bahkan jika ada yang salah (apa yang mungkin salah?) Mis

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);
}
David Clarke
sumber
2
Ini telah berhasil untuk saya, menugaskan buku kerja ke variabel sehingga bisa dihapus. Juga satu pengamatan, saya memiliki kode yang persis sama untuk membersihkan aplikasi excel di aplikasi Web dan aplikasi konsol. Kode sebelum pembaruan untuk menghilangkan titik ganda berfungsi dengan baik di aplikasi konsol tetapi ketika dijalankan di aplikasi web itu tidak menghapus EXCEL.EXE. Saya tidak yakin mengapa mereka berperilaku berbeda tetapi menghapus referensi titik ganda memperbaikinya di aplikasi web.
IronHide
bekerja untuk saya. Saya pikir untuk melepaskan objek, kita harus melepaskan semua objek terkait. Saya memiliki masalah yang sama tentang program solidworks.
Gs.
1
Tutup buku kerja, keluar dari aplikasi Excel, hindari panggilan titik ganda, dan lepaskan setiap objek COM yang dibuat. Itu berhasil untuk saya. Jawaban yang menyelamatkan hidup. Terima kasih.
Sinan ILYAS
13

Pikirkan ini, itu membunuh proses:

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

Juga, apakah Anda mencoba menutupnya secara normal?

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
Morris Miao
sumber
Terima kasih atas jawaban Anda Solusi pertama Anda menutup Semua file Excel yang terbuka. Ketika saya menggunakan 'excelBook.Close', dialog simpan excel muncul, dan saya tidak menginginkannya :(
Javad Yousefi
1
Saya mengedit dan menambahkannya dengan baris untuk melakukan saveAs dalam kode yang akan menggantikan dialog dengan kode, semoga membantu. :)
Morris Miao
1
Saya baru saja menggunakan ini dengan pemeriksaan awal untuk proses Excel terbuka dan menyimpan ID dalam daftar. Kemudian buat proses Excel baru, lakukan pengeditan yang harus saya lakukan dan tutup semua proses Excel yang tidak ada dalam daftar ID.
182764125216
Ini bukan cara yang benar untuk merilis excel dari pengelola tugas. Anda harus melepaskan semua objek yang telah dibuat termasuk yang dibuat di belakang layar seperti WorkBOoks.
ehh
Dengan cara ini, Anda akan menghentikan setiap proses Excel yang sedang berjalan. Masalahnya, mungkin ada pengguna atau aplikasi lain yang menggunakan Excel secara bersamaan. Perlu diingat jika Anda bersedia melakukan ini.
Sinan ILYAS
6

Membunuh Excel tidak selalu mudah; lihat artikel ini: 50 Cara Membunuh Excel

Artikel ini mengambil saran terbaik dari Microsoft ( Artikel Dasar Pengetahuan MS ) tentang cara membuat Excel berhenti dengan baik, tetapi juga memastikannya dengan menghentikan proses jika perlu. Saya suka parasut kedua.

Pastikan untuk menutup semua buku kerja yang terbuka, keluar dari aplikasi dan lepaskan objek xlApp. Terakhir periksa untuk melihat apakah prosesnya masih hidup dan jika demikian maka matikan.

Artikel ini juga memastikan bahwa kami tidak menghentikan semua proses Excel tetapi hanya menghentikan proses persis seperti yang telah dimulai.

Lihat juga Mendapatkan Proses dari Tuas Jendela

Berikut kode yang saya gunakan: (berfungsi setiap saat)

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
D_Bester
sumber
Ini adalah satu-satunya solusi yang berhasil untuk saya. Terima kasih.
Jon Vote
2

Saya menemui masalah yang sama dan mencoba banyak metode untuk menyelesaikannya tetapi tidak berhasil. Akhirnya, saya menemukan jalan saya. Beberapa referensi masukkan deskripsi tautan di sini

Semoga kode saya dapat membantu seseorang di masa depan. Saya telah menghabiskan lebih dari dua hari untuk menyelesaikannya. Di bawah ini adalah Kode saya:

//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();
                    }        
                }
            }
Kenneth Wong
sumber
1

excelBook.Close (); excelApp.Quit (); tambahkan akhir kode, itu sudah cukup. itu bekerja pada kode saya

pengguna2605046
sumber
Ya, tetapi ketika saya menggunakannya, dialog simpan muncul, dan saya tidak ingin itu muncul :(
Javad Yousefi
1

Anda dapat menghentikan proses dengan COMobjek excel pid Anda sendiri

tambahkan di suatu tempat di bawah kode impor dll

[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowThreadProcessId(IntPtr hwnd, ref int lpdwProcessId);

dan gunakan

 if (excelApp != null)
            {
                int excelProcessId = -1;
                GetWindowThreadProcessId(new IntPtr(excelApp.Hwnd), ref excelProcessId);

                Process ExcelProc = Process.GetProcessById(excelProcessId);
                if (ExcelProc != null)
                {
                    ExcelProc.Kill();
                }
            }
Alican Kuklaci
sumber
1

Saya telah menemukan bahwa penting untuk memiliki Marshal.ReleaseComObjectsatu Whilelingkaran DAN menyelesaikannya dengan Pengumpulan Sampah .

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();
}
Emanuel Oliveira
sumber
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 { }
             }
         }

Ini Menutup proses 10 detik terakhir dengan nama "Excel"

xrhstos
sumber
0

Berdasarkan solusi lain. Saya telah menggunakan ini:

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

Menggunakan "MainWindowHandle" untuk mengidentifikasi proses dan menutupnya.

excelObj: Ini adalah objek excel Interop Aplikasi saya

merryrppin
sumber
0

Gunakan variabel untuk setiap objek Excel dan harus berulang Marshal.ReleaseComObject >0. Tanpa perulangan, proses Excel masih tetap aktif.

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);
        }
}
pengguna10170010
sumber
0

Kita dapat menutup Aplikasi Excel sambil mengubah xls menjadi xlsx dengan menggunakan kode berikut. Saat kita melakukan tugas semacam ini maka aplikasi Excel sedang berjalan di task manager, kita harus menutup excel yang sedang berjalan di latar belakang ini. Interop adalah komponen Com, untuk melepaskan komponen com kami menggunakan 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);
   }
Sumant Singh
sumber
0

Sebagian besar metode berfungsi, tetapi proses excel selalu bertahan sampai aplikasi ditutup.

Ketika proses kill excel setelah itu tidak dapat dijalankan sekali lagi di utas yang sama - tidak tahu mengapa.

Atanas Atanasov
sumber
0

Cara yang tepat untuk menutup semua proses excel

var _excel = new Application();
foreach (Workbook _workbook in _excel.Workbooks) {
    _workbook.Close(0);
}

_excel.Quit();
_excel = null;

Menggunakan contoh proses, ini dapat menutup semua proses excel.

var process = System.Diagnostics.Process.GetProcessesByName("Excel");
foreach (var p in process) {
    if (!string.IsNullOrEmpty(p.ProcessName)) {
        try {
            p.Kill();
        } catch { }
    }
}
Md. Alim Ul Karim
sumber
Ini juga akan mematikan semua instance resmi dari excel yang terbuka di luar lingkungan VS. mis. katakanlah saya memiliki lembar kerja excel lain yang terbuka di aplikasi excel yang sebenarnya, kode Anda juga mematikannya.
Tandai
Terima kasih telah memperbarui catatannya.
Md. Alim Ul Karim
0
workbook.Close(0);
excelApp.Quit();

Bekerja untuk saya.

quan_bui
sumber
-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 ini menemukan Id Proses yang benar o excell .... Setelah membunuhnya .... Enjoy It !!!

xrhstos
sumber
-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();
    }
}
Mehmet Yardım
sumber
Meskipun kode ini dapat menyelesaikan pertanyaan, termasuk penjelasan tentang bagaimana dan mengapa ini menyelesaikan masalah akan sangat membantu meningkatkan kualitas posting Anda, dan mungkin menghasilkan lebih banyak suara. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa depan, bukan hanya orang yang bertanya sekarang. Harap edit jawaban Anda untuk menambahkan penjelasan, dan berikan indikasi batasan dan asumsi apa yang berlaku.
Dave