myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » Office-Technologien » EXCEL wirklich schliessen
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

EXCEL wirklich schliessen

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
cel
myCSharp.de-Mitglied

Dabei seit: 10.01.2007
Beiträge: 6


cel ist offline

EXCEL wirklich schliessen

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Bei der Erstellung einer Applikation, die mit EXCEL arbeitet stiess ich auf das Problem, dass sich EXCEL nicht sauber schliessen lässt. Die Artikel in diesem Forum waren recht hilfreich, die endgültige Lösung habe ich aber in dem grandiosen Artikel von  Scott Rutherford gefunden. Die dort beschriebene Lösung ist in Visual Basic geschrieben und lässt sich eins zu eins auf C# übertragen:


Bei dem Versuch EXCEL wieder sauber zu schliessen tritt das Problem auf, dass man die Applikation zwar schliessen und beenden kann, der Hauptprozess aber im Hintergrund erhalten bleibt. Das frisst nicht nur Ressourcen, sondern blockiert unter Umständen auch (temporäre) Dateien, die man nicht löschen, ändern oder überschreiben kann.

Der typsiche Ausstieg sieht wohl ao aus:

C#-Code:
// --- alles ordentlich schliessen
excelWorkbook.Close(false, MISSING, MISSING);
excelApp.Application.Quit();
excelApp.Quit();

// --- COM Objekte wieder freigeben
Marshal.ReleaseComObject(excelWorksheet);
Marshal.ReleaseComObject(excelWorkbook);
Marshal.ReleaseComObject(excelApp);

// --- variablen nullen, damit GC eine Chance hat den Speicher zu raeumen
excelWorksheet = null;
excelWorkbook = null;
excelApp = null;

// --- evtl. GC direkt aufrufen ... muss man aber nicht
//GC.Collect();
//GC.WaitForPendingFinalizers();

Das reicht aber nicht aus. Um EXCEL wirklich zu beenden, muss man den Prozess abschiessen!

Nun ist die Frage natürlich, wie kommt man den Prozess ran? Antwort: wir geben EXCEL bei der Initialisierung eine 'Markierung' mit:

C#-Code:
string GuiId  = System.Guid.NewGuid().ToString().ToUpper();
excelApp.Caption   = GuiId; // 'unser' EXCEL eindeutig markieren!

Hierüber können wir später 'unser' - und nur unser - EXCEL Fenster wiederfinden:

C#-Code:
IntPtr hWnd = FindWindow(null, GuiId);

.. und dann die Prozess-ID identifizieren:

C#-Code:
int iProcID;
GetWindowThreadProcessId(hWnd, out iProcID);

Achtung:

C#-Code:
GetWindowThreadProcessId

verlangt als 2. Argument eine Zeiger-Referenz auf eine

C#-Code:
int

Variable. In C# muss daher unbedingt das

C#-Code:
out

benutzt werden!

Mit der Prozess-ID kommen wir dann wieder sehr leicht an den EXCEL Prozess ran:

C#-Code:
Process p = Process.GetProcessById((int)iProcID);

Und nun hat EXCEL endgültig verloren:

C#-Code:
p.CloseMainWindow();
p.Refresh();
p.Kill();

Dann noch ein letzter Hinweis: um die oben genannten Funktionen

C#-Code:
FindWindow

und

C#-Code:
GetWindowThreadProcessId

benutzen zu können, müssen die vorab in der Klasse sauber deklariert werden:

C#-Code:
[DllImport("user32")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);

Ich habe ein komplettes Beispiel angehängt. Wenn man das ausführt und den Task-Manager offen hat, kann man sehen, wie der EXCEL Prozess wieder verschwindet.


Dateianhang:
unknown XlsTest.zip (30 KB, 982 mal heruntergeladen)
10.01.2007 16:27 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
apollo apollo ist männlich
myCSharp.de-Mitglied

Dabei seit: 20.10.2006
Beiträge: 72
Entwicklungsumgebung: Visual Studio 2005/VC# Express
Herkunft: Moers


apollo ist offline Füge apollo Deiner Kontaktliste hinzu MSN-Passport-Profil von apollo anzeigen

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

woa super, es wäre schön wenn man das als FAQ beitrag sichtbar machen kann. ich hatte auch schon das problem, bin aber nicht auf die idee gekommen die besagte Markierung mitzugeben.

gut gemacht, ich danke dir!
11.01.2007 09:25 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Rainbird Rainbird ist männlich
myCSharp.de-Poweruser/ Experte

avatar-2834.jpg


Dabei seit: 28.05.2005
Beiträge: 3.721
Entwicklungsumgebung: Visual Studio 2012
Herkunft: Mauer


Rainbird ist offline

Hart abschießen

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Es kann nicht die Lösung sein, einfach den Prozess abzuschießen. Das ist absolut dreckig.

Wenn der Excel-Prozess sich nicht richtig beendet, stimmt was nicht. Du solltest lieber die Ursache finden und sie beheben, statt nur die Auswirkungen zu bekämpfen.

Vielleicht ist ein AddIn etc. geladen, welches Excel am beenden hindert?

Ich hatte dieses "Excel beendet sich nicht"-Problem noch nicht. Es muss also irgendwas an Deiner Umgebung nicht stimmen. Excel an sicht funktioniert und beendet auch korrekt (So meine Erfahrung!).
11.01.2007 11:20 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
cel
myCSharp.de-Mitglied

Dabei seit: 10.01.2007
Beiträge: 6

Themenstarter Thema begonnen von cel

cel ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Nein, dem ist nicht so. Spätestens wenn EXCEL mehrfach geöffnet wird, bleiben die Prozesse hängen, in der Regel aber schon nach einmaligem öffnen. Microsoft weist in den Foren selber auf diesen Bug hin. Es schliessen sich zwar alle Fenster, d.h. die Applikation ist vermeintlich nicht mehr da, aber im Task-Manager kann man den Prozess noch sehen.
11.01.2007 15:41 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
apollo apollo ist männlich
myCSharp.de-Mitglied

Dabei seit: 20.10.2006
Beiträge: 72
Entwicklungsumgebung: Visual Studio 2005/VC# Express
Herkunft: Moers


apollo ist offline Füge apollo Deiner Kontaktliste hinzu MSN-Passport-Profil von apollo anzeigen

???

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

@Rainbird: das kann ich nicht bestätigen, da geb ich cel Recht.
selbst wenn ich excel nicht aus einer meiner applikationen öffne, sind teilweise die prozesse noch offen.
Aus c# heraus das selbe spiel. wenn (wenn nötig) alles gespeichert ist, ist es kein thema das man excel einfach abschiesst. solang man auch den richtigen prozess erwischt, daher hat er die Lösung schon gut getroffen.

@cel: Hast du was dagegen wenn ich mir deinen Beitrag kopiere? ^^
12.01.2007 09:13 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
cel
myCSharp.de-Mitglied

Dabei seit: 10.01.2007
Beiträge: 6

Themenstarter Thema begonnen von cel

cel ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ich dachte ein Forum ist dazu da, dass man Ergebnisse teilit und wiederverwendet =kopiert?
12.01.2007 11:11 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
apollo apollo ist männlich
myCSharp.de-Mitglied

Dabei seit: 20.10.2006
Beiträge: 72
Entwicklungsumgebung: Visual Studio 2005/VC# Express
Herkunft: Moers


apollo ist offline Füge apollo Deiner Kontaktliste hinzu MSN-Passport-Profil von apollo anzeigen

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

ja kopieren in dem sinne das ich die lösung dazu, die sehr nützlich ist, in mein forum stelle ^^
vllt findet das ja jemand auch so hilfreich und muss nicht erst lange im internet suchen.
weil bei mir im forum treffen sich nur die selben leute, die nur programmieren (beruf ^^)
12.01.2007 13:45 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Rainbird Rainbird ist männlich
myCSharp.de-Poweruser/ Experte

avatar-2834.jpg


Dabei seit: 28.05.2005
Beiträge: 3.721
Entwicklungsumgebung: Visual Studio 2012
Herkunft: Mauer


Rainbird ist offline

Excel-Mysterien

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Bei mir hat sich Excel bis jetzt immer sauber geschlossen. Ich habe zu Hause allerdings nur Excel 2000. Tritt das erst bei neueren Versionen auf?

Was muss ich tun, um das zu simulieren?

Hat jemand von euch vielleicht einen Link auf die Microsoft-Foren, in denen das diskutiert wurde?
14.01.2007 12:59 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Underscare Underscare ist männlich
myCSharp.de-Mitglied

Dabei seit: 20.10.2006
Beiträge: 195
Entwicklungsumgebung: Visual Studio


Underscare ist offline Füge Underscare Deiner Kontaktliste hinzu

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Also ich kann dieses Problem nur bestätigen. Nutze Excel 2003 und greife über PIA's auf Excel zu.

Hier mal die Code-Stelle, an der ich Excel schliesse:

C#-Code:
if (chkShowExcel.Checked)
            {
                excelApp.Visible = true;
            }
            else
            {
                //Excel schliessen
                excelWorkbook.Close(false,missing,missing);
                excelApp.Application.Quit();
                excelApp.Quit();

                //Variablen nullen
                excelApp = null;
                excelSheets = null;
                excelWorkbook = null;
                excelWorksheet = null;

                //Speicher aufräumen lassen (Muss nicht gemacht werden, aber doppelt hällt bekanntlich besser ;) )
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }

Auch bei mir bleibt der Prozess offen. Und ich hab keine Ahnung warum großes Grinsen


Vielleicht könnte mir ja jemand beiläufig erklären, wofür das gemacht wird:

C#-Code:
// --- COM Objekte wieder freigeben
                Marshal.ReleaseComObject(excelWorksheet);
                Marshal.ReleaseComObject(excelWorkbook);
                Marshal.ReleaseComObject(excelApp);

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Underscare am 21.01.2007 15:46.

21.01.2007 15:41 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Thorsten1983 Thorsten1983 ist männlich
myCSharp.de-Mitglied

Dabei seit: 14.06.2005
Beiträge: 147


Thorsten1983 ist offline MSN-Passport-Profil von Thorsten1983 anzeigen

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

auch ich habe mich in den letzten Tagen sehr ausführlich mit Excel vergnügt. Ich kann jedem der mit einem Office Programm in Berührung kommt nur LateBinding empfehlen da man da immer Versionsunabhängig ist, sofern man Funktionen nutzt die von allen angezielten Versionen supported werden.

Nun aber zum Thema, ich selbst verwende Office 2007 Beta und bei der Version wird Excel nicht korrekt geschlossen wenn vor dem Close und dem ReleaseComObject eine Exception geschmissen wird.

Vielleicht ist dass ja mal ein Ansatz, ansonsten wenn der Code keine Exception auslöst, schließt sich Excel normal, das kann ich von Version 2000, 2003 und 2007 sagen.
22.01.2007 09:11 Beiträge des Benutzers | zu Buddylist hinzufügen
sheitman sheitman ist männlich
myCSharp.de-Mitglied

Dabei seit: 02.11.2005
Beiträge: 1.047


sheitman ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ich habe vor 2 Jahren mal ein COM-Addin für Word und Excel geschrieben und hatte nur am Anfang Probleme mit nicht wirklich geschlossenen Prozessen.

Nach ein wenig Nachforschung fand ich dann den Hinweis mit Marshal.ReleaseComObject, und seitdem hat ich das Problem nie wieder.

Auf irgendeiner Seite laß ich dann, dass man wirklich jedes Objekt was man direkt oder indirekt nutzt wieder freigeben soll... vielleicht macht ihr genau das nicht?

Direkt heißt dabei z.b.

C#-Code:
Word.Application app = new Word.Application();

Indirekt wäre bei

C#-Code:
Word.Document doc = app.Documents.Add(...);

das Documents Objekt.

Besser wäre also

C#-Code:
Word.Documents docs = app.Documents;
Word.Document doc = docs.Add(...);

Dabei halt immer die Resourcen der Objekte wieder freigeben.
Ich fahr damit seht gut.

Zudem sind mir häufig schlechte Addins untergekommen die selbst wohl nicht ganz sauber programmiert sind und z.b. Word daran hintern die normal.dot am Ende ordentlich zu speichern... (gerade erst wieder durch Acrobat 7.0.0 gehabt, Update auf 7.0.5 hats behoben).

Den Prozess abzuschießen halte ich nicht für eine saubere Lösung. Aber müßt ihr selbst wissen ob ihr das verantworten könnt. Man weiß ja nie ob nicht doch mal ein wichtiges Dokument mit abgeschossen wird.

Zitat:
Vielleicht könnte mir ja jemand beiläufig erklären, wofür das gemacht wird:

C#-Code:
Marshal.ReleaseComObject(excelWorksheet);
Marshal.ReleaseComObject(excelWorkbook);
Marshal.ReleaseComObject(excelApp);

Allein durch diese Frage könnt ich dir fast sagen warum dein Programm Probleme hat Excel richtig zu schließen...

Wenn du Objekte von Excel oder Word benutzt, dann sind das COM-Objekte. Diese werden nicht durch den Garbage Collector verwaltet und müßen selbst frei gegeben werden. Das macht man mit der Methode Marshal.ReleaseComObject. Deien explizieten Aufrufe vom GC nutzen also nichts.

Gibst du die Objekte nicht frei wirst du höchstwahrscheinlich einen noch hängenden Prozess haben.

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von sheitman am 22.01.2007 10:42.

22.01.2007 10:34 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Underscare Underscare ist männlich
myCSharp.de-Mitglied

Dabei seit: 20.10.2006
Beiträge: 195
Entwicklungsumgebung: Visual Studio


Underscare ist offline Füge Underscare Deiner Kontaktliste hinzu

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Also, ersmal vielen Dank für deine Erklärung sheitman. Meine "Beendungs-Prozedur" von Excel sieht nun folgender Maßen aus:

C#-Code:
//Excel schliessen
                excelWorkbook.Close(false,missing,missing);
                excelApp.Application.Quit();
                excelApp.Quit();

                //Variablen nullen
                /*excelApp = null;
                excelSheets = null;
                excelWorkbook = null;
                excelWorksheet = null;*/


                // --- COM Objekte wieder freigeben
                Marshal.ReleaseComObject(excelSheets);
                Marshal.ReleaseComObject(excelWorksheet);
                Marshal.ReleaseComObject(excelWorkbook);
                Marshal.ReleaseComObject(excelApp);

Jetzt sieht es folgender Maßen aus. Der Excel Prozess bleibt solange aktiv (also im TaskManager sichtbar) bis ich mein Programm BEENDE. (Das Programm lief in VS). Also Excel wird erst geschlossen, wenn ich mein Programm schliesse. Weiß jemand vielleicht warum?

Muss ich vielleicht auch meine ganzen Ranges (mit denen ich die Excel Zellen anspreche) nullen oder freigeben? Sind ja an sich ganz normale Variablen oder sind es auch solche COM Objekte?

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Underscare am 22.01.2007 18:18.

22.01.2007 18:16 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Rainbird Rainbird ist männlich
myCSharp.de-Poweruser/ Experte

avatar-2834.jpg


Dabei seit: 28.05.2005
Beiträge: 3.721
Entwicklungsumgebung: Visual Studio 2012
Herkunft: Mauer


Rainbird ist offline

Ranges

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ja das sind auch COM-Objekte. Die solltest Du auch freigeben, wenn sie klassenweit deklariert sind.

Ich bleibe dabei. Wenn sich Excel nicht richtig schließt, hat man was falsch gemacht.
22.01.2007 19:07 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Underscare Underscare ist männlich
myCSharp.de-Mitglied

Dabei seit: 20.10.2006
Beiträge: 195
Entwicklungsumgebung: Visual Studio


Underscare ist offline Füge Underscare Deiner Kontaktliste hinzu

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Puuh, ey ich hab voll viele Ranges in meinem Programm (sind auch extrem viele verschiedene Daten, die mein Programm an Excel schickt)....So 50 -60 Ranges dürften das sein....glaub da wärs einfacher, den Prozess einfach abzuknallen^^

//edit:

Bin das Prog grad nochma durchgegange und hab mir selbst im Arsch getreten...Ich voll Idiot hab bei vielen Sachen jedes Mal ne neue Range Variable erstellt, wobei ich die alte hätte nutzen können...hab jetzt so 10 mal mehr Ranges als ich bräuchte^^....Muss ich ma wenn ich Zeit hab verbessern....

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Underscare am 22.01.2007 22:21.

22.01.2007 19:19 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
sheitman sheitman ist männlich
myCSharp.de-Mitglied

Dabei seit: 02.11.2005
Beiträge: 1.047


sheitman ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat:
Nun aber zum Thema, ich selbst verwende Office 2007 Beta und bei der Version wird Excel nicht korrekt geschlossen wenn vor dem Close und dem ReleaseComObject eine Exception geschmissen wird.

Vielleicht ist dass ja mal ein Ansatz, ansonsten wenn der Code keine Exception auslöst, schließt sich Excel normal, das kann ich von Version 2000, 2003 und 2007 sagen.

würde ich übrigens fast auch meine hand für ins feuer legen das es hier am fehlenden Marshal.ReleaseComObject liegt...

hast du alles was du mit excel machst in einen try... catch... finally bzw try... finally ... eingebetten? im finally müßte dann das Marshall.ReleaseComObject rein...

würde also so aussehen

C#-Code:
//deklaration der variablen
Word.Documents oDocs = null;
Word.Document oDoc = null;
try {
    oDocs = oWord.Documents;
    oDoc = oDocs.Add(...);
    ...
} catch (SomeException e) {
    ...
} finally {
    if(oDocs!=null) {
        Marshall.ReleaseComObject(oDocs);
    }
    if(oDoc!=null) {
        Marshall.ReleaseComObject(oDoc);
    }
}

wobei es sich schon fast lohnt den ReleaseComObject - code in eine neue methode auszulagern, der auch auf null vorher überprüft^^

jedenfalls ne menge schreibarbeit... aber damit hab ich jedenfalls nie probleme... solange mir kein anderes addin mein word zerschießt^^

Zitat:
Muss ich vielleicht auch meine ganzen Ranges (mit denen ich die Excel Zellen anspreche) nullen oder freigeben? Sind ja an sich ganz normale Variablen oder sind es auch solche COM Objekte?

jedes objekt einer klasse aus dem word, excel oder office namespace dürfte i.d.r. ein com object sein...

Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von sheitman am 23.01.2007 09:58.

23.01.2007 09:54 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegt mehr als ein Monat.
Sirox
myCSharp.de-Mitglied

Dabei seit: 04.12.2006
Beiträge: 64


Sirox ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hi , ich war an dem gleichen Problem ich hätte da nur eine Andere Lösungsart ( ich hab aber von oben gespickt großes Grinsen ) aber die PInvokes haben mir nicht so gefallen also :

C#-Code:
Excel.Application xlApp = new Excel.Application();
xlApp.Caption = xlGuid;
//In meinem Programm ist es so dass man das Fenster nicht sehn muss
xlApp.Visible = false;

//Workbook und Worksheet öffnen und sachen damit machen

//Hier muss das Fenster geöffnet werden sonst kann man es nicht Identifizieren, aber hald nur Minimiert so merkt nicht ( bzw. kaum )
xlApp.WindowState = Excel.XlWindowState.xlMinimized;
xlApp.Visible = true;

foreach (System.Diagnostics.Process procI in System.Diagnostics.Process.GetProcessesByName("EXCEL")){
      if (procI.MainWindowTitle.IndexOf(xlGuid) != -1) {
                    procI.CloseMainWindow();
                    procI.Refresh();
                    procI.Kill();
       }
}

So spart man sich den PInvoke

lG

Sirox

Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von Sirox am 05.03.2007 15:07.

05.03.2007 15:05 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
sheitman sheitman ist männlich
myCSharp.de-Mitglied

Dabei seit: 02.11.2005
Beiträge: 1.047


sheitman ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

wie oben schon geschrieben war ists nicht besonders gut einfach so den prozess zu killn.letzlich verdeckt man damit nur das man selbst das problem nicht anders in den griff bekommen hat.

falsl du mal ein com-addin entwickelst stehst du eh wieder vor dem selben problem. und da kannst du wirklich nicht einfach den prozess abschießen... und unsaubere addins sind oft das quell so manch einen übels^^
05.03.2007 15:47 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
DarKlajid DarKlajid ist männlich
myCSharp.de-Mitglied

Dabei seit: 25.01.2007
Beiträge: 386
Herkunft: Köln


DarKlajid ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat:
Original von Underscare
Also ich kann dieses Problem nur bestätigen. Nutze Excel 2003 und greife über PIA's auf Excel zu.

Hier mal die Code-Stelle, an der ich Excel schliesse:

C#-Code:
if (chkShowExcel.Checked)
            {
                excelApp.Visible = true;
            }
            else
            {
                //Excel schliessen
                excelWorkbook.Close(false,missing,missing);
                excelApp.Application.Quit();
                excelApp.Quit();

                //Variablen nullen
                excelApp = null;
                excelSheets = null;
                excelWorkbook = null;
                excelWorksheet = null;

                //Speicher aufräumen lassen (Muss nicht gemacht werden, aber doppelt hällt bekanntlich besser ;) )
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }


Offtopic, aber: Lass die Finger vom GarbageCollector. Ich wette jede Menge Bier darauf, dass dieser Aufruf nicht besser haelt, sondern Unfug ist und nicht das macht was du willst..

Edit: Quoting repariert..

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von DarKlajid am 05.03.2007 17:21.

05.03.2007 17:20 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
rokohl
myCSharp.de-Mitglied

Dabei seit: 07.11.2006
Beiträge: 39


rokohl ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

hi,

ich habe mich auch eine zeitlang mit diesem problem beschäftigt und bin zu dem schluss gekommen das es ein garbage-collector problem ist.

wenn man extrem sauber und garbage collector "freundlich" programmiert so das er
alle verwendeten variablen problemlos löschen kann, geht auch excel zu. vergisst man aber eine variable in der funktion auf null zu setzten oder noch schlimmer ein dipose aufruf eines erstellten objektes, geht excel erst beim beenden des programmes zu. :-(

anbei ein kleines beispiel progi was bei mir excel wieder zumacht. setzt man aber eine von den variablen am ende nicht null geht excel nicht zu.

C#-Code:
            Excel.ApplicationClass app = null;
            Excel.Workbook workBook = null;
            Excel.Worksheet workSheet = null;
            Excel.Range range = null;


            app = new Excel.ApplicationClass();
            // create the workbook object by opening the excel file.
            workBook = app.Workbooks.Open(@"test.xls",
                                                     0,
                                                     true,
                                                     5,
                                                     "",
                                                     "",
                                                     true,
                                                     Excel.XlPlatform.xlWindows,
                                                     "\t",
                                                     false,
                                                     false,
                                                     0,
                                                     true,
                                                     Missing.Value,
                                                     Missing.Value
                                                     );

            if (null != workBook.ActiveSheet)
            {
                workSheet = (Excel.Worksheet)workBook.ActiveSheet;
                range = (Excel.Range)workSheet.Cells[1, 1];
            }

            workBook.Close(false, Missing.Value, Missing.Value);

            app.Application.Quit();
            app.Quit();

            Marshal.ReleaseComObject(range);
            Marshal.ReleaseComObject(workSheet);
            Marshal.ReleaseComObject(workBook);
            Marshal.ReleaseComObject(app);

            range = null;
            workSheet = null;
            workBook = null;
            app = null;
            GC.Collect();
            MessageBox.Show("done");

Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von rokohl am 06.03.2007 11:37.

06.03.2007 11:34 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
rokohl
myCSharp.de-Mitglied

Dabei seit: 07.11.2006
Beiträge: 39


rokohl ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Nachsatz:

als ich meine function dazu bringen wollte excel nach beendigung wierder zu schließen bin ich übrigens an der function xdoc.CreateElement gescheitert.
was auch wieder auf den gc deutet!
06.03.2007 11:43 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Programmierhans
myCSharp.de-Poweruser/ Experte

avatar-1651.gif


Dabei seit: 05.04.2005
Beiträge: 4.221
Entwicklungsumgebung: VS2003-VS2013 / SAP WebIDE
Herkunft: Zentralschweiz


Programmierhans ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

ReleaseComObject liefert doch einen int zurück welcher anzeigt wie oft das Objekt noch referenziert ist...

Wenn ein call von ReleaseComObject einen Wert > 0 zurückliefert, dann ist eine Instanz (Com-mässig) nicht freigegeben... ergo kann Excel nicht geschlossen werden.


Nachtrag:

Seit Version 2.0 bietet sich hierführ an:

FinalReleaseComObject
06.03.2007 16:36 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
rokohl
myCSharp.de-Mitglied

Dabei seit: 07.11.2006
Beiträge: 39


rokohl ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

mhmmm ich würd aber gerne mal wissen wieso er in meinem beispiel bei

Marshal.ReleaseComObject(workSheet) keine null zurück gibt.

ich sehe da keine referenz ???
06.03.2007 18:56 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Programmierhans
myCSharp.de-Poweruser/ Experte

avatar-1651.gif


Dabei seit: 05.04.2005
Beiträge: 4.221
Entwicklungsumgebung: VS2003-VS2013 / SAP WebIDE
Herkunft: Zentralschweiz


Programmierhans ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat:
Original von rokohl
ich sehe da keine referenz ???

C#-Code:
if (null != workBook.ActiveSheet)  //das erste Marshalling
            {
                workSheet = (Excel.Worksheet)workBook.ActiveSheet; //das zweite Marshalling

Somit zählt er vermutlich auf 2 rauf...

Und du releast nur 1

probier es mal so:

C#-Code:
workSheet = (Excel.Worksheet)workBook.ActiveSheet; //das zweite
if (workSheet!=null)
.
..
06.03.2007 20:59 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
rokohl
myCSharp.de-Mitglied

Dabei seit: 07.11.2006
Beiträge: 39


rokohl ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

du hast recht. das zählt er als ref.
mhm...aber ich verstehe das immer noch nicht 100%ig.
ich hatte den fall das es an einem xdoc.CreateElement aufruf lag den ich zwischen den excel befehlen verwendet hatte. ohne ihn lief es - mit ihm hat er excel nicht zu gemacht. obwohl da nix von excel verwendet wurde sondern nur xml krams.

desweiteren is an meinem beispiel interessant das es excel auch zu macht wenn man alles am ende auf null setzt. heißt das das ReleaseComObject automatisch aufgerufen wird? das würde ja bedeuten das man ReleaseComObject garnicht aufrufen muss.

naja egal, aber komisch ist das schon...

danke nochmal
07.03.2007 09:25 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegen mehr als 5 Monate.
Pendi Pendi ist männlich
myCSharp.de-Mitglied

avatar-2411.jpg


Dabei seit: 30.11.2006
Beiträge: 27
Entwicklungsumgebung: Visual Studio 2005
Herkunft: Linz, Österreich


Pendi ist offline Füge Pendi Deiner Kontaktliste hinzu

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

*aufweck*

Hab auch ein Problem mit dem Schließen von Excel.

Meine Methode sieht so aus (bitte nicht den Sinn hinterfragen...):

C#-Code:
private void ReSaveExcelFile(string filename)
        {
            Excel.Application excelApp = new Microsoft.Office.Interop.Excel.ApplicationClass();
            Excel.Workbook wb = null;
            try
            {
                wb = excelApp.Workbooks.Open(filename, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                     Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                     Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
                wb.SaveAs(filename,Excel.XlFileFormat.xlExcel7,
                    Type.Missing,Type.Missing,Type.Missing,Type.Missing, Excel.XlSaveAsAccessMode.xlNoChange,
                    Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Fehler beim Speichern der Datei '" + filename + "': " + ex.Message,
                        this.messageBoxCaption, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                wb.Close(Type.Missing, Type.Missing, Type.Missing);
                excelApp.Application.Quit();
                excelApp.Quit();
                System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp);
                System.Runtime.InteropServices.Marshal.ReleaseComObject(wb);
                wb = null;
                excelApp = null;
            }

        }

Obwohl ich mMn alles richtig geschlossen und freigegeben habe, bleibt der Excel-Prozess bis ich meine Anwendung geschlossen habe offen.

Warum?

thx for hints
05.09.2007 09:47 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
él toro él toro ist männlich
myCSharp.de-Mitglied

avatar-1582.gif


Dabei seit: 11.10.2004
Beiträge: 183
Entwicklungsumgebung: VS2008 & VS2010
Herkunft: Dresden


él toro ist offline Füge él toro Deiner Kontaktliste hinzu

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Moin,

Ursache:

C#-Code:
wb = excelApp.Workbooks.Open([...]);   // Marshalled Workbooks und zählt den Referenzzähler für Workbooks hoch
excelApp.Application.Quit();  // Marshalled Application und zählt den Referenzzähler dafür hoch

also lieber so

C#-Code:
Excel.Workbooks wbs = excelApp.Workbooks;
wb = wbs.Open([...]);

Excel.Application app = excelApp.Application;
app.Quit();

System.Runtime.InteropServices.Marshal.ReleaseComObject(wbs);
System.Runtime.InteropServices.Marshal.ReleaseComObject(app);

wobei

C#-Code:
excelApp.Application == excelApp

Daumen hoch

Warum nutzt du nicht System.IO.File.Copy verwirrt

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von él toro am 05.09.2007 10:37.

05.09.2007 10:32 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Pendi Pendi ist männlich
myCSharp.de-Mitglied

avatar-2411.jpg


Dabei seit: 30.11.2006
Beiträge: 27
Entwicklungsumgebung: Visual Studio 2005
Herkunft: Linz, Österreich


Pendi ist offline Füge Pendi Deiner Kontaktliste hinzu

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat:
Original von él toro
Warum nutzt du nicht System.IO.File.Copy verwirrt

Ich hab doch gesagt nicht hinterfragen ;-)
Die Funktion soll eine Excel-Datei unter einer anderen Excel-Version speichern, da ich von einer anderen Anwendung eine Datei im Excel 3.0-Format erhalte und das zur Weiterverarbeitung nicht geeignet ist...

@tipp:
funktioniert, danke!

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Pendi am 05.09.2007 10:47.

05.09.2007 10:47 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
él toro él toro ist männlich
myCSharp.de-Mitglied

avatar-1582.gif


Dabei seit: 11.10.2004
Beiträge: 183
Entwicklungsumgebung: VS2008 & VS2010
Herkunft: Dresden


él toro ist offline Füge él toro Deiner Kontaktliste hinzu

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Bitte großes Grinsen
05.09.2007 10:53 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegt mehr als ein Jahr.
red_dragon69 red_dragon69 ist männlich
myCSharp.de-Mitglied

Dabei seit: 12.08.2009
Beiträge: 56
Entwicklungsumgebung: VisualStudio 2008, 2010


red_dragon69 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Leute.

Jetzt muss ich einen alten Beitrag wieder aufwärmen, weils bei mir einfach nicht hinhaut.
Der Prozess "Excel.exe" wird einfach nicht beendet.

Weis jemand an was das liegen könnte? Benutze Vista Enterprise und Office 2007.

Folgend noch mein code:

C#-Code:
private void button1_Click(object sender, EventArgs e)
{
    object missing = Type.Missing;
    string PosX, PosY;
    int i;

    //.xml-File mit Excel öffnen und Daten auslesen um die ovl Dateien zu erzeugen
    Excel.Application excelApp = new Excel.Application();
    Excel.Workbook workbook = excelApp.Workbooks.Open(Dateipfad() + @"\File.xml", missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing);
    Excel.Worksheet worksheet = (Excel.Worksheet)workbook.Worksheets["wks-Name"];

    excelApp.Visible = true;

    //Anzahl der Zeilen ermitteln
    string beginCell = "A" + worksheet.Rows.Count;
    string endCell = "AA" + worksheet.Rows.Count;

    int row = worksheet.get_Range(beginCell, endCell).get_End(Excel.XlDirection.xlUp).Row;

    for (i = 2; i <= row; i++)
    {
        //Daten aus Excelfile ermitteln
        Excel.Range Xrng = worksheet.get_Range("A"+i, "F"+i);
        Excel.Range Yrng = worksheet.get_Range("P"+i, "S"+i);

        PosX = (string)Xrng.get_Value(missing);
        PosY = (string)Yrng.get_Value(missing);

        //Textdatei erstellen, Daten eintragen und Text speichern
        StreamWriter Writer = new StreamWriter(Dateipfad() + ".txt", false, Encoding.Default);

        //Daten für Markierung eintragen
        Writer.WriteLine("TextTextText");

        Writer.Close();
    }

    //Excel schließen
    workbook.Close(false, missing, missing);
    excelApp.Application.Quit();
    excelApp.Quit();

    //COM Objekte freigeben um EXCEL.exe zu schließen
    Marshal.FinalReleaseComObject(worksheet);
    Marshal.FinalReleaseComObject(workbook);
    Marshal.FinalReleaseComObject(excelApp);

    //Variablen auf Null setzen
    PosX = null;
    PosY = null;
    worksheet = null;
    workbook = null;
    excelApp = null;
}

Gruß
Red_Dragon69
27.08.2009 09:17 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Programmierhans
myCSharp.de-Poweruser/ Experte

avatar-1651.gif


Dabei seit: 05.04.2005
Beiträge: 4.221
Entwicklungsumgebung: VS2003-VS2013 / SAP WebIDE
Herkunft: Zentralschweiz


Programmierhans ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

el toro hat in seinem Beitrag aufgezeigt wo Fehler gemacht wurden.

Du machst genau dieselben Fehler... findest allerdings diesen Thread....

Hast Du den Beitrag auch mal ernsthaft durchgelesen ??? eher nicht, sonst hättest Du den Fehler ja gefunden ...

--> Lies nochmals alles durch ... bin überzeugt dass Du den Fehler selber findest.

Gruss
Programmierhans
27.08.2009 17:38 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegt mehr als ein Monat.
Tschebbe
myCSharp.de-Mitglied

Dabei seit: 22.09.2009
Beiträge: 34
Herkunft: BW - Kaiserstuhl


Tschebbe ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Also ich schliess mich mal Rainbird an. Hab alles sauber zugemacht und Excel wird geschlossen.

gute und hilfreiche Diskussion hier.
05.10.2009 19:45 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegt mehr als ein Monat.
Gabe
myCSharp.de-Mitglied

Dabei seit: 03.11.2009
Beiträge: 22


Gabe ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Kurze Ergänzung für die Suchmaschinen:

Das Schließen von offenen Word- und Visio-Dateien funktioniert genauso... smile

Super Thread. Ist der nicht schon was für die FAQs? Daumen hoch

Gruß Gabe
27.11.2009 14:12 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegen mehr als 8 Jahre.
Sio_x0911
myCSharp.de-Mitglied

Dabei seit: 09.10.2018
Beiträge: 1
Entwicklungsumgebung: Visual Studio 2017


Sio_x0911 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Egal wie alt dieser Beitrag ist. Genau das freigeben der COM Objekte hat mir bei diesem Problem geholfen. Dabei gebe ich mittlerweile alle Objekte direkt wieder frei, egal ob in For Schleifen oder sonst wo. Wenn diese nicht mehr benötigt werden werden sie freigegeben.

Vielen Dank Daumen hoch großes Grinsen


mycsharp.de  Moderationshinweis von Abt (09.10.2018 17:08):

Keine Full Quotes
 [Hinweis] Wie poste ich richtig?

 
09.10.2018 16:40 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegt mehr als ein Jahr.
ChrisProg ChrisProg ist männlich
myCSharp.de-Mitglied

avatar-3533.jpg


Dabei seit: 27.01.2009
Beiträge: 138
Entwicklungsumgebung: VS 2017 C#


ChrisProg ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

ich habe mich nun auch länger mit dem Thema beschäftigen müssen, aber leider komme ich an einem Punkt nicht weiter geschockt

C#-Code:
    try
    {
        // First Contact: Excel Prozess initialisieren
        oExcel = new Excel.Application();
        //oExcel.Visible = false;
        oExcel.ScreenUpdating = true;

        // Excel Datei anlegen: Workbook
        oExcelWorkbooks = oExcel.Workbooks;
        oExcelWorkbook = oExcelWorkbooks.Add(System.Reflection.Missing.Value);
        oExcelWorkSheet = oExcelWorkbook.ActiveSheet;
        oExcelWorkSheet.Name = x_dateiname.ToString().Trim();

        // Überschriften eingeben
        oExcelWorkSheet.Cells[1, 1] = "test";

        // Excel Datei abspeichern
        oExcelWorkbook.Close(true, auswertung_speichern_unter.FileName, System.Reflection.Missing.Value);

    }
    catch (Exception ex)
    {
        Fehlermeldung.ErrorMessage(ex, "( --> Datei geöffnet ???   <--  )");
        vorgang_fortsetzen = false;
    }
    finally
    {
        // Excel beenden
        if (oExcel != null)
        {
            oExcel.Quit();
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oExcelWorkSheet);
            oExcelWorkSheet = null;
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oExcelWorkbook);
            oExcelWorkbook = null;
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oExcelWorkbooks);
            oExcelWorkbooks = null;
            System.Runtime.InteropServices.Marshal.FinalRelease(oExcel);
            oExcel = null;
        }
    }

kommentiere ich die Zeile "oExcelWorkSheet.Cells[1, 1] = "test";" aus, funktioniert alles so wie es soll, u. es wird Excel im TaskManager geschlossen

da es wohl für Cells kein Comobjekt gibt (zumindest habe ich keins gefunden...)
habe ich es dann mit Hilfe von Range versucht :

C#-Code:
        Excel.Range x_celle = (Excel.Range)oExcelWorkSheet.Cells[1, 1];
        x_celle.Value2 = "test";
        System.Runtime.InteropServices.Marshal.FinalReleaseComObject(x_celle);

aber auch dann wird Excel nicht mehr im TaskManager geschlossen Zunge raus


Wenn ich die entsprechenden Release-Befehle im Direktfenster eingebe, bekomme ich immer "0" zurück, was nach den obigen Ausführungen ja bedeutet, das alle Objekte geschlossen sind ...

Was sehe ich hier nicht / mache ich immer noch falsch ?

Bin für jede Hilfe dankbar ...

MfG ChrisProrg

Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von ChrisProg am 11.03.2020 14:15.

11.03.2020 13:04 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 13 Jahre.
Antwort erstellen


© Copyright 2003-2020 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 10.04.2020 04:59