Fermeture du processus de demande Excel en C# après accès aux données

j'écris une application en C# qui ouvre un fichier de modèle Excel pour les opérations de lecture/écriture. Je veux quand l'utilisateur ferme la demande, le processus de demande excel a été fermé, sans enregistrer le fichier excel. Voir mon Gestionnaire des tâches après plusieurs passages de l'application.

enter image description here

j'utilise ce code pour ouvrir le fichier excel :

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

et pour l'accès aux données j'utilise ce code :

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

je vois des questions similaires dans stackoverflow telles que cette question et cette , et des réponses d'essai, mais cela ne fonctionne pas.

62
demandé sur Community 2013-07-22 02:20:35

15 réponses

essayez ceci:

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

lors de la fermeture du cahier de travail, vous avez trois paramètres optionnels:

Workbook.close SaveChanges, filename, routeworkbook 

Workbook.Close(false) ou si vous faites une fixation tardive, il est parfois plus facile d'utiliser zéro Workbook.Close(0) C'est ce que j'ai fait en automatisant la fermeture des classeurs.

Aussi j'ai regardé la documentation pour elle, et l'a trouvé ici: Classeur Excel Fermer

Merci,

71
répondu Michael 2015-06-18 08:54:58
xlBook.Save();
xlBook.Close(true);
xlApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);

essayez ceci.. il a travaillé pour moi... vous devez libérer cet objet XL application pour arrêter le processus.

18
répondu Sameera R. 2013-11-26 09:23:46

pensez à ça, ça tue le processus:

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

avez-vous essayé de la fermer normalement?

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
répondu Morris Miao 2013-07-21 23:02:57

Réf: https://stackoverflow.com/a/17367570/132599

éviter d'utiliser des expressions à double point, comme ceci:

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

...parce que de cette façon, vous créez des objets RCW non seulement pour les classeurs, mais aussi pour les classeurs, et vous devriez les publier aussi (ce qui n'est pas possible si une référence à l'objet n'est pas maintenue).

cela a résolu la question pour je. Votre code devient:

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;

et puis libérer tous ces objets:

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

Je l'enroule dans un try {} finally {} pour m'assurer que tout est libéré même si quelque chose tourne mal (qu'est-ce qui pourrait mal tourner?) par exemple

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);
}
8
répondu David Clarke 2017-05-23 12:03:03

tuer Excel N'est pas toujours facile; voir cet article: 50 façons de tuer Excel

cet article prend le meilleur conseil de Microsoft ( article de base de MS Knowlege ) sur la façon D'obtenir Excel pour cesser de fumer bien, mais puis s'assure également à ce sujet en tuant le processus si nécessaire. J'aime avoir un second parachute.

assurez-vous de fermer tous les manuels ouverts, quitter l'application et libérer le xlApp objet. Vérifiez enfin si le processus est toujours en vie et si oui, tuez-le.

cet article s'assure également que nous ne tuons pas tous les processus Excel, mais ne tuons que le processus exact qui a été démarré.

Voir aussi obtenir le processus à partir de la poignée de la fenêtre

Voici le code que j'utilise: (fonctionne à chaque fois)

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
3
répondu D_Bester 2017-05-23 10:31:30

excelBook.Proche(); excelApp.Quitter(); ajoutez la fin du code, ça pourrait suffire. il travaille sur mon code

1
répondu user2605046 2013-07-21 22:37:12

j'ai rencontré les mêmes problèmes et j'ai essayé de nombreuses méthodes pour les résoudre mais ça ne marche pas. Enfin , j'ai trouvé ma voie. Quelques référence entrez la description du lien ici

J'espère que mon code peut aider quelqu'un à l'avenir. J'ai été passé plus de deux jours pour le résoudre. Ci-dessous mon Code:

//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
répondu Kenneth Wong 2017-03-16 09:42:14

vous pouvez tuer le processus avec votre propre COM objet excel pid

ajouter quelque part au-dessous de dll code d'importation

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

et utilisation

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

                Process ExcelProc = Process.GetProcessById(excelProcessId);
                if (ExcelProc != null)
                {
                    ExcelProc.Kill();
                }
            }
1
répondu Alican Kuklaci 2018-01-17 20:55:33
         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 { }
             }
         }

il ferme le dernier processus de 10 secondes avec le nom "Excel"

0
répondu xrhstos 2015-05-27 08:05:51

La bonne façon de fermer tous les processus 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
répondu Md. Alim Ul Karim 2016-05-17 10:47:01

basé sur une autre solution. Je l'ai utilisé:

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

utilisant le "MainWindowHandle" pour identifier le processus et le fermer.

excelObj: C'est mon application Interop excel objecto

0
répondu merryrppin 2017-05-16 22:51:06

utiliser une variable pour chaque objet Excel et doit boucler Marshal.ReleaseComObject >0 . Sans la boucle, le processus Excel reste actif.

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
répondu user10170010 2018-08-02 09:08:34

nous pouvons fermer L'application Excel en convertissant xls en xlsx en utilisant le code suivant. Lorsque nous effectuons ce genre de tâche puis L'application Excel est en cours d'exécution dans le Gestionnaire des tâches, nous devrions fermer cet excel qui est en cours d'exécution en arrière-plan. Interop est un composant Com, pour libérer le composant com que nous avons utilisé 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
répondu Sumant Singh 2018-08-18 03:28:13

la plupart des méthodes fonctionnent, mais le processus excel reste toujours jusqu'à la fin de l'application.

quand kill excel process une fois qu'il ne peut pas être exécuté une fois de plus dans le même thread - ne sait pas pourquoi.

0
répondu Atanas Atanasov 2018-09-30 09:58:48
        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;

ce GetWindowThreadProcessId trouve le bon Id de processus o excell .... Après le tue.... Profitez-En!!!

-1
répondu xrhstos 2015-06-16 13:37:15