2009-06-11 82 views
9

從C#WinForms應用程序嘿,我自動化PowerPoint和Excel;我所做的是從PowerPoint中讀取幻燈片並將它們保存在Excel中,然後退出這兩個應用程序。 Excel成功退出,但PowerPoint不會退出。問題是當我第一次轉換它不退出時,但是當我再次轉換它時。PowerPoint中通過C#推出不退出

這裏是我的代碼

try 
{ 
    PowerPoint.Application ppApp; 
    PowerPoint.Presentation ppPres; 
    List<Company> companies = new List<Company>(); 

    ppApp = new PowerPoint.Application(); 
    ppApp.Visible = Microsoft.Office.Core.MsoTriState.msoTrue; 
    ppApp.WindowState = Microsoft.Office.Interop.PowerPoint.PpWindowState.ppWindowMinimized; 

    ppPres = ppApp.Presentations.Open(fileTxtBox.Text, 
             Microsoft.Office.Core.MsoTriState.msoFalse, 
             Microsoft.Office.Core.MsoTriState.msoFalse, 
             Microsoft.Office.Core.MsoTriState.msoTrue); 

    int slides = ppPres.Slides.Count; 

    for (int slide = 1; slide <= slides; slide++) 
    { 
     int rows = 1; 
     PowerPoint.Cell cell; 
     int shape = 1; 

     for (; shape < ppPres.Slides[slide].Shapes.Count; shape++) 
     { 
      if (ppPres.Slides[slide].Shapes[shape].HasTable == Microsoft.Office.Core.MsoTriState.msoTrue) 
      { 
       cell = ppPres.Slides[slide].Shapes[shape].Table.Cell(1, 1); 

       if (cell.Shape.TextFrame.TextRange.Text.Trim().ToLower().Contains("realized")) 
       { 
        rows = ppPres.Slides[slide].Shapes[shape].Table.Rows.Count; 
        break; 
       } 
      } 
     } 

     Company comp = new Company(rows); 
     InitializeCompany(ref comp, ppPres.Slides[slide]); 
     companies.Add(comp); 
    } 

    SaveInExcel(companies); 

    ppPres.Close(); 
    ppPres = null; 
    ppApp.Quit(); 
    ppApp = null; 

    return; 
} 

catch (Exception ex) 
{ 
    MessageBox.Show(ex.Message); 
} 

finally 
{ 
    GC.Collect(); 
    GC.WaitForPendingFinalizers(); 
} 

回答

12

關閉Microsoft Office應用程序似乎很難全面恢復在第一,但一旦你建立正確的操作順序,它實際上不是很辛苦的。

釋放你的MS Office應用程序可以在兩個階段安全有效地完成:

(1)首先釋放所有的到你不持有命名的變量中引用的次要對象。您可以通過致電GC.Collect()然後GC.WaitForPendingFinalizers()來完成此操作。請注意,如果您使用的是Visual Studio Tools for Office(VSTO),那麼您需要調用這對命令兩次以便使COM對象成功發佈。但是,您沒有使用VSTO,因此只需調用一次就足夠了。

(2)然後明確釋放出您通過使用您所擁有的每個變量Marshall.FinalReleaseComObject()呼叫的命名變量持有的對象。

記住明確釋放,你必須COM組件都變量。如果你錯過了一個,那麼你的MS Office應用程序將掛起。在您的代碼中,您似乎有三個命名變量可以保存對您的PowerPoint應用程序的引用:ppAppppPrescell

考慮到所有這些因素,我認爲你的清理應該看起來像以下,這使得無論是命名空間中或在代碼文件的頂部使用using System.Runtime.InteropServices

// using System.Runtime.InteropServices 

// Cleanup: 
GC.Collect(); 
GC.WaitForPendingFinalizers(); 

Marshal.ReleaseComObject(cell); 

ppPres.Close(); 
Marshal.ReleaseComObject(ppPres); 

ppApp.Quit(); 
Marshal.ReleaseComObject(ppApp); 

給它一個試試,我認爲這應該爲你工作?(如果沒有,你可能需要表現出更多的代碼)的更多信息,我就如何正確釋放Excel應用程序在這裏詳細的解釋:

How to properly clean up Excel interop objects in C#

希望這會有所幫助,讓我們知道如何去...

邁克 -

+1

嘿邁克感謝,但這個沒有一件事我想告訴你的是,當我關閉自己的WinForm應用程序時,PowerPoint也會關閉。 – akif 2009-06-11 16:32:59

+1

是的,關閉WinForm時關閉它是正常的,因爲任何你釋放的對象都是終於發佈d當運行時間被拆除時。 你可以嘗試調用GC.Collect()和GC.WaitForPending()終結器TWICE。如果你不使用VSTO,這應該不重要,但它不會受到傷害。 您需要考慮其他變量在這裏玩什麼......(請參閱下一條評論。) – 2009-06-11 17:41:26

+2

您需要考慮其他變量在此處播放的內容,並釋放它們。例如: (1)有沒有其他的靜態變量在任何地方? (2)你的InitializeCompany(ref comp,ppPres.Slides [slide])調用是做什麼的?如果它在公司對象中存儲對PowerPoint幻燈片的引用,則此調用將與companies.Add(comp)一起創建對PowerPoint引用的永久引用。這些必須通過調用Marshal.FinalReleaseComObject()來切斷,否則PowerPoint將掛起。我不知道這是發生了什麼,但是您需要釋放*所有*您的PowerPoint引用。 – 2009-06-11 17:44:53

1

它看起來像您這樣的受力點的應用程序實例可見,但如果不是,它可能是有正在呈現一個對話框,你看不到 - 也許保存更改對話框。如果應用程序正在隱藏運行狀態,請使其可見,以查看是否有任何此類對話框彈出,從而阻止關閉Power Point。

+0

沒有沒有任何這樣的事情:( – akif 2009-06-11 15:08:26

0

調用退出後()ppApp對象嘗試以下

System.Runtime.InteropServices.Marshal.ReleaseComObject(ppApp); 

沒有承諾然而,它可能工作,也可能什麼也不做。正確關閉Office COM的東西對我來說一直有點像巫術。

+0

沒有工作:( – akif 2009-06-11 15:07:55

2

你好,我注意到沒有任何東西可以解決垃圾收集到退出和關閉物體的問題。提出一個替代方案。一旦我的工作完成,我發現了正在運行的進程,然後通過代碼殺死它。

代碼:

Process[] pros = Process.GetProcesses(); 
    for (int i = 0; i < pros.Count(); i++) 
    { 
    if (pros[i].ProcessName.ToLower().Contains("powerpnt")) 
     { 
      pros[i].Kill(); 
     } 
    } 
0

這項工作對我來說

 var app = new PowerPoint.Application(); 
      PowerPoint.Presentations pres = app.Presentations; 
      PowerPoint.Presentation ActivePresentation = pres.Open(fileIn, MsoTriState.msoTrue, MsoTriState.msoTrue, MsoTriState.msoFalse); 
(...) 
      ActivePresentation.SaveAs(fileOut, PowerPoint.PpSaveAsFileType.ppSaveAsDefault, MsoTriState.msoTrue); 

      ActivePresentation.Close(); 
      app.Quit();