我正在编写一个Windows服务来扫描一组目录中的新PDF文件,并使用Ghostscript.NET将它们转换为TIFF。当我编译并运行代码作为普通程序时,它运行得很好,但是当我使用相同的代码作为服务时,输出TIFF永远不会出现。我已将目标目录设置为允许为Everyone编写,并且原始PDF正在被删除,因此它不应该是“本地系统”用户的权限问题。审核目录以进行访问失败和成功只显示成功列表。
有一个功能可以读取PDF的颜色总体,以确定它是彩色文档,还是B& W扫描为彩色。该部分有效,因此访问和阅读PDF没有问题。
我也尝试从Ghostscript开关中删除'-q'并且我没有报告任何错误,并且“-dDEBUG”输出了太多垃圾我不知道它在说什么 - 但没有任何标记为错误。
public static void ConvertPDF(string file, GSvalues gsVals)
{
gsProc = new Ghostscript.NET.Processor.GhostscriptProcessor();
System.Collections.Generic.List<string> switches = new System.Collections.Generic.List<string>();
switches.Add("-empty"); // GS.NET ignores the first switch
switches.Add("-r" + gsVals.Resolution); // dpi
switches.Add("-dDownScaleFactor=" + gsVals.ScaleFactor); // Scale the image back down
switches.Add("-sCompression=lzw"); // Compression
switches.Add("-dNumRenderingThreads=" + Environment.ProcessorCount);
switches.Add("-c \"30000000 setvmthreshold\"");
switches.Add("-dNOGC");
string device;
if (_checkPdf(file, gsVals.InkColorLevels, gsVals))
{
gsVals.WriteLog("Color PDF");
device = "-sDEVICE=tiffscaled24"; // 24bit Color TIFF
}
else
{
gsVals.WriteLog("Grayscale PDF");
device = "-sDEVICE=tiffgray"; // grayscale TIFF
}
switches.Add(device);
// Strip the filename out of the full path to the file
string filename = System.IO.Path.GetFileNameWithoutExtension(file);
// Set the output file tag
string oFileName = _setFileName(oPath + "\\" + filename.Trim(), GSvalues.Extension);
string oFileTag = "-sOutputFile=" + oFileName;
switches.Add(oFileTag);
switches.Add(file);
// Process the PDF file
try
{
string s = string.Empty;
foreach (string sw in switches) s += sw + ' ';
gsVals.DebugLog("Switches:\n\t" + s);
gsProc.StartProcessing(switches.ToArray(), new GsStdio());
while (gsProc.IsRunning) System.Threading.Thread.Sleep(1000);
}
catch (Exception e)
{
gsVals.WriteLog("Exception caught: " + e.Message);
Console.Read();
}
gsVals.DebugLog("Archiving PDF");
try
{
System.IO.File.Move(file, _setFileName(gsVals.ArchiveDir + "\\" + filename, ".pdf"));
}
catch (Exception e)
{
gsVals.WriteLog("Error moving PDF: " + e.Message);
}
}
private static string _setFileName(string path, string tifExt)
{
if (System.IO.File.Exists(path + tifExt)) return _setFileName(path, 1, tifExt);
else return path + tifExt;
}
private static string _setFileName(string path, int ctr, string tifExt)
{
// Test the proposed altered filename. It it exists, move to the next iteration
if(System.IO.File.Exists(path + '(' + ctr.ToString() + ')' + tifExt)) return _setFileName(path, ++ctr, tifExt);
else return path + '(' + ctr.ToString() + ')' + tifExt;
}
这是生成的开关的示例输出(从输出日志中提取):
Switches: -empty -r220 -dDownScaleFactor=1 -sCompression=lzw -dNumRenderingThreads=4 -c "30000000 setvmthreshold" -dNOGC -sDEVICE=tiffscaled24 -sOutputFile=\\[servername]\amb_ops_scanning$\Test.tiff \\[servername]\amb_ops_scanning$\Test.pdf
设置在XML文件中读取并存储在类GSVals中。该类还处理写入系统日志以进行输出,或处理正常程序版本中的文本文件。 GSSTDIO是一个用于处理GS输入和输出的类,它只是将所有输出重定向到与GSVals相同的日志。程序版本和服务版本之间唯一的代码更改是服务处理代码,输出从文本文件更改为系统日志。 Ghostscript处理没有任何改变。
这是为了便携性编译为x86,但正在x64上运行。安装了GS 9.15,x86和x64版本。 GS.NET是通过NuGet安装到VS 2012的版本4.0.30319.ILMerge 2.13.0307用于将GS.NET dll打包到exe中,也用于可移植性。在正常的EXE和Windows服务版本之间没有这些变化,正如我所说的那样,正常的EXE没有任何问题。
答案 0 :(得分:1)
我使用来自advapi32.dll的CreateProcessAsUser(),使用this article中的代码来实现它。
我还必须重新调整开关的顺序:
switches.Add("-c 30000000 setvmthreshold -f\"" + file + "\"")
我用来加速转换的原始资源遗漏了&#39; -f&#39;部分,以及-f是标记文件的标记的事实。我不知道为什么这在GS.NET中有效,但是使用普通的gswin32c.exe我得到一个错误,说它是一个无效的文件,直到我用这种方式设置开关。
奇怪的是,这个方法创建的进程仍然是Session 0,但它确实有效。我会继续修补,但现在它正在工作。