c# - 以编程方式更改 Windows 中的打印机首选项

标签 c# python vb.net command-line printing

我编写了一个为新用户安装多台打印机的脚本。

我想更改其中一些设置,以便它们可以在页面的双面打印。

我相信这涉及使用 printui 修改属性,但它可能需要 VB 脚本或可能需要另一种 .NET 语言(我会使用 VB、C# 或 IronPython)。

我可以向给定打印机添加注释,但如何选择首选项并修改它们?

伪代码如下所示:

printui.exe/n 打印机名称/??? [如何更改所需的质量]

或调用相关的 Windows API。

最佳答案

您可能可以使用 printui 来执行此操作,将打印机设置为双面打印,然后使用 printui/Ss 将设置放入文件中。浏览各种选项,即 2、7、d...,然后查看哪个文件保存双工设置。

另一种方法是使用打印机 api,并使用 PRINTER_INFO_8(全局)或 PRINTER_INFO_9(用户)结构 - MSDN link 。然后使用DEVMODE结构体将dmDuplex设置为双面。

首先打开打印机,完成后将其关闭:

[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);

使用 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);

实际执行此操作的代码应类似于:

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

关于c# - 以编程方式更改 Windows 中的打印机首选项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10707900/

相关文章:

python - 有可能删除元素的循环

python - python 中的日期时间荒谬错误

c# - C# 中的 XMLSerializer 不包括类的所有属性

c# - 读取二维码最快的方式 客户端与服务器端

python - 无法根据规则 ('float64' 将数组数据从 dtype ('int32' ) 转换为 dtype 'safe' )

vb.net - 读取页面回发动态复选框的 'Checked'属性

.net - WInforms Combobox SelectionChangeCommitted 事件并不总是改变 SelectedValue

python - 如何在 XML 文件中定义应用程序的验证规则

c# - Azure Key Vault : AADSTS700024: . NET Core,Linux 容器。客户端断言不在其有效时间范围内

c# - Dapper 可以用来更新和插入模型吗?