2013-08-09 24 views
7

Mam program C#, który nigdy nie zamyka procesu programu Excel. Zasadniczo znajduje liczbę wystąpień łańcuch pojawia się w zakresie w programie Excel. Próbowałem różnych rzeczy, ale to nie działa. Istnieje formularz, który wywołuje tę metodę, ale to nie powinno zmienić przyczyny, dla której proces się nie zamyka. Przyjrzałem się sugestiom Hansa Passanta, ale żaden z nich nie działa.Proces programu Excel nie zamyka się

EDYCJA: Próbowałem rzeczy wymienione i nadal nie będzie można zamknąć. Oto mój zaktualizowany kod. EDYCJA: Próbowałem cały Process.Kill() i to działa, ale wydaje się trochę hack na coś, co powinno po prostu działać.

+0

Mniejsza repro pomoże. W każdym razie uruchomiłem to na moim komputerze i program Excel kończy się dobrze. Czy są zainstalowane jakieś źle zachowane dodatki programu Excel? Spróbuj usunąć je jeden po drugim, aby sprawdzić, czy ma to wpływ na możliwość wyłączenia programu Excel. –

+0

Próbowałem proces Vanilla Excel i nadal nie zamknął.Używam formularza jako interfejsu do wywoływania tej klasy, czy może to zrobić coś, aby zachować otwarty program Excel? – user1017719

+0

To jest właściwie trzecia odpowiedź, którą myślę, że będziesz chciał z powyższego linku. – devuxer

Odpowiedz

3

Oto interesująca baza wiedzy na temat aplikacji biurowych pozostających otwartymi po odłączeniu się aplikacji .NET.

Office application does not quit after automation from Visual Studio .NET client

przykłady kodu są w linku (vb.net przepraszam). Zasadniczo pokazuje, jak poprawnie skonfigurować i oderwać aplikację biurową, aby zamknęła się, gdy skończysz.

System.Runtime.InteropServices.Marshal.FinalReleaseComObject to miejsce, w którym dzieje się magia.

EDYTOWANIE: Musisz wywołać FinalReleaseComObject dla każdego utworzonego obiektu programu Excel.

if (excelWorkSheet1 != null) 
{ 
    Marshal.FinalReleaseComObject(excelWorkSheet1); 
    excelWorkSheet1 = null; 
} 
if (excelWorkbook != null) 
{ 
    Marshal.FinalReleaseComObject(excelWorkbook); 
    excelWorkbook = null; 
} 
if (excelApp != null) 
{ 
    Marshal.FinalReleaseComObject(excelApp); 
    excelApp = null; 
} 
+0

Próbowałem tej metody i to nie działa. Czy istnieje zasób, który nie jest wydany, a Excel pozostanie otwarty? – user1017719

+0

Tak, istnieje RCW "Ralfime Callable Wrapper", który spowoduje, że proces pozostanie aktywny, jeśli nie zostanie zwolniony w aplikacji .NET. – JeremiahDotNet

+0

Próbowałem również tej metody i to też nie działało dla mnie. –

0

W końcu udało się to zamknąć. Musisz dodać zmienną do kolekcji Skoroszytów, a następnie użyć FinalReleaseComObject, jak podano w innych odpowiedziach. Domyślam się, że każdy możliwy obiekt COM COM, którego używasz, musi zostać usunięty w ten sposób.

+0

Próbowałem tego i nadal nie działa. Czy istnieje sposób, w jaki mogę znaleźć ID procesu excelApp i po prostu go zabić? – user1017719

+0

Możesz to dodać w przypadkach, w których zatrzymujesz program Excel podczas debugowania/awarii. Ale nie jest zalecane do normalnego użytkowania. Skomentuj sekcje i rozwiąż problemy w tej sekcji, która daje ci problem. –

+0

Użyłem Twojej dokładnej próbki kodu, wykazując ten sam problem, a po dodaniu kroku do NAR skoroszytów rozwiązano problem. –

1

DotNet zwolni obiekt COM dopiero po zwolnieniu wszystkich uchwytów. To, co robię, to komentowanie wszystkiego, a następnie dodawanie części. Sprawdź, czy zwalnia program Excel. Jeśli nie przestrzega następujących zasad. Po jej zwolnieniu dodaj więcej kodu, aż nie zwolni się ponownie.

1) Podczas tworzenia zmiennych Excel, należy ustawić wszystkie wartości null (nie unikają zainicjowany błędów)

2) Nie używaj zmiennych bez zwalniania najpierw Marshal.FinalReleaseComObject

3) Nie należy podwoić kropka (a.b = z). dotNet utworzyć tymczasową zmienną, która nie zostanie zwolniona.

c = a.b; 
c = z; 
Marshal.FinalReleaseComObject(c); 

4) Zwolnij wszystkie zmienne excela. Im szybciej, tym lepiej.

5) Ustaw ponownie z powrotem na NULL.

Ustaw kulturę na "en-US". Istnieje błąd powodujący awarię Excela w niektórych kulturach. Zapewni to, że nie będzie.

Oto pomysł, jak Twój kod powinien mieć strukturę:

 thisThread.CurrentCulture = new System.Globalization.CultureInfo("en-US"); 
     InteropExcel.Application excelApp = null; 
     InteropExcel.Workbooks wkbks = null; 
     InteropExcel.Workbook wkbk = null; 
     try 
     { 
       excelApp = new InteropExcel.Application(); 
       wkbks = excelApp.Workbooks; 
       wkbk = wkbks.Open(fileName); 
... 

     } 
     catch (Exception ex) 
     { 
     } 

     if (wkbk != null) 
     { 
      excelApp.DisplayAlerts = false; 
      wkbk.Close(false); 
      Marshal.FinalReleaseComObject(wkbk); 
      wkbk = null; 
     } 

     if (wkbks != null) 
     { 
      wkbks.Close(); 
      Marshal.FinalReleaseComObject(wkbks); 
      wkbks = null; 
     } 

     if (excelApp != null) 
     { 
      // Close Excel. 
      excelApp.Quit(); 
      Marshal.FinalReleaseComObject(excelApp); 
      excelApp = null; 
     } 

     // Change culture back from en-us to the original culture. 
     thisThread.CurrentCulture = originalCulture;  
    } 
Powiązane problemy