Cambiar las preferencias de la impresora en Windows mediante programación

He escrito un script que instala varias impresoras para un nuevo usuario.

Quiero cambiar la configuración de algunos de estos para que puedan imprimirse en ambos lados de la página.

CREO que esto implica modificar un atributo con printui, sin embargo, podría necesitar una secuencia de comandos VB o posiblemente otro lenguaje .NET (yo usaría VB, C # o IronPython).

Puedo agregar un comentario a una impresora determinada, pero ¿cómo selecciono las preferencias y las modifico?

El pseudocódigo se vería así:

printui.exe /n nombre de impresora /??? [cómo cambiar la calidad deseada]

O llamadas a la API de Windows correspondiente.

preguntado el 22 de mayo de 12 a las 19:05

1 Respuestas

Probablemente podría hacer esto usando printui, configurar una impresora en dúplex y luego usar printui /Ss para colocar la configuración en un archivo. Revise las distintas opciones, es decir, 2, 7, d... y vea qué archivo contiene la configuración dúplex.

La otra forma es usar la API de la impresora y usar la estructura PRINTER_INFO_8 (global) o PRINTER_INFO_9 (usuario) - Enlace de MSDN. Luego use la estructura DEVMODE para configurar el dmDuplex a doble cara.

Primero abra la impresora y luego ciérrela cuando haya terminado:

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

Utilice GetPrinter para recuperar la configuración actual de la impresora y SetPrinter para recuperar la configuración modificada:

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

El código para hacer esto realmente debería ser algo como:

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

Respondido el 18 de diciembre de 12 a las 23:12

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.