嘿,我正在使用C#WinForms应用程序自动化PowerPoint和Excel;我所做的是从PowerPoint中读取幻灯片并将其保存在Excel中,然后退出这两个应用程序。 Excel已成功退出,但PowerPoints未退出。问题是,当我第一次转换时它不会退出,但是当我再次转换时它就会退出。
这是我的代码
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();
}
答案 0 :(得分: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应用程序的引用:ppApp
,ppPres
和cell
。
考虑到这一点,我认为您的清理应该类似于以下内容,它在命名空间内或代码文档的顶部使用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 :(得分:2)
以下是一篇描述问题和解决方案的MSDN文章
http://msdn.microsoft.com/en-us/library/aa679807%28office.11%29.aspx
基本上是重做(注意:GC.Collect()的两次迭代
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
答案 2 :(得分:2)
Hie folks.lately我发现从垃圾收集到退出和关闭物体没有任何效果。所以我提出了另一种选择。我的工作完成后,我发现了正在运行的进程,然后通过代码将其杀死。
<强>代码:强>
Process[] pros = Process.GetProcesses();
for (int i = 0; i < pros.Count(); i++)
{
if (pros[i].ProcessName.ToLower().Contains("powerpnt"))
{
pros[i].Kill();
}
}
答案 3 :(得分:1)
看起来您正在使Power Point应用程序实例可见,但如果没有,则可能会出现一个您看不到的对话框 - 可能是保存更改对话框。如果应用程序正在隐藏运行,请将其显示为是否弹出任何此类对话框,从而阻止Power Point关闭。
答案 4 :(得分:0)
为 ppApp 对象调用 Quit()后,请尝试以下
System.Runtime.InteropServices.Marshal.ReleaseComObject(ppApp);
然而,没有承诺,它可能会起作用,或者它根本不会做任何事情。正确关闭Office COM的东西对我来说一直有点像伏都教。
答案 5 :(得分: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();
答案 6 :(得分:0)
我在 VS2019 中使用 VSTO 来管理 Office-365 应用程序,一切都使用“Application.Quit()”完美运行 - 除了 Powerpoint!
PP 有时会死机,有时它会在几秒钟内引发很多“ThreadException”直到退出(我猜它真的中止了它的线程)。我已经测试了上述所有代码以及在 Google 中找到的许多其他提示,但均未成功。
这是一个肮脏的解决方案,但它可以工作并在保存演示文稿后立即关闭 PP。
但我建议您,我的解决方案是通过自定义 RIBBON GROUP 中按钮的点击事件启动的;否则,您将不得不以编程方式“找到”PP 窗口并选择它(将焦点放在它上面)。
GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()
GC.WaitForPendingFinalizers()
SendKeys.Send("%{F4}")
这就是大家...