【问题标题】:how to close a running instance of Word document? (C#)如何关闭正在运行的 Word 文档实例? (C#)
【发布时间】:2016-11-11 16:03:36
【问题描述】:

我可以看到很多非常相似的线程,但似乎没有什么能给我一个应该是非常基本的解决方案。

在我的 winforms 应用程序中,我需要关闭一个正在运行的 word 文档实例(从应用程序本身打开)。当我从应用程序中打开 word 文档时,我会在列表中对其进行跟踪。现在我怎样才能关闭同一个文档?

这是我尝试过的:

private bool CloseWord(string osPath) //here I pass the fully qualified path of the file
{
    try
    {
        Word.Application app = (Word.Application)Marshal.GetActiveObject("Word.Application");
        if (app == null)
            return true;

        foreach (Word.Document d in app.Documents)
        {
            if (d.FullName.ToLower() == osPath.ToLower())
            {
               d.What? //How to close here?
               return true;
            }
        }
        return true;
    }
    catch
    {
        return true;
    }
}

我得到了很多文档对象的方法,但只有一个 .Close() 要关闭,它有这样的参数:ref object SaveChanges, ref object OriginalFormat, ref object RouteDocument 我不明白。

什么是理想的方式?谢谢..

编辑:

  1. 我无法关闭整个 Word 应用程序 (WinWord),因为用户可能打开了其他 Word 文件。

  2. 我只需要终止单词实例(类似于Process.Kill()),而不提示用户是否保存等。

【问题讨论】:

    标签: c# c#-2.0 office-automation running-other-programs


    【解决方案1】:

    此解决方案来自here 解决方案。

    Word.Application app = (Word.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Word.Application");
    if (app == null)
        return true;
    
    foreach (Word.Document d in app.Documents)
    {
        if (d.FullName.ToLower() == osPath.ToLower())
        {
            object saveOption = Word.WdSaveOptions.wdDoNotSaveChanges;
            object originalFormat = Word.WdOriginalFormat.wdOriginalDocumentFormat;
            object routeDocument = false;
            d.Close(ref saveOption, ref originalFormat, ref routeDocument);
            return true;
        }
    }
    return true;
    

    【讨论】:

    • @nawfal:我有同样的问题,当我运行程序并且打开另一个同名文档时,(事实上它已经被关闭而没有处理(在某些情况下)),这个代码不起作用,我的意思是我得到另一个实例正在运行的错误。正如你所说,我无法关闭整个 WinWord.exe,因为用户可能打开了其他 Word 文件。这让我抓狂,我希望你可以给我一些帮助。
    • @nawfa : 我说的错误是:Word 无法保存这个文件,因为它已经在别处打开了。
    • @raha,让它成为另一个问题,并在那里阐明更多信息。从这里很难给出解决方案。我只能说,您应该使用一些智能代码来处理现有的 word 实例。请搜索“处理掉词实例”左右。 SO上有很多线程
    • @nawfal :谢谢,但是我已经提出了另一个问题,并且在互联网上搜索了一整天,但找不到任何解决方案,还是谢谢你。
    【解决方案2】:

    如何使用类似的东西:

    修改自:http://www.dreamincode.net/code/snippet1541.htm

    public static bool KillProcess(string name)
    {
        //here we're going to get a list of all running processes on
        //the computer
        foreach (Process clsProcess in Process.GetProcesses())
        {
            if (Process.GetCurrentProcess().Id == clsProcess.Id)
                continue;
            //now we're going to see if any of the running processes
            //match the currently running processes. Be sure to not
            //add the .exe to the name you provide, i.e: NOTEPAD,
            //not NOTEPAD.EXE or false is always returned even if
            //notepad is running.
            //Remember, if you have the process running more than once, 
            //say IE open 4 times the loop thr way it is now will close all 4,
            //if you want it to just close the first one it finds
            //then add a return; after the Kill
            if (clsProcess.ProcessName.Contains(name))
            {
                clsProcess.Kill();
                return true;
            }
        }
        //otherwise we return a false
        return false;
    }
    

    【讨论】:

    • Chuck,此方法按进程名称搜索进程。例如,我的 word 文件可以具有名称(我传递的参数)“C:\doc.doc”,而进程的名称是不匹配的 WINWORD。因此 .Kill() 永远不会被击中。
    【解决方案3】:

    我知道为时已晚,但我发现这个话题是因为我遇到了同样的问题。

    我的解决方案可能对其他人有所帮助。

    上述解决方案效果不佳,因为它杀死了所有正在运行的 Word 实例,尽管它不是由 c# 程序打开,而是由用户打开。

    所以这不是那么用户友好。

    我的代码检查在 c# 中创建 Word.Application 对象之前/之后的进程,并在 List<int> 中写入 WINWORD 进程的 ID 然后它比较List<int> 中的值。 当processID 在两个List<int> 中都找不到时,它会终止具有此ID 的进程。

    public List<int> getRunningProcesses()
    {
        List<int> ProcessIDs = new List<int>();
        //here we're going to get a list of all running processes on
        //the computer
        foreach (Process clsProcess in Process.GetProcesses())
        {
            if (Process.GetCurrentProcess().Id == clsProcess.Id)
                continue;             
            if (clsProcess.ProcessName.Contains("WINWORD"))
            {
                ProcessIDs.Add(clsProcess.Id);
            }
        }
        return ProcessIDs;
    }
    

    运行两次(一次在创建 Word.Application 之前,一次之后)。

     List<int> processesbeforegen = getRunningProcesses();
     // APP CREATION/ DOCUMENT CREATION HERE...
     List<int> processesaftergen = getRunningProcesses();
    

    然后运行killProcesses(processesbeforegen, processesaftergen);

     private void killProcesses(List<int> processesbeforegen, List<int> processesaftergen)
     {
        foreach (int pidafter in processesaftergen)
        {
            bool processfound = false;
            foreach (int pidbefore in processesbeforegen)
            {
                if (pidafter == pidbefore)
                {
                    processfound = true;
                }
            }
    
            if (processfound == false)
            {
                Process clsProcess = Process.GetProcessById(pidafter);
                clsProcess.Kill();
            }
        }
     }
    

    【讨论】:

    • 这种方法绝对不应该使用,因为它没有安全性。调用之间可以启动任意数量的进程...
    • 如果您在创建 Word 应用程序对象并启动进程后立即调用第二种方法,则不会。嗯,是的,可能会有一秒的时间间隔,但在那段时间里,几乎没有用户会打开另一个 Word 实例。
    • 我仍然认为这是一个不可靠的解决方案。它适用于您在家中进行的小型项目,但不应用于任何工业环境,您的第二句话清楚地说明了原因。
    【解决方案4】:

    如果你想关闭整个单词应用程序,你可以调用:

    Word.Application app = (Word.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Word.Application");
    if (app == null)
        return true;
    app.Quit(false);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-05
      • 1970-01-01
      • 2023-03-10
      • 2014-01-03
      • 2013-04-20
      • 1970-01-01
      相关资源
      最近更新 更多