Ghostscript.NET - 作为Windows服务运行时没有输出文件

时间:2014-11-17 17:17:49

标签: c# ghostscript ghostscript.net

我正在编写一个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没有任何问题。

1 个答案:

答案 0 :(得分:1)

我使用来自advapi32.dll的CreateProcessAsUser(),使用this article中的代码来实现它。

我还必须重新调整开关的顺序:

switches.Add("-c 30000000 setvmthreshold -f\"" + file + "\"")

我用来加速转换的原始资源遗漏了&#39; -f&#39;部分,以及-f是标记文件的标记的事实。我不知道为什么这在GS.NET中有效,但是使用普通的gswin32c.exe我得到一个错误,说它是一个无效的文件,直到我用这种方式设置开关。

奇怪的是,这个方法创建的进程仍然是Session 0,但它确实有效。我会继续修补,但现在它正在工作。