gsapi_init_with_args为:-100

时间:2017-12-14 08:16:51

标签: c# ghostscript.net

我正在尝试使用Ghostscript.Net构建PostScript到PDF转换器。 GetArgs返回的Args是我通常用来调用gswin32c.exe的它们,它们工作正常。

但每次我调用Process时,都会收到错误Saying"调用' gsapi_init_with_args'时出现错误制作:-100"。谷歌搜索该错误并没有带来任何好处,所以我想我可能会问这里。

使用Ghostscript.net直接调用.dll时是否需要考虑不同的参数?或者我在其他地方犯了错误?

这是我的班级:

public class PdfConverter
{
    #region Private Fields
    private List<GhostscriptVersionInfo> _Versions = GhostscriptVersionInfo.GetInstalledVersions(GhostscriptLicense.GPL | GhostscriptLicense.AFPL | GhostscriptLicense.Artifex);
    #endregion


    #region Private Properties
    private GhostscriptVersionInfo Version { get; set; }
    #endregion


    #region Construction
    public PdfConverter()
    {
        Version = GhostscriptVersionInfo.GetLastInstalledVersion(); 
    }
    #endregion


    #region Public Members
    public bool ConvertToPdf(DirectoryInfo dir)
    {
        var d = dir;
        if(!d.Exists)
            return false;

        var postScriptFiles = d.GetFiles("*.ps");
        var pdfFiles        = postScriptFiles.Select(psf => new FileInfo(Path.ChangeExtension(psf.FullName, ".pdf")));

        foreach(var file in postScriptFiles) {
            //ThreadPool.QueueUserWorkItem(new WaitCallback((o) => { 
                Process(file, new FileInfo(Path.ChangeExtension(file.FullName, ".pdf")));
            //}));
        }

        pdfFiles.ForEach(pdf => pdf?.Refresh());
        return pdfFiles.All(pdf => pdf.Exists);
    }
    #endregion


    #region Private Helpers
    private void Process(FileInfo inputFile, FileInfo outputFile)
    {
        Console.WriteLine($"Converting {inputFile} to {outputFile}");
        var proc = new GhostscriptProcessor(Version, true);
        proc.Process(GetArgs(inputFile, outputFile).ToArray(), new ConsoleStdIO(true, true, true));
    }


    private IEnumerable<string> GetArgs(FileInfo inputFile, FileInfo outputFile)
    {
        return new [] {
            $"-q ",
            $"-sDEVICE=pdfwrite",
            $"-dSAFER",
            $"-dNOPAUSE",
            $"-dBATCH",
            $"-sPAPERSIZE=a4",
            $"-dEmbedAllFonts=true",
            $"-dAutoRotatePages=/None",
            $"-sOutputFile=\"{outputFile.FullName}\"",
            $"-dCompatibilityLevel#1.4",
            $"-c .setpdfwrite",
            $"-f \"{inputFile.FullName}\""
        };
    }
    #endregion
}

编辑: 我忘了提到:要实现它,我必须自己创建GhostsdcriptStdIO类。我承认我不能完全确定我是否做得对。虽然它确实在没有异常的情况下实现了,并且覆盖了调用StdOut(...)的get,并且输出按预期写入控制台。 override void StdError(...)也被调用。并且也被写入控制台。 错误输出btw是:

&#34; ****无法打开文件&#34; c:\ temp \ test.pdf&#34;&#34; &#34; ****无法打开初始设备,退出。&#34;

这是我的ConsoleStdIO课程:

public class ConsoleStdIO : Ghostscript.NET.GhostscriptStdIO
{
    #region Construction
    public ConsoleStdIO(bool handleStdIn, bool handleStdOut, bool handleStdError) : base(handleStdIn, handleStdOut, handleStdError) { }  
    #endregion


    #region Overrides
    public override void StdError(string error)
    {
        var foo    = Encoding.Default.GetBytes(error);
        var lenght = foo.Length;

        using (var err = Console.OpenStandardError()) {
            if(err.CanWrite)
                err.Write(foo, 0, lenght);
        }
    }

    public override void StdIn(out string input, int count)
    {
        byte[] bytes = new byte[0];
        using(var stdInput = Console.OpenStandardInput()) {
            stdInput.Read(bytes, 0, count);
        }
        input = Encoding.Default.GetString(bytes);
    }

    public override void StdOut(string output)
    {
        var foo    = Encoding.Default.GetBytes(output);
        var lenght = foo.Length;

        using (var err = Console.OpenStandardError()) {
            if(err.CanWrite)
                err.Write(foo, 0, lenght);
        }           
    }
    #endregion
}

再次:使用gswin32c.exe对完全相同的文件和参数执行相同的操作可以正常工作。 快乐黑客

2 个答案:

答案 0 :(得分:2)

错误-100是gs_error_Fatal,这意味着发生了灾难性的错误&#39;。这表明程序无法正常启动,我们无法说明原因。反向频道可能包含更多信息。

事实上,后退频道告诉你错误:

****无法打开文件&#34; c:\ temp \ test.pdf ****无法打开初始设备,退出。

Ghostscript无法打开输出文件,这意味着它无法打开pdfwrite设备(因为需要输出文件),因此它会中止操作。

Ghostscript无法打开输出文件可能有很多原因。我要做的第一件事是减少参数的数量;

当您尝试调试问题时,您不希望-q(安静),您需要获得所有信息。

我至少要删除-dSAFER,因为这会阻止Ghostscript访问当前工作目录之外的目录以及某些特殊的&#39;那些。它可能会阻止您访问临时目录。

如果EmbedAllFonts的值与默认值相同,则无需设置{。}}。

您可以放弃CompatibilityLevel(并注意您已使用#there而不是=)开关,并AutoRotatePages同时启用此功能。

&#34; -c .setpdfwrite -f&#34;字符串多年来毫无意义,但人们仍然继续使用它。这些天所做的一切都是在处理开始时放慢了,放弃它。

最后,您可以尝试更改反斜杠(&#39; \&#39;)字符以转发斜杠(&#39; /&#39;),以防您的字符串处理搞乱,或使用双反斜杠(我自己使用正斜杠)。

您还应检查c:\ test \ temp.pdf是否存在,或者它是否存在不是只读的或已在其他应用程序中打开。

答案 1 :(得分:0)

所以我解决了这个问题...... 在听完KenS的建议后,我可以运行没有Ghostscript(而不是Ghostscript.NET)的应用程序给我任何错误。但它没有产生实际的PDF文件。

所以KenS的答案并没有完全解决问题,但是因为'少即是多'而且由于他花时间在IRC上与我交谈以确认我的args本身是正确的,我仍然会给出答案点。

实际解决了我的问题如下:
这是我原来的GetArgs(...)

    private IEnumerable<string> GetArgs(FileInfo inputFile, FileInfo outputFile)
    {
        return new [] {
            $"-sDEVICE=pdfwrite",
            $"-dNOPAUSE",
            $"-dBATCH",
            $"-sPAPERSIZE=a4",
            @"-sFONTPATH=" + System.Environment.GetFolderPath(System.Environment.SpecialFolder.Fonts),
            $"-sOutputFile={outputFile.FullName}",
            $"{inputFile.FullName}",
        };
    }

#csharp中的某个人向我指出,在c中,第一个参数始终是命令的名称。所以他建议只把“gs”作为第一个参数(作为假人)并尝试......这就是实际解决了我的问题。

所以这就是GetArgs(...)的工作方式:

    private IEnumerable<string> GetArgs(FileInfo inputFile, FileInfo outputFile)
    {
        return new [] {
            $"gs",
            $"-sDEVICE=pdfwrite",
            $"-dNOPAUSE",
            $"-dBATCH",
            $"-sPAPERSIZE=a4",
            @"-sFONTPATH=" + System.Environment.GetFolderPath(System.Environment.SpecialFolder.Fonts),
            $"-sOutputFile={outputFile.FullName}",
            $"{inputFile.FullName}",
        };
    }