Ghostscript.NET - tidak ada file keluaran saat dijalankan sebagai layanan Windows

Saya sedang menulis Layanan Windows untuk memindai sekumpulan direktori untuk file PDF baru dan mengonversinya menjadi TIFF dengan Ghostscript.NET. Ketika saya mengkompilasi dan menjalankan kode sebagai program normal, kode tersebut berfungsi dengan sempurna, tetapi ketika saya menggunakan kode yang sama sebagai Layanan, output TIFF tidak pernah muncul. Saya telah menetapkan direktori tujuan untuk mengizinkan penulisan untuk Semua Orang, dan PDF asli dihapus sebagaimana mestinya, jadi ini seharusnya tidak menjadi masalah izin bagi pengguna "Sistem Lokal". Mengaudit direktori untuk mengakses Kegagalan dan Keberhasilan hanya menampilkan daftar Keberhasilan.

Terdapat fungsi yang membaca populasi warna PDF untuk menentukan apakah itu dokumen berwarna, atau Hitam Putih yang dipindai sebagai warna. Bagian itu berfungsi, jadi tidak ada masalah saat mengakses dan membaca PDF.

Saya juga mencoba menghapus '-q' dari sakelar Ghostscript dan tidak ada kesalahan yang dilaporkan, dan "-dDEBUG" menghasilkan begitu banyak sampah. Saya tidak tahu apa yang dikatakannya - tetapi tidak ada yang ditandai sebagai kesalahan.

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;
    }

Ini adalah contoh keluaran dari sakelar yang dihasilkan (diambil dari log keluaran):

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 

Pengaturan dibaca dalam file XML dan disimpan di kelas, GSVals. Kelas ini juga menangani penulisan ke log Sistem untuk keluaran, atau ke file teks dalam versi Program normal. GSSTDIO adalah kelas untuk menangani input dan output GS, yang hanya mengalihkan semua output ke log yang sama dengan GSVals. Satu-satunya perubahan kode antara versi Program dan versi Layanan adalah kode penanganan Layanan, dan outputnya diubah dari file teks ke log sistem. Tidak ada apa pun tentang pemrosesan Ghostscript yang diubah.

Ini sedang dikompilasi sebagai x86 untuk portabilitas, tetapi dijalankan pada x64. GS 9.15 sudah terinstall, baik versi x86 maupun x64. GS.NET adalah versi 4.0.30319 yang diinstal melalui NuGet ke VS 2012. ILMerge 2.13.0307 digunakan untuk mengemas GS.NET dll ke dalam exe, juga untuk portabilitas. Tak satu pun dari hal-hal ini berubah antara versi EXE normal dan versi Layanan Windows, dan seperti yang saya katakan, EXE normal berfungsi tanpa masalah apa pun.


person Scott    schedule 17.11.2014    source sumber
comment
Kemungkinannya memerlukan sesi 0 untuk rendering. Layanan Windows memblokir sesi 0 untuk tujuan keamanan.   -  person Aron    schedule 17.11.2014
comment
Melihat hal itu, terima kasih... sesi ghostscript 0 di Google sekarang menampilkan halaman ini sebagai hit pertama :)   -  person Scott    schedule 17.11.2014
comment
Sudahkah Anda mencentang Izinkan layanan berinteraksi dengan desktop.? Mungkin patut dicoba. stackoverflow.com/q/4237225/397817 Selain itu, Layanan Windows memblokir sesi 0 di Google, hasil pertama: stackoverflow.com/q/17364932/397817 :)   -  person Stephen Kennedy    schedule 17.11.2014
comment
Berinteraksi dengan Desktop tidak membantu. Saya menemukan Buku Putih MS yang memaparkan perubahan pada Layanan 0 di Vista+. Sepertinya semua layanan adalah Sesi 0, dan sesi pengguna 1+. Karena Sesi 0 bukan lagi sesi pengguna, layanan yang berjalan di Sesi 0 tidak memiliki akses ke driver video. Ini berarti bahwa setiap upaya yang dilakukan layanan untuk merender grafik akan gagal.   -  person Scott    schedule 17.11.2014
comment
Apakah Anda yakin layanan windows Anda memiliki akses ke \[nama server]\? Bisakah Anda mencoba mengatur file input dan output ke drive lokal Anda?   -  person HABJAN    schedule 17.11.2014
comment
Selain itu, coba catat pesan stdio Ghostscript dengan cara ini: pastebin.com/1F5wCu8M   -  person HABJAN    schedule 17.11.2014
comment
Itu dapat membuka PDF sumber, yang berada di direktori yang sama dengan jalur keluaran, dan mengarsipkan PDF (menghapusnya) tanpa kesalahan. Jadi itu menunjukkan bahwa ia memiliki akses R/W ke server berbagi.   -  person Scott    schedule 18.11.2014
comment
Saya harus mengutak-atik pengalihan keluaran GS dari GS.NET, tetapi saya membuatnya berfungsi dengan membuat proses tambahan - lihat jawaban saya.   -  person Scott    schedule 18.11.2014
comment
Saya tidak dapat memahami gambaran Anda, filter web kejam perusahaan saya membenci produktivitas sebenarnya. Tapi saya telah mengalihkan keluaran Ghostscript.NET menggunakan kelas GsStdio, yang hanya mencetak keluaran apa pun ke log. Saya tidak pernah melihat apa pun kecuali Tekan tombol apa saja untuk melanjutkan jenis pesan. Apakah tautan Anda seperti -sstdout=[nama file]?   -  person Scott    schedule 18.11.2014


Jawaban (1)


Saya membuatnya berfungsi dengan menggunakan CreateProcessAsUser() dari advapi32.dll, menggunakan kode dari artikel ini.

Saya juga harus merestrukturisasi urutan sakelar:

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

Sumber asli yang saya gunakan untuk mempercepat konversi tidak menyertakan bagian '-f', dan fakta bahwa -f adalah tag yang menandai file. Saya tidak tahu mengapa ini berhasil di GS.NET, tetapi dengan gswin32c.exe normal saya mendapat kesalahan yang mengatakan bahwa itu adalah file yang tidak valid, sampai saya mengatur sakelar dengan cara ini.

Anehnya, proses yang dibuat oleh metode ini masih Sesi 0, tetapi sebenarnya berfungsi. Saya akan terus mengutak-atik, tetapi untuk saat ini berhasil.

person Scott    schedule 18.11.2014
comment
-f tidak 'menandai file', ini menutup input PostScript langsung, yang dimulai dengan '-c'. Jika Anda tidak menggunakan -c, Anda tidak memerlukan -f.... - person KenS; 19.11.2014