2017-03-05 63 views
0

我使用Ghostcript(GS)修改Windows 10系統上的PDF文件,雖然我認爲我有一個普遍問題,但與GS無關。寫訪問System.Diagnostics.Process

當我從命令提示符運行GS時,它工作正常。當我嘗試從由C#代碼創建的進程執行相同的操作時,出現錯誤。我懷疑問題是由於我的進程沒有對正在創建輸出文件的文件夾的寫入權限而造成的。

我的問題是:

  1. 如何打開權限在目標文件夾?向誰或我需要授予寫入權限?我嘗試使用資源管理器將「完全控制」授予「每個人」,但這並沒有幫助。

  2. 我可以以某種方式給我的過程賦予「超級」權力,以便它可以隨心所欲地寫出來嗎? (我不擔心安全問題)。

這裏是GS命令(工作):

gswin64c.exe -sDEVICE=pdfwrite –q -o outFile.pdf -c "[/CropBox [72 72 144 216] /PAGES pdfmark" -f inFile.pdf 

這裏是試圖執行此相同的命令(不工作),我的C#代碼:

using System; 
using System.Diagnostics; 

namespace pdfcropper 
{ 
    class Program 
    { 
     static void Main() 
     { 
     string gspath = @"D:\ciao\Documents\Visual Studio 2013\Projects\itextsharp\gswin64c.exe"; 

     ProcessStartInfo psi= new ProcessStartInfo(gspath); 
     psi.UseShellExecute = false; 
     psi.WorkingDirectory = @"D:\ciao\Documents\Visual Studio 2013\Projects\itextsharp"; 
     psi.Arguments = @" -sDEVICE=pdfwrite -dBATCH –q -o outFile.pdf -c ""[/CropBox [72 72 144 216] /PAGES pdfmark"" -f inFile.pdf"; 

     Process myProcess = new Process(); 
     myProcess.StartInfo = psi; 
     myProcess.Start(); 

     myProcess.Close(); 
     } 
    } 
} 

該錯誤消息我得到的是:

**** Unable to open the initial device, quitting. 
Unrecoverable error: undefinedfilename in setpagedevice 

這非常神祕,但用谷歌搜索似乎表明它與創建輸出文件失敗(outFile.pdf)有關。

+1

嘗試指定一個完整的pathspec而不是'outFile.pdf'。請注意,如果您已經打開'outFile.pdf',那麼命令將失敗,因爲GS無法打開文件進行寫入。您可能也必須以這種方式指定輸入文件。我猜想這個問題可能與當前工作目錄不正確有關。 – KenS

+0

@KenS:謝謝你的幫助。我嘗試了許多不同的工作目錄和完整路徑名的變體。我終於決定嘗試調用itextsharp API,而這確實奏效了。但是我想知道我使用GS有什麼問題,無論如何我都需要給GS打電話(謝謝)。 – bubba

+1

很難猜測。我首先要做的是去除-q,在調試時你並不想真的抑制消息。我希望Ghostscript進程繼承父進程的特權(即你的進程),但我不寫C#,所以我不能確定。也許Process類文檔有更多的信息。該錯誤是從PostScript環境返回的,意味着指定的設備無法打開。 PostScript無法爲您提供更多信息。如果你可以調試孩子的Ghostscript過程,我可以告訴你在C代碼中停下來看看。 – KenS

回答

0

這是一些有效的代碼。這是一項正在進行中的工作,無論如何,我不是程序員,所以請原諒醜陋/愚蠢。但它使用itextSharp而不是Ghostscript進行裁剪。我仍然想知道我打電話給Ghostscript的方式有什麼問題。

using System; 
using System.Diagnostics; 
using System.IO; 
using iTextSharp.text.pdf; 
using iTextSharp.text; 

namespace pdfcropper 
{ 
    class Program 
    { 
     public static void Main(string[] args) 
     { 
     string[] config = System.IO.File.ReadAllLines(@"D:\public\pdfcropperConfig.txt"); 

     float d = float.Parse(config[0]);   // border size (n points) 
     int show = int.Parse(config[1]);   // >0 to view after cropping; =0 to not 
     string gspath = config[2];     // path of Ghostscript executable 

     string inFile = args[0]; 

     float[] b = GetBounds(gspath, inFile); 
     PdfRectangle rect = new PdfRectangle(b[0] - d, b[1] - d, b[2] + d, b[3] + d); 

     PdfReader reader = new PdfReader(inFile); 
     PdfDictionary pageDict = reader.GetPageN(1); 
     pageDict.Put(PdfName.CROPBOX, rect); 

     string tempPath = System.IO.Path.GetTempPath(); 
     string tempOutFile = Path.Combine(tempPath, "tempPDF.pdf"); 
     FileStream fs = new FileStream(tempOutFile, FileMode.Create, FileAccess.Write); 

     // The "stamper" actually does the copying, when closed 
     PdfStamper stamper = new PdfStamper(reader, fs); 
     stamper.Close(); 

     reader.Close(); 

     // Replace original file by cropped one 
     File.Copy(tempOutFile, inFile, true); 
     File.Delete(tempOutFile); 

     // Start Acrobat reader to view the output file 
     if (show > 0) Process.Start(inFile); 
     } 

     private static float[] GetBounds(string gspath, string infilePath) 
     { 
     //string gspath = @"C:\Program Files\gs\gs9.15\bin\gswin64c.exe"; 

     ProcessStartInfo psi = new ProcessStartInfo(); 
     psi.FileName = gspath; 
     psi.UseShellExecute = false; 
     psi.RedirectStandardError = true; 
     psi.RedirectStandardOutput = true; 
     psi.WorkingDirectory = System.IO.Path.GetDirectoryName(infilePath); 
     psi.Arguments = @" -sDEVICE=bbox -dBATCH -dNOPAUSE -q " + infilePath; 

     Process proc = new Process(); 
     proc.StartInfo = psi; 
     proc.Start(); 

     StreamReader myStreamReader = proc.StandardError; 
     string output = myStreamReader.ReadToEnd(); 
     char sep = ' '; 
     string output2 = output.Replace('\n', sep); 
     string[] words = output2.Split(sep); 

     float[] bounds = new float[4]; 

     bounds[0] = float.Parse(words[6]); // xmin 
     bounds[1] = float.Parse(words[7]); // ymin 
     bounds[2] = float.Parse(words[8]); // xmax 
     bounds[3] = float.Parse(words[9]); // ymax 

     proc.Close(); 

     return bounds; 
     } 

    } 
}