POS for .Net can not detect printer - c#

I am using POS for .Net framework version 1.12 for one of my project.
Microsoft POS for .NET is a class library that is part of Microsoft Windows Embedded for Point of Service.
http://msdn.microsoft.com/en-us/library/ms828083%28v=winembedded.10%29.aspx
private PosPrinter GetReceiptPrinter()
{
PosExplorer posExplorer = new PosExplorer(this);
DeviceInfo receiptPrinterDevice = posExplorer.GetDevice(DeviceType.PosPrinter);
return (PosPrinter)posExplorer.CreateInstance(receiptPrinterDevice);
}
above is the sample code for find the printer. Now my issue is that POS is not able to detect the printer but only open simulator with data when i run my application.
can anyone please help me ?

I had developed an application for a POS running Windows CE as the operating System but for that POS, the manufacturer provided a custom dll for invoking the operations of the printer which I consumed in my C# code. Check with the POS manufacturer and see if they are providing custom dll for the same.

Your line of code
DeviceInfo receiptPrinterDevice = posExplorer.GetDevice(DeviceType.PosPrinter);
will return the default or first PosPrinter found, which in your case looks like it is the simulator.
You need to either (1) Iterate over the collection of printers and somehow select the one you want. i.e.
foreach (DeviceInfo deviceInfo in explorer.GetDevices(DeviceType.PosPrinter))
{
if (isThisThePrinterIWant(deviceInfo)) // user defined function (maybe lookup saved preference file)
{
return (PosPrinter)posExplorer.CreateInstance(deviceInfo );
}
} // Note: GetDevices() not GetDevice()
or (2) Set a logical name for your printer (using software that came with your printer, or the POSDM utility included with Pos for .Net SDK) and change the above line to
DeviceInfo receiptPrinterDevice = posExplorer.GetDevice(DeviceType.PosPrinter, "madeUpLogicalName");
or (3) Simply set the desired printer as the default printer, and leave your code the way it is.

Related

Detect barcode scanner with PointOfService on Windows 10

I would like to use a barcode scanner with Windows 10 (Build 15063) via the Windows.Devices.PointOfService namespace. The scanner is a Datalogic Quickscan QD2430 and I tried with all RS-232 and Keyboard mode.
I used the official sample application https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/BarcodeScanner with no luck. It can detect a device but it's definitely the in-built webcam (HP laptop).
I tried to modify the source, the DeviceHelpers's GetFirstDeviceAsync function https://github.com/Microsoft/Windows-universal-samples/blob/master/SharedContent/cs/DeviceHelpers.cs.
The DeviceInformation.FindAllAsync also returns only the camera's info as result.
string selector = BarcodeScanner.GetDeviceSelector(PosConnectionTypes.All);
DeviceInformation.FindAllAsync(selector);
It returns nothing.
DeviceInformation.FindAllAsync(DeviceClass.ImageScanner);
It returns every connected and I think the previously connected but currently offline devices too. I tried to filter the scanner by name. There was a lot filterd result too, but the convertAsync function returned null for all excepts one, it thrown an Exception "A device attached to the system is not functioning. (Exception from HRESULT: 0x8007001F)".
DeviceInformationCollection infos = await DeviceInformation.FindAllAsync(DeviceClass.All);
foreach(DeviceInformation info in infos)
{
if (info.Name.ToUpper().Contains("BARCODE"))
{
T scanner = await convertAsync(info.Id);
if (scanner != null)
{
return scanner;
}
}
}
Datalogic Quickscan QD2430 is not in the list of devices supported by Windows.Devices.PointOfService.
Ask Datalogic to provide a device driver that supports Windows.Devices.PointOfService, or change the scanner to the one described in the supported list.
Alternatively, create your own device driver according to the Point of Service (POS) of Windows Driver Kit.

Kick Cash Drawer using Control Code

I am working with Epson Thermal printer and Cash Drawer. Cash Drawer is connected with the printer. Reference to http://keyhut.com/popopen.htm, the code to kick cash drawer is 27,112,0,50,250. I tried to send this code to printer but nothing happens. I used POS for .NET and the printer is registed in SetupPos.
Here is my code:
deviceInfo = posExplorer.GetDevice(DeviceType.PosPrinter, strLogicalName);
m_Printer = (PosPrinter)posExplorer.CreateInstance(deviceInfo);
m_Printer.Open();
m_Printer.Claim(1000);
m_Printer.DeviceEnabled = true;
//command = "ESC|p|0|25|251";
command = "\x1B|\x70|\x00|\x19|\xFB";
m_Printer.PrintImmediate(PrinterStation.Receipt, command);
//m_Printer.CutPaper(100);
m_Printer.DeviceEnabled = false;
m_Printer.Release();
m_Printer.Close();
Print text is ok, but send code is not working. What can I do? Thanks.
POS for.NET(UnifiedPOS) specification does not support CashDrawer opening by the PrintNormal()/PrintImmediate() method of POSPrinter device.
Since there is a independent CashDrawer device associated with the POSPrinter device, please open() the corresponding device as a CashDrawer and open the drawer with the OpenDrawer() method.
However, depending on the vendor, there is a possibility of supporting usage like you.
I do not have information on whether EPSON POSPrinter supports such usage or not.
Please ask EPSON or your distributor whether or not you can use such a way.
In addition:
Instead of POS for.NET, there is a way to install and use a device driver as a regular Windows Printer.
Some vendors offer Windows Printer Driver for receipt printers and also support paper cutting and drawer opening functions.
In EPSON, it is provided under the name Advanced Printer Driver.
The questioner seems to have solved the problem using this.
However, this device driver is often used exclusively with POS for.NET/OPOS/JavaPOS, and when printing, it is necessary to use Windows standard printing API.
The third code from open drawer kick code "ESC|p|0|25|251" to send is actually a symbol to control cash drawer 1 or 2, which is using '0' or '1'. The 0 or 1 symbol in the ASCII table is mapped to decimal 48 or 49. So you need to use the Hex x30 or x31 not x00.
Just to add more info, the forth and the fifth code are the time when the signal kick is ON or OFF by sending decimal (value between 0 to 255) * 2ms.
I hope this solve the problem if you still want to use the cash drawer kick code and attach the device to the printer.

Access MacBook camera using C# and Xamarin.Mac forms on Visual Studio?

I need to integrate a video stream from my Macbook camera using a Xamarin.Mac form. However, all of the documentation that I find only tells you how to do so in iOS and Android platforms.
How would you go at getting a video stream from a Macbook then? Any libraries I should look at?
You will want to review the AVFoundation APIs (QTKit is deprecated).
You can create a custom Xamarin.Forms View renderer based on a NSView and assign the AVCaptureVideoPreviewLayer as the control's layer to stream the camera output to this control.
Store class level references to following and make sure you Dispose them when your control goes out of scope otherwise there will be leaks:
AVCaptureDevice device;
AVCaptureDeviceInput input;
AVCaptureStillImageOutput output;
AVCaptureSession session;
In your capture setup, you can grab the default AV device assuming you want to use the build-in FaceTime Camera (also known as iSight).
macOS/Forms Example:
device = AVCaptureDevice.GetDefaultDevice(AVMediaTypes.Video);
input = AVCaptureDeviceInput.FromDevice(device, out var error);
if (error == null)
{
session = new AVCaptureSession();
session.AddInput(input);
session.SessionPreset = AVCaptureSession.PresetPhoto;
var previewLayer = AVCaptureVideoPreviewLayer.FromSession(session);
previewLayer.Frame = Control.Bounds;
Control.Layer = previewLayer;
output = new AVCaptureStillImageOutput();
session.AddOutput(output);
session.StartRunning();
}
Note: A lot of the AVFoundation framework is shared between iOS and MacOS, but there are some differences so if you end up looking at iOS sample code be aware you might need to alter it for macOS.
https://developer.apple.com/documentation/avfoundation

Programmatically create/destroy network bridges with .NET on Windows 7

I am trying to programmatically create and destroy a network bridge on Windows 7. Technologically I would love to stay within the .Net 4 realm (PInvokes are fine, ofc), but utilizing C++ is an option.
My research so far turned up that for configuration, netsh-commands are the route to go. However, there seems to be no option to actually spin up a new bridge with them.
I am currently investigating this program that uses the INetCfg APIs, but it appears that the program or, more specifically, the APIs, are not able to (again) build a new bridge.
If anyone can contribute to solving the problem, any kind of help is greatly appreciated.
[Update:] It seems that newtork bridges are implemented using a driver which then binds to both devices. I cannot yet make much of that information, so still any help is appreciated.
I've found a solution that works for both bridge service and bridge adapter driver. I don't use UpdateDriverForPlugAndPlayDevices like devcon but I'm using DiInstallDevice instead.
However, installing the drivers for the first time in non interactive mode (without user interaction) is not possible. This is because there are no corresponding .cat files for the builtin bridge .inf files. Neither UpdateDriverForPlugAndPlayDevices nor DiInstallDevice nor DiInstallDriver is intended for manual driver installation where .inf file is already contained in %SystemRoot%\inf but not yet in %SystemRoot%\System32\DriverStore.
The files should be on the distribution media or in a vendor-created directory, not in a system location such as %SystemRoot%\inf
All of the mentioned installation methods will create a OEM copy of the .inf file and will install it in driver store. Because this OEM copy is initially not part of the driver store, windows will show a prompt dialog and ask for user interaction either force installing the driver or canceling. Subsequent driver installations is possible without any user interaction by the way. Also preinstalled drivers (see pnputil -a) can be installed in non interactive mode.
So this is my solution:
First a device entry in HKLM\System\CurrentControlSet\Enum\Root is created with the given hardware id as device name (ms_bridge, ms_bridgemp) with the help of SetupDiCreateDeviceInfo
The hardware id is assigned with SetupDiSetDeviceRegistryProperty
The driver list is builded by exactly the given single .inf file with the help of SetupDiSetDeviceInstallParams
Enumerating and preselecting driver with SetupDiSetSelectedDriver
Registering device with SetupDiCallClassInstaller(DIF_REGISTERDEVICE...)
Installing with DiInstallDevice
This is the full code:
HRESULT InstallDriver(const wchar_t* DriverInfFile, const wchar_t* HardwareId) {
HRESULT Hr = S_OK;
GUID ClassGUID;
wchar_t ClassName[MAX_CLASS_NAME_LEN] = {0};
if (SetupDiGetINFClass(DriverInfFile, &ClassGUID, ClassName, sizeof(ClassName) / sizeof(wchar_t), nullptr) == FALSE) {
Hr = HRESULT_FROM_SETUPAPI(GetLastError());
return Hr;
}
HDEVINFO DeviceInfoSet = SetupDiCreateDeviceInfoList(&ClassGUID, nullptr);
if (DeviceInfoSet == INVALID_HANDLE_VALUE) {
Hr = HRESULT_FROM_SETUPAPI(GetLastError());
return Hr;
}
SP_DEVINFO_DATA DeviceInfoData = {
sizeof(SP_DEVINFO_DATA), 0
};
if (SetupDiCreateDeviceInfo(DeviceInfoSet, HardwareId, &ClassGUID, nullptr, nullptr, DICD_GENERATE_ID, &DeviceInfoData) == FALSE) {
Hr = HRESULT_FROM_SETUPAPI(GetLastError());
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
return Hr;
}
if (SetupDiSetDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, SPDRP_HARDWAREID, (LPBYTE) HardwareId, (DWORD) (wcslen(HardwareId) + 1) * sizeof(wchar_t)) == FALSE) {
Hr = HRESULT_FROM_SETUPAPI(GetLastError());
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
return Hr;
}
SP_DEVINSTALL_PARAMS InstallParams = {sizeof(SP_DEVINSTALL_PARAMS), 0};
InstallParams.FlagsEx = DI_FLAGSEX_ALLOWEXCLUDEDDRVS | DI_FLAGSEX_ALWAYSWRITEIDS;
InstallParams.Flags = DI_QUIETINSTALL | DI_ENUMSINGLEINF;
wcscpy_s(InstallParams.DriverPath, DriverInfFile);
if (SetupDiSetDeviceInstallParams(DeviceInfoSet, &DeviceInfoData, &InstallParams) == FALSE) {
Hr = HRESULT_FROM_SETUPAPI(GetLastError());
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
return Hr;
}
SP_DRVINFO_DATA DriverInfoData = {sizeof(SP_DRVINFO_DATA), 0};
if (SetupDiBuildDriverInfoList(DeviceInfoSet, &DeviceInfoData, SPDIT_COMPATDRIVER) == FALSE) {
Hr = HRESULT_FROM_SETUPAPI(GetLastError());
SetupDiDestroyDriverInfoList(DeviceInfoSet, &DeviceInfoData, SPDIT_COMPATDRIVER);
}
// Use first best driver (since specified by inf file)
if (SetupDiEnumDriverInfo(DeviceInfoSet, &DeviceInfoData, SPDIT_COMPATDRIVER, 0, &DriverInfoData)) {
SetupDiSetSelectedDriver(DeviceInfoSet, &DeviceInfoData, &DriverInfoData);
}
if (SetupDiCallClassInstaller(DIF_REGISTERDEVICE, DeviceInfoSet, &DeviceInfoData) == FALSE) {
Hr = HRESULT_FROM_SETUPAPI(GetLastError());
}
// TODO: Allow non interactive mode for drivers already contained in %SystemRoot%\inf directory
//BOOL PreviousMode = SetupSetNonInteractiveMode(TRUE);
if (Hr == S_OK) {
if (DiInstallDevice(nullptr, DeviceInfoSet, &DeviceInfoData, &DriverInfoData, 0, nullptr) == FALSE) {
Hr = HRESULT_FROM_SETUPAPI(GetLastError());
// Ensure that the device entry in \ROOT\ENUM\ will be removed...
SetupDiRemoveDevice(DeviceInfoSet, &DeviceInfoData);
}
}
//SetupSetNonInteractiveMode(PreviousMode);
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
return Hr;
}
Todo's: Find a way to install this bridge drivers from within %SystemRoot%\inf without creating OEM copies and without any user interaction.
You can gain read/write access to subversion repository at Sourceforge
Any additional information or suggestion for improvement is appreciated! Everyone please feel free to checkout/modify the code.
Basic commands:
bridgeutil.exe /install
bridgeutil.exe /uninstall
bridgeutil.exe /attach
bridgeutil.exe /detach
Examples:
bridgeutil.exe /attach "PCI\VEN_10EC&DEV_8169" /attach {5d624f94-8850-40c3-a3fa-a4fd2080baf3}\vwifimp
Attaches each Realtek 8169 Network Interface Cards and Microsoft Virtual Wifi Adapter to bridge. If the bridge is not installed yet, it will be installed first.
bridgeutil.exe /detach 1
Detaches adapter with id 1 from bridge.
To see a list of bridgeable adapters, just call bridgeutil.exe without any arguments.
It is actually possible to create and network bridges via the SetupAPI.
Using the DevCon Tool, destroying them is as easy as this...
devcon.exe remove ms_bridgemp
...while building bridges can be done with this command:
devcon.exe install "C:\Windows\inf\netbrdgm.inf" ms_bridgemp
DevCon is open source, so you can dig into the sources to see how it implements those commands (the DevCon Tool is essentially a CLI to the SetupAPI).
Please note: The commands relate to Windows 7. The approach is said to work on XP and I suppose it works on other Windows Versions, too, but the .INF-File might have a different name or the device ID might differ.
After much unsuccessful searching on the Internet I wrote and have been successfully using the following Windows Script Host script "BridgeConnections.vbs" to create a network bridge on Windows XP (this method also works on Windows 7 and Windows 8 with slight modifications). It can be run from the command prompt or from a batch file as follows:
C:\Temp> cscript BridgeConnections.vbs
File BridgeConnections.vbs:
' This VBScript opens the "Network Connections" control panel window,
' sends Ctrl+A ("Select All") and Alt+N ("Advanced" menu) and
' C ("Bridge Connections" menu command) keystrokes to it and then waits
' until the splash window "Please wait while Windows bridges the connections..."
' disappears from the screen
Dim WshShell, Count
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Exec("rundll32.exe shell32.dll,Control_RunDLL ncpa.cpl")
Count = 0
Do While Not WshShell.AppActivate("Network Connections") And Count < 10
Count = Count + 1
WScript.Sleep 1000
WScript.Echo "Waiting for the 'Network Connections' window... " & CStr(Count) & "s"
Loop
WshShell.SendKeys "^(a)"
WshShell.SendKeys "%(n)"
WshShell.SendKeys "c"
Count = 0
Do While Not WshShell.AppActivate("Network Bridge") And Count < 10
Count = Count + 1
WScript.Sleep 1000
WScript.Echo "Waiting for the 'Network Bridge' splash window... " & CStr(Count) & "s"
Loop
Count = 0
Do While WshShell.AppActivate("Network Bridge") And Count < 120
Count = Count + 1
WScript.Sleep 1000
WScript.Echo "Waiting for the 'Network Bridge' splash window to disappear... " & CStr(Count) & "s"
Loop
Likewise one could modify the script to "Delete" the bridge if required (make a single selection with Shift and navigate keys and send a different keystroke command). In my case I only need to bridge all available ethernet adapters from a batch file so the above method works just fine.
In my experience, the "slight" problem with the
devcon.exe install "C:\Windows\inf\netbrdgm.inf" ms_bridgemp
approach posted here earlier is that it would create an empty, "half-backed" bridge with no adapters in it. So you will still have to go to the Windows GUI and "Add" adapters it one by one manually before it becomes really usable.
The only fully automated solution that really works for me it the above script.
To do the same actions from a C++ or C# code without the script you'd need to know and call undocumented Shell Network Interfaces (NETSHELL.DLL) functions which in turn are called by the Explorer Shell when the user initiates the actions via list view item selection and context menu command in the Windows GUI. A C++ sample of calling into the Shell Network Interface for programmatically disabling/enabling a Network Adapter can be seen here. Unfortunately there is no sample yet for creating/removing the Network Bridge adapter. So until it becomes available I'll stick with the script.
Based on the bindview example, I put up an utilitary called bindbridge, which works as following:
Usage: bindbridge <deviceId> <bind|unbind>
The source can be found at https://github.com/OurGrid/OurVirt/tree/master/tools/win32/bindbridge, and it assumes the bridge device already exists - which can be created with devcon, as per previous answers - and its name to be ms_bridge, what can be easily changed in the sources.
I'm using it to programatically add tap interfaces to the bridge, so my command line is something in the lines of:
bindbridge ROOT\NET\0001 bind
It turns out that, unfortunately, there is no documented way of setting up a network bridge.
The code which does that is located inside hnetcfg.dll, and is invoked only by Windows Explorer. It installs bridge driver, and configures bridge interface.
It might be possible to call it yourself (using COM), but that would require reverse engineering and may break on any system update, so I recommend against doing that.

PrintNormal() Issue 'It is not Initialized'

Current C# POS.NET Printing Issue:
PrintNormal() Throws Exception = 'It is not initialized'
CheckHealth = 'It is not initialized'
'It is not initialized' exception when Printing to Epson TM-T88IV
Using POS for .NET 1.12 and the Epson OPOS ADK for .NET (v1.11.9) service-objects
Successfully able to Open, Claim and Set the DeviceEnabled-true for PosPrinter
Issue sending anything to the printer after this
PrintNormal() results in a 'It is not initialized' exception being thrown.
CheckHealth Utility that came with the Epson OPOS ADK results in exactly the same error. When using PrintNormal(PrinterStation.Receipt the exception is 'The specified station is not mounted."
printer prints fine using direct parallel
printer itself prints
How can we not throw the exemption with the message - 'It is not initialized'?
void K8POSPrint()
{
/// <summary>
/// PosPrinter object
/// </summary>
PosPrinter m_Printer = null;
try
{
//Use a Logical Device Name which has been set on the SetupPOS.
string strLogicalName = "PosPrinter";
try
{
//Create PosExplorer
PosExplorer posExplorer = new PosExplorer();
DeviceInfo deviceInfo = null;
try
{
// Device Info is not null when the printer has the logical name
deviceInfo = posExplorer.GetDevice(DeviceType.PosPrinter, strLogicalName);
m_Printer = (PosPrinter)posExplorer.CreateInstance(deviceInfo);
}
catch (Exception ExDevice)
{
}
//Open the device
m_Printer.Open();
//Get the exclusive control right for the opened device. Then the device is disable from other application.
m_Printer.Claim(1000);
//Enable the device.
m_Printer.DeviceEnabled = true;
// ////CheckHealth.
//m_Printer.CheckHealth(Microsoft.PointOfService.HealthCheckLevel.Interactive);
// //As using the PrintNormal method, send strings to a printer, and print it [\n] is the standard code for starting a new line.
/// Current Issue Next Line thows an exception - 'It is not initialized'
m_Printer.PrintNormal(PrinterStation.Receipt, "Hey Now OPOS for .NET\n");
// the next line would throw the exception 'The specified station is not mounted.'
// m_Printer.PrintNormal(PrinterStation.Slip,"Hey Now Slip OPOS.NET\n");
}
catch (PosControlException)
{
}
}
catch (Exception ex)
{
}
}
Additional Information:
Programs installed while attempting to print on the pos printer are:
1. Installed APD4 Printer Driver Epson TI88IV
APD_412EWM.exe
https://www.epsonexpert.com/ee/techRes/index.htm?ProductId=570
After this set in control panel printers I can select the printer's properties & print a test to the printer successfully.
2. Installed Microsoft POS.NET 1.12
POSfor.NET.msi
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=eaae202a-0fcc-406a-8fde-35713d7841ca
3. Installed Epson OPOS ADK v2.67
ADK267ER4.exe
https://www.epsonexpert.com/ee/appDev/appDevOPOS.htm
4. Installed EPSON OPOS ADK for .NET 1.11.8
OPOSN 1 11 18.exe
https://www.epsonexpert.com/ee/appDev/appDevOPOS.htm
5. Installed OPOS Common Control Objects 1.13.001
OPOS_CCOs_1.13.001.msi
http://monroecs.com/oposccos_current.htm
6. SetupPOS - Added device & Logical Name
7. Check Health still throws the errors
It is not initialized
OPOS_E_ILLEGAL 10007 (0x00002717)
The problem might not be software, but hardware. I saw a similar question (at http://social.msdn.microsoft.com/Forums/vstudio/en-US/446fd4cc-db6b-4822-b3c8-7d9a98bf7eb4/it-is-not-initialized-when-trying-to-printnormal?forum=posfordotnet), where the developer was using an extension cable which was not parallel. As soon as he connected the parallel cable directly to the printer (without the extension cable), his software worked. This was after he called Epson and ordered a newer printer, because they told him his original printer was not compatible with .NET, so that could also be your problem.
I had the same error "It is not initialized" on brand new Epson TM-T88VI.
The printer came with IDN Card and default the ethernet card was partially blocked. You can use the ethernet card to connect to "Epson Net Config", but it did not work when you try to print by OPOS ADK for NET.
The solution was to set switches on IDN Card as:
DS1
DS2
DS3
DS4
DS5
DS6
DS7
OFF
OFF
OFF
OFF
ON
ON
ON
Make sure Power OFF when you changing the switches.

Categories

Resources