none
Richtigen Prozess zu einer "Excel Instanz" ermitteln RRS feed

  • Frage

  • Hallo,

    ich will mit c# ein Excel Objekt erzeugen und dann herausfinden, welcher der zugehörige Prozess ist.

    Ist das irgendwie möglich? Wenn ja wie?

            private void button5_Click(object sender, EventArgs e)
            {
    
                Excel.Application myExcel = new Excel.Application();
    
                var procList = Process.GetProcessesByName("EXCEL");
    
                for (int i = 0; i < procList.Count(); i++)
                {
                    //Wie finde ich nun heraus, welcher der laufenden Excel Prozesse mein "myExcel" Prozess ist?
    
                }
            }

    Vielen Dank für eure Infos.

    Thomas



    Donnerstag, 18. April 2013 09:33

Antworten

  • Hallo Thomas,

    das Verhalten, das Du beschreibst, kenne ich nur aus älteren Excel-Versionen. Da mußte man Code wie diesen schreiben, um den Speicher zu bereinigen:

    // [...] alle Referenzen freigeben und dann:
    System.Runtime.InteropServices.Marshal.ReleaseComObject(myExcel); 
    myExcel = null;
    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.Collect();
    GC.WaitForPendingFinalizers();

    Blieb dennoch eine Instanz im Speicher übrig, so behalf man sich, indem man VOR dem Aufruf von new Excel.Application() eine Liste der laufenden Excel-Prozesse erstellte und nach Beenden der eigenen Arbeit killte man eben jene, die nicht in dieser Liste standen.

    P.S. Auch wenn Du die Excel-Instanz nicht sichtbar machst, gibt es dennoch eine Hwnd-Eigenschaft dazu, die ein gültiges Fenster-Handle enthält. Über die Windows API kann man dann herausfinden, zu welchem Prozess das Handle gehört:

    int processId;
    Excel.Application myExcel = new Excel.Application();
    GetWindowThreadProcessId(new HandleRef(null, (IntPtr)myExcel.Hwnd), out processId);
    // processId enthält nun die ID des gestarteten Prozesses
    // und der Prozess kann beendet werden
    Process.GetProcessById(processId).Kill();

    Gruß
    Marcel

    Freitag, 19. April 2013 07:47
    Moderator

Alle Antworten

  • Hallo, das Process-Objekt wirst du kaum mit deiner Arbeitsmappe vergleichen können. Was genau möchtest du denn mit dem Prozess machen? Vielleicht gibt es einen Alternativweg.

    <Code:13/> - Koopakiller [kuːpakɪllɐ]
    Webseite | Code Beispiele | Facebook | Snippets
    Wenn die Frage beantwortet ist, dann markiert die hilfreichsten Beiträge als Antwort und bewertet die Beiträge. Danke.
    Einen Konverter zwischen C# und VB.NET Code gibt es hier.

    Donnerstag, 18. April 2013 16:43
    Moderator
  • Hallo zusammen,

    da das Excel.Application-Objekt über eine Hwnd-Eigenschaft verfügt, kann man diese mit der Process.MainWindowHandle vergleichen:

    using System;
    using System.Diagnostics;
    using System.Linq;
    using Excel = Microsoft.Office.Interop.Excel;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                Excel.Application myExcel = new Excel.Application();
                myExcel.Visible = true;
    
                try
                {
                    var procList = Process.GetProcessesByName("EXCEL");
    
                    for (int i = 0; i < procList.Count(); i++)
                    {
                        if (procList[i].MainWindowHandle == (IntPtr)myExcel.Hwnd)
                        {
                            Console.WriteLine("Prozess ID: {0}. Hauptfenster: {1}", procList[i].Id, procList[i].MainWindowTitle);
                        }
                    }
                }
                finally
                {
                    myExcel.Quit();
                }
    
                Console.ReadKey(true);
            }
        }
    }
    

    Gruß
    Marcel
    Donnerstag, 18. April 2013 23:44
    Moderator
  • Hallo Marcel,

    danke für die Info.

    Das funktioniert jedoch nur, wenn

    myExcel.Visible = true;

    Eigentlich will ich alles im Hintergrund machen (Excel nicht sichtbar). Dann funktioniert das ganze jedoch nicht.

    Eventuell noch eine Idee?

    Thomas

    Freitag, 19. April 2013 06:52
  • Hallo Koopakiller,

    eigenlicht ist mein Zweck ein ganz einfacher!

    Ich greife auf das Excel Objekt zu. Wenn ich jedoch mit Excel fertig bin, wird das Excel Objekt nicht aus dem Speicher gelöscht.

    Ich habe schon alles mögliche versucht

    z.B.

                    exl.Quit();
                    Marshal.ReleaseComObject(exl);
    

    Jedoch sehe ich im Task Manager immer noch die Excel Instanz.

    Darum wollte ich nun, wenn das Excel Objekt noch vorhanden ist, einfach den Prozess abschiessen. Damit ich nicht alle Excel Prozesse schliesse, will ich nur "den eben geöffneten" wieder beenden.

    procList[i].Kill();
    Thomas

    Freitag, 19. April 2013 06:58
  • Hi,
    um das Excel-Application-Objekt vollständig zu entfernen, müssen alle Verweise vernichtet werden mit ggf. vorherigem Dispose.
     
    Das betrifft Workbooks (Close), ExcelApplication (Quit) mit Saved=true und alle weiteren genutzten Objekte. Oft werden unnötig Objekte der Oberfläche genutzt, die nicht richtig entsorgt wurden und deshlab ein Entfernen der Excel-Application verhindern. Die Oberflächen-Objekte werden z.B. implizit erzeugt, wenn Activate und Select genutzt wird. Auf diese Techniken sollte man zugunsten der Nutzung von Range-Objekten verzichten.
     
    --
    Peter Fleischer
    Freitag, 19. April 2013 07:43
  • Hallo Thomas,

    das Verhalten, das Du beschreibst, kenne ich nur aus älteren Excel-Versionen. Da mußte man Code wie diesen schreiben, um den Speicher zu bereinigen:

    // [...] alle Referenzen freigeben und dann:
    System.Runtime.InteropServices.Marshal.ReleaseComObject(myExcel); 
    myExcel = null;
    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.Collect();
    GC.WaitForPendingFinalizers();

    Blieb dennoch eine Instanz im Speicher übrig, so behalf man sich, indem man VOR dem Aufruf von new Excel.Application() eine Liste der laufenden Excel-Prozesse erstellte und nach Beenden der eigenen Arbeit killte man eben jene, die nicht in dieser Liste standen.

    P.S. Auch wenn Du die Excel-Instanz nicht sichtbar machst, gibt es dennoch eine Hwnd-Eigenschaft dazu, die ein gültiges Fenster-Handle enthält. Über die Windows API kann man dann herausfinden, zu welchem Prozess das Handle gehört:

    int processId;
    Excel.Application myExcel = new Excel.Application();
    GetWindowThreadProcessId(new HandleRef(null, (IntPtr)myExcel.Hwnd), out processId);
    // processId enthält nun die ID des gestarteten Prozesses
    // und der Prozess kann beendet werden
    Process.GetProcessById(processId).Kill();

    Gruß
    Marcel

    Freitag, 19. April 2013 07:47
    Moderator
  • Hallo Thomas,

    Du automatierst Excel nicht zufällig aus einer Dienstanwendung heraus? Falls doch, ist das IMHO keine gute Idee. Siehe dazu u.a.:

      http://support.microsoft.com/kb/257757

    In dem Fall würde ich dir eher empfehlen, eine Komponente wie bspw. Aspose.Cells zu verwenden. Ob das in deinem Fall möglich ist, hängt aber von den genauen Anforderungen ab.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Freitag, 19. April 2013 09:15
    Moderator
  • Vielen Dank für die Hilfe

    mit

    GetWindowThreadProcessId

    kann ich mein Problem lösen.

    Danke euch allen, für die weiteren Hinweise. Werde ich auf jeden Fall beachten.

    Thomas

    Freitag, 19. April 2013 11:47