我正在尝试使用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对完全相同的文件和参数执行相同的操作可以正常工作。 快乐黑客
答案 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}",
};
}