【问题标题】:ASP.net C# - WINWORD.exeASP.net C# - WINWORD.exe
【发布时间】:2009-12-02 15:50:19
【问题描述】:

我正在使用 ASP.NET/C# 程序中的 Microsoft Word 文档。

我的程序在内部打开了 word 文档。使用

app = new Word.Application();
app.Documents.Open

它创建了一个winword.exe进程的实例,我可以在任务管理器中看到它。

即使我使用 close()app.quit() 关闭 Doc。它应该终止进程。但是这个进程不会被杀死。

知道如何以编程方式终止此进程。

【问题讨论】:

  • 我知道这可能没有帮助,但您可能不想这样做 - com 互操作在最好的情况下并不出色,从网络应用程序来看这是一个非常糟糕的主意 - 只是不是为了应对那种环境而设计的。你想达到什么目的?

标签: asp.net ms-office


【解决方案1】:

首先,我同意 Arthur 和 Ivo:不要在服务器上使用 Word 自动化......它不受支持,而且很痛苦。

  1. 如果可以,请尝试通过 DOCX 格式支持 Word 输入/输出(fully documentedXML format 使用 .NET Framework 支持的压缩进行打包,并且通过插件支持 pre-Office 2007)
  2. 如果不创建一个服务来处理队列中的请求,以防止多个线程同时使用它(ala Ivo's answer

如果您必须使用 Word 自动化:

  1. 确保设置尽可能多的应用程序选项以防止出现对话框
  2. 确保您将WdSaveOptions.wdDoNotSaveChanges 传递给Document.Close
  3. 查看此文档:How To: Dismiss a Dialog Box Displayed by an Office Application with Visual Basic .NET(显然也适用于 C#)
  4. 确保在 Document 和 Application 对象上调用 Marshal.ReleaseComObject,并确保它位于 finally 块中。

winword.exe 应该如果你按照上面的方法消失,你应该不需要杀死进程。

编辑: 不是你的问题的真正答案,但仍然是主题。请记住,您也会在服务器上遇到权限问题。确保为它创建一个特定用户并将该用户用作您的 AppPool 身份(或服务身份)。然后,您需要执行以下操作:

  1. 确保您已经安装了自动化组件,很明显
  2. 运行“dcomcnfg”
  3. 组件服务 -> 计算机 -> 我的电脑 -> COM+ 应用程序
  4. “Microsoft Word 文档”(或“{000209FF-0000-0000-C000-000000000046}”)-> 属性
  5. 安全选项卡 -> 启动和激活权限 -> 自定义
  6. 点击“编辑”并从上方添加您的 AppPool 用户
  7. 重复步骤 5-6,但选择“访问权限”

除此之外,您可能仍需要作为 AppPool 用户直接从服务器运行一次 winword.exe,尽管有上述对话框选项,以初始设置配置文件。

【讨论】:

  • 谢谢理查德......但现在发生了一些可疑的事情。我已遵循所有步骤。它奏效了。现在的事情是我想重现这个错误,以便我可以归结为使其工作的特定修改。但现在我恢复到旧代码。重建它...我仍然无法在 TM 中看到 winword.exe。旧代码给了我预期的行为,但没有 winword.exe :(
  • 这可能是对 Marshal.ReleaseComObject 的调用(当您切换到自动化用户时,其他人只是保护您免受奇怪的情况的影响 - 请参阅上面的编辑)。如果您根本看不到 winword.exe,可能是因为它是由另一个用户启动的,并且您没有勾选“显示所有用户的进程”复选框
【解决方案2】:

Office 应用不会“破坏”创建的第一个实例。使用excel也会遇到同样的问题。

看看这个和其他

50 Ways to Kill Excel

How to kill a process given a name

【讨论】:

  • 第二个链接不需要,可以使用System.Diagnostics.Process。有一个名为 GetProcessesByName 的方法,它返回一个进程数组。拿那个数组循环并杀死每个。将它包裹在 try / catch 块中并捕获任何异常。
【解决方案3】:

查看 System.Diagnostics.Process.GetProcessesByName 和 System.Diagnostics.Process.Kill

试试类似的东西

string processName = "ProcessName";
Process[] processes = Process.GetProcessesByName(processName);

foreach(Process process in processes)
{
    process.Kill();
}

【讨论】:

  • 你必须在那里抛出一个 WaitForExit 否则 word 可能试图关闭。
【解决方案4】:

你应该能够抓取单词的每个进程并杀死它:

foreach(Process p in System.Diagnostics.Process.GetProcessesByName("winword"))
 {
   p.kill();
   p.WaitForExit();
 }

您还应该尝试将文档对象设为 null 吗?

【讨论】:

  • 这会杀死所有的winword实例。对吧?如何杀死我的 C# 程序创建的 winword 实例?
【解决方案5】:

在服务器上使用 (Microsoft) Office 的最安全方法是创建一个可以接受流的服务,并创建一个 Word 实例(或任何其他 Office 应用程序)执行此操作,然后终止该应用程序。 如果您不这样做,对正在运行的 Office 应用程序的引用将保留在您的 asp 工作进程中。这意味着许多进程将继续运行,直到您的 asp 工作进程被回收。这是一个很大的潜在内存泄漏。

我们就是这样做的。正确构建它需要花费大量时间,但这是最安全的方法。

【讨论】:

    【解决方案6】:

    这让我发疯了,直到我在这个网站上找到this post。该页面上的第二个解决方案对我有用 - 第一个看起来更简单,但实际上很难跟踪您引用的所有隐藏 COM 对象。第二种方法总是有效 - 您不必跟踪每个对象。

    【讨论】:

      【解决方案7】:

      只是说:Office 应用程序不应该在服务器上运行。它们也不应该被服务或 Web 应用程序使用。

      是的 - 我们还有一些要求迫使我们在服务器上使用 Office 产品。我们总是遇到麻烦。

      如果有机会不使用 Office(处理 WordML,新的 Office XML 格式),那么就这样做。

      【讨论】:

        猜你喜欢
        • 2011-10-27
        • 1970-01-01
        • 2017-02-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-24
        相关资源
        最近更新 更多