Я пишу службу Windows для сканирования набора каталогов на наличие новых файлов PDF и преобразования их в TIFF с помощью Ghostscript.NET. Когда я скомпилировал и запустил код как обычную программу, он работал отлично, но когда я использовал тот же код в качестве службы, выходной TIFF никогда не отображался. Я установил целевой каталог, чтобы разрешить запись для всех, и исходный PDF-файл удаляется, как и предполагалось, поэтому это не должно быть проблемой разрешений для пользователя «Локальная система». Аудит каталога для доступа к ошибкам и успехам просто показывает список успехов.
Существует функция, которая считывает цветовую популяцию PDF-файла, чтобы определить, является ли он цветным документом или черно-белым, отсканированным как цветной. Эта часть работает, поэтому нет проблем с доступом и чтением PDF.
Я также попытался удалить «-q» из ключей Ghostscript, и у меня не было сообщений об ошибках, а «-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 — это версия 4.0.30319, установленная через NuGet в VS 2012. ILMerge 2.13.0307 используется для упаковки DLL GS.NET в исполняемый файл, а также для переносимости. Ни одна из этих вещей не изменилась между обычным EXE и версиями службы Windows, и, как я уже сказал, обычный EXE работает без проблем.