| param([switch]$Debug) |
| |
| |
| |
| $c=@' |
| using System; |
| using System.Runtime.InteropServices; |
| using System.ComponentModel; |
| using Microsoft.Win32; |
| |
| public class PrinterSettings |
| { |
| [DllImport("kernel32.dll", EntryPoint = "GetLastError", SetLastError = false, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] |
| private static extern Int32 GetLastError(); |
| |
| [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] |
| private static extern bool ClosePrinter(IntPtr hPrinter); |
| |
| [DllImport("winspool.Drv", EntryPoint="DocumentPropertiesA", SetLastError=true, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)] |
| private static extern int DocumentProperties(IntPtr hwnd, IntPtr hPrinter, [MarshalAs(UnmanagedType.LPStr)] string pDeviceName, IntPtr pDevModeOutput, ref IntPtr pDevModeInput, int fMode); |
| |
| [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] |
| private static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr PrinterDefaults); |
| |
| [DllImport("winspool.drv", CharSet = CharSet.Ansi, SetLastError = true)] |
| private static extern bool SetPrinter(IntPtr hPrinter, int Level, IntPtr pPrinter, int Command); |
| |
| [StructLayout(LayoutKind.Sequential)] |
| public struct PRINTER_INFO_9 |
| { |
| public IntPtr pDevMode; |
| } |
| |
| private const short CCDEVICENAME = 32; |
| private const short CCFORMNAME = 32; |
| [StructLayout(LayoutKind.Sequential)] |
| public struct DEVMODE |
| { |
| [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; |
| } |
| private const int PRINTER_ACCESS_USE = 0x8; |
| private const int DM_OUT_BUFFER = 0x2; |
| private const int DM_MODIFY = 0x8; |
| private const int DM_PAPERSIZE = 0x2; |
| private const int DM_PAPERLENGTH = 0x4; |
| private const int DM_PAPERWIDTH = 0x8; |
| |
| public static bool ChangePaperSize(string sPrinterName, short nSize, short nWidth, short nHeight, out string sDebug) |
| { |
| DEVMODE oDM; |
| IntPtr pNativeDM = IntPtr.Zero; |
| int nBytesNeeded = 0; |
| IntPtr hPrinter = new System.IntPtr(); |
| PRINTER_INFO_9 oPrinterInfo; |
| IntPtr pNativePrinterInfo = IntPtr.Zero; |
| IntPtr pDummy=IntPtr.Zero; |
| bool bChanged=false; |
| |
| sDebug=""; |
| |
| //Console.WriteLine("Open printer"); |
| if (!OpenPrinter(sPrinterName, out hPrinter, IntPtr.Zero)) |
| { |
| Console.WriteLine("OpenPrinter() failed with error "+Marshal.GetLastWin32Error()+", aborting."); |
| sDebug += "OpenPrinter() failed with error "+Marshal.GetLastWin32Error()+", aborting.\n"; |
| return false; |
| } |
| |
| //Console.WriteLine("Getting bytes needed for DEVMODE via DocumentProperties"); |
| nBytesNeeded=DocumentProperties(IntPtr.Zero,hPrinter,sPrinterName,IntPtr.Zero,ref pDummy,0); |
| //Console.WriteLine("Bytes needed: "+nBytesNeeded+", allocating."); |
| pNativeDM=Marshal.AllocHGlobal(nBytesNeeded); |
| //Console.WriteLine("Fetching DEVMODE via DocumentProperties"); |
| DocumentProperties(IntPtr.Zero,hPrinter,sPrinterName,pNativeDM,ref pDummy,DM_OUT_BUFFER); |
| oDM = (DEVMODE)Marshal.PtrToStructure(pNativeDM, typeof(DEVMODE)); |
| //Console.WriteLine("Free native DM"); |
| Marshal.FreeHGlobal(pNativeDM); |
| |
| //Console.WriteLine("Old size: "+oDM.dmPaperSize); |
| if (oDM.dmPaperSize != nSize) |
| { |
| Console.WriteLine("dmPaperSize="+oDM.dmPaperSize+" => "+nSize); |
| sDebug += "dmPaperSize="+oDM.dmPaperSize+" => "+nSize + "\n"; |
| oDM.dmPaperSize = nSize; |
| oDM.dmFields |= DM_PAPERSIZE; |
| bChanged=true; |
| } |
| |
| if (nWidth != 0 && oDM.dmPaperWidth != nWidth) |
| { |
| Console.WriteLine("dmPaperWidth="+oDM.dmPaperWidth+" => " +nWidth); |
| sDebug += "dmPaperWidth="+oDM.dmPaperWidth+" => " +nWidth + "\n"; |
| oDM.dmPaperWidth=nWidth; |
| oDM.dmFields |= DM_PAPERWIDTH; |
| bChanged=true; |
| } |
| if (nHeight != 0 && oDM.dmPaperLength != nHeight) |
| { |
| Console.WriteLine("dmPaperLength="+oDM.dmPaperLength+" => " +nHeight); |
| sDebug += "dmPaperLength="+oDM.dmPaperLength+" => " +nHeight + "\n"; |
| oDM.dmPaperLength=nHeight; |
| oDM.dmFields |= DM_PAPERLENGTH; |
| bChanged=true; |
| } |
| |
| if (bChanged) |
| { |
| //Console.WriteLine("Allocating memory for new native DEVMODE"); |
| pNativeDM = Marshal.AllocHGlobal(Marshal.SizeOf(oDM)); |
| //Console.WriteLine("Copy managed DEVMODE to native memory"); |
| Marshal.StructureToPtr(oDM, pNativeDM, true); |
| |
| //Console.WriteLine("Modifying DEVMODE with DocumentProperties"); |
| DocumentProperties(IntPtr.Zero,hPrinter,sPrinterName,pNativeDM,ref pDummy,DM_MODIFY); |
| |
| oPrinterInfo.pDevMode = pNativeDM; |
| //Console.WriteLine("Copy managed PRINTER_INFO_9 to native memory"); |
| pNativePrinterInfo = Marshal.AllocHGlobal(Marshal.SizeOf(oPrinterInfo)); |
| Marshal.StructureToPtr(oPrinterInfo, pNativePrinterInfo, true); |
| //Console.WriteLine("Writing new PRINTER_INFO_9 to printer"); |
| if (!SetPrinter(hPrinter, 9, pNativePrinterInfo, 0)) |
| { |
| Console.WriteLine("SetPrinter() failed with error "+Marshal.GetLastWin32Error()+", aborting."); |
| sDebug += "SetPrinter() failed with error "+Marshal.GetLastWin32Error()+", aborting.\n"; |
| Cleanup(pNativeDM, pNativePrinterInfo, hPrinter); |
| return false; |
| } |
| Cleanup(pNativeDM, pNativePrinterInfo, hPrinter); |
| } |
| else |
| { |
| Console.WriteLine("Nothing to do, exiting."); |
| sDebug += "Nothing to do, exiting.\n"; |
| } |
| return true; |
| } |
| |
| public static void Cleanup(IntPtr pNativeDM,IntPtr pNativePrinterInfo,IntPtr hPrinter) |
| { |
| try |
| { |
| //Console.WriteLine("Memory and handle cleanup"); |
| if (hPrinter != IntPtr.Zero) ClosePrinter(hPrinter); |
| if (pNativeDM != IntPtr.Zero) Marshal.FreeHGlobal(pNativeDM); |
| if (pNativePrinterInfo != IntPtr.Zero) Marshal.FreeHGlobal(pNativePrinterInfo); |
| } |
| catch (Exception) |
| { |
| } |
| } |
| } |
| '@ |
| |
| if ($Debug) |
| { |
| Start-Transcript "$($env:Temp)\PaperSize.log" |
| } |
| |
| Add-Type -TypeDefinition $c -ReferencedAssemblies System.Runtime.InteropServices,System.ComponentModel |
| Add-Type -AssemblyName System.Drawing |
| |
| $printers="\\printserver\printer1~495~360#\\printserver\printer2~USER~495~360" |
| |
| foreach ($printerinfo in $printers.Split(' |
| { |
| Write-Host "=====================================================" |
| $printer=$printerinfo.Split('~')[0] |
| $paper=$printerinfo.Split('~')[1] |
| $width=$printerinfo.Split('~')[2] |
| $height=$printerinfo.Split('~')[3] |
| |
| $ps=New-Object System.Drawing.Printing.PrinterSettings |
| $ps.PrinterName=$printer |
| $size=$ps.PaperSizes|? PaperName -eq $paper |
| |
| if ($null -ne $size) |
| { |
| Write-Host "$($printer): size (raw): $($size.RawKind)" |
| |
| $messages="" |
| $success=[PrinterSettings]::ChangePaperSize($printer,$size.RawKind,$width,$height,[ref]$messages) |
| if ($Debug) { $messages } |
| if ($success) |
| { |
| Write-Host " ==> SUCCESS" |
| } |
| else |
| { |
| Write-Host " ==> ERROR" |
| } |
| } |
| else |
| { |
| Write-Host "$($printer): PaperSize $($paper) not found." |
| } |
| } |
| |
| if ($Debug) |
| { |
| Stop-Transcript |
| } |
| |