2008-10-29 7 views
1

J'ai un programme Visual Basic .NET qui doit ouvrir et fermer une feuille de calcul Excel. L'ouverture et la lecture de la feuille de calcul fonctionnent correctement, mais la fermeture de l'application Excel 2007 entraîne son blocage. Il semble se fermer, mais si vous regardez dans le gestionnaire de tâches, l'application est toujours en cours d'exécution. Le code que j'utilise pour le fermer estExcel 2007 se bloque lors de la fermeture via .NET

wbkData.Close(saveChanges:=False) 
appExcel.Quit() 
wbkData = Nothing 
appExcel = Nothing 

Comment fermer Excel correctement?

Répondre

0

J'ai trouvé un solution in the MSDN Excel Blog qui a fonctionné pour moi. Il est expliqué que

Il y a deux problèmes avec ce qui précède:

(1) Bien que le code semble Éliminez l'objet « wbkData » abord, etc., le code ci-dessus ne fait pas appliquer cela comme la procédure .NET Garbage Collection peut disposer de ses objets dans n'importe quel ordre. (GC est non déterministe afin, non seulement non déterministe dans le calendrier.)

(2) des commandes telles que 'wsh = wbkData.Workssheets.Item (1)' - ou lignes like it - sont très communs et va créer un objet RCW enveloppant un objet 'Worksheets' . Vous ne possédez pas de variable contenant une référence, donc vous ne pensez généralement pas à cela, mais cet objet RCW ne sera pas disposé jusqu'à la prochaine collection Garbage. Cependant, le code ci-dessus appelle GC.Collect() dernière, et donc le RCW tient toujours une référence à cet objet « » quand Worksheets appExcel.Quit() est appelée. Par conséquent, Excel se bloque .

Le code final ressemble

GC.Collect() 
GC.WaitForPendingFinalizers() 

wbkData.Close(SaveChanges:=False) 
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(wbkData) : wbkData = Nothing 
appExcel.Quit() 
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(appExcel) : appExcel = Nothing 
5

La réponse à votre question a été abordé ici, je pense: How to properly clean up excel interop objects in c

je ne peux pas voir à partir de votre exemple de code, mais fondamentalement, Assignez toujours votre excelle les objets en variables locales, sans jamais aller «deux points vers le bas», comme ceci:

//FAIL 

Workbook wkBook = xlApp.Workbooks.Open(@"C:\mybook.xls"); 

ref au lieu chaque obj individuellement:

//WIN 

Worksheets sheets = xlApp.Worksheets; 
Worksheet sheet = sheets.Open(@"C:\mybook.xls"); 
... 
Marshal.ReleaseComObject(sheets); 
Marshal.ReleaseComObject(sheet); 

.NET crée une enveloppe pour l'objet COM qui est invisible pour vous et n'est pas libéré jusqu'à ce que le GC tisse sa magie. Jusqu'à ce que je découvre cela, j'exécutais le code hacky ci-dessous dans une application ASP.NET chaque fois que je créais un nouveau classeur qui vérifie l'ancienneté du processus excel.exe et tue tous ceux qui datent de plus d'une minute:

//force kill any excel processes over one minute old. 
try 
{ 
    Process[] procs = Process.GetProcessesByName("EXCEL"); 
    foreach (Process p in procs) 
    { 
     if (p.StartTime.AddMinutes(1) < DateTime.Now) 
     { 
      p.Kill(); 
     } 
    } 
} 
catch (Exception) 
{} 
+0

Merci pour le pointeur vers l'autre question. Ils semblent traiter le même problème. –

1

j'ai écrit ce poste vous mentioned on the Excel Team Blog ...

J'ai également discuté ce problème précédemment sur StackOverflow pour la question How to properly clean up Excel interop objects in C#.

La première réponse à cette question a été marquée comme "correcte" et a obtenu 11 votes, mais je vous assure que cette politique est extrêmement difficile à utiliser correctement dans la pratique. Si jamais on glisse n'importe où et utilise "deux points", ou itère des cellules via un pour chaque boucle, ou n'importe quel autre type de commande, alors vous aurez des objets COM non référencés et vous risquez un blocage - et il n'y aura aucun moyen de trouver la cause de cela dans le code. Au lieu de cela, la procédure de nettoyage que vous adoptez est définitivement la voie à suivre.

+0

Bonjour Mike. Merci pour votre message incroyablement utile sur le blog de l'équipe Excel. C'était la seule information que j'ai pu trouver sur Internet à propos de ce problème. Cela m'a sauvé de beaucoup d'heures de frustration. –

+0

Pas de problème, Eric, je suis content que ça ait aidé! :-) –

Questions connexes