gsapi_init_with_args 制作:-100
gsapi_init_with_args is made: -100
我正在尝试使用 Ghostscript.Net 构建 PostScript 到 PDF 转换器。
GetArgs return 的 Args 是我通常用来调用 gswin32c.exe 的那些,它们工作正常。
但是每次我调用 Process 时,我都会收到一个错误 Saying "An error occured when call to 'gsapi_init_with_args' is made: -100"。谷歌搜索该错误没有发现任何问题,所以我想我可以在这里问一下。
直接使用 Ghostscript.net 调用 .dll 时是否需要考虑不同的参数?还是我其他地方弄错了?
这是我的 class:
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 class。我承认我不完全确定我这样做是否正确。尽管它确实无一例外地被实例化,并覆盖 StdOut(...) 被调用,并且输出按预期写入控制台。 override void StdError(...) 也被调用。并且还按预期写入控制台。
顺便说一句,错误的输出是:
“**** 无法打开文件 "c:\temp\test.pdf"”
"**** 无法打开初始设备,正在退出。"
这是我的 ConsoleStdIO class:
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 对完全相同的文件和参数执行相同的操作效果很好。
快乐黑客
错误-100是gs_error_Fatal,意思是'something catastrophic went wrong'。这表明该程序未能正常启动,我们无法确定原因。后台频道可能包含更多信息。
事实上,后台渠道会告诉您哪里出了问题:
**** 无法打开文件“c:\temp\test.pdf
**** 无法打开初始设备,正在退出。
Ghostscript 无法打开输出文件,这意味着它无法打开 pdfwrite 设备(因为 需要 输出文件)所以它中止了操作。
Ghostscript 无法打开输出文件的原因可能有多种。我要做的第一件事是 trim 减少参数的数量;
当你试图调试一个问题时,你不希望-q
(安静),你想要你能得到的所有信息。
我至少要删除 -dSAFER
,因为这样可以防止 Ghostscript 访问当前工作目录和某些 'special' 目录之外的目录。它可能会阻止您访问临时目录。
当它与默认值相同时,您不需要设置EmbedAllFonts
。
您可以删除 CompatibilityLevel
(请注意,您在此处使用了 # 而不是 =)开关,并在使其正常工作时删除 AutoRotatePages
。
“-c .setpdfwrite -f
”字符串多年来一直毫无意义,但人们仍在继续使用它。这些天所做的只是减慢处理的启动速度,放弃它。
最后,您可以尝试将反斜杠('\')字符更改为正斜杠('/'),以防您的字符串处理弄乱它,或者使用双反斜杠(我自己会使用正斜杠) .
您还应检查 c:\test\temp.pdf 是否不存在,或者如果它存在则不是只读的或已在其他应用程序中打开。
所以我解决了问题...
在接受了 KenS 的建议后,我可以 运行 没有 Ghostscript 的应用程序(不是 Ghostscript.NET)给我任何错误。但它没有生成实际的 PDF 文件。
所以 KenS 的回答并没有完全解决问题,但是由于 'less is more' 并且由于他花时间在 IRC 上与我交谈以验证我的参数本身是否正确,所以我会给出答案尽管如此。
真正解决我的问题如下:
这是我原来的 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}",
};
}
我正在尝试使用 Ghostscript.Net 构建 PostScript 到 PDF 转换器。 GetArgs return 的 Args 是我通常用来调用 gswin32c.exe 的那些,它们工作正常。
但是每次我调用 Process 时,我都会收到一个错误 Saying "An error occured when call to 'gsapi_init_with_args' is made: -100"。谷歌搜索该错误没有发现任何问题,所以我想我可以在这里问一下。
直接使用 Ghostscript.net 调用 .dll 时是否需要考虑不同的参数?还是我其他地方弄错了?
这是我的 class:
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 class。我承认我不完全确定我这样做是否正确。尽管它确实无一例外地被实例化,并覆盖 StdOut(...) 被调用,并且输出按预期写入控制台。 override void StdError(...) 也被调用。并且还按预期写入控制台。 顺便说一句,错误的输出是:
“**** 无法打开文件 "c:\temp\test.pdf"” "**** 无法打开初始设备,正在退出。"
这是我的 ConsoleStdIO class:
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 对完全相同的文件和参数执行相同的操作效果很好。 快乐黑客
错误-100是gs_error_Fatal,意思是'something catastrophic went wrong'。这表明该程序未能正常启动,我们无法确定原因。后台频道可能包含更多信息。
事实上,后台渠道会告诉您哪里出了问题:
**** 无法打开文件“c:\temp\test.pdf **** 无法打开初始设备,正在退出。
Ghostscript 无法打开输出文件,这意味着它无法打开 pdfwrite 设备(因为 需要 输出文件)所以它中止了操作。
Ghostscript 无法打开输出文件的原因可能有多种。我要做的第一件事是 trim 减少参数的数量;
当你试图调试一个问题时,你不希望-q
(安静),你想要你能得到的所有信息。
我至少要删除 -dSAFER
,因为这样可以防止 Ghostscript 访问当前工作目录和某些 'special' 目录之外的目录。它可能会阻止您访问临时目录。
当它与默认值相同时,您不需要设置EmbedAllFonts
。
您可以删除 CompatibilityLevel
(请注意,您在此处使用了 # 而不是 =)开关,并在使其正常工作时删除 AutoRotatePages
。
“-c .setpdfwrite -f
”字符串多年来一直毫无意义,但人们仍在继续使用它。这些天所做的只是减慢处理的启动速度,放弃它。
最后,您可以尝试将反斜杠('\')字符更改为正斜杠('/'),以防您的字符串处理弄乱它,或者使用双反斜杠(我自己会使用正斜杠) .
您还应检查 c:\test\temp.pdf 是否不存在,或者如果它存在则不是只读的或已在其他应用程序中打开。
所以我解决了问题...
在接受了 KenS 的建议后,我可以 运行 没有 Ghostscript 的应用程序(不是 Ghostscript.NET)给我任何错误。但它没有生成实际的 PDF 文件。
所以 KenS 的回答并没有完全解决问题,但是由于 'less is more' 并且由于他花时间在 IRC 上与我交谈以验证我的参数本身是否正确,所以我会给出答案尽管如此。
真正解决我的问题如下:
这是我原来的 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}",
};
}