Доступ к настройкам в очереди принтера с помощью API диспетчера очереди печатиC#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Доступ к настройкам в очереди принтера с помощью API диспетчера очереди печати

Сообщение Anonymous »

В настоящее время я пишу программу на C#, которая использует Spooler Api для печати PDF-документов. На самом деле он печатает стабильно, но проблема возникает, когда я хочу сделать это с разными настройками (ориентация, размер бумаги и т. д.). У него есть проблема: по-видимому, программа обходит драйверы принтера и отправляет документы с настройками по умолчанию. Мы используем принтер Konica Minolta 650i. Есть возможность складывания, но я понятия не имею, как к ней получить доступ. Поскольку мы вызываем очередь принтера как имя принтера, я подумал, что использования структуры DEVMODE и отправки ее в функцию SetPrinter будет достаточно. Итак, моя проблема в том, что я не могу понять, как заставить программу применять настройки из различных очередей печати.
Учитывая, что это проект моей работы, я обычно не делаю этого. У меня нет прав администратора. Хотя я однажды протестировал этот процесс, когда ИТ-команда предоставила мне их, но результат был тот же.
Что мне нужно сделать, чтобы получить доступ к настройкам очереди печати? Каковы реквизиты? Ниже приведен код, который я использую.

Код: Выделить всё

public enum PrintDocumentTemplateType
{
A3 = 1,
A4 = 2,
A5 = 3
}

public enum PrintDocumentOrientationType
{
Portrait = 1,
Landscape = 2
}

public class PrintingOptions
{
private readonly Dictionary
 _templates
= new Dictionary()
{
{ PrintDocumentTemplateType.A3, "A3" },
{ PrintDocumentTemplateType.A4, "A4" },
{ PrintDocumentTemplateType.A5, "A5" },
};

public bool IsUserAdmin { get { return GetIsUserAdmin(); } }
/// 
/// Set to true if you want to use the printer's queue/driver
/// 
public bool AllowAdvancedSettings { get; set; } = true;
/// 
/// Set to true if you want ot change the settings of a printer with the properties here.
/// 
public bool ModifyPrinterSettings { get; set; } = false;
public PrintDocumentOrientationType Orientation { get; set; } = PrintDocumentOrientationType.Portrait;
public PrintDocumentTemplateType TemplateType { get; set; } = PrintDocumentTemplateType.A3;
public string TemplateTypeStr { get { return _templates[this.TemplateType]; } }
public bool FoldDocument { get; set;  } = false;
private bool GetIsUserAdmin()
{
using (WindowsIdentity identity = WindowsIdentity.GetCurrent())
{
WindowsPrincipal principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
}
}

// Printer Invoke declarations
[DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool OpenPrinter(string printerName, out IntPtr hPrinter, IntPtr pDefault);
[DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool OpenPrinter(string printerName, out IntPtr hPrinter, ref PRINTER_DEFAULTS pDefaults);
[DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool SetPrinter(IntPtr hPrinter, int Level, IntPtr pPrinterInfo, int Command);

[DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool ClosePrinter(IntPtr hPrinter);

[DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool StartDocPrinter(IntPtr hPrinter, int level, [In] ref DOCINFO pDocInfo);

[DllImport("winspool.drv", SetLastError = true)]
private static extern bool EndDocPrinter(IntPtr hPrinter);

[DllImport("winspool.drv", SetLastError = true)]
private static extern bool StartPagePrinter(IntPtr hPrinter);

[DllImport("winspool.drv", SetLastError = true)]
private static extern bool EndPagePrinter(IntPtr hPrinter);

[DllImport("winspool.drv", SetLastError = true)]
private static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, int dwCount, out int dwWritten);

[DllImport("winspool.drv", SetLastError = true)]
private static extern int DocumentProperties(IntPtr hWnd, IntPtr hPrinter, string pDeviceName, IntPtr pDevModeOutput, IntPtr pDevModeInput, int fMode);

[DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool GetPrinter(IntPtr hPrinter, uint Level, IntPtr pPrinter, uint cbBuf, out uint pcbNeeded);
[DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool GetDefaultPrinter(StringBuilder pszBuffer, ref int pcchBuffer);
[DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Auto)]
static extern int SetPrinterData(IntPtr hPrinter, string pValueName, uint Type, IntPtr pData,  uint cbData);

private const int PRINTER_CONTROL_SET = 2;

private const int DM_IN_BUFFER = 1;
private const int DM_OUT_BUFFER = 2;

// field selection in bits
private const int DM_ORIENTATION = 0x00000001;
private const int DM_PAPERSIZE = 0x00000002;
private const int DM_PAPERLENGTH = 0x00000004;
private const int DM_PAPERWIDTH = 0x00000008;
private const int DM_SCALE = 0x00000010;
private const int DM_POSITION = 0x00000020;
private const int DM_NUP = 0x00000040;
private const int DM_DISPLAYORIENTATION = 0x00000080;
private const int DM_COPIES = 0x00000100;
private const int DM_DEFAULTSOURCE = 0x00000200;
private const int DM_PRINTQUALITY = 0x00000400;
private const int DM_COLOR = 0x00000800;
private const int DM_DUPLEX = 0x00001000;
private const int DM_YRESOLUTION = 0x00002000;
private const int DM_TTOPTION = 0x00004000;
private const int DM_COLLATE = 0x00008000;
private const int DM_FORMNAME = 0x00010000;
private const int DM_LOGPIXELS = 0x00020000;
private const int DM_BITSPERPEL = 0x00040000;
private const int DM_PELSWIDTH = 0x00080000;
private const int DM_PELSHEIGHT = 0x00100000;
private const int DM_DISPLAYFLAGS = 0x00200000;
private const int DM_DISPLAYFREQUENCY = 0x00400000;
private const int DM_ICMMETHOD = 0x00800000;
private const int DM_ICMINTENT = 0x01000000;
private const int DM_MEDIATYPE = 0x02000000;
private const int DM_DITHERTYPE = 0x04000000;
private const int DM_PANNINGWIDTH = 0x08000000;
private const int DM_PANNINGHEIGHT = 0x10000000;
private const int DM_DISPLAYFIXEDOUTPUT = 0x20000000;

// values for DM_PAPERSIZE
private const short DMPAPER_A3 = 8;
private const short DMPAPER_A4 = 9;
private const short DMPAPER_A5 = 11;

// values for DM_ORIENTATION
private const short DMORIENT_PORTRAIT = 1;
private const short DMORIENT_LANDSCAPE = 2;

//const for security access
private const int PRINTER_ACCESS_ADMINISTER = 0x4;
private const int PRINTER_ACCESS_USE = 0x8;
private const int STANDARD_RIGHTS_REQUIRED = 0xF0000;
private const int PRINTER_COMPLETE_ACCESS = (PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE | STANDARD_RIGHTS_REQUIRED);

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct DOCINFO
{
[MarshalAs(UnmanagedType.LPTStr)]
public string pDocName;
[MarshalAs(UnmanagedType.LPTStr)]
public string pOutputFile;
[MarshalAs(UnmanagedType.LPTStr)]
public string pDataType;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct PRINTER_DEFAULTS
{
public IntPtr pDatatype;
public IntPtr pDevMode;
public int DesiredAccess;
}

[StructLayout(LayoutKind.Sequential)]
public struct DEVMODE
{
private const int CCDEVICENAME = 32;
private const int CCFORMNAME = 32;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCDEVICENAME)]
public string dmDeviceName;
public short dmSpecVersion;
public short dmDriverVersion;
public short dmSize;
public short dmDriverExtra;
public int dmFields;
public short dmOrientation;
public short dmPaperSize;
public short dmPaperLength;
public short dmPaperWidth;
public short dmScale;
public short dmCopies;
public short dmDefaultSource;
public short dmPrintQuality;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCFORMNAME)]
public string dmFormName;
public short dmUnusedPadding;
public short dmBitsPerPel;
public int dmPelsWidth;
public int dmPelsHeight;
public int dmDisplayFlags;
public int dmDisplayFrequency;
}

[StructLayout(LayoutKind.Sequential,  CharSet = CharSet.Auto)]
public struct PRINTER_INFO_2
{
[MarshalAs(UnmanagedType.LPTStr)]
public string pServerName;
[MarshalAs(UnmanagedType.LPTStr)]
public string pPrinterName;
[MarshalAs(UnmanagedType.LPTStr)]
public string pShareName;
[MarshalAs(UnmanagedType.LPTStr)]
public string pPortName;
[MarshalAs(UnmanagedType.LPTStr)]
public string pDriverName;
[MarshalAs(UnmanagedType.LPTStr)]
public string pComment;
[MarshalAs(UnmanagedType.LPTStr)]
public string pLocation;
public IntPtr pDevMode;
[MarshalAs(UnmanagedType.LPTStr)]
public string pSepFile;
[MarshalAs(UnmanagedType.LPTStr)]
public string pPrintProcessor;
[MarshalAs(UnmanagedType.LPTStr)]
public string pDatatype;
[MarshalAs(UnmanagedType.LPTStr)]
public string pParameters;
public IntPtr pSecurityDescriptor;
public int Attributes;
public int Priority;
public int DefaultPriority;
public int StartTime;
public int UntilTime;
public int Status;
public int cJobs;
public int AveragePPM;
}

private static bool PrintFileWithWin32Api(string printerName, string filePath, PrintingOptions printingOptions)
{
uint pcbNeeded;

IntPtr pDevmode = IntPtr.Zero;
IntPtr pPrinter = IntPtr.Zero;

var pDefaults = new PRINTER_DEFAULTS()
{
//DesiredAccess = PRINTER_ACCESS_USE,
DesiredAccess = printingOptions.IsUserAdmin ? PRINTER_COMPLETE_ACCESS : PRINTER_ACCESS_USE,
pDatatype = IntPtr.Zero,
pDevMode = IntPtr.Zero
};

if (!OpenPrinter(printerName, out IntPtr hPrinter, ref pDefaults))
{
Console.WriteLine("Failed to open printer. Last win32 error: {0}", Marshal.GetLastWin32Error());
return false;
}

if (printingOptions.AllowAdvancedSettings)
{
// first call to DocumentProperties for setting up the size needed
int sizeNeeded = DocumentProperties(IntPtr.Zero, hPrinter, printerName, IntPtr.Zero, IntPtr.Zero, 0);
if (sizeNeeded  0)
{
IntPtr extraDataPointer = IntPtr.Add(pDevmode, devmode.dmSize);

byte[] extraData = new byte[devmode.dmDriverExtra];
Marshal.Copy(extraDataPointer, extraData, 0, devmode.dmDriverExtra);
}

#region Modifying DEVMODE
if (printingOptions.ModifyPrinterSettings)
{
// set bitflags
devmode.dmFields |= DM_PAPERSIZE | DM_ORIENTATION;

// set paper size
switch (printingOptions.TemplateType)
{
case PrintDocumentTemplateType.A3:
devmode.dmPaperSize = DMPAPER_A3;
break;
case PrintDocumentTemplateType.A4:
devmode.dmPaperSize = DMPAPER_A4;
break;
case PrintDocumentTemplateType.A5:
devmode.dmPaperSize = DMPAPER_A5;
break;
}

// set orientation
switch (printingOptions.Orientation)
{
case PrintDocumentOrientationType.Portrait:
devmode.dmOrientation = DMORIENT_PORTRAIT;
break;
case PrintDocumentOrientationType.Landscape:
devmode.dmOrientation = DMORIENT_LANDSCAPE;
break;
}

if (printingOptions.FoldDocument)
{
// TODO
}

// third call to modify the current devmode
if (DocumentProperties(IntPtr.Zero, hPrinter, printerName, pDevmode, pDevmode, DM_OUT_BUFFER | DM_IN_BUFFER)  0)
{
IntPtr unmanagedBytes = Marshal.AllocHGlobal(bytesRead);
Marshal.Copy(buffer, 0, unmanagedBytes, bytesRead);

if (!WritePrinter(hPrinter, unmanagedBytes, bytesRead, out int bytesWritten))
{
Console.WriteLine("Error writing to printer.");
return false;
}

Marshal.FreeHGlobal(unmanagedBytes);
}
}
}
catch (Exception ex)
{
Console.WriteLine("Error reading the file: " + ex.Message);
return false;
}

Marshal.FreeHGlobal(pDevmode);
Marshal.FreeHGlobal(pPrinter);
EndPagePrinter(hPrinter);
EndDocPrinter(hPrinter);
ClosePrinter(hPrinter);

Console.WriteLine("File sent to printer successfully.");
return true;
}

public static void PrintFile()
{
string filePath = "pdfPath.pdf";
string printerName = "specificPrinterQueue";

var printerOptions = new PrintingOptions()
{
// setting which accesses the DEVMODE struct and sends it to Setprinter
AllowAdvancedSettings = true
};

bool successfulPrint = PrintFileWithWin32Api(filePath, printerName, printerOptions);
}
Я пробовал использовать Spire.PDF. Он применяет такие настройки, как ориентация и размер, но я не знаю, смогу ли я использовать его для более сложных настроек.


Подробнее здесь: https://stackoverflow.com/questions/793 ... pooler-api
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»