2009-06-11 107 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();