I am using RawPrinterHelper for printing. And it works fine with Windows 7 and previous versions. When we tried it with a printer installed on Windows 8 pc, it did not work.
After reading this post I've learned that I have to set dataType variable to "XPS_PASS" instead of "RAW". Setting it to "XPS_PASS" works fine on windows 8 by the way.
But in my environment, there are windows 8s and windows 7s and XPs also.
Is it possible to make this switch programmatically?
How can I set pDataType variable to "RAW" for windows 7 and lower operating systems, and to "XPS_PASS" to windows 8?
Edit: After a couple of hours digging google I've found this article. Here it says:
- Call GetPrinterDriver to retrieve the DRIVER_INFO_8 struct.
- Check DRIVER_INFO_8::dwPrinterDriverAttributes for the PRINTER_DRIVER_XPS flag.
Choose your datatype based on the presence or absence of the flag:
- If the flag is set, use ‘XPS_PASS’
- If the flag is not set, use ‘RAW’
I am not familiar with unmanaged code, but I've tried the followig:
[DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetPrinterDriver(IntPtr hPrinter, string pEnvironment, uint Level, IntPtr pDriverInfo, int cbBuf, out int pcbNeeded);
private static void GetPrinterDataType(IntPtr hPrinter )
{
IntPtr driverInfo = new IntPtr();
driverInfo = IntPtr.Zero;
int buf_len = 0;
int IntPtrSize = Marshal.SizeOf(typeof(IntPtr));
int a = GetPrinterDriver(hPrinter, "", 8, driverInfo, 0, out buf_len);
driverInfo = Marshal.AllocHGlobal(buf_len);
a = GetPrinterDriver(hPrinter, "", 8, driverInfo, buf_len, out buf_len);
for (int i = 0; i <= 24; i++)
{
if (i == 12 || i == 15 || i == 11 || i == 14)
continue;
IntPtr ptr = Marshal.ReadIntPtr(driverInfo, IntPtrSize * i);
Console.WriteLine("DRIVER INFO {0}: {1}", i, Marshal.PtrToStringUni(ptr));
}
}
I am calling this method after OpenPrinter() method of the RawPrinterHelper class. But the dwPrinterDriverAttributes (number 21) is empty.
Am I doing something wrong?

Okay, I've managed to work out how to get a value showing for the dwPrinterDriverAttributes field.
I added this definition of the DRIVER_INFO_8 structure to my solution (found here).
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct DRIVER_INFO_8
{
public uint cVersion;
[MarshalAs(UnmanagedType.LPTStr)]
public string pName;
[MarshalAs(UnmanagedType.LPTStr)]
public string pEnvironment;
[MarshalAs(UnmanagedType.LPTStr)]
public string pDriverPath;
[MarshalAs(UnmanagedType.LPTStr)]
public string pDataFile;
[MarshalAs(UnmanagedType.LPTStr)]
public string pConfigFile;
[MarshalAs(UnmanagedType.LPTStr)]
public string pHelpFile;
[MarshalAs(UnmanagedType.LPTStr)]
public string pDependentFiles;
[MarshalAs(UnmanagedType.LPTStr)]
public string pMonitorName;
[MarshalAs(UnmanagedType.LPTStr)]
public string pDefaultDataType;
[MarshalAs(UnmanagedType.LPTStr)]
public string pszzPreviousNames;
FILETIME ftDriverDate;
UInt64 dwlDriverVersion;
[MarshalAs(UnmanagedType.LPTStr)]
public string pszMfgName;
[MarshalAs(UnmanagedType.LPTStr)]
public string pszOEMUrl;
[MarshalAs(UnmanagedType.LPTStr)]
public string pszHardwareID;
[MarshalAs(UnmanagedType.LPTStr)]
public string pszProvider;
[MarshalAs(UnmanagedType.LPTStr)]
public string pszPrintProcessor;
[MarshalAs(UnmanagedType.LPTStr)]
public string pszVendorSetup;
[MarshalAs(UnmanagedType.LPTStr)]
public string pszzColorProfiles;
[MarshalAs(UnmanagedType.LPTStr)]
public string pszInfPath;
public uint dwPrinterDriverAttributes;
[MarshalAs(UnmanagedType.LPTStr)]
public string pszzCoreDriverDependencies;
FILETIME ftMinInboxDriverVerDate;
UInt64 dwlMinInboxDriverVerVersion;
}
Then I added this line of code to what you have above in your GetPrinterDriverDataType() method:
var info = (DRIVER_INFO_8)Marshal.PtrToStructure(driverInfo, typeof(DRIVER_INFO_8));
Now you will be able to see what the dwPrinterDriverAttributes field is populated with.
EDIT: Updated the protection level of dwPrinterDriverAttributes to be public so it can be accessed/viewed.
Also worth noting this (found here):
dwPrinterDriverAttributes: A bit field that specifies attributes of the printer driver.
So I've converted the uint to a BitArray and checked to see if the PRINTER_DRIVER_XPS flag/bit is set.
i.e.
PRINTER_DRIVER_XPS flag = 0x00000002
So we need to check the second bit. I do this with the following:
var value = (int)info.dwPrinterDriverAttributes;
BitArray b = new BitArray(new int[] { value } );
bool[] bits = new bool[b.Count];
b.CopyTo(bits, 0);
if (bits[1])
Console.WriteLine("flag set");
else
Console.WriteLine("flag not set");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With