By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,958 Members | 1,179 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,958 IT Pros & Developers. It's quick & easy.

Changing printer setting using .NET

P: n/a
Hi all
I am trying to change the printer(like paper source ,etc) setting in C#. But i am unable to do it. I am not sure how to do it. should i have to use WIN API like Openprinter , getprinter , setprinter . I did try with PrinterSetting.setHDevMode but it does not work. Its their is a simple way to change printersetting.
thanks
umesh.

Jul 21 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
Try using the PageSetupDialog class. I think this has the functionality
that you are looking for.

Hope that helps,
--
Marc Butenko
mb******@bresnan.net
"Umesh" <an*******@discussions.microsoft.com> wrote in message
news:BB**********************************@microsof t.com...
Hi all
I am trying to change the printer(like paper source ,etc) setting in C#. But i am unable to do it. I am not sure how to do it. should i have to use
WIN API like Openprinter , getprinter , setprinter . I did try with
PrinterSetting.setHDevMode but it does not work. Its their is a simple way
to change printersetting. thanks
umesh.b

Jul 21 '05 #2

P: n/a
Try using the PageSetupDialog class. I think this has the functionality
that you are looking for.

Hope that helps,
--
Marc Butenko
mb******@bresnan.net
"Umesh" <an*******@discussions.microsoft.com> wrote in message
news:BB**********************************@microsof t.com...
Hi all
I am trying to change the printer(like paper source ,etc) setting in C#. But i am unable to do it. I am not sure how to do it. should i have to use
WIN API like Openprinter , getprinter , setprinter . I did try with
PrinterSetting.setHDevMode but it does not work. Its their is a simple way
to change printersetting. thanks
umesh.b

Jul 21 '05 #3

P: n/a
Thanks Marc for reply . I appreciate it
My requirement was to change the printer setting programmatically. I found out the solution . Word API do provide interface to change pagesource of the document (ActiveDocument.PageSetting). But is does not guarantee the duplex property will work.() . We have to do this by using WIN API like setprinter. The problem what I was facing about setprinter is it was not working. At last I re-wrote some portion of the code and IT worked , Following is the C# code for changing the printer setting , again it will not work for network printer . It will throw up access denied error. I am not able to understand why MS office is able to change the network printer propertied but why not C# code using win api
//Cod

private const int DM_DUPLEX = 0x1000
private const int DM_IN_BUFFER = 8
private const int DM_OUT_BUFFER = 2
private const int PRINTER_ACCESS_ADMINISTER = 0x4
private const int PRINTER_ACCESS_USE = 0x8
private const int STANDARD_RIGHTS_REQUIRED = 0xF0000
private const int PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE)

[DllImport("kernel32.dll", EntryPoint="GetLastError", SetLastError=false
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)
internal static extern Int32 GetLastError()

[DllImport("winspool.Drv", EntryPoint="ClosePrinter", SetLastError=true,
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)
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 pDeviceNameg,
IntPtr pDevModeOutput, ref IntPtr pDevModeInput, int fMode)

[DllImport("winspool.Drv", EntryPoint="GetPrinterA", SetLastError=true, CharSet=CharSet.Ansi
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)
private 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)
static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter,
out IntPtr hPrinter, ref PRINTER_DEFAULTS pd

[ DllImport( "winspool.drv",CharSet=CharSet.Unicode,ExactSpelli ng=false
CallingConvention=CallingConvention.StdCall )
public static extern long OpenPrinter(string pPrinterName,ref IntPtr phPrinter, int pDefault);*
/*[DllImport("winspool.Drv", EntryPoint="OpenPrinterA", SetLastError=true, CharSet=CharSet.Ansi,
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)
static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter,
out IntPtr hPrinter, ref PRINTER_DEFAULTS pd)

*/
[DllImport("winspool.Drv", EntryPoint="OpenPrinterA", SetLastError=true, CharSet=CharSet.Ansi,
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)
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)

public bool ChangePrintersetting(string sPrinterName, printer.PaperSource PS , printer.PageOrientation PO , printer.PageDuplex PD , printer.PaperSize Size, int numbeOfCopies,bool preserverOldSettings)

IntPtr hPrinter = new System.IntPtr()
PRINTER_DEFAULTS PrinterValues = new PRINTER_DEFAULTS()
PRINTER_INFO_2 pinfo = new PRINTER_INFO_2()
DEVMODE dm
IntPtr ptrDM
IntPtr ptrPrinterInfo
int sizeOfDevMode = 0
int lastError
int nBytesNeeded
long nRet;
int intError
System.Int32 nJunk
if (((int)PD < 1) || ((int)PD > 3)

throw new ArgumentOutOfRangeException("nDuplexSetting","nDup lexSetting is incorrect.")
}
else
{

const int PRINTER_ACCESS_ADMINISTER = 0x4;
const int PRINTER_ACCESS_USE = 0x8;
const int PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE);
PrinterValues.pDatatype =0;
PrinterValues.pDevMode = 0 ;
PrinterValues.DesiredAccess = PRINTER_ALL_ACCESS;
nRet = Convert.ToInt32(OpenPrinter(sPrinterName, out hPrinter, ref PrinterValues));
if (nRet == 0)
{
lastError = Marshal.GetLastWin32Error();
throw new Win32Exception(Marshal.GetLastWin32Error());
}
GetPrinter(hPrinter, 2, IntPtr.Zero, 0, out nBytesNeeded);
if (nBytesNeeded <= 0)
{
return false;
}

// Allocate enough space for PRINTER_INFO_2...
//ptrPrinterInfo = Marshal.AllocCoTaskMem(nBytesNeeded);
ptrPrinterInfo = Marshal.AllocHGlobal(nBytesNeeded);
// The second GetPrinter fills in all the current settings, so all you
// need to do is modify what you're interested in...
nRet = Convert.ToInt32(GetPrinter(hPrinter, 2, ptrPrinterInfo, nBytesNeeded, out nJunk));
if (nRet == 0)
{

lastError = Marshal.GetLastWin32Error();
throw new Win32Exception(Marshal.GetLastWin32Error());
}
pinfo = (PRINTER_INFO_2)Marshal.PtrToStructure(ptrPrinterI nfo, typeof(PRINTER_INFO_2));
IntPtr Temp = new IntPtr();
i1 = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, IntPtr.Zero , ref Temp , 0);
//IntPtr yDevModeData = Marshal.AllocCoTaskMem(i1);
IntPtr yDevModeData= Marshal.AllocHGlobal(i1);
i1 = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, yDevModeData , ref Temp , 2);
dm = (DEVMODE)Marshal.PtrToStructure(yDevModeData, typeof(DEVMODE));
dm.dmDefaultSource =(short)PS;
dm.dmOrientation = (short)PO;
dm.dmPaperSize =(short)Size;
dm.dmDeviceName = dm.dmDeviceName;
dm.dmCopies =(short) 1;
dm.dmDuplex = 2;
Marshal.StructureToPtr( dm,yDevModeData,true);
//nRet = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, yDevModeData
// , ref yDevModeData, (DM_IN_BUFFER | DM_OUT_BUFFER));

if ((nRet == 0) || (hPrinter == IntPtr.Zero))
{
lastError = Marshal.GetLastWin32Error();
//string myErrMsg = GetErrorMessage(lastError);
throw new Win32Exception(Marshal.GetLastWin32Error());

}
if (pinfo.pDevMode == IntPtr.Zero)
{
// If GetPrinter didn't fill in the DEVMODE, try to get it by calling
// DocumentProperties...

IntPtr ptrZero = IntPtr.Zero;

//get the size of the devmode structure
sizeOfDevMode = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, ptrZero, ref ptrZero, 0);
if (nRet <= 0)
{
return false;
}

ptrDM = Marshal.AllocCoTaskMem(sizeOfDevMode);
int i ;
i = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, ptrDM,
ref ptrZero, DM_OUT_BUFFER);
if ((i < 0) || (ptrDM == IntPtr.Zero))
{
//Cannot get the DEVMODE structure.
return false;
}

pinfo.pDevMode = ptrDM;

}

if (!Convert.ToBoolean(dm.dmFields & DM_DUPLEX))
{
//You cannot modify the duplex flag for this printer
//because it does not support duplex or the driver does not support setting
//it from the Windows API.
//return false;
}
pinfo.pDevMode = yDevModeData;
pinfo.pSecurityDescriptor = IntPtr.Zero;

/*update driver dependent part of the DEVMODE

i1 = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, yDevModeData
, ref pinfo.pDevMode, (DM_IN_BUFFER | DM_OUT_BUFFER));*/
if (i1 < 0)
{
//Unable to set duplex setting to this printer.
return false;
}

Marshal.StructureToPtr(pinfo,ptrPrinterInfo,true);
lastError = Marshal.GetLastWin32Error();
nRet = Convert.ToInt16(SetPrinter(hPrinter, 2, ptrPrinterInfo, 0));
if (nRet == 0)
{
//Unable to set shared printer settings.
lastError = Marshal.GetLastWin32Error();
//string myErrMsg = GetErrorMessage(lastError);
throw new Win32Exception(Marshal.GetLastWin32Error());

}
if (hPrinter != IntPtr.Zero)
ClosePrinter(hPrinter);

return Convert.ToBoolean(nRet);

}

}
Jul 21 '05 #4

P: n/a
Thanks Marc for reply . I appreciate it
My requirement was to change the printer setting programmatically. I found out the solution . Word API do provide interface to change pagesource of the document (ActiveDocument.PageSetting). But is does not guarantee the duplex property will work.() . We have to do this by using WIN API like setprinter. The problem what I was facing about setprinter is it was not working. At last I re-wrote some portion of the code and IT worked , Following is the C# code for changing the printer setting , again it will not work for network printer . It will throw up access denied error. I am not able to understand why MS office is able to change the network printer propertied but why not C# code using win api
//Cod

private const int DM_DUPLEX = 0x1000
private const int DM_IN_BUFFER = 8
private const int DM_OUT_BUFFER = 2
private const int PRINTER_ACCESS_ADMINISTER = 0x4
private const int PRINTER_ACCESS_USE = 0x8
private const int STANDARD_RIGHTS_REQUIRED = 0xF0000
private const int PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE)

[DllImport("kernel32.dll", EntryPoint="GetLastError", SetLastError=false
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)
internal static extern Int32 GetLastError()

[DllImport("winspool.Drv", EntryPoint="ClosePrinter", SetLastError=true,
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)
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 pDeviceNameg,
IntPtr pDevModeOutput, ref IntPtr pDevModeInput, int fMode)

[DllImport("winspool.Drv", EntryPoint="GetPrinterA", SetLastError=true, CharSet=CharSet.Ansi
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)
private 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)
static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter,
out IntPtr hPrinter, ref PRINTER_DEFAULTS pd

[ DllImport( "winspool.drv",CharSet=CharSet.Unicode,ExactSpelli ng=false
CallingConvention=CallingConvention.StdCall )
public static extern long OpenPrinter(string pPrinterName,ref IntPtr phPrinter, int pDefault);*
/*[DllImport("winspool.Drv", EntryPoint="OpenPrinterA", SetLastError=true, CharSet=CharSet.Ansi,
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)
static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter,
out IntPtr hPrinter, ref PRINTER_DEFAULTS pd)

*/
[DllImport("winspool.Drv", EntryPoint="OpenPrinterA", SetLastError=true, CharSet=CharSet.Ansi,
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)
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)

public bool ChangePrintersetting(string sPrinterName, printer.PaperSource PS , printer.PageOrientation PO , printer.PageDuplex PD , printer.PaperSize Size, int numbeOfCopies,bool preserverOldSettings)

IntPtr hPrinter = new System.IntPtr()
PRINTER_DEFAULTS PrinterValues = new PRINTER_DEFAULTS()
PRINTER_INFO_2 pinfo = new PRINTER_INFO_2()
DEVMODE dm
IntPtr ptrDM
IntPtr ptrPrinterInfo
int sizeOfDevMode = 0
int lastError
int nBytesNeeded
long nRet;
int intError
System.Int32 nJunk
if (((int)PD < 1) || ((int)PD > 3)

throw new ArgumentOutOfRangeException("nDuplexSetting","nDup lexSetting is incorrect.")
}
else
{

const int PRINTER_ACCESS_ADMINISTER = 0x4;
const int PRINTER_ACCESS_USE = 0x8;
const int PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE);
PrinterValues.pDatatype =0;
PrinterValues.pDevMode = 0 ;
PrinterValues.DesiredAccess = PRINTER_ALL_ACCESS;
nRet = Convert.ToInt32(OpenPrinter(sPrinterName, out hPrinter, ref PrinterValues));
if (nRet == 0)
{
lastError = Marshal.GetLastWin32Error();
throw new Win32Exception(Marshal.GetLastWin32Error());
}
GetPrinter(hPrinter, 2, IntPtr.Zero, 0, out nBytesNeeded);
if (nBytesNeeded <= 0)
{
return false;
}

// Allocate enough space for PRINTER_INFO_2...
//ptrPrinterInfo = Marshal.AllocCoTaskMem(nBytesNeeded);
ptrPrinterInfo = Marshal.AllocHGlobal(nBytesNeeded);
// The second GetPrinter fills in all the current settings, so all you
// need to do is modify what you're interested in...
nRet = Convert.ToInt32(GetPrinter(hPrinter, 2, ptrPrinterInfo, nBytesNeeded, out nJunk));
if (nRet == 0)
{

lastError = Marshal.GetLastWin32Error();
throw new Win32Exception(Marshal.GetLastWin32Error());
}
pinfo = (PRINTER_INFO_2)Marshal.PtrToStructure(ptrPrinterI nfo, typeof(PRINTER_INFO_2));
IntPtr Temp = new IntPtr();
i1 = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, IntPtr.Zero , ref Temp , 0);
//IntPtr yDevModeData = Marshal.AllocCoTaskMem(i1);
IntPtr yDevModeData= Marshal.AllocHGlobal(i1);
i1 = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, yDevModeData , ref Temp , 2);
dm = (DEVMODE)Marshal.PtrToStructure(yDevModeData, typeof(DEVMODE));
dm.dmDefaultSource =(short)PS;
dm.dmOrientation = (short)PO;
dm.dmPaperSize =(short)Size;
dm.dmDeviceName = dm.dmDeviceName;
dm.dmCopies =(short) 1;
dm.dmDuplex = 2;
Marshal.StructureToPtr( dm,yDevModeData,true);
//nRet = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, yDevModeData
// , ref yDevModeData, (DM_IN_BUFFER | DM_OUT_BUFFER));

if ((nRet == 0) || (hPrinter == IntPtr.Zero))
{
lastError = Marshal.GetLastWin32Error();
//string myErrMsg = GetErrorMessage(lastError);
throw new Win32Exception(Marshal.GetLastWin32Error());

}
if (pinfo.pDevMode == IntPtr.Zero)
{
// If GetPrinter didn't fill in the DEVMODE, try to get it by calling
// DocumentProperties...

IntPtr ptrZero = IntPtr.Zero;

//get the size of the devmode structure
sizeOfDevMode = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, ptrZero, ref ptrZero, 0);
if (nRet <= 0)
{
return false;
}

ptrDM = Marshal.AllocCoTaskMem(sizeOfDevMode);
int i ;
i = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, ptrDM,
ref ptrZero, DM_OUT_BUFFER);
if ((i < 0) || (ptrDM == IntPtr.Zero))
{
//Cannot get the DEVMODE structure.
return false;
}

pinfo.pDevMode = ptrDM;

}

if (!Convert.ToBoolean(dm.dmFields & DM_DUPLEX))
{
//You cannot modify the duplex flag for this printer
//because it does not support duplex or the driver does not support setting
//it from the Windows API.
//return false;
}
pinfo.pDevMode = yDevModeData;
pinfo.pSecurityDescriptor = IntPtr.Zero;

/*update driver dependent part of the DEVMODE

i1 = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, yDevModeData
, ref pinfo.pDevMode, (DM_IN_BUFFER | DM_OUT_BUFFER));*/
if (i1 < 0)
{
//Unable to set duplex setting to this printer.
return false;
}

Marshal.StructureToPtr(pinfo,ptrPrinterInfo,true);
lastError = Marshal.GetLastWin32Error();
nRet = Convert.ToInt16(SetPrinter(hPrinter, 2, ptrPrinterInfo, 0));
if (nRet == 0)
{
//Unable to set shared printer settings.
lastError = Marshal.GetLastWin32Error();
//string myErrMsg = GetErrorMessage(lastError);
throw new Win32Exception(Marshal.GetLastWin32Error());

}
if (hPrinter != IntPtr.Zero)
ClosePrinter(hPrinter);

return Convert.ToBoolean(nRet);

}

}
Jul 21 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.