.net 在windows 7上访问打印机设置(DEVMODE)
在windows 7上访问和更改打印机设置时遇到严重问题.net 在windows 7上访问打印机设置(DEVMODE),.net,vb.net,printing,.net,Vb.net,Printing,在windows 7上访问和更改打印机设置时遇到严重问题 Option Strict On Imports System.Runtime.InteropServices Imports System.ComponentModel <StructLayout(LayoutKind.Sequential)> _ Structure PRINTER_DEFAULTS Public pDatatype As IntPtr Public pDevMode As IntPtr
Option Strict On
Imports System.Runtime.InteropServices
Imports System.ComponentModel
<StructLayout(LayoutKind.Sequential)> _
Structure PRINTER_DEFAULTS
Public pDatatype As IntPtr
Public pDevMode As IntPtr
Public DesiredAccess As Integer
End Structure
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
Public Structure PRINTER_INFO_2
<MarshalAs(UnmanagedType.LPTStr)> _
Public pServerName As String
<MarshalAs(UnmanagedType.LPTStr)> _
Public pPrinterName As String
<MarshalAs(UnmanagedType.LPTStr)> _
Public pShareName As String
<MarshalAs(UnmanagedType.LPTStr)> _
Public pPortName As String
<MarshalAs(UnmanagedType.LPTStr)> _
Public pDriverName As String
<MarshalAs(UnmanagedType.LPTStr)> _
Public pComment As String
<MarshalAs(UnmanagedType.LPTStr)> _
Public pLocation As String
Public pDevMode As IntPtr
<MarshalAs(UnmanagedType.LPTStr)> _
Public pSepFile As String
<MarshalAs(UnmanagedType.LPTStr)> _
Public pPrintProcessor As String
<MarshalAs(UnmanagedType.LPTStr)> _
Public pDatatype As String
<MarshalAs(UnmanagedType.LPTStr)> _
Public pParameters As String
Public pSecurityDescriptor As IntPtr
Public Attributes As UInteger
Public Priority As UInteger
Public DefaultPriority As UInteger
Public StartTime As UInteger
Public UntilTime As UInteger
Public Status As UInteger
Public cJobs As UInteger
Public AveragePPM As UInteger
End Structure
Structure POINTL
Public x As Int32
Public y As Int32
End Structure
<Flags()> _
Enum DM As Integer
Orientation = &H1
PaperSize = &H2
PaperLength = &H4
PaperWidth = &H8
Scale = &H10
Position = &H20
NUP = &H40
DisplayOrientation = &H80
Copies = &H100
DefaultSource = &H200
PrintQuality = &H400
Color = &H800
Duplex = &H1000
YResolution = &H2000
TTOption = &H4000
Collate = &H8000
FormName = &H10000
LogPixels = &H20000
BitsPerPixel = &H40000
PelsWidth = &H80000
PelsHeight = &H100000
DisplayFlags = &H200000
DisplayFrequency = &H400000
ICMMethod = &H800000
ICMIntent = &H1000000
MediaType = &H2000000
DitherType = &H4000000
PanningWidth = &H8000000
PanningHeight = &H10000000
DisplayFixedOutput = &H20000000
End Enum
<StructLayout(LayoutKind.Explicit, CharSet:=CharSet.Ansi)> _
Structure DEVMODE
Public Const CCHDEVICENAME As Integer = 32
Public Const CCHFORMNAME As Integer = 32
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=CCHDEVICENAME)> _
<System.Runtime.InteropServices.FieldOffset(0)> _
Public dmDeviceName As String
<System.Runtime.InteropServices.FieldOffset(32)> _
Public dmSpecVersion As Int16
<System.Runtime.InteropServices.FieldOffset(34)> _
Public dmDriverVersion As Int16
<System.Runtime.InteropServices.FieldOffset(36)> _
Public dmSize As Int16
<System.Runtime.InteropServices.FieldOffset(38)> _
Public dmDriverExtra As Int16
<System.Runtime.InteropServices.FieldOffset(40)> _
Public dmFields As DM
<System.Runtime.InteropServices.FieldOffset(44)> _
Private dmOrientation As Int16
<System.Runtime.InteropServices.FieldOffset(46)> _
Private dmPaperSize As Int16
<System.Runtime.InteropServices.FieldOffset(48)> _
Private dmPaperLength As Int16
<System.Runtime.InteropServices.FieldOffset(50)> _
Private dmPaperWidth As Int16
<System.Runtime.InteropServices.FieldOffset(52)> _
Public dmScale As Int16
<System.Runtime.InteropServices.FieldOffset(54)> _
Public dmCopies As Int16
<System.Runtime.InteropServices.FieldOffset(56)> _
Private dmDefaultSource As Int16
<System.Runtime.InteropServices.FieldOffset(58)> _
Private dmPrintQuality As Int16
<System.Runtime.InteropServices.FieldOffset(44)> _
Public dmPosition As POINTL
<System.Runtime.InteropServices.FieldOffset(52)> _
Public dmDisplayOrientation As Int32
<System.Runtime.InteropServices.FieldOffset(56)> _
Public dmDisplayFixedOutput As Int32
<System.Runtime.InteropServices.FieldOffset(60)> _
Public dmColor As Short
<System.Runtime.InteropServices.FieldOffset(62)> _
Public dmDuplex As Short
<System.Runtime.InteropServices.FieldOffset(64)> _
Public dmYResolution As Short
<System.Runtime.InteropServices.FieldOffset(66)> _
Public dmTTOption As Short
<System.Runtime.InteropServices.FieldOffset(68)> _
Public dmCollate As Short
<System.Runtime.InteropServices.FieldOffset(72)> _
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=CCHFORMNAME)> _
Public dmFormName As String
<System.Runtime.InteropServices.FieldOffset(102)> _
Public dmLogPixels As Int16
<System.Runtime.InteropServices.FieldOffset(104)> _
Public dmBitsPerPel As Int32
<System.Runtime.InteropServices.FieldOffset(108)> _
Public dmPelsWidth As Int32
<System.Runtime.InteropServices.FieldOffset(112)> _
Public dmPelsHeight As Int32
<System.Runtime.InteropServices.FieldOffset(116)> _
Public dmDisplayFlags As Int32
<System.Runtime.InteropServices.FieldOffset(116)> _
Public dmNup As Int32
<System.Runtime.InteropServices.FieldOffset(120)> _
Public dmDisplayFrequency As Int32
End Structure
Class PrinterSettings
Private gPrinter As IntPtr = New System.IntPtr()
Private gPrinterValues As New PRINTER_DEFAULTS()
Private gPInfo As New PRINTER_INFO_2()
Private gDevMode As DEVMODE
Private gPtrDevMode As IntPtr
Private gPtrPrinterInfo As IntPtr
Private gSizeOfDevMode As Integer = 0
Private gLastError As Integer
Private gNBytesNeeded As Integer
Private gNRet As Long
Private gIntError As Integer
Private gNTemporary As Integer
Private gDevModeData As IntPtr
<DllImport("winspool.Drv", EntryPoint:="ClosePrinter", SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
Private Shared Function ClosePrinter(ByVal hPrinter As IntPtr) As Boolean
End Function
<DllImport("winspool.Drv", EntryPoint:="DocumentPropertiesA", SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
Private Shared Function DocumentProperties(ByVal hwnd As IntPtr, ByVal hPrinter As IntPtr, <MarshalAs(UnmanagedType.LPStr)> ByVal pDeviceName As String, ByVal pDevModeOutput As IntPtr, ByVal pDevModeInput As IntPtr, ByVal fMode As Integer) As Integer
End Function
<DllImport("winspool.drv", SetLastError:=True, CharSet:=CharSet.Auto)> _
Public Shared Function GetPrinter(ByVal hPrinter As IntPtr, ByVal dwLevel As Int32, ByVal pPrinter As IntPtr, ByVal dwBuf As Int32, ByRef dwNeeded As Int32) As Boolean
End Function
<DllImport("winspool.Drv", EntryPoint:="OpenPrinterA", SetLastError:=True, CharSet:=CharSet.Ansi, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
Private Shared Function OpenPrinter(<MarshalAs(UnmanagedType.LPStr)> ByVal szPrinter As String, ByRef hPrinter As IntPtr, ByRef pd As PRINTER_DEFAULTS) As Boolean
End Function
<DllImport("winspool.drv", CharSet:=CharSet.Ansi, SetLastError:=True)> _
Private Shared Function SetPrinter(ByVal hPrinter As IntPtr, ByVal Level As Integer, ByVal pPrinter As IntPtr, ByVal Command As Integer) As Boolean
End Function
Private Const DM_DUPLEX As Integer = 4096
''0x1000
Private Const DM_IN_BUFFER As Integer = 8
Private Const DM_OUT_BUFFER As Integer = 2
Private Const PRINTER_ACCESS_ADMINISTER As Integer = 4
''0x4
Private Const STANDARD_RIGHTS_REQUIRED As Integer = 983040
''0xF0000
Private Const PRINTER_ALL_ACCESS As Integer = STANDARD_RIGHTS_REQUIRED Or PRINTER_ACCESS_ADMINISTER Or PRINTER_ACCESS_USE
Private Const PRINTER_ACCESS_USE As Integer = 8
''0x8
Public Function SetPrinterSettings(ByVal iPrinterName As String, ByVal dm As DEVMODE, Optional ByVal ShowPreferences As Integer = 0) As Integer
gDevMode = dm
Marshal.StructureToPtr(gDevMode, gDevModeData, True)
gPInfo.pDevMode = gDevModeData
gPInfo.pSecurityDescriptor = IntPtr.Zero
''optionally brings up the printer preferences dialog
If ShowPreferences = 1 Then
Dim retval As Integer
retval = DocumentProperties(IntPtr.Zero, gPrinter, iPrinterName, gDevModeData, gPInfo.pDevMode, DM_IN_BUFFER Or DM_OUT_BUFFER Or PRINTER_ACCESS_ADMINISTER)
If retval = DialogResult.Cancel Then Return -1
End If
''update driver dependent part of the DEVMODE
''HERE CRASHES ******************************
Marshal.StructureToPtr(gPInfo, gPtrPrinterInfo, True)
''
gLastError = Marshal.GetLastWin32Error()
gNRet = Convert.ToInt16(SetPrinter(gPrinter, 2, gPtrPrinterInfo, 0))
If gNRet = 0 Then
''Unable to set extern printer settings.
gLastError = Marshal.GetLastWin32Error()
Throw New Win32Exception(gLastError)
End If
If gPrinter <> IntPtr.Zero Then
ClosePrinter(gPrinter)
End If
Return CInt(gNRet)
End Function
Public Function GetPrinterSettings(ByVal PrinterName As String) As DEVMODE
Dim lDevMode As DEVMODE
gPrinterValues.pDatatype = IntPtr.Zero
gPrinterValues.pDevMode = IntPtr.Zero
gPrinterValues.DesiredAccess = PRINTER_ALL_ACCESS
gNRet = Convert.ToInt32(OpenPrinter(PrinterName, gPrinter, gPrinterValues))
If gNRet = 0 Then
gLastError = Marshal.GetLastWin32Error()
Throw New Win32Exception(gLastError)
End If
GetPrinter(gPrinter, 2, IntPtr.Zero, 0, gNBytesNeeded)
If gNBytesNeeded <= 0 Then
Throw New System.Exception("Unable to allocate memory")
Else
'' Allocate enough space for PRINTER_INFO_2...
gPtrPrinterInfo = Marshal.AllocCoTaskMem(gNBytesNeeded)
gPtrPrinterInfo = Marshal.AllocHGlobal(gNBytesNeeded)
''The second GetPrinter fills in all the current settings, so all you
''need to do is modify what youre interested in...
gNRet = Convert.ToInt32(GetPrinter(gPrinter, 2, gPtrPrinterInfo, gNBytesNeeded, gNTemporary))
If gNRet = 0 Then
gLastError = Marshal.GetLastWin32Error()
Throw New Win32Exception(gLastError)
End If
gPInfo = CType(Marshal.PtrToStructure(gPtrPrinterInfo, GetType(PRINTER_INFO_2)), PRINTER_INFO_2)
Dim lTempBuffer As New IntPtr()
If gPInfo.pDevMode = IntPtr.Zero Then
''if GetPrinter didnt fill in the DEVMODE, try to get it by calling
''DocumentProperties...
Dim ptrZero As IntPtr = IntPtr.Zero
''get the size of the devmode struct
gSizeOfDevMode = DocumentProperties(IntPtr.Zero, gPrinter, PrinterName, ptrZero, ptrZero, 0)
gPtrDevMode = Marshal.AllocCoTaskMem(gSizeOfDevMode)
Dim i As Integer = DocumentProperties(IntPtr.Zero, gPrinter, PrinterName, gPtrDevMode, ptrZero, DM_OUT_BUFFER)
If i < 0 OrElse gPtrDevMode <> IntPtr.Zero Then
''Cannot get the DEVMODE struct.
Throw New System.Exception("Cannot get DEVMODE data")
End If
gPInfo.pDevMode = gPtrDevMode
End If
gIntError = DocumentProperties(IntPtr.Zero, gPrinter, PrinterName, IntPtr.Zero, lTempBuffer, 0)
gDevModeData = Marshal.AllocHGlobal(gIntError)
gIntError = DocumentProperties(IntPtr.Zero, gPrinter, PrinterName, gDevModeData, lTempBuffer, 2)
lDevMode = CType(Marshal.PtrToStructure(gDevModeData, GetType(DEVMODE)), DEVMODE)
If gNRet = 0 OrElse gPrinter = IntPtr.Zero Then
gLastError = Marshal.GetLastWin32Error()
Throw New Win32Exception(gLastError)
End If
Return lDevMode
End If
End Function
End Class
编辑:
调用SetPrinter API时,最后一个错误可能仍然存在
gNRet = Convert.ToInt16(SetPrinter(gPrinter, 2, gPtrPrinterInfo, 0))
这会引发错误:“打印机驱动程序未知”,
但是
工作无误但不可靠
如何消除最后一个错误?以下是一些提示:
- 检查结构和dllimport函数是否定义正确。在pinvoke.net上,您可以找到经过测试的签名(示例DocumentProperties函数)
- 如果您正在运行x64系统,请注意pinvoke.net上的注释。需要在x64系统上更改某些函数/结构
- 您是以管理员还是普通用户的身份运行程序/visual studio?这可能会有所不同
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;
namespace PrintersettingsTest
{
[StructLayout(LayoutKind.Sequential)]
struct PRINTER_DEFAULTS
{
public IntPtr pDatatype;
public IntPtr pDevMode;
public int DesiredAccess;
}
[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 uint Attributes;
public uint Priority;
public uint DefaultPriority;
public uint StartTime;
public uint UntilTime;
public uint Status;
public uint cJobs;
public uint AveragePPM;
}
struct POINTL
{
public Int32 x;
public Int32 y;
}
[Flags()]
enum DM : int
{
Orientation = 0x1,
PaperSize = 0x2,
PaperLength = 0x4,
PaperWidth = 0x8,
Scale = 0x10,
Position = 0x20,
NUP = 0x40,
DisplayOrientation = 0x80,
Copies = 0x100,
DefaultSource = 0x200,
PrintQuality = 0x400,
Color = 0x800,
Duplex = 0x1000,
YResolution = 0x2000,
TTOption = 0x4000,
Collate = 0x8000,
FormName = 0x10000,
LogPixels = 0x20000,
BitsPerPixel = 0x40000,
PelsWidth = 0x80000,
PelsHeight = 0x100000,
DisplayFlags = 0x200000,
DisplayFrequency = 0x400000,
ICMMethod = 0x800000,
ICMIntent = 0x1000000,
MediaType = 0x2000000,
DitherType = 0x4000000,
PanningWidth = 0x8000000,
PanningHeight = 0x10000000,
DisplayFixedOutput = 0x20000000
}
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
struct DEVMODE
{
public const int CCHDEVICENAME = 32;
public const int CCHFORMNAME = 32;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
[System.Runtime.InteropServices.FieldOffset(0)]
public string dmDeviceName;
[System.Runtime.InteropServices.FieldOffset(32)]
public Int16 dmSpecVersion;
[System.Runtime.InteropServices.FieldOffset(34)]
public Int16 dmDriverVersion;
[System.Runtime.InteropServices.FieldOffset(36)]
public Int16 dmSize;
[System.Runtime.InteropServices.FieldOffset(38)]
public Int16 dmDriverExtra;
[System.Runtime.InteropServices.FieldOffset(40)]
public DM dmFields;
[System.Runtime.InteropServices.FieldOffset(44)]
Int16 dmOrientation;
[System.Runtime.InteropServices.FieldOffset(46)]
Int16 dmPaperSize;
[System.Runtime.InteropServices.FieldOffset(48)]
Int16 dmPaperLength;
[System.Runtime.InteropServices.FieldOffset(50)]
Int16 dmPaperWidth;
[System.Runtime.InteropServices.FieldOffset(52)]
Int16 dmScale;
[System.Runtime.InteropServices.FieldOffset(54)]
Int16 dmCopies;
[System.Runtime.InteropServices.FieldOffset(56)]
Int16 dmDefaultSource;
[System.Runtime.InteropServices.FieldOffset(58)]
Int16 dmPrintQuality;
[System.Runtime.InteropServices.FieldOffset(44)]
public POINTL dmPosition;
[System.Runtime.InteropServices.FieldOffset(52)]
public Int32 dmDisplayOrientation;
[System.Runtime.InteropServices.FieldOffset(56)]
public Int32 dmDisplayFixedOutput;
[System.Runtime.InteropServices.FieldOffset(60)]
public short dmColor;
[System.Runtime.InteropServices.FieldOffset(62)]
public short dmDuplex;
[System.Runtime.InteropServices.FieldOffset(64)]
public short dmYResolution;
[System.Runtime.InteropServices.FieldOffset(66)]
public short dmTTOption;
[System.Runtime.InteropServices.FieldOffset(68)]
public short dmCollate;
[System.Runtime.InteropServices.FieldOffset(72)]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHFORMNAME)]
public string dmFormName;
[System.Runtime.InteropServices.FieldOffset(102)]
public Int16 dmLogPixels;
[System.Runtime.InteropServices.FieldOffset(104)]
public Int32 dmBitsPerPel;
[System.Runtime.InteropServices.FieldOffset(108)]
public Int32 dmPelsWidth;
[System.Runtime.InteropServices.FieldOffset(112)]
public Int32 dmPelsHeight;
[System.Runtime.InteropServices.FieldOffset(116)]
public Int32 dmDisplayFlags;
[System.Runtime.InteropServices.FieldOffset(116)]
public Int32 dmNup;
[System.Runtime.InteropServices.FieldOffset(120)]
public Int32 dmDisplayFrequency;
}
class PrinterSettings
{
private IntPtr gPrinter = new System.IntPtr();
private PRINTER_DEFAULTS gPrinterValues = new PRINTER_DEFAULTS();
private PRINTER_INFO_2 gPInfo = new PRINTER_INFO_2();
private DEVMODE gDevMode;
private IntPtr gPtrDevMode;
private IntPtr gPtrPrinterInfo;
private int gSizeOfDevMode = 0;
private int gLastError;
private int gNBytesNeeded;
private long gNRet;
private int gIntError;
private int gNTemporary;
private IntPtr gDevModeData;
[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, IntPtr pDevModeInput, int fMode);
[DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool GetPrinter(IntPtr hPrinter, Int32 dwLevel, IntPtr pPrinter, Int32 dwBuf, out Int32 dwNeeded);
[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, ref PRINTER_DEFAULTS pd);
[DllImport("winspool.drv", CharSet = CharSet.Ansi, SetLastError = true)]
private static extern bool SetPrinter(IntPtr hPrinter, int Level,
IntPtr pPrinter, int Command);
private const int DM_DUPLEX = 4096; //0x1000
private const int DM_IN_BUFFER = 8;
private const int DM_OUT_BUFFER = 2;
private const int PRINTER_ACCESS_ADMINISTER = 4; //0x4
private const int STANDARD_RIGHTS_REQUIRED = 983040; //0xF0000
private const int PRINTER_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE;
private const int PRINTER_ACCESS_USE = 8; //0x8
public bool ChangePrinterSetting(string iPrinterName)
{
gDevMode = this.GetPrinterSettings(iPrinterName);
Marshal.StructureToPtr(gDevMode, gDevModeData, true);
gPInfo.pDevMode = gDevModeData;
gPInfo.pSecurityDescriptor = IntPtr.Zero;
//bring up the printer preferences dialog
DocumentProperties(IntPtr.Zero, gPrinter, iPrinterName, gDevModeData
, gPInfo.pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER | PRINTER_ACCESS_ADMINISTER);
//update driver dependent part of the DEVMODE
Marshal.StructureToPtr(gPInfo, gPtrPrinterInfo, true);
gLastError = Marshal.GetLastWin32Error();
gNRet = Convert.ToInt16(SetPrinter(gPrinter, 2, gPtrPrinterInfo, 0));
if (gNRet == 0)
{
//Unable to set extern printer settings.
gLastError = Marshal.GetLastWin32Error();
throw new Win32Exception(gLastError);
}
if (gPrinter != IntPtr.Zero)
{
ClosePrinter(gPrinter);
}
return Convert.ToBoolean(gNRet);
}
public DEVMODE GetPrinterSettings(string PrinterName)
{
DEVMODE lDevMode;
gPrinterValues.pDatatype = IntPtr.Zero;
gPrinterValues.pDevMode = IntPtr.Zero;
gPrinterValues.DesiredAccess = PRINTER_ALL_ACCESS;
// HERE CRASHES
gNRet = Convert.ToInt32(OpenPrinter(PrinterName, out gPrinter, ref gPrinterValues));
if (gNRet == 0)
{
gLastError = Marshal.GetLastWin32Error();
throw new Win32Exception(gLastError);
}
GetPrinter(gPrinter, 2, IntPtr.Zero, 0, out gNBytesNeeded);
if (gNBytesNeeded <= 0)
throw new System.Exception("Unable to allocate memory");
else
{
// Allocate enough space for PRINTER_INFO_2...
gPtrPrinterInfo = Marshal.AllocCoTaskMem(gNBytesNeeded);
gPtrPrinterInfo = Marshal.AllocHGlobal(gNBytesNeeded);
//The second GetPrinter fills in all the current settings, so all you
//need to do is modify what youre interested in...
gNRet = Convert.ToInt32(GetPrinter(gPrinter, 2,
gPtrPrinterInfo, gNBytesNeeded, out gNTemporary));
if (gNRet == 0)
{
gLastError = Marshal.GetLastWin32Error();
throw new Win32Exception(gLastError);
}
gPInfo = (PRINTER_INFO_2)Marshal.PtrToStructure(gPtrPrinterInfo, typeof(PRINTER_INFO_2));
IntPtr lTempBuffer = new IntPtr();
if (gPInfo.pDevMode == IntPtr.Zero)
{
//if GetPrinter didnt fill in the DEVMODE, try to get it by calling
//DocumentProperties...
IntPtr ptrZero = IntPtr.Zero;
//get the size of the devmode struct
gSizeOfDevMode = DocumentProperties(IntPtr.Zero, gPrinter,
PrinterName, ptrZero, ptrZero, 0);
gPtrDevMode = Marshal.AllocCoTaskMem(gSizeOfDevMode);
int i = DocumentProperties(IntPtr.Zero, gPrinter, PrinterName, gPtrDevMode,
ptrZero, DM_OUT_BUFFER);
if (i < 0 || gPtrDevMode != IntPtr.Zero)
{
//Cannot get the DEVMODE struct.
throw new System.Exception("Cannot get DEVMODE data");
}
gPInfo.pDevMode = gPtrDevMode;
}
gIntError = DocumentProperties(IntPtr.Zero, gPrinter,
PrinterName, IntPtr.Zero, lTempBuffer, 0);
gDevModeData = Marshal.AllocHGlobal(gIntError);
gIntError = DocumentProperties(IntPtr.Zero, gPrinter,
PrinterName, gDevModeData, lTempBuffer, 2);
lDevMode = (DEVMODE)Marshal.PtrToStructure(gDevModeData, typeof(DEVMODE));
if (gNRet == 0 || gPrinter == IntPtr.Zero)
{
gLastError = Marshal.GetLastWin32Error();
throw new Win32Exception(gLastError);
}
return lDevMode;
}
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Runtime.InteropServices;
使用系统组件模型;
命名空间PrintersettingsTest
{
[StructLayout(LayoutKind.Sequential)]
结构打印机默认值
{
公共IntPtr数据类型;
公共IntPtr pDevMode;
公众期望访问;
}
[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto)]
公用结构打印机\u信息\u 2
{
[Marshallas(UnmanagedType.LPTStr)]
公共字符串pServerName;
[Marshallas(UnmanagedType.LPTStr)]
公共字符串名称;
[Marshallas(UnmanagedType.LPTStr)]
公共字符串pShareName;
[Marshallas(UnmanagedType.LPTStr)]
公共字符串pPortName;
[Marshallas(UnmanagedType.LPTStr)]
公共字符串名称;
[Marshallas(UnmanagedType.LPTStr)]
公共字符串命令;
[Marshallas(UnmanagedType.LPTStr)]
公共字符串拼音;
公共IntPtr pDevMode;
[Marshallas(UnmanagedType.LPTStr)]
公共字符串pSepFile;
[Marshallas(UnmanagedType.LPTStr)]
公共字符串处理器;
[Marshallas(UnmanagedType.LPTStr)]
公共字符串pDatatype;
[Marshallas(UnmanagedType.LPTStr)]
公共字符串参数;
公共IntPtr pSecurityDescriptor;
公共单位属性;
公共利益优先;
公共信息优先权;
公共uint开始时间;
公共时间;
公共部门地位;
公共部门联合通讯社;
公共单位平均百万分之一;
}
结构点
{
公共Int32 x;
公共利益;
}
[标志()]
枚举DM:int
{
方向=0x1,
纸张尺寸=0x2,
纸张长度=0x4,
纸张宽度=0x8,
比例=0x10,
位置=0x20,
NUP=0x40,
DisplayOrientation=0x80,
拷贝数=0x100,
DefaultSource=0x200,
打印质量=0x400,
颜色=0x800,
双工=0x1000,
YResolution=0x2000,
t选项=0x4000,
Collate=0x8000,
FormName=0x10000,
对数像素=0x20000,
BitsPerPixel=0x40000,
PelsWidth=0x80000,
PelsHeight=0x100000,
DisplayFlags=0x200000,
显示频率=0x400000,
ICMMethod=0x800000,
ICMIntent=0x1000000,
MediaType=0x2000000,
DitherType=0x4000000,
平移宽度=0x8000000,
平移高度=0x10000000,
DisplayFixedOutput=0x20000000
}
[StructLayout(LayoutKind.Explicit,CharSet=CharSet.Ansi)]
结构DEVMODE
{
public const int CCHDEVICENAME=32;
公共常数int CCHFORMNAME=32;
[Marshallas(UnmanagedType.ByValTStr,SizeConst=CCHDEVICENAME)]
[System.Runtime.InteropServices.FieldOffset(0)]
公共字符串dmDeviceName;
[System.Runtime.InteropServices.FieldOffset(32)]
公共Int16版本;
[System.Runtime.InteropServices.FieldOffset(34)]
公共Int16 dmDriverVersion;
[System.Runtime.InteropServices.FieldOffset(36)]
公共Int16 dmSize;
[System.Runtime.InteropServices.FieldOffset(38)]
公共Int16 dmDriverExtra;
[System.Runtime.InteropServices.FieldOffset(40)]
公共领域;
[System.Runtime.InteropServices.FieldOffset(44)]
Int16定向;
[System.Runtime.InteropServices.FieldOffset(46)]
Int16 DMS纸张尺寸;
[System.Runtime.InteropServices.FieldOffset(48)]
Int16-dml纸张长度;
[System.Runtime.InteropServices.FieldOffset(50)]
Int16-dml纸张宽度;
[System.Runtime.InteropServices.FieldOffset(52)]
Int16-dmScale;
[System.Runtime.InteropServices.FieldOffset(54)]
Int16数字媒体副本;
[System.Runtime.InteropServices.FieldOffset(56)]
Int16数字信号源;
[System.Runtime.InteropServices.FieldOffset(58)]
Int16数字印刷质量;
[System.Runtime.InteropServices.FieldOffset(44)]
公共点位置;
[System.Runtime.InteropServices.FieldOffset(52)]
公共Int32数字显示方向;
[System.Runtime.InteropServices.FieldOffset(56)]
公共Int32 dmDisplayFixedOutput;
[System.Runtime.InteropServices.FieldOffset(60)]
公共短彩色;
[System.Runtime.InteropServices.FieldOffset(62)]
公共短双工;
[System.Runtime.InteropServices.FieldOffset(64)]
公共短期债务解决方案;
[系统
gNRet = Convert.ToInt16(SetPrinter(gPrinter, 0, gPtrPrinterInfo, 3))
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;
namespace PrintersettingsTest
{
[StructLayout(LayoutKind.Sequential)]
struct PRINTER_DEFAULTS
{
public IntPtr pDatatype;
public IntPtr pDevMode;
public int DesiredAccess;
}
[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 uint Attributes;
public uint Priority;
public uint DefaultPriority;
public uint StartTime;
public uint UntilTime;
public uint Status;
public uint cJobs;
public uint AveragePPM;
}
struct POINTL
{
public Int32 x;
public Int32 y;
}
[Flags()]
enum DM : int
{
Orientation = 0x1,
PaperSize = 0x2,
PaperLength = 0x4,
PaperWidth = 0x8,
Scale = 0x10,
Position = 0x20,
NUP = 0x40,
DisplayOrientation = 0x80,
Copies = 0x100,
DefaultSource = 0x200,
PrintQuality = 0x400,
Color = 0x800,
Duplex = 0x1000,
YResolution = 0x2000,
TTOption = 0x4000,
Collate = 0x8000,
FormName = 0x10000,
LogPixels = 0x20000,
BitsPerPixel = 0x40000,
PelsWidth = 0x80000,
PelsHeight = 0x100000,
DisplayFlags = 0x200000,
DisplayFrequency = 0x400000,
ICMMethod = 0x800000,
ICMIntent = 0x1000000,
MediaType = 0x2000000,
DitherType = 0x4000000,
PanningWidth = 0x8000000,
PanningHeight = 0x10000000,
DisplayFixedOutput = 0x20000000
}
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
struct DEVMODE
{
public const int CCHDEVICENAME = 32;
public const int CCHFORMNAME = 32;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
[System.Runtime.InteropServices.FieldOffset(0)]
public string dmDeviceName;
[System.Runtime.InteropServices.FieldOffset(32)]
public Int16 dmSpecVersion;
[System.Runtime.InteropServices.FieldOffset(34)]
public Int16 dmDriverVersion;
[System.Runtime.InteropServices.FieldOffset(36)]
public Int16 dmSize;
[System.Runtime.InteropServices.FieldOffset(38)]
public Int16 dmDriverExtra;
[System.Runtime.InteropServices.FieldOffset(40)]
public DM dmFields;
[System.Runtime.InteropServices.FieldOffset(44)]
Int16 dmOrientation;
[System.Runtime.InteropServices.FieldOffset(46)]
Int16 dmPaperSize;
[System.Runtime.InteropServices.FieldOffset(48)]
Int16 dmPaperLength;
[System.Runtime.InteropServices.FieldOffset(50)]
Int16 dmPaperWidth;
[System.Runtime.InteropServices.FieldOffset(52)]
Int16 dmScale;
[System.Runtime.InteropServices.FieldOffset(54)]
Int16 dmCopies;
[System.Runtime.InteropServices.FieldOffset(56)]
Int16 dmDefaultSource;
[System.Runtime.InteropServices.FieldOffset(58)]
Int16 dmPrintQuality;
[System.Runtime.InteropServices.FieldOffset(44)]
public POINTL dmPosition;
[System.Runtime.InteropServices.FieldOffset(52)]
public Int32 dmDisplayOrientation;
[System.Runtime.InteropServices.FieldOffset(56)]
public Int32 dmDisplayFixedOutput;
[System.Runtime.InteropServices.FieldOffset(60)]
public short dmColor;
[System.Runtime.InteropServices.FieldOffset(62)]
public short dmDuplex;
[System.Runtime.InteropServices.FieldOffset(64)]
public short dmYResolution;
[System.Runtime.InteropServices.FieldOffset(66)]
public short dmTTOption;
[System.Runtime.InteropServices.FieldOffset(68)]
public short dmCollate;
[System.Runtime.InteropServices.FieldOffset(72)]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHFORMNAME)]
public string dmFormName;
[System.Runtime.InteropServices.FieldOffset(102)]
public Int16 dmLogPixels;
[System.Runtime.InteropServices.FieldOffset(104)]
public Int32 dmBitsPerPel;
[System.Runtime.InteropServices.FieldOffset(108)]
public Int32 dmPelsWidth;
[System.Runtime.InteropServices.FieldOffset(112)]
public Int32 dmPelsHeight;
[System.Runtime.InteropServices.FieldOffset(116)]
public Int32 dmDisplayFlags;
[System.Runtime.InteropServices.FieldOffset(116)]
public Int32 dmNup;
[System.Runtime.InteropServices.FieldOffset(120)]
public Int32 dmDisplayFrequency;
}
class PrinterSettings
{
private IntPtr gPrinter = new System.IntPtr();
private PRINTER_DEFAULTS gPrinterValues = new PRINTER_DEFAULTS();
private PRINTER_INFO_2 gPInfo = new PRINTER_INFO_2();
private DEVMODE gDevMode;
private IntPtr gPtrDevMode;
private IntPtr gPtrPrinterInfo;
private int gSizeOfDevMode = 0;
private int gLastError;
private int gNBytesNeeded;
private long gNRet;
private int gIntError;
private int gNTemporary;
private IntPtr gDevModeData;
[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, IntPtr pDevModeInput, int fMode);
[DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool GetPrinter(IntPtr hPrinter, Int32 dwLevel, IntPtr pPrinter, Int32 dwBuf, out Int32 dwNeeded);
[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, ref PRINTER_DEFAULTS pd);
[DllImport("winspool.drv", CharSet = CharSet.Ansi, SetLastError = true)]
private static extern bool SetPrinter(IntPtr hPrinter, int Level,
IntPtr pPrinter, int Command);
private const int DM_DUPLEX = 4096; //0x1000
private const int DM_IN_BUFFER = 8;
private const int DM_OUT_BUFFER = 2;
private const int PRINTER_ACCESS_ADMINISTER = 4; //0x4
private const int STANDARD_RIGHTS_REQUIRED = 983040; //0xF0000
private const int PRINTER_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE;
private const int PRINTER_ACCESS_USE = 8; //0x8
public bool ChangePrinterSetting(string iPrinterName)
{
gDevMode = this.GetPrinterSettings(iPrinterName);
Marshal.StructureToPtr(gDevMode, gDevModeData, true);
gPInfo.pDevMode = gDevModeData;
gPInfo.pSecurityDescriptor = IntPtr.Zero;
//bring up the printer preferences dialog
DocumentProperties(IntPtr.Zero, gPrinter, iPrinterName, gDevModeData
, gPInfo.pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER | PRINTER_ACCESS_ADMINISTER);
//update driver dependent part of the DEVMODE
Marshal.StructureToPtr(gPInfo, gPtrPrinterInfo, true);
gLastError = Marshal.GetLastWin32Error();
gNRet = Convert.ToInt16(SetPrinter(gPrinter, 2, gPtrPrinterInfo, 0));
if (gNRet == 0)
{
//Unable to set extern printer settings.
gLastError = Marshal.GetLastWin32Error();
throw new Win32Exception(gLastError);
}
if (gPrinter != IntPtr.Zero)
{
ClosePrinter(gPrinter);
}
return Convert.ToBoolean(gNRet);
}
public DEVMODE GetPrinterSettings(string PrinterName)
{
DEVMODE lDevMode;
gPrinterValues.pDatatype = IntPtr.Zero;
gPrinterValues.pDevMode = IntPtr.Zero;
gPrinterValues.DesiredAccess = PRINTER_ALL_ACCESS;
// HERE CRASHES
gNRet = Convert.ToInt32(OpenPrinter(PrinterName, out gPrinter, ref gPrinterValues));
if (gNRet == 0)
{
gLastError = Marshal.GetLastWin32Error();
throw new Win32Exception(gLastError);
}
GetPrinter(gPrinter, 2, IntPtr.Zero, 0, out gNBytesNeeded);
if (gNBytesNeeded <= 0)
throw new System.Exception("Unable to allocate memory");
else
{
// Allocate enough space for PRINTER_INFO_2...
gPtrPrinterInfo = Marshal.AllocCoTaskMem(gNBytesNeeded);
gPtrPrinterInfo = Marshal.AllocHGlobal(gNBytesNeeded);
//The second GetPrinter fills in all the current settings, so all you
//need to do is modify what youre interested in...
gNRet = Convert.ToInt32(GetPrinter(gPrinter, 2,
gPtrPrinterInfo, gNBytesNeeded, out gNTemporary));
if (gNRet == 0)
{
gLastError = Marshal.GetLastWin32Error();
throw new Win32Exception(gLastError);
}
gPInfo = (PRINTER_INFO_2)Marshal.PtrToStructure(gPtrPrinterInfo, typeof(PRINTER_INFO_2));
IntPtr lTempBuffer = new IntPtr();
if (gPInfo.pDevMode == IntPtr.Zero)
{
//if GetPrinter didnt fill in the DEVMODE, try to get it by calling
//DocumentProperties...
IntPtr ptrZero = IntPtr.Zero;
//get the size of the devmode struct
gSizeOfDevMode = DocumentProperties(IntPtr.Zero, gPrinter,
PrinterName, ptrZero, ptrZero, 0);
gPtrDevMode = Marshal.AllocCoTaskMem(gSizeOfDevMode);
int i = DocumentProperties(IntPtr.Zero, gPrinter, PrinterName, gPtrDevMode,
ptrZero, DM_OUT_BUFFER);
if (i < 0 || gPtrDevMode != IntPtr.Zero)
{
//Cannot get the DEVMODE struct.
throw new System.Exception("Cannot get DEVMODE data");
}
gPInfo.pDevMode = gPtrDevMode;
}
gIntError = DocumentProperties(IntPtr.Zero, gPrinter,
PrinterName, IntPtr.Zero, lTempBuffer, 0);
gDevModeData = Marshal.AllocHGlobal(gIntError);
gIntError = DocumentProperties(IntPtr.Zero, gPrinter,
PrinterName, gDevModeData, lTempBuffer, 2);
lDevMode = (DEVMODE)Marshal.PtrToStructure(gDevModeData, typeof(DEVMODE));
if (gNRet == 0 || gPrinter == IntPtr.Zero)
{
gLastError = Marshal.GetLastWin32Error();
throw new Win32Exception(gLastError);
}
return lDevMode;
}
}
}
}
Marshal.StructureToPtr(gPInfo, gPtrPrinterInfo, True)