posts - 10,comments - 35,trackbacks - 0

往期回顾

  .Net初次使用FlashPaper主要讲述了.Net使用FlashPaper来进行文档转换,同时也留下了一些问题等待我们解决:

  1. 不能同时转换多个文件,否则将导致失败
  2. 如果转换失败导致进程不结束,将会照成死循环
  3. Office文件总转换失败,之前能成功

不能同时转换多个文件,否则将导致失败

  因为我的需求是小数量人员使用系统,所以用了加锁的形式来保证同一时刻只有一个转换进程。

//创建一个静态类,静态变量,供锁使用
public class PageHelper : System.Web.UI.Page
{
    public static Object LockObject = 0;
}

//调用转换代码
protected void btnConvertFile_Click(object sender, EventArgs e)
{
  if (Monitor.TryEnter(LockObject))
  { 
    //转换操作
    if(ConvertFile("Test.doc"))
      ShowMessage("转换成功!");
    else
      ShowMessage("转换失败!");

    Monitor.Exit(PageHelper.LockObject);
  }
  else
  {
                    //告知请稍等
    ShowMessage("有操作正在进行,请稍后再试!")
  }
}   


如果转换失败导致进程不结束,将会照成死循环

  当转换进程不结束时 pss.HasExited 一直为false。所以代码更改如下。

        protected Boolean ConvertFile(string fileName)
        {
            //FlashPaper文件安装路径 可自行设置
            string flashPrinter = Server.MapPath("~/FlashPaper/FlashPrinter.exe");

            string inFile = GetFilePath(fileName);
            string outFile = GetFlashPath(GetFlashName(fileName));

            //进程操作
            Process pss = new Process();
            pss.StartInfo.CreateNoWindow = false;
            pss.StartInfo.FileName = flashPrinter;
            pss.StartInfo.Arguments = string.Format("{0} {1} -o {2}", flashPrinter, inFile, outFile);
            try
            {
                pss.Start();
                //设置300*200毫秒不结束则退出循环
                for (int i = 0; i < 300 && !File.Exists(outFile); i += 1)
                    System.Threading.Thread.Sleep(200);
                //返回输出文件是否存在
                return File.Exists(outFile);
            }
            catch (Exception)
            {
                //如果报错 将输出文件删除
                if (File.Exists(outFile)) File.Delete(outFile);
                return false;
            }
        }

 

 

Office文件总转换失败,之前能成功

  发布后使用时发现Office总是转换失败,本地测试完全正常。调查中发现服务器任务管理器中有很多FlashPaper进程和Office各各组件的进程,结合FlashPaper转换原理。得出结论:Office组件被FlashPaper打开后,未正常关闭,导致进程长期驻留在任务管理器中,导致后续转换无法进行。

心想难道在服务器端,进程无法自动关闭。于是在代码中增加了杀死进程树的功能

 

        protected Boolean ConvertFile(string fileName)
        {
            //FlashPaper文件安装路径 可自行设置
            string flashPrinter = Server.MapPath("~/FlashPaper/FlashPrinter.exe");

            string inFile = GetFilePath(fileName);
            string outFile = GetFlashPath(GetFlashName(fileName));

            //进程操作
            Process pss = new Process();
            pss.StartInfo.CreateNoWindow = false;
            pss.StartInfo.FileName = flashPrinter;
            pss.StartInfo.Arguments = string.Format("{0} {1} -o {2}", flashPrinter, inFile, outFile);
            try
            {
                pss.Start();
                //设置300*200毫秒不结束则退出循环
                for (int i = 0; i < 300 && !File.Exists(outFile); i += 1)
                    System.Threading.Thread.Sleep(200);
                //返回输出文件是否存在
                return File.Exists(outFile);
            }
            catch (Exception)
            {
                //如果报错 将输出文件删除
                if (File.Exists(outFile)) File.Delete(outFile);
                return false;
            }
            finally
            {
                //如果进程还未结束,杀死进程树
                if (!pss.HasExited) KillProcess(pss.Id);
            }
        }

        //杀死进程树
        private static bool KillProcess(int pid)
        {
            Process[] procs = Process.GetProcesses();
            for (int i = 0; i < procs.Length; i++)
            {
                if (GetParentProcess(procs[i].Id) == pid)
                    KillProcess(procs[i].Id);
            }

            try
            {
                Process myProc = Process.GetProcessById(pid);
                myProc.Kill();
            } 
            catch (ArgumentException)
            {
                ;
            }

            return true;
        }

        //获取父进程
        private static int GetParentProcess(int Id)
        {
            int parentPid = 0;
            using (ManagementObject mo = new ManagementObject("win32_process.handle='" + Id.ToString(CultureInfo.InvariantCulture) + "'"))
            {
                try
                {
                    mo.Get();
                }
                catch (ManagementException)
                {
                    return -1;
                }
                parentPid = Convert.ToInt32(mo["ParentProcessId"], CultureInfo.InvariantCulture);
            }
            return parentPid;
        }

 

发布后,跟踪发现,转换完成后FlashPaper真的没有了,但是Office进程却依然存在,好郁闷啊。随后在网络收集各种方法,都未能达到想要的效果。这可是真真的郁闷啊。

最后无奈在服务器上闲逛,想看看是不是设置的问题。在服务器端打开Office组件查看,谁知竟弹出窗口:

难道是因为这个对话框导致Office未正常关闭。和很多药品广告一样:“我抱着试试看的态度”用Office Toolkit把Office2010激活。

手动杀死所有已开阻拦进程,启动系统,转换开始。

啊~成功。没想到真是这个激活窗口导致了这个问题。希望大家引以为戒,以免浪费了青春。

 Demo下载

   最后提供Demo下载:在线Flash转换.rar

 

posted on 2012-09-06 15:25 Arvin.Mei 阅读(...) 评论(...) 编辑 收藏