.Net再次使用FlashPaper


往期回顧

  .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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM