【问题标题】:Write access for a System.Diagnostics.ProcessSystem.Diagnostics.Process 的写入权限
【发布时间】:2017-07-25 00:12:54
【问题描述】:

我在 Windows 10 系统上使用 Ghostcript (GS) 修改 PDF 文件,但我认为我有一个普遍问题,与 GS 无关。

当我从命令提示符运行 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) 失败有关。

【问题讨论】:

  • 尝试指定一个完整的路径规范,而不仅仅是“outFile.pdf”。请注意,如果您已经打开了“outFile.pdf”,那么该命令将失败,因为 GS 无法打开文件进行写入。您可能还必须以这种方式指定输入文件。我猜这个问题很可能与当前工作目录不正确有关。
  • @KenS:感谢您的帮助。我尝试了许多具有不同工作目录和完整路径名的变体。我最终决定尝试调用 itextsharp API,结果确实有效。但我想了解我使用 GS 有什么问题,无论如何我需要调用 GS 来获取边界框(谢天谢地,这确实有效)。
  • 很难猜。我要做的第一件事是删除-q,你真的不想在调试时抑制消息。我希望 Ghostscript 进程继承其父进程(即您的进程)的权限,但我不编写 C#,所以我不能确定。也许 Process 类文档对此有更多信息。该错误是从 PostScript 环境返回的,表示无法打开指定的设备。 PostScript 无法为您提供更多信息。如果您可以调试子 Ghostscript 进程,我可以告诉您在 C 代码中停止查看的位置。
  • 当然,另一种选择是使用 Ghostscript.NET,我知道它可以工作,但它使用 DLL,它不会产生新进程。
  • 它指的是pdfwrite设备(由-sDEVICE=设置)。但这无法打开,因为它无法打开文件,大概是输出文件。大概您可以重建 Ghostscript 可执行文件,您使用的是 Visual Studio,对吧?因此,您可以下载源代码,对其进行修补以提供更多错误信息(printf 到 stdout),然后重新构建并使用它。同样,我可以就进行这些修改提供建议。人们使用进程而不是使用 DLL 的一个原因是为了避免 AGPL 许可。

标签: .net process file-permissions ghostscript


【解决方案1】:

这是一些有效的代码。这是一个正在进行的工作,无论如何我不是程序员,所以请原谅丑陋/愚蠢。但它使用 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;
      }

   }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-06
    • 2011-01-20
    • 2011-01-08
    • 2012-02-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多