一个关于c#操纵word进程的问题,难,请高手帮忙一个ASP.net应用程序,现在并发200用户同时访问服务器,请求系统某一功能,功能描述:把某一web页面内容,输出生成到一个word文件中。当系统只有一个人访问的时候,请求系统这一功能,没有问题,打开服务器任务管理器,能看到有一个winword.exe进程(我的系统是WIN2003)。但是,当系统并发200或更多用户的时候,瞬间,服务器任务管理器,就会出现200个或更多word进程,就是一个用户请求产生一个word进程,这个时候,服务器cpu\内存资源,就会被耗尽。虽然,我在生成WORD文件后,立即关闭该WORD进程,但是,那个瞬间,服务器资源耗尽会产生堵塞,服务器无法处理其他事情,这样很容易崩溃的。
已经听人说:先判断系统进程有没有WORD进程,如果有,当用户来生成WORD的时候,就不重新开WORD进程,即使200个用户并发也没事,都直接用这个进程。如果没WORD进程,当有用户来生成WORD,就开一个WORD进程来使用,后面再来的用户或更多并发用户,也都使用这个新开的进程。
我现在的问题就是:先判断系统进程里有没有WORD进程,或关闭它,这个用C#实现,比较简单的。可是,当我知道系统进程里已经有WORD进程,当有用户来请求生成WORD功能的时候,我就不需要重新开进程了,那么我怎么利用这个,系统已有的WORD进程了,怎么操作它,来实现这个生成WORD的功能了?(听说,用WORD句柄什么的,可以操纵,可是我不会WINDOWS编程,请大家帮忙,在C#里怎么实现)请高手指点一下,万分感谢!!!

解决方案 »

  1.   

    论坛上有很多关于“关闭Word进程、关闭Excel进程”等等的帖子,其出现的问题原本都是打开进程时的问题,却被一些人归咎于关闭进程问题。打开 Excel 进程应该这样写:Microsoft.Office.Interop.Excel.Application ap;
    try
    {
        ap =(Microsoft.Office.Interop.Excel.Application)
            Microsoft.VisualBasic.Interaction.GetObject(null, "Excel.Application");
    }
    catch
    {
        ap = new Microsoft.Office.Interop.Excel.Application();
    }
    打开Word是一样的,只不过它的COM注册类型是 Word.Application。至于使用 Quit() 关闭的时候,Task Manager中仍然能够看到有至少一个进程,这是正常的,过去的进程外服务器系统就是这样设计的!否则当初也不会对COM进程外服务器提供 GetObject 和 CreateObject 两套方法。
      

  2.   

    要了解这个问题的原理,就要理解Windows过去的OLE进程外服务器的知识。要了解这个问题的根源,就要记住不是什么对象都可以随便new的,所有跨进程对象都要区分清楚该GetObject还是CreateInstance。
      

  3.   

    讨论ASP。NET 2.0 新技术 QQ群:20810637(顶者有好报~)
      

  4.   

    建议使用SingleTon的方式,在后台驻留一个应用,利用这个应用去分配同时可以转接多少个Word应用,达到一定的并发量时,后续的请求都只能等待。
      

  5.   

    建议使用SingleTon的方式,在后台驻留一个应用,利用这个应用去分配同时可以转接多少个Word应用,达到一定的并发量时,后续的请求都只能等待。
    ——————————————————————————————————————————
    那么谁是服务器呢?为什么要自己写一个服务器程序来再次引用OLE进程外服务,而不是直接在应用程序中使用已经写好的OLE服务?自己写服务是否就能让所有今后的应用都使用它从而取代已经有的OLE进程外服务?这样的解决方案是比一条 GetObject 命令更简单了还是更加清晰了?
      

  6.   

    TO:sp1234(如果只为活着,还不如不活)
    我测试了,用了你这段程序可还是,每新增一个用户操作生成WORD,就新一个WORD建进程,任务管理器里Microsoft.Office.Interop.Excel.Application ap;
    try
    {
        ap =(Microsoft.Office.Interop.Excel.Application)
            Microsoft.VisualBasic.Interaction.GetObject(null, "Excel.Application");
    }
    catch
    {
        ap = new Microsoft.Office.Interop.Excel.Application();
    }我的操作系统是WIN2003/vs.net2003
      

  7.   

    就和使用new一样,新建一个进程请指点,谢谢
      

  8.   

    上面只是个手写的例子,无法凭想象写却面,所以比较简略。按说 catch 后边必须捕获异常,仅仅对“不存在Excel.Application”的情况才应该new,其它情况说明系统有问题,应该 Throw new Exception。我手写代码的时候不知道 catch 后边捕获的特定 Exception 的类型怎么写,但是你写程序应该查资料写上。调试的时候,应该让所有 Exception (的ToString())都显示或者记录到系统日志中。你要拷贝信息到这里,才知道问题出在什么地方。
      

  9.   

    你可以先把catch部分注释掉,然后把程序运行的异常信息的内容、堆栈等打印出来,贴出来!
      

  10.   

    我已经注释了catch部分不过我用的是ApplicationClass类,而不是Application接口,我想这两个应该一样的吧
    下面就是:Microsoft.Office.Interop.Excel.ApplicationClass ap;
    try
    {
        ap =(Microsoft.Office.Interop.Word.ApplicationClass)
            Microsoft.VisualBasic.Interaction.GetObject(null, "Excel.Application");
    }
    catch
    {
        //ap = new Microsoft.Office.Interop.Word.ApplicationClass();

    请指点,谢谢你了
      

  11.   

    Microsoft.Office.Interop.Word.ApplicationClass ap;
    try
    {
        ap =(Microsoft.Office.Interop.Word.ApplicationClass)
            Microsoft.VisualBasic.Interaction.GetObject("", "Word.Application");
    }
    catch
    {
        //ap = new Microsoft.Office.Interop.Word.ApplicationClass();
    } 上贴写错了,不好意思
      

  12.   

    我的意思意思是Microsoft.Office.Interop.Word.ApplicationClass ap;
    //try
    //{
        ap =(Microsoft.Office.Interop.Word.ApplicationClass)
            Microsoft.VisualBasic.Interaction.GetObject("", "Word.Application");
    //}
    //catch
    //{
    //    ap = new Microsoft.Office.Interop.Word.ApplicationClass();
    //}这样看看到底一返回什么异常。 
      

  13.   

    哦,我用程序调试了一下,Microsoft.VisualBasic.Interaction.GetObject果然厉害,可以在进程不存在的时候自动创建(肯定是通过读注册表来获得它的信息),比过去.NET之前要简单多了。过去要检测GetObject,然后在返回null或者异常的时候调用CreateObject。Microsoft.VisualBasic 中的很多方法、函数的功能都很强大,普遍比 .net framework 中其它地方同样功能的方法、函数都强大。既然如此,打开Office的进程对象就根本不应该写new了,仅仅需要一句话:Microsoft.Office.Interop.Word.ApplicationClass ap = 
     (Microsoft.Office.Interop.Word.ApplicationClass)
    Microsoft.VisualBasic.Interaction.GetObject("", "Word.Application");
      

  14.   

    呵呵,突然意识到你把我给“骗”啦!我写的 GetObject 中第一个参数是 null,你怎么能给写成""呢?
      

  15.   

    参数是null的话,调试不通过啊只有""才能通过啊
      

  16.   

    只要问题,还不是这个,还是用GetObject的话,还是产生很多word进程
      

  17.   

    你自己查看文档!第一个参数是"",功能就是创建对象,而是null才是查询对象。总应该是为了功能,你不能为了“调试通过”而写程序吧。如果没有运行时异常发生,也就没有调试,也就不用在发布的程序中要写上try...catch。你调试不通过,那么不正说明你的曾旭应该在catch处理吗?我上面很多文字都白费了。呵呵。