web-dev-qa-db-fra.com

Fermeture du processus de candidature Excel en C # après l'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 souhaite que lorsque l'utilisateur ferme l'application, le processus d'application Excel a été fermé, sans enregistrer le fichier Excel. Voir mon gestionnaire de tâches après plusieurs exécutions 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 accéder 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 ceci , et les réponses test, mais cela ne fonctionne pas.

67
Javad Yousefi

Essaye ça: 

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

Lors de la fermeture du classeur, vous avez trois paramètres facultatifs:

Workbook.close SaveChanges, filename, routeworkbook 

Workbook.Close(false) ou si vous utilisez une liaison tardive, il est parfois plus facile d'utiliser zéro Workbook.Close(0) C'est ce que j'ai fait lors de l'automatisation de la fermeture des classeurs. 

Je suis aussi allé chercher la documentation à ce sujet et je l’ai trouvée ici: Excel Workbook Close

Merci, 

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

essayez ceci .. cela a fonctionné pour moi ... vous devriez libérer cet objet application xl pour arrêter le processus.

19
Sameera R.

Pensez-y, cela 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 { }
    }
}

Aussi, avez-vous essayé de le 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
Morris Miao

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

Évitez d’utiliser des expressions appelant deux points, telles que:

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

... parce que de cette manière, vous créez des objets RCW non seulement pour classeur, mais également pour classeurs, et vous devez également le publier (ce qui est impossible si une référence à l'objet n'est pas conservée).

Cela a résolu le problème pour moi. 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 relâchez 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);

J'emballe ceci dans un try {} finally {} pour m'assurer que tout est publié, même en cas de problème (que pourrait-il bien se passer?), P. Ex.

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

Tuer Excel n'est pas toujours facile. voir cet article: 50 façons de tuer Excel

Cet article tient compte des meilleurs conseils de Microsoft ( Article de base de la base de connaissances Microsoft ) sur la façon de bien arrêter Excel, mais s’assure également que le processus est arrêté si nécessaire. J'aime avoir un deuxième parachute.

Assurez-vous de fermer tous les classeurs ouverts, de quitter l'application et de libérer l'objet xlApp. Enfin, vérifiez si le processus est toujours actif et si c'est le cas, tuez-le.

Cet article garantit également que nous ne supprimons pas tous les processus Excel, mais uniquement le processus exact qui a été démarré.

Voir aussi Obtenir le processus depuis la poignée de 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
4
D_Bester

Vous pouvez tuer le processus avec votre propre objet COM Excel pid

ajouter quelque part sous le code d'importation dll

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

et utilise

 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

J'ai rencontré les mêmes problèmes et essayé de nombreuses méthodes pour le résoudre mais cela ne fonctionne pas… .. Enfin, j'ai trouvé le moyen. Quelques références entrez la description du lien ici

J'espère que mon code peut aider quelqu'un de l'avenir. J'ai passé plus de deux jours à le résoudre . Voici 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
Kenneth Wong

excelBook.Close (); excelApp.Quit (); ajouter la fin du code, cela pourrait être suffisant. ça marche sur mon code

1
user2605046

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

Lorsque tuer le processus Excel une fois, il ne peut pas être exécuté à nouveau dans le même thread - je ne sais pas pourquoi.

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

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

0
xrhstos

Basé sur une autre solution. J'ai utilisé ceci:

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

Utilisation du "MainWindowHandle" pour identifier le processus et le fermer.

excelObj: Ceci est mon application Interop Excel objet

0
merryrppin

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

Utilisez une variable pour chaque objet Excel et devez boucler Marshal.ReleaseComObject >0. Sans la boucle, le processus Excel reste toujours 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
user10170010

Nous pouvons fermer l'application Excel lors de la conversion de xls en xlsx en utilisant le code suivant: . Lorsque nous effectuons ce type de tâche, l'application Excel s'exécute dans le gestionnaire de tâches. Interop est un composant Com, pour libérer le composant com utilisé, 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
Sumant Singh