Как настроить виртуальный принтер и монитор с драйвером UniDrv или XPS v3 в Windows

Я пытаюсь создать виртуальный принтер для захвата распечаток из приложений в моем собственном приложении.

Я успешно реализовал тот, который использует драйвер Microsoft PostScript и создает файлы ps. (много кода взято из разных проектов с открытым исходным кодом)

Однако из-за проблем с лицензированием GhostScript на производственных серверах (это НЕ бесплатно для бизнес-решений) я хочу реализовать другой драйвер, который создает файлы XPS или любой другой формат, который я могу использовать для извлечения текста, преобразования в PDF, извлекать изображения каждой страницы и т. д.

Код, который я использую с драйвером PostScript и который действительно работает довольно хорошо, выглядит следующим образом:

// Declare the AddPrinterDriver as extern.
[DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool AddPrinterDriver(String pName, UInt32 Level, ref DRIVER_INFO_3 pDriverInfo);

// Create a function to call it.
public void AddPrinterDriver(string driverName, string driverPath, string dataPath, string configPath, string helpPath)
{
    DRIVER_INFO_3 di = new DRIVER_INFO_3();
    di.cVersion = 3;
    di.pName = driverName;
    di.pEnvironment = null;
    di.pDriverPath = driverPath;
    di.pDataFile = dataPath;
    di.pConfigFile = configPath;
    di.pHelpFile = helpPath;
    di.pDependentFiles = "";
    di.pMonitorName = null;
    di.pDefaultDataType = "RAW";

    if (!AddPrinterDriver(null, 3, ref di))
    {
         Exception exc = new Win32Exception(Marshal.GetLastWin32Error());
         throw exc;
    }
}

Метод установки принтера (без надлежащей проверки и ведения журнала):

public void InstallVirtualPrinter()
{
    // Declare file names for PostScript printer driver. (Preinstalled in Vista and Up)
    string driverFileName = "PSCRIPT5.DLL";
    string configFileName = "PS5UI.DLL";
    string helpFileName = "PSCRIPT.HLP";
    string dataFileName = "MyCustomConfig.PPD";

    string driverPath = null;
    string dataPath = null;
    string configPath = null;
    string helpPath = null;

    try
    {
        //Set Printer Driver Path and Files.
        string printerDriverPath = Path.Combine(GetPrinterDirectory(), "3");

        // Set the path for the driver files.
        if (!String.IsNullOrWhiteSpace(printerDriverPath))
        {
            driverPath = string.Format("{0}\\{1}", printerDriverPath, driverFileName);
            dataPath = string.Format("{0}\\{1}", printerDriverPath, dataFileName);
            configPath = string.Format("{0}\\{1}", printerDriverPath, configFileName);
            helpPath = string.Format("{0}\\{1}", printerDriverPath, helpFileName);
        }

        // Add Printer Monitor
        if (!DoesMonitorExist(PrinterMonitorName))
        {
            AddPrinterMonitor(PrinterMonitorName); 
        }

        // Add Printer Port
        if (!DoesPrinterPortExist(PrinterPortName))
        {
            AddPrinterPort(PrinterPortName, PrinterMonitorName);
        }

        // Add Printer Driver
        if (!DoesPrinterDriverExist(PrinterDriverName))
        {
            //
            //
            //
            //
            // This references the above method in this SO question.

            AddPrinterDriver(PrinterDriverName, driverPath, dataPath, configPath, helpPath);
            //
            // This fails when trying with a driver different than PScript.
            //
        }

        // Add Printer
        if (!DoesPrinterExist(PrinterName))
        {
            InstallPrinter(PrinterName, PrinterPortName, PrinterDriverName);
        }

        // Configure Virtual Port
        ConfigureVirtualPort(PrinterMonitorName, PrinterPortName);

        // Restart Spool Service
        RestartSpoolService();

        log.Info("Virtual printer installation completed successfully");
        return;
    }
    catch (Exception exc)
    {
        log.ErrorFormat("An exception has been raise when attempting to install the printer \n{0}", exc);
    }
}

Итак, вот вопрос:

Как использовать другой драйвер, например UniDrv или XPS, для реализации виртуального принтера/монитора?.

Я попытался использовать UniDrv, заменив следующие строки в приведенном выше коде:

string driverFileName = "unidrv.dll";
string dataFileName = "sample.GPD";
string configFileName = "unidrvui.dll";
string helpFileName = "unidrv.hlp";

Когда я запускаю метод AddPrinterDriver, я получаю исключение, указывающее "The system cannot find the file specified".

Не сказано, какой файл отсутствует. Я предполагаю, что могут отсутствовать некоторые зависимости, или файл sample.GPD, который я нашел, не годится.

Любая помощь будет оценена.


person agarcian    schedule 01.09.2015    source источник
comment
Я не думаю, что драйвер можно написать на C#. Вы использовали С++? И как так можно отображать виртуальный принтер среди других принтеров. Это делается первой функцией AddPrinterDriver?   -  person Shameel Mohamed    schedule 03.04.2017
comment
Он написан на C и доступен из C#. В конце концов я остановился на другом драйвере, поскольку этот не был действительно правильной реализацией.   -  person agarcian    schedule 04.04.2017
comment
О, пожалуйста, опишите больше. Я тоже работаю с похожей ситуацией. Мне нужно выбрать между unidrv, postscript и xpsdrv. Полагаю, я бы не выбрал Postscript, так как он казался очень старым. И я хочу написать из него виртуальный принтер, который должен перенаправлять данные печати в мое приложение. Ваши знания действительно помогут.   -  person Shameel Mohamed    schedule 04.04.2017
comment
Кто-нибудь понял, как это сделать?   -  person jNewbie    schedule 30.01.2018


Ответы (1)


Перед выполнением AddPrinterDriver установите все файлы (unidrv.dll, unidrvui.dll, sample.gpd) по пути к драйверу, т. е. по пути spool/drivers/x86Orx64.

person Rajaram Ashok    schedule 19.01.2016