2017-03-05 39 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; 
     } 

    } 
}