简体   繁体   English

在Windows中以编程方式更改打印机首选项

[英]Changing printer preferences in Windows programmatically

I've written a script that installs several printers for a new user. 我编写了一个脚本,可以为一个新用户安装多台打印机。

I want to change the settings on some of these so that they can print on both sides of the page. 我想更改其中一些设置,以便它们可以在页面的两面打印。

I BELIEVE this involves modifying an attribute with printui, however it might need VB script or possibly another .NET language (I'd either use VB, C# or IronPython). 我相信这涉及使用printui修改属性,但是它可能需要VB脚本或另一种.NET语言(我将使用VB,C#或IronPython)。

I can add a comment to a given printer, but how do I select preferences and modify them? 我可以在给定的打印机上添加注释,但是如何选择首选项并进行修改?

Pseudocode would look like this: 伪代码如下所示:

printui.exe /n printername /??? printui.exe / n打印机名称/ ??? [how to change quality desired] [如何更改所需的质量]

OR calls to the relevant Windows API. 或调用相关的Windows API。

You could probably do this using printui, set a printer to duplex then use printui /Ss to drop the settings into a file. 您可能可以使用printui进行此操作,将打印机设置为双面打印机,然后使用printui / Ss将设置放入文件中。 Go through the various options, ie 2, 7, d... and see which file holds the duplex setting. 遍历各个选项,即2、7,d ...,然后查看哪个文件具有双工设置。

The other way is to use the printer api, and use either PRINTER_INFO_8 (global) or PRINTER_INFO_9 (user) structure - MSDN link . 另一种方法是使用打印机api,并使用PRINTER_INFO_8(全局)或PRINTER_INFO_9(用户)结构-MSDN链接 Then use the DEVMODE structure to set the dmDuplex to double sided. 然后,使用DEVMODE结构将dmDuplex设置为双面。

First open the printer, and then close it when you're finished: 首先打开打印机,然后在完成后将其关闭:

[DllImport("winspool.drv", EntryPoint = "OpenPrinter", SetLastError = true)]
    internal static extern bool OpenPrinter(string pPrinterName, ref IntPtr phPrinter, PRINTER_DEFAULTS pDefault);
[DllImport("winspool.drv", EntryPoint = "ClosePrinter", SetLastError = true)]
    internal static extern int ClosePrinter(IntPtr hPrinter);

Use GetPrinter to retrieve the current printer settings, and SetPrinter to put back the modified settings: 使用GetPrinter检索当前的打印机设置,并使用SetPrinter放回修改后的设置:

[DllImport("winspool.drv", CharSet = CharSet.Auto, EntryPoint = "GetPrinter", SetLastError = true)]
        internal static extern bool GetPrinter(IntPtr hPrinter, uint Level, IntPtr pPrinter, uint cbBuf, out uint pcbNeeded);
[DllImport("winspool.drv", CharSet = CharSet.Auto, EntryPoint = "SetPrinter", SetLastError = true)]
    internal static extern bool SetPrinter(IntPtr hPrinter, uint Level, IntPtr pPrinter, uint Command);

The code to actually do this should look something like: 实际执行此操作的代码应类似于:

var oldPrinter = printerFunctions.OpenPrinterHandle(String.Format(@"{0}\{1}", oldServerName, oldPrinterName));
var printerInfo8 = printerFunctions.GetPrinterInfo<PRINTER_INFO_8>(oldPrinter, 8);

// Change the dmDuplex value here.

printerFunctions.SetPrinter(oldPrinter, printerInfo8, 8);
printerFunctions.ClosePrinterHandle(oldPrinter);

public IntPtr OpenPrinterHandle(string printerName)
{
    var def = new PRINTER_DEFAULTS { pDatatype = null, pDevMode = IntPtr.Zero, DesiredAccess = OpenPrinterAccessCodes.PRINTER_ALL_ACCESS };
    var hPrinter = IntPtr.Zero;
    if (!PrinterNativeMethods.OpenPrinter(printerName, ref hPrinter, def))
    {
        var lastWin32Error = new Win32Exception(Marshal.GetLastWin32Error());
        Logger.Log("Failed open Printer: " + lastWin32Error.Message);
        throw lastWin32Error;
    }
    return hPrinter;
}

public void ClosePrinterHandle(IntPtr hPrinter)
{
    PrinterNativeMethods.ClosePrinter(hPrinter);
}

public void SetPrinter<T>(IntPtr hPrinter, T printerInfo, uint level)
{
    var size = (uint)Marshal.SizeOf(printerInfo);
    var printerInfoPtr = Marshal.AllocHGlobal((int)size);
    Marshal.StructureToPtr(printerInfo, printerInfoPtr, true);
    var result = PrinterNativeMethods.SetPrinter(hPrinter, level, printerInfoPtr, 0);
    if (!result)
    {
        var win32Error = Marshal.GetLastWin32Error();
        var lastWin32Error = new Win32Exception(win32Error);
        Logger.Log("Failed set printer: " + lastWin32Error.Message);
        throw lastWin32Error;
    }
    Marshal.FreeHGlobal(printerInfoPtr);
}

public T GetPrinterInfo<T>(IntPtr hPrinter, uint level)
{
    uint pcbNeeded;
    var bFlag = PrinterNativeMethods.GetPrinter(hPrinter, level, IntPtr.Zero, 0, out pcbNeeded);
    var win32Error = Marshal.GetLastWin32Error();
    if ((!bFlag) && (win32Error != PrinterNativeMethods.ERROR_INSUFFICIENT_BUFFER) || (pcbNeeded == 0))
    {
        var lastWin32Error = new Win32Exception(win32Error);
        Logger.Log("Failed get printer: " + lastWin32Error.Message);
        throw lastWin32Error;
    }

    var currentPrinterInfoPtr = Marshal.AllocHGlobal((int)pcbNeeded);
    bFlag = PrinterNativeMethods.GetPrinter(hPrinter, level, currentPrinterInfoPtr, pcbNeeded, out pcbNeeded);
    if (!bFlag)
    {
        var lastWin32Error = new Win32Exception();
        Logger.Log("Failed get printer: " + lastWin32Error.Message);
        throw lastWin32Error;
    }
    return (T)Marshal.PtrToStructure(currentPrinterInfoPtr, typeof(T));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM