473,386 Members | 1,720 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Getting the default printer in 64-bit Vista

Hi,

I have used the code below to return the default printer in 32-bit WinXP
Pro, but now that I am running 64-bit Vista Business I'm getting an error:

using System.Drawing.Printing;

using (PrintDocument objPrintDocument = new PrintDocument())
{
string strDefaultPrinter =
objPrintDocument.PrinterSettings.PrinterName;
}

The error message is: "No printers are installed." and which seems to come
from a method called HdevmodeInternal

However, I have several printers installed, and the default printer is an
old HP LaserJet 5.

Does the above code not work on 64-bit Vista? The app in question is
compiled for x86...

Would I be better off using WMI to return the name of the default printer?

I've tried to find a solution in Google and MSDN, but haven't had much
luck...

Any assistance gratefully received.
--
http://www.markrae.net
Jun 8 '07 #1
13 9050
"Mark Rae" <ma**@markNOSPAMrae.netwrote in message
news:u5**************@TK2MSFTNGP04.phx.gbl...
Hi,

I have used the code below to return the default printer in 32-bit WinXP
Pro, but now that I am running 64-bit Vista Business I'm getting an error:

using System.Drawing.Printing;

using (PrintDocument objPrintDocument = new PrintDocument())
{
string strDefaultPrinter =
objPrintDocument.PrinterSettings.PrinterName;
}

The error message is: "No printers are installed." and which seems to come
from a method called HdevmodeInternal

However, I have several printers installed, and the default printer is an
old HP LaserJet 5.

Does the above code not work on 64-bit Vista? The app in question is
compiled for x86...

Would I be better off using WMI to return the name of the default printer?

I've tried to find a solution in Google and MSDN, but haven't had much
luck...

Any assistance gratefully received.
--
http://www.markrae.net


Works for me on Vista 64 and 32 bit. What happens if you make "Microsoft XPS
Document Writer" the default printer?

Willy.
Jun 9 '07 #2
"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:%2****************@TK2MSFTNGP06.phx.gbl...
"Mark Rae" <ma**@markNOSPAMrae.netwrote in message
news:u5**************@TK2MSFTNGP04.phx.gbl...
>Hi,

I have used the code below to return the default printer in 32-bit WinXP
Pro, but now that I am running 64-bit Vista Business I'm getting an
error:

using System.Drawing.Printing;

using (PrintDocument objPrintDocument = new PrintDocument())
{
string strDefaultPrinter =
objPrintDocument.PrinterSettings.PrinterName;
}

The error message is: "No printers are installed." and which seems to
come from a method called HdevmodeInternal

However, I have several printers installed, and the default printer is an
old HP LaserJet 5.

Does the above code not work on 64-bit Vista? The app in question is
compiled for x86...

Would I be better off using WMI to return the name of the default
printer?

I've tried to find a solution in Google and MSDN, but haven't had much
luck...

Any assistance gratefully received.
--
http://www.markrae.net

Works for me on Vista 64 and 32 bit. What happens if you make "Microsoft
XPS Document Writer" the default printer?
Same thing... Incidentally, it works for me on 32-bit Vista... Did you try
it with a 32-bit app running on 64-bit Vista...?

Also, when I try to query objPrintDocument.PrinterSettings.PrinterName, it
returns "Default printer is not set.", though it definitely is...

The Exception generated still doesn't have any value for InnerException, and
the <Exception>.TargetSite.Name is "HdevmodeInternal" - I can't even find
that anywhere in Google!
--
http://www.markrae.net

Jun 9 '07 #3
"Mark Rae" <ma**@markNOSPAMrae.netwrote in message
news:u4**************@TK2MSFTNGP04.phx.gbl...
"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:%2****************@TK2MSFTNGP06.phx.gbl...
>"Mark Rae" <ma**@markNOSPAMrae.netwrote in message
news:u5**************@TK2MSFTNGP04.phx.gbl...
>>Hi,

I have used the code below to return the default printer in 32-bit WinXP
Pro, but now that I am running 64-bit Vista Business I'm getting an
error:

using System.Drawing.Printing;

using (PrintDocument objPrintDocument = new PrintDocument())
{
string strDefaultPrinter =
objPrintDocument.PrinterSettings.PrinterName;
}

The error message is: "No printers are installed." and which seems to
come from a method called HdevmodeInternal

However, I have several printers installed, and the default printer is
an old HP LaserJet 5.

Does the above code not work on 64-bit Vista? The app in question is
compiled for x86...

Would I be better off using WMI to return the name of the default
printer?

I've tried to find a solution in Google and MSDN, but haven't had much
luck...

Any assistance gratefully received.
--
http://www.markrae.net

Works for me on Vista 64 and 32 bit. What happens if you make "Microsoft
XPS Document Writer" the default printer?

Same thing... Incidentally, it works for me on 32-bit Vista... Did you try
it with a 32-bit app running on 64-bit Vista...?
Yep, both X86 and X64 flavors work on 64-bit Vista Ultimate.

Note that I'm allways adding an application manifest to my executable
assemblies. If you don't add a manifest to an application that runs under
wow64, this application will get a virtualized view of the registry (part
off) and the file system (part off).

To prevent virtualization you have to add a manifest like this:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0"
name="MyApplication.app"></assemblyIdentity>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel
level="asInvoker"></requestedExecutionLevel>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>

save above contents in a file named "MyApplication.manifest", where
"MyApplication" is the name of the assembly (not absolutely required any
name will do as manifest filename).
When done, run the following command:
mt -manifest MyApplication.manifest -outputresource:MyApplication.exe;#1

mt.exe is part of VS2005.

I'm not sure this will be of any help, but it's worth a try.

Willy.
Jun 9 '07 #4
"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:uK**************@TK2MSFTNGP04.phx.gbl...
I'm not sure this will be of any help, but it's worth a try.
Didn't help, unfortunately...

However, I'm wondering if there's something more fundamental going on
here...

When I run e.g. Word 2007, it "sees" the collection of printers installed,
and selects the default one.

However, when I open a PDF in Acrobat Reader 8.0 and try to print it, I get
a MessageBox saying:

"Before you can perform print-related tasks such as page setup or printing a
document, you need to install a printer."

Maybe Word and Acrobat Reader are using different methods to interrogate the
collection if installed printers...?
--
http://www.markrae.net

Jun 9 '07 #5
"Mark Rae" <ma**@markNOSPAMrae.netwrote in message
news:un**************@TK2MSFTNGP04.phx.gbl...
However, I'm wondering if there's something more fundamental going on
here...
Also, when debugging the app in VS.NET 2005 and I force it to quit as soon
as the Exception is thrown, the Output window shows:

"A first chance exception of type
'System.Drawing.Printing.InvalidPrinterException' occurred in
System.Drawing.dll"
--
http://www.markrae.net

Jun 9 '07 #6
"Mark Rae" <ma**@markNOSPAMrae.netwrote in message
news:un**************@TK2MSFTNGP04.phx.gbl...
"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:uK**************@TK2MSFTNGP04.phx.gbl...
>I'm not sure this will be of any help, but it's worth a try.

Didn't help, unfortunately...

However, I'm wondering if there's something more fundamental going on
here...

When I run e.g. Word 2007, it "sees" the collection of printers installed,
and selects the default one.

However, when I open a PDF in Acrobat Reader 8.0 and try to print it, I
get a MessageBox saying:

"Before you can perform print-related tasks such as page setup or printing
a
document, you need to install a printer."
This is basically the same error as yours.
I'm running AR 8.1.0 and everything works as expected.
Maybe Word and Acrobat Reader are using different methods to interrogate
the collection if installed printers...?
Probably they do.
Note that .NET uses PrintDlg from comdlg32.dll (SysWow64), probably Adobe
uses the same.

Could you try this?

// start of code X86 only!
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;

namespace Willys
{
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto, Pack=0x1)]
public class PRINTDLG
{
public int lStructSize;
public IntPtr hwndOwner;
public IntPtr hDevMode;
public IntPtr hDevNames;
public IntPtr hDC;
public int Flags;
public short nFromPage;
public short nToPage;
public short nMinPage;
public short nMaxPage;
public short nCopies;
public IntPtr hInstance;
public IntPtr lCustData;
public IntPtr lpfnPrintHook;
public IntPtr lpfnSetupHook;
public string lpPrintTemplateName;
public string lpSetupTemplateName;
public IntPtr hPrintTemplate;
public IntPtr hSetupTemplate;
}

class Program
{
[DllImport("comdlg32.dll", CharSet=CharSet.Auto, SetLastError=true)]
static extern int PrintDlg([In, Out] PRINTDLG lppd);
[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true,
ExactSpelling=true)]
public static extern IntPtr GlobalLock(HandleRef handle);
[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true,
ExactSpelling=true)]
public static extern bool GlobalUnlock(HandleRef handle);
[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true,
ExactSpelling=true)]
public static extern IntPtr GlobalFree(HandleRef handle);

static void Main()
{
Console.WriteLine(GetDefaultPrinterName());
}
private static PRINTDLG CreatePRINTDLG()
{
PRINTDLG printdlg = new PRINTDLG();
printdlg.lStructSize = Marshal.SizeOf(typeof(PRINTDLG));
printdlg.hwndOwner = IntPtr.Zero;
printdlg.hDevMode = IntPtr.Zero;
printdlg.hDevNames = IntPtr.Zero;
printdlg.Flags = 0x0;
printdlg.hwndOwner = IntPtr.Zero;
printdlg.hDC = IntPtr.Zero;
printdlg.nFromPage = 0x1;
printdlg.nToPage = 0x1;
printdlg.nMinPage = 0x0;
printdlg.nMaxPage = 0x270f;
printdlg.nCopies = 0x1;
printdlg.hInstance = IntPtr.Zero;
printdlg.lCustData = IntPtr.Zero;
printdlg.lpfnPrintHook = IntPtr.Zero;
printdlg.lpfnSetupHook = IntPtr.Zero;
printdlg.lpPrintTemplateName = null;
printdlg.lpSetupTemplateName = null;
printdlg.hPrintTemplate = IntPtr.Zero;
printdlg.hSetupTemplate = IntPtr.Zero;
return printdlg;
}
static string GetDefaultPrinterName()
{
PRINTDLG printdlg = CreatePRINTDLG();
printdlg.Flags = 0x400; //PD_RETURNDEFAULT
if (PrintDlg(printdlg) == 0)
return "No Default Printer Set";
IntPtr hDevNames = printdlg.hDevNames;
IntPtr handle = GlobalLock(new HandleRef(printdlg, hDevNames));
if (handle == IntPtr.Zero)
throw new Win32Exception();
// calculate offset of dev names in DEVNAMES struct allocated by
PrintDlg
// X86 platforms only!!!!!!!!
int devOffset = Marshal.SystemDefaultCharSize *
Marshal.ReadInt16((IntPtr) (((int) handle) + 2));
string name = Marshal.PtrToStringAuto((IntPtr) (((int) handle) +
devOffset));
GlobalUnlock(new HandleRef(printdlg, hDevNames));
GlobalFree(new HandleRef(printdlg, printdlg.hDevNames));
GlobalFree(new HandleRef(printdlg, printdlg.hDevMode));
return name;
}
}
}
// end of code

If this doesn't work, you have a fundamental issue, not related to .NET.
Sure you can also give WMI a try.
Willy.

Jun 9 '07 #7
"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:e5**************@TK2MSFTNGP05.phx.gbl...
Could you try this?
That returns "No Default Printer Set"
If this doesn't work, you have a fundamental issue, not related to .NET.
Hmm - that's a bit worrying... :-(
Sure you can also give WMI a try.
WMI works perfectly, however...

using (ManagementObjectSearcher objMOS = new
ManagementObjectSearcher("SELECT * FROM Win32_Printer"))
{
Dictionary<string, booldicResults = new Dictionary<string, bool>();
using (ManagementObjectCollection objMOC = objMOS.Get())
{
foreach (ManagementObject objMO in objMOC)
{
dicResults.Add(objMO["Name"].ToString(),
Convert.ToBoolean(objMO["Default"]));
}
}
return dicResults;
}
--
http://www.markrae.net

Jun 9 '07 #8
"Mark Rae" <ma**@markNOSPAMrae.netwrote in message
news:Or**************@TK2MSFTNGP05.phx.gbl...
"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:e5**************@TK2MSFTNGP05.phx.gbl...
>Could you try this?

That returns "No Default Printer Set"
That means that the PrintDlg call returns 0, which means "failure" to get
the default printer..... which does not necessarily means there is no
default printer :-)

>If this doesn't work, you have a fundamental issue, not related to .NET.

Hmm - that's a bit worrying... :-(
>Sure you can also give WMI a try.

WMI works perfectly, however...

using (ManagementObjectSearcher objMOS = new
ManagementObjectSearcher("SELECT * FROM Win32_Printer"))
{
Dictionary<string, booldicResults = new Dictionary<string, bool>();
using (ManagementObjectCollection objMOC = objMOS.Get())
{
foreach (ManagementObject objMO in objMOC)
{
dicResults.Add(objMO["Name"].ToString(),
Convert.ToBoolean(objMO["Default"]));
}
}
return dicResults;
}
--
http://www.markrae.net

WMI does not use comdlg32.dll, anyway, it looks like there the issue is with
the 32bit version of the common dialog component or (more probably) one of
it's dependents. Mind to check the version installed in %windir%\SysWow64? I
have 6.0.6000.16386, however I can't believe yours would be different.

Willy.
Jun 9 '07 #9
"Mark Rae" <ma**@markNOSPAMrae.netwrote in message
news:Or**************@TK2MSFTNGP05.phx.gbl...
"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:e5**************@TK2MSFTNGP05.phx.gbl...
>Could you try this?

That returns "No Default Printer Set"
>If this doesn't work, you have a fundamental issue, not related to .NET.

Hmm - that's a bit worrying... :-(
>Sure you can also give WMI a try.

WMI works perfectly, however...

using (ManagementObjectSearcher objMOS = new
ManagementObjectSearcher("SELECT * FROM Win32_Printer"))
{
Dictionary<string, booldicResults = new Dictionary<string, bool>();
using (ManagementObjectCollection objMOC = objMOS.Get())
{
foreach (ManagementObject objMO in objMOC)
{
dicResults.Add(objMO["Name"].ToString(),
Convert.ToBoolean(objMO["Default"]));
}
}
return dicResults;
}
--
http://www.markrae.net


Note that you can simplify/optimize your query like this:

string DefaultPrinterName() {
string defaultPrinter = null;
SelectQuery q = new SelectQuery("select caption from win32_printer where
default = true");
using(ManagementObjectSearcher searcher = new
ManagementObjectSearcher(q))
{
foreach (ManagementObject printer in searcher.Get()) {
defaultPrinter = printer["Caption"].ToString();
}
}
return defaultPrinter;
}

Willy.

Jun 9 '07 #10
"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:u%****************@TK2MSFTNGP03.phx.gbl...
>That returns "No Default Printer Set"

That means that the PrintDlg call returns 0, which means "failure" to get
the default printer..... which does not necessarily means there is no
default printer :-)
OK... Do I need to be concerned about this, do you think...?
WMI does not use comdlg32.dll, anyway, it looks like there the issue is
with the 32bit version of the common dialog component or (more probably)
one of it's dependents. Mind to check the version installed in
%windir%\SysWow64? I have 6.0.6000.16386, however I can't believe yours
would be different.
Yes - that's what I have...
--
http://www.markrae.net

Jun 9 '07 #11
"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:OH**************@TK2MSFTNGP03.phx.gbl...
Note that you can simplify/optimize your query like this:

string DefaultPrinterName() {
string defaultPrinter = null;
SelectQuery q = new SelectQuery("select caption from win32_printer
where default = true");
using(ManagementObjectSearcher searcher = new
ManagementObjectSearcher(q))
{
foreach (ManagementObject printer in searcher.Get()) {
defaultPrinter = printer["Caption"].ToString();
}
}
return defaultPrinter;
}
Yes indeed - my method is part of a WMI base class which returns several of
these collections (OperatingSystem, ComputerSystem, BIOS, Processor,
PhysicalMemory, Printer etc), so I don't really need an extra method to
return the default printer specifically. I do appreciate, however, that that
would represent a small performance boost, especially on a system with very
many printers installed...
--
http://www.markrae.net

Jun 9 '07 #12
"Mark Rae" <ma**@markNOSPAMrae.netwrote in message
news:%2****************@TK2MSFTNGP06.phx.gbl...
"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:u%****************@TK2MSFTNGP03.phx.gbl...
>>That returns "No Default Printer Set"

That means that the PrintDlg call returns 0, which means "failure" to get
the default printer..... which does not necessarily means there is no
default printer :-)

OK... Do I need to be concerned about this, do you think...?
It's not that critical, but as it applies to all applications that use
PrintDlg, I would suggest you to post a bug request in the connect site,
especially because this was done for a 64-bit Vista beta (you do run an RTM
version I suppose), but was apparently closed with status "non
reproducible".

http://connect.microsoft.com/VisualS...dbackID=242908
Willy.

Jun 9 '07 #13
"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:%2****************@TK2MSFTNGP05.phx.gbl...
>OK... Do I need to be concerned about this, do you think...?

It's not that critical, but as it applies to all applications that use
PrintDlg, I would suggest you to post a bug request in the connect site,
especially because this was done for a 64-bit Vista beta (you do run an
RTM version I suppose), but was apparently closed with status "non
reproducible".

http://connect.microsoft.com/VisualS...dbackID=242908
I have done so (I am running RTM).
--
http://www.markrae.net

Jun 9 '07 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Pablo | last post by:
Friends, how can i get the name of the default printer??. I'm working with winforms. VB,C#, nevermind. Thanks a lot Pablo
0
by: Esmee | last post by:
Hi there, I have created an Access 2002 db which contains several reports. Some reports need to be printed on a Laserjet and others on a Labelprinter. One of my clients wants to be able to print...
1
by: Bruce Wood | last post by:
I'm having a devil of a time calling DeviceCapabilities() in order to get the list of paper names / codes / sizes for a printer. Here is my code and the input it produces: static extern Int32...
3
by: Geraldine Hobley | last post by:
Hello, How would you get and set the current default printer by using the system.drawing.printing class or any other class. Regards Geri
1
by: Geraldine Hobley | last post by:
Hello, I have the following code that sets the default printer using the WMI (windows management system). ' Add a Reference to System.Management Dim moReturn As...
4
by: Sean Shanny | last post by:
To all, Running into an out of memory error on our data warehouse server. This occurs only with our data from the 'September' section of a large fact table. The exact same query running over...
3
by: Panos | last post by:
Hi, is there a way that i could get the default printer of the system? I'm using VB.net 2001. There is a function in SDK called "GetDefaultPrinter", but i don't understand how to use it.
0
by: Karthick_Microsoft | last post by:
Actually, in my ASP.Net application, i have a requirement of automatically changing the default printer. I did a OCX using VB and put it on the web page. The client machines do not have local...
1
by: i8mypnuts | last post by:
Could someone please help? I am using the 'defaultprt.zip' tool provided by Ken Getz to change the default printer via VBA code (code below). My problem is that once the default printer has been...
5
by: Glenn | last post by:
Hi We have a ASP.net app which calls into a web service which allow users to print stuff. At the moment they have to specify the printer. Apparently this is too much for our users, so I was...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.