PosPrinter GetDefaultAsync always returns null - c#

I'm trying to print a ticket using .NET POS but i'm not able to get the Default printer.
PosPrinter defaultPrinter = await PosPrinter.GetDefaultAsync();
I also tried this:
string deviceSelector = PosPrinter.GetDeviceSelector();
PosPrinter printer = await PosPrinter.FromIdAsync(deviceSelector);
I have my thermal printer configured as default.

Have you tried the way using the PosExplorer and the printer name? Snippet:
public PosPrinter GetPrinterByName(System.Windows.Forms.Form mainForm, string printerName)
{
PosPrinter printer = null;
PosExplorer explorer = new PosExplorer(mainForm);
DeviveCollection printers = explorer.GetDevices(DeviceType.PosPrinter);
if (printers != null && printers.Count > 0)
{
for (int i = 0; i < printers.Count; i++)
{
if(0 == string.Compare(printerName, printers[i].ServiceObjectName))
{
printer = printers[i];
break;
}
}
}
return printer;
}

Related

getting serial number for usb using the usb name

I have winform application working on USB, I distribute the application on USB for the clients, I'm checking the the USB serial number if the application moved to another USB the application shows a message to the user that he cant run this app because he is not registered, I have a method getting the USB serial number by USB letter, but the problem is windows changing the USB letter dynamically, so its hard to get the USB letter and I cannot make the letter fixed so I can't read it.
I'm looking for a way to get the serial number for the USB by the USB Name is That possible ?? and if not what is the best way to manage my problem ??
Here is the Class I use to get the USB serial number :
class USBSerialNumber
{
string _serialNumber;
string _driveLetter;
public string getSerialNumberFromDriveLetter(string driveLetter)
{
this._driveLetter = driveLetter.ToUpper();
if (!this._driveLetter.Contains(":"))
{
this._driveLetter += ":";
}
matchDriveLetterWithSerial();
return this._serialNumber;
}
private void matchDriveLetterWithSerial()
{
string[] diskArray;
string driveNumber;
string driveLetter;
ManagementObjectSearcher searcher1 = new ManagementObjectSearcher("SELECT * FROM Win32_LogicalDiskToPartition");
foreach (ManagementObject dm in searcher1.Get())
{
diskArray = null;
driveLetter = getValueInQuotes(dm["Dependent"].ToString());
diskArray = getValueInQuotes(dm["Antecedent"].ToString()).Split(',');
driveNumber = diskArray[0].Remove(0, 6).Trim();
if (driveLetter == this._driveLetter)
{
/* This is where we get the drive serial */
ManagementObjectSearcher disks = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
foreach (ManagementObject disk in disks.Get())
{
if (disk["Name"].ToString() == ("\\\\.\\PHYSICALDRIVE" + driveNumber) & disk["InterfaceType"].ToString() == "USB")
{
this._serialNumber = parseSerialFromDeviceID(disk["PNPDeviceID"].ToString());
}
}
}
}
}
private string parseSerialFromDeviceID(string deviceId)
{
string[] splitDeviceId = deviceId.Split('\\');
string[] serialArray;
string serial;
int arrayLen = splitDeviceId.Length - 1;
serialArray = splitDeviceId[arrayLen].Split('&');
serial = serialArray[0];
return serial;
}
private string getValueInQuotes(string inValue)
{
string parsedValue = "";
int posFoundStart = 0;
int posFoundEnd = 0;
posFoundStart = inValue.IndexOf("\"");
posFoundEnd = inValue.IndexOf("\"", posFoundStart + 1);
parsedValue = inValue.Substring(posFoundStart + 1, (posFoundEnd - posFoundStart) - 1);
return parsedValue;
}
}

c# Cross-Platform device information from local network from lan scan

I have currently wrote a code which scans the local network with a function called "bool ping()". I want to add a capability to provide basic device information when the function returns 'true'. I've found 'ManagementObjectSearcher'.
At first it looked perfect but when It gets used for a non-windows device it crash. Therefore I suppose that this method cannot be used for non-windows devices.
As I want to add the below code ( or login , after enough polishing ), to an android app that scans the local network and returns the
A) IP address and
B) (one of the following )
the device type ( desktop , laptop , smartphone)
and/or
the OS type ( android , windows , linux , tvOS )
Is there a valid way I can do what I am looking for? I believe I have experienced apps that do stuff like that, though I don't know what language they were based on.
namespace LanConsole
{
class Program
{
static void Main(string[] args)
{
string host = "192.168.1.10"; // android smartphone IP
string temp = null;
// arguments I found
string[] _searchClass = { "Win32_ComputerSystem", "Win32_OperatingSystem", "Win32_BaseBoard", "Win32_BIOS" };
string[] param = { "UserName", "Caption", "Product", "Description" };
bool v = ping(host, 10, 900); // bool function send ping to host
if (v == true)
{
Console.WriteLine("true");
for (int i = 0; i <= _searchClass.Length - 1; i++)
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("\\\\" + host + "\\root\\CIMV2", "SELECT *FROM " + _searchClass[i]);
foreach (ManagementObject obj in searcher.Get())
{
temp += obj.GetPropertyValue(param[i]).ToString() + "\n";
if (i == _searchClass.Length - 1)
{
Console.WriteLine(temp, "Hostinfo: " + host);
break;
}
}
Console.WriteLine("");
}
}
else
Console.WriteLine("false");
}
public static bool ping(string host, int attempts, int timeout)
{
System.Net.NetworkInformation.Ping ping = new System.Net.NetworkInformation.Ping();
System.Net.NetworkInformation.PingReply pingReply;
for (int i = 0; i < attempts; i++)
{
try
{
pingReply = ping.Send(host, timeout);
// If there is a successful ping, return true.
if (pingReply != null &&
pingReply.Status == System.Net.NetworkInformation.IPStatus.Success)
{
return true;
}
}
catch
{
// supressing errors
}
}
// Return false if ping fales "attempts" times
return false;
}
}
}

Printing with Zebra Link-Os SDK

I am using this code to print an image to a zebra printer.
ZebraPrinterConnection connection = new TcpPrinterConnection(ipAddress,port);
connection.Open();
ZebraPrinter printer = ZebraPrinterFactory.GetInstance(connection);
printer.GetGraphicsUtil().PrintImage("imageAddress");
It works fine but some times the printer doesn't print and in the code I dont get any errors. Is there a way to check if physically the label was printed?
There are a couple of ways to do this.
First way is to check the status during/after you print and confirm there are no bytes in the buffer and no error on the printer:
private boolean postPrintCheckPrinterStatus(Connection connection)
{
ZebraPrinter printer = ZebraPrinterFactory.getInstance(PrinterLanguage.ZPL, connection);
PrinterStatus printerStatus = printer.getCurrentStatus();
// loop while printing until print is complete or there is an error
while ((printerStatus.numberOfFormatsInReceiveBuffer > 0) && (printerStatus.isReadyToPrint))
{
printerStatus = printer.getCurrentStatus();
}
if (printerStatus.isReadyToPrint) {
System.out.println("Ready To Print");
return true;
} else if (printerStatus.isPaused) {
System.out.println("Cannot Print because the printer is paused.");
} else if (printerStatus.isHeadOpen) {
System.out.println("Cannot Print because the printer head is open.");
} else if (printerStatus.isPaperOut) {
System.out.println("Cannot Print because the paper is out.");
} else {
System.out.println("Cannot Print.");
}
return false;
}
The other way to check this would be to use the printer odometer to ensure the label was printed. Check the odometer before and then again after:
// Set settings, check status, print, etc.
if (setPrintLanguage(statusConnection) && checkPrinterStatus(statusConnection))
{
int labelCount = Integer.parseInt(SGD.GET("odometer.total_label_count", statusConnection));
// Send Print Job (1 label)
String zplData = "^XA^FO20,20^A0N,25,25^FDThis is a ZPL test.^FS^XZ";
printerConnection.write(zplData.getBytes());
if (postPrintCheckPrinterStatus(statusConnection))
{
int newLabelCount = Integer.parseInt(SGD.GET("odometer.total_label_count", statusConnection));
if (newLabelCount == labelCount + 1)
{
System.out.println("Print Successful.");
}
}
//else reprint?
}
Please try with following code:
id<GraphicsUtil, NSObject> graphicsUtil = [zebraPrinter getGraphicsUtil];
UIImage* image = [UIImage imageNamed:#"ImageName"];
BOOL success = [graphicsUtil printImage:[image CGImage] atX:155 atY:0 withWidth:200 withHeight:80 andIsInsideFormat:NO error:&error];
if(error) {
NSLog(#"ERROR: %#", error);
}

Using ManagementObjectSearcher and Win32_Printer to check Status

I have been forced to use the RawPrinterHelper class to print to a thermal printer because the PrintDocument method has proven unfit for POS printing.
I now need to check the status of the printer prior to printing to be sure that it is, online and ready to print. I have been able to successful check attributes from Win32_Printer. I can see properties such as PrinterStatus, changing from 3, to a 2 or a 1 when out of paper or tray is open. This is great.
My question is, which properties should indicate it is O.K. to print? There must be more than just checking if PrinterStatus is idle (3).
private bool ReadyCheck(string printerName)
{
bool ready = false;
string query = string.Format("SELECT * from Win32_Printer WHERE Name LIKE '%{0}'", printerName);
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query))
using (ManagementObjectCollection coll = searcher.Get())
{
try
{
foreach (ManagementObject printer in coll)
{
// Print status = 3, idle and ready to print
string status = printer.Properties["PrinterStatus"].Value.ToString();
string extendedPrinterStatus = printer.Properties["ExtendedPrinterStatus"].Value.ToString();
// What else means printer is ready?
if (status.Trim() == "3")
ready = true;
}
}
catch (ManagementException ex)
{
Console.WriteLine(ex.Message);
}
}
return ready;
}
Edit:
#vendettamit Sorry I didn't ask very well. For instance, Idle (3) indicates it's OK to print. I am wondering if there are more which also indicate it's OK to print such as; Printing (4), WarmUp (5), ect, or is Idle (3) the only time you should send the next print job? Thanks
Below are the values that you can take into account to check if It's ready to print:
Other (1)
Unknown (2)
Idle (3)
Printing (4)
Warmup (5)
Stopped Printing (6)
Offline (7)
Also a note from Remarks on MSDN documentation for Win32_Printer-
If you are retrieving PrinterStatus = 3 or PrinterState = 0, the printer driver may not be feeding accurate information into WMI. WMI retrieves the printer information from the spoolsv.exe process. It is possible the printer driver does not report its status to the spooler. In this case, Win32_Printer reports the printer as Idle.
**//check printer is online**
private static bool IsOnline(ManagementBaseObject printer)
{
bool isOnlineprinter = true;
PrinterNative.PrinterNative.PrinterNative printerNative = new PrinterNative.PrinterNative.PrinterNative();
var PrinterName = printerNative.GetPrinterName();
var PrinterNameProperty = printer.Properties["DeviceId"].Value.ToString();
var ResultPrinter01 = printer.Properties["ExtendedPrinterStatus"].Value.ToString();
var ResultPrinter02 = printer.Properties["PrinterState"].Value.ToString();
if (PrinterNameProperty == PrinterName)
{
//(no internet connection or printer switched off):PrinterState
if (ResultPrinter02 == "128"|| ResultPrinter02=="4096")
{
isOnlineprinter = false;
}
////printer is initializing....
//if (ResultPrinter02 == "16")
//{
// isOnlineprinter = false;
//}
//(no internet connection or printer switched off):ExtendedPrinterStatus
if (ResultPrinter01 == "7")
{
isOnlineprinter = false;
}
}
return isOnlineprinter;
}
**//check for out of paper**
private static bool IspaperOK(ManagementBaseObject printer)
{
bool PaperOK = true;
PrinterNative.PrinterNative.PrinterNative printerNative = new PrinterNative.PrinterNative.PrinterNative();
var PrinterName = printerNative.GetPrinterName();
var PrinterNameProperty = printer.Properties["DeviceId"].Value.ToString();
var PaperStatus = printer.Properties["PrinterState"].Value.ToString();
if (PrinterNameProperty == PrinterName)
{
//(PrinterState)16 = Out of Paper
//(PrinterState)5 = Out of paper
//(PrinterState)4 = paperjam
//(PrinterState)144 = Out of paper
if ((PaperStatus == "5") || (PaperStatus == "16")||(PaperStatus=="144"))
{
PaperOK = false;
}
}
return PaperOK;
}
**//Verify still printing state or not**
private static bool Isprinting(ManagementBaseObject printer)
{
bool Isprintingnow = false;
PrinterNative.PrinterNative.PrinterNative printerNative = new PrinterNative.PrinterNative.PrinterNative();
var PrinterName = printerNative.GetPrinterName();
var PrinterNameProperty = printer.Properties["DeviceId"].Value.ToString();
var printing01 = printer.Properties["PrinterState"].Value.ToString();
var printing02 = printer.Properties["PrinterStatus"].Value.ToString();
if (PrinterNameProperty == PrinterName)
{
//(PrinterState)11 = Printing
//(PrinterState)1024 = printing
//(PrinterStatus)4 = printing
if (printing01 == "11" || printing01 == "1024" || printing02=="4")
{
Isprintingnow = true;
}
}
return Isprintingnow;
}
**//check for error (Printer)**
private static bool IsPrinterError(ManagementBaseObject printer)
{
bool PrinterOK = true;
PrinterNative.PrinterNative.PrinterNative printerNative = new PrinterNative.PrinterNative.PrinterNative();
var PrinterName = printerNative.GetPrinterName();
var PrinterNameProperty = printer.Properties["DeviceId"].Value.ToString();
var PrinterSpecificError = printer.Properties["PrinterState"].Value.ToString();
var otherError = printer.Properties["ExtendedPrinterStatus"].Value.ToString();
if (PrinterNameProperty == PrinterName)
{
//(PrinterState)2 - error of printer
//(PrinterState)131072 - Toner Low
//(PrinterState)18 - Toner Low
//(PrinterState)19 - No Toner
if ((PrinterSpecificError == "131072")||(PrinterSpecificError == "18")||(PrinterSpecificError == "19")||(PrinterSpecificError == "2")||(PrinterSpecificError == "7"))
{
PrinterOK = false;
}
//(ExtendedPrinterStatus) 2 - no error
if (otherError=="2")
{
PrinterOK = true;
}
else
{
PrinterOK = false;
}
}
return PrinterOK;
}
**//check Network or USB**
private static bool IsNetworkPrinter(ManagementBaseObject printer)
{
bool IsNetwork = true;
PrinterNative.PrinterNative.PrinterNative printerNative = new PrinterNative.PrinterNative.PrinterNative();
var PrinterName = printerNative.GetPrinterName();
var PrinterNameProperty = printer.Properties["DeviceId"].Value.ToString();
var network = printer.Properties["Network"].Value.ToString();
var local = printer.Properties["Local"].Value.ToString();
if (PrinterNameProperty == PrinterName)
{
if (network == "True")
{
IsNetwork = true;
}
if (network == "True" && local == "True")
{
IsNetwork = true;
}
if (local == "True" && network=="False")
{
IsNetwork = false;
}
}
return IsNetwork;
}
//(PrinterState)16 = Out of Paper
//(PrinterState)5 = Out of paper
//(PrinterState)4 = paperjam
//(PrinterState)144 = Out of paper
//(PrinterState)4194432 = Lid Open
//(PrinterState)4194448 = Out of paper/Lid open
//(PrinterState)4096= Offline
//(PrinterState)1024= Printing
//(PrinterState)128= Printer is offline

Using a scanner without dialogs in C#

I'm building a .Net 4.0 application for remote control of a scanner device. I have tried both TWAIN and WIA libraries, but I have the same problem. Scanning images without scanner selection and scanning settings dialogs.
I found a useful article on WIA scripting in .Net, and modified it to this:
private Image Scan(string deviceName)
{
WiaClass wiaManager = null; // WIA manager COM object
CollectionClass wiaDevs = null; // WIA devices collection COM object
ItemClass wiaRoot = null; // WIA root device COM object
CollectionClass wiaPics = null; // WIA collection COM object
ItemClass wiaItem = null; // WIA image COM object
try
{
// create COM instance of WIA manager
wiaManager = new WiaClass();
// call Wia.Devices to get all devices
wiaDevs = wiaManager.Devices as CollectionClass;
if ((wiaDevs == null) || (wiaDevs.Count == 0))
{
throw new Exception("No WIA devices found!");
}
object device = null;
foreach (IWiaDeviceInfo currentDevice in wiaManager.Devices)
{
if (currentDevice.Name == deviceName)
{
device = currentDevice;
break;
}
}
if (device == null)
{
throw new Exception
(
"Device with name \"" +
deviceName +
"\" could not be found."
);
}
// select device
wiaRoot = (ItemClass)wiaManager.Create(ref device);
// something went wrong
if (wiaRoot == null)
{
throw new Exception
(
"Could not initialize device \"" +
deviceName + "\"."
);
}
wiaPics = wiaRoot.GetItemsFromUI
(
WiaFlag.SingleImage,
WiaIntent.ImageTypeColor
) as CollectionClass;
if (wiaPics == null || wiaPics.Count == 0)
{
throw new Exception("Could not scan image.");
}
Image image = null;
// enumerate all the pictures the user selected
foreach (object wiaObj in wiaPics)
{
if (image == null)
{
wiaItem = (ItemClass)Marshal.CreateWrapperOfType
(
wiaObj, typeof(ItemClass)
);
// create temporary file for image
string tempFile = Path.GetTempFileName();
// transfer picture to our temporary file
wiaItem.Transfer(tempFile, false);
// create Image instance from file
image = Image.FromFile(tempFile);
}
// release enumerated COM object
Marshal.ReleaseComObject(wiaObj);
}
if (image == null)
{
throw new Exception("Error reading scanned image.");
}
return image;
}
finally
{
// release WIA image COM object
if (wiaItem != null)
Marshal.ReleaseComObject(wiaItem);
// release WIA collection COM object
if (wiaPics != null)
Marshal.ReleaseComObject(wiaPics);
// release WIA root device COM object
if (wiaRoot != null)
Marshal.ReleaseComObject(wiaRoot);
// release WIA devices collection COM object
if (wiaDevs != null)
Marshal.ReleaseComObject(wiaDevs);
// release WIA manager COM object
if (wiaManager != null)
Marshal.ReleaseComObject(wiaManager);
}
}
With this I actually managed to select the device from configuration (input parameter of the Scan method) and retrieve the resulting image after scan.
But the problem with scanning options dialog (Scan using DEVICENAME). As this is a remote control application, dialog will not be visible to the user, so I need to either skip it using default settings, or use settings from a configuration if necessary.
Scanning options dialog:
In the end I did not use the code written in the question for scanning dialogs. I found a useful example of Scanning with Windows Image Acquisition 2.0 which by the way also had a blocking dialog, but this was easily modified and in moments I had a simple class with a Scan(string scannerId) function which would just scan with a selected device and nothing more, see code () below:
using System;
using System.Collections.Generic;
using System.IO;
using System.Drawing;
namespace WIATest
{
class WIAScanner
{
const string wiaFormatBMP = "{B96B3CAB-0728-11D3-9D7B-0000F81EF32E}";
class WIA_DPS_DOCUMENT_HANDLING_SELECT
{
public const uint FEEDER = 0x00000001;
public const uint FLATBED = 0x00000002;
}
class WIA_DPS_DOCUMENT_HANDLING_STATUS
{
public const uint FEED_READY = 0x00000001;
}
class WIA_PROPERTIES
{
public const uint WIA_RESERVED_FOR_NEW_PROPS = 1024;
public const uint WIA_DIP_FIRST = 2;
public const uint WIA_DPA_FIRST = WIA_DIP_FIRST + WIA_RESERVED_FOR_NEW_PROPS;
public const uint WIA_DPC_FIRST = WIA_DPA_FIRST + WIA_RESERVED_FOR_NEW_PROPS;
//
// Scanner only device properties (DPS)
//
public const uint WIA_DPS_FIRST = WIA_DPC_FIRST + WIA_RESERVED_FOR_NEW_PROPS;
public const uint WIA_DPS_DOCUMENT_HANDLING_STATUS = WIA_DPS_FIRST + 13;
public const uint WIA_DPS_DOCUMENT_HANDLING_SELECT = WIA_DPS_FIRST + 14;
}
/// <summary>
/// Use scanner to scan an image (with user selecting the scanner from a dialog).
/// </summary>
/// <returns>Scanned images.</returns>
public static List<Image> Scan()
{
WIA.ICommonDialog dialog = new WIA.CommonDialog();
WIA.Device device = dialog.ShowSelectDevice(WIA.WiaDeviceType.UnspecifiedDeviceType, true, false);
if (device != null)
{
return Scan(device.DeviceID);
}
else
{
throw new Exception("You must select a device for scanning.");
}
}
/// <summary>
/// Use scanner to scan an image (scanner is selected by its unique id).
/// </summary>
/// <param name="scannerName"></param>
/// <returns>Scanned images.</returns>
public static List<Image> Scan(string scannerId)
{
List<Image> images = new List<Image>();
bool hasMorePages = true;
while (hasMorePages)
{
// select the correct scanner using the provided scannerId parameter
WIA.DeviceManager manager = new WIA.DeviceManager();
WIA.Device device = null;
foreach (WIA.DeviceInfo info in manager.DeviceInfos)
{
if (info.DeviceID == scannerId)
{
// connect to scanner
device = info.Connect();
break;
}
}
// device was not found
if (device == null)
{
// enumerate available devices
string availableDevices = "";
foreach (WIA.DeviceInfo info in manager.DeviceInfos)
{
availableDevices += info.DeviceID + "n";
}
// show error with available devices
throw new Exception("The device with provided ID could not be found. Available Devices:n" + availableDevices);
}
WIA.Item item = device.Items[1] as WIA.Item;
try
{
// scan image
WIA.ICommonDialog wiaCommonDialog = new WIA.CommonDialog();
WIA.ImageFile image = (WIA.ImageFile)wiaCommonDialog.ShowTransfer(item, wiaFormatBMP, false);
// save to temp file
string fileName = Path.GetTempFileName();
File.Delete(fileName);
image.SaveFile(fileName);
image = null;
// add file to output list
images.Add(Image.FromFile(fileName));
}
catch (Exception exc)
{
throw exc;
}
finally
{
item = null;
//determine if there are any more pages waiting
WIA.Property documentHandlingSelect = null;
WIA.Property documentHandlingStatus = null;
foreach (WIA.Property prop in device.Properties)
{
if (prop.PropertyID == WIA_PROPERTIES.WIA_DPS_DOCUMENT_HANDLING_SELECT)
documentHandlingSelect = prop;
if (prop.PropertyID == WIA_PROPERTIES.WIA_DPS_DOCUMENT_HANDLING_STATUS)
documentHandlingStatus = prop;
}
// assume there are no more pages
hasMorePages = false;
// may not exist on flatbed scanner but required for feeder
if (documentHandlingSelect != null)
{
// check for document feeder
if ((Convert.ToUInt32(documentHandlingSelect.get_Value()) &amp;amp;amp; WIA_DPS_DOCUMENT_HANDLING_SELECT.FEEDER) != 0)
{
hasMorePages = ((Convert.ToUInt32(documentHandlingStatus.get_Value()) &amp;amp;amp; WIA_DPS_DOCUMENT_HANDLING_STATUS.FEED_READY) != 0);
}
}
}
}
return images;
}
/// <summary>
/// Gets the list of available WIA devices.
/// </summary>
/// <returns></returns>
public static List<string> GetDevices()
{
List<string> devices = new List<string>();
WIA.DeviceManager manager = new WIA.DeviceManager();
foreach (WIA.DeviceInfo info in manager.DeviceInfos)
{
devices.Add(info.DeviceID);
}
return devices;
}
}
}
First off, many thanks to Miljenko Barbir for his above solution, it works great.
I would like to add that if you want zero dialogs, you can use (from Milijenko's demo code)
WIA.ImageFile image = item.Transfer(wiaFormatBMP);
instead of
WIA.ImageFile image = (WIA.ImageFile)wiaCommonDialog.ShowTransfer(item, wiaFormatBMP, false);
This basically removes the progress bar as well, so you get scanning without any dialogs.
// show scanner view
guif.ShowUI = 0;
guif.ModalUI = 0;
You can see in this code that's I've implemented.

Categories