I am hoping someone can have suggestions about this issue.
We have a custom driver taken from https://learn.microsoft.com/en-us/samples/microsoft/windows-driver-samples/xpsdrv-driver-and-filter-sample/
The print driver works well and outputs XPS when the documents are opened in MS word or PDF. But when a document is printed from HP5Si series printer, the driver returns 0 bytes. The job is sent from HP5Si printer to the XPS driver. Why is the driver rejecting this input when the source is a HP series printer. What can I do to fix it?
The printer on the AS400 is setup with an IBM HP5Si driver and sends the job to a windows service on a server. This windows service routes the job to XPS driver as if it were an HP series printer. The XPS driver processes this job and returns XPS to the windows service. The windows service then converts to a tiff file.
For some reason if printing is done using this workflow XPS driver returns 0.
If the same document is opened in word or notepad or any not AS400+ HP, it works and XPS is returned.
To prove my theory, I sent a PCL file in C# code to the driver and it returned 0 bytes.
public static void SendBytesToPrinterPCL(string printerName, string szFileName) {
IntPtr lhPrinter;
OpenPrinter(printerName, out lhPrinter, new IntPtr(0));
if (lhPrinter.ToInt32() == 0) return; //Printer not found!!
var rawPrinter = new DOCINFOA() {
pDocName = "My Document",
pDataType = "RAW"
};
StartDocPrinter(lhPrinter, 1, rawPrinter);
using(var b = new BinaryReader(File.Open(szFileName, FileMode.Open))) {
var length = (int) b.BaseStream.Length;
const int bufferSize = 8192;
var numLoops = length / bufferSize;
var leftOver = length % bufferSize;
for (int i = 0; i < numLoops; i++) {
var buffer = new byte[bufferSize];
int dwWritten;
b.Read(buffer, 0, bufferSize);
IntPtr unmanagedPointer = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, unmanagedPointer, buffer.Length);
WritePrinter(lhPrinter, unmanagedPointer, bufferSize, out dwWritten);
Marshal.FreeHGlobal(unmanagedPointer);
}
if (leftOver > 0) {
var buffer = new byte[leftOver];
int dwWritten;
b.Read(buffer, 0, leftOver);
IntPtr unmanagedPointer = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, unmanagedPointer, buffer.Length);
WritePrinter(lhPrinter, unmanagedPointer, leftOver, out dwWritten);
Marshal.FreeHGlobal(unmanagedPointer);
}
}
EndDocPrinter(lhPrinter);
ClosePrinter(lhPrinter);
}
string filePath = #"C:\Users\tom\Desktop\form.PCL";
string szPrinterName = #"\\server\xpsdrv";
Print.SendBytesToPrinterPCL(szPrinterName, filePath);
Then I sent a regular text file to the driver and it successfully converted to XPS.
public static void SendToPrinterNonPCL(string filePath)
{
ProcessStartInfo info = new ProcessStartInfo();
info.Verb = "print";
info.FileName = filePath;
info.CreateNoWindow = true;
info.WindowStyle = ProcessWindowStyle.Hidden;
Process p = new Process();
p.StartInfo = info;
p.Start();
p.WaitForInputIdle();
System.Threading.Thread.Sleep(3000);
if (false == p.CloseMainWindow())
p.Kill();
}
string filePath = #"C:\Users\tom\Desktop\form.txt";
string szPrinterName = #"\\server\xpsdrv";
Print.SendToPrinterNonPCL(filePath);
Why doesn't the driver in Microsoft samples accept PCL? What should I do. I am not a driver developer. This project was given to me.
EDIT:
Initally I didn't know of this printing from AS400. Our legacy driver was built 15 years back. The developer wrote a custom print driver to PCL and a Custom converter to Tiff. But the driver only supported monochrome. I am not a driver expert or a PCL expert or a converter expert. In order to support color and less pixelated feel for the final Tiff, I decided to change it to a XPS driver. Also it is less custom code and could use Microsoft's XPS conversion in WPF. It is not a very big learning curve for a non-driver development person compared to learning PCL and then changing the converter to accomodate color Tiff. But I guess it is falling apart since the users also print from AS400 which sends PCL.
Do you know any good products which we could purchase a license to? We need a PCL driver and a converter to Tiff
Thank you
Related
The question is similar to question in this thread Windows IoT - Zebra Bluetooth Printer .
I have a Zebra GX420d printer. The only difference is, it is not connected via Bluetooth but via USB. I can't seem to get it paired with my raspberry pi 2. I need to print something out (like "Hello world"). Please help.
Update:
So, i installed the usb driver for the printer, now the Raspberry can see it, but i still can't write anything to the printer. Now i get the "Attempted to read or write protected memory" Exception.
My code:
private async void getObject()
{
var devices = await DeviceInformation.FindAllAsync();
UInt32 vid = 0x0A5F;
UInt32 pid = 0x0084;
//Guid winusbInterfaceGuid = new Guid("532C0D5D-1122-4378-96D3-1BCDF8FB31A2");
string aqs = UsbDevice.GetDeviceSelector(vid, pid);
var myDevices = await Windows.Devices.Enumeration.DeviceInformation.FindAllAsync(aqs, null);
if (myDevices.Count == 0)
{
return;
}
String str = "ABCDEFGH";
IBuffer buffUTF8 = CryptographicBuffer.ConvertStringToBinary(str, BinaryStringEncoding.Utf8);
UsbDevice device = await UsbDevice.FromIdAsync(myDevices[0].Id);
var send = await device.SendControlOutTransferAsync(new UsbSetupPacket(buffUTF8));
You likely need to also allow the USB capability. Here's how:
<DeviceCapability Name="usb">
<Device Id="vidpid:xxxx xxxx">
<Function Type="classId:xx xx xx"/>
<Function Type="name:xxxxx"/>
<Function Type="winUsbId:xxxxx"/>
</Device>
</DeviceCapability>
Details here:
https://msdn.microsoft.com/en-us/library/windows/apps/dn263092.aspx
and here:
https://msdn.microsoft.com/en-us/library/windows/hardware/dn303351(v=vs.85).aspx
Public Function GenerateReportAsExcel()
Dim workbook = WorkbookFactory.Create(template)
template.Close()
Dim worksheet = workbook.GetSheetAt(0)
// Writing record to worksheet
Dim workbookStream = New MemoryStream()
workbookStream.Flush()
workbookStream.Position = 0
workbook.Write(workbookStream) //throws error if the rocord is more then 500000...runs fine for 400000
Return New MemoryStream(workbookStream.ToArray())
End Function
WorkbookFactory is using NPOI.SS.UserModel ....
Is there a way to increase the memory stream capacity? I am getting System.OutOfMemoryException while writing 500000 record to the excel but upto 400000 record works fine.
I found couple of similar issue but not getting any solid solution to this problem...
Someone one suggested to use
workbookStream.Flush()
workbookStream.Position = 0
but not of any help....
Thanks for the concern..
What environment you are running in?
If it's 32 bit you get OutOfMemoryException at aprox. 500meg memory stream.
static void Main(string[] args)
{
var buffer = new byte[1024 * 1024];
Console.WriteLine(IntPtr.Size);
using (var memoryStream = new MemoryStream())
{
for (var i = 0; i < 100000000; i++)
{
try
{
memoryStream.Write(buffer, 0, 1024);
}
catch (OutOfMemoryException e)
{
Console.WriteLine("Out of memory at {0} meg", i);
break;
}
}
}
Console.ReadKey();
}
If you run on a 64bit os, make sure you build with 'Prefer 32 bit' switch off.
Turn off the switch in project properties:
I would recommend using a FileStream instead of MemoryStream here.
The following code adds nothing, so you can let it go:
workbookStream.Flush() ' Does nothing
workbookStream.Position = 0 ' Does nothing
But the rest is a matter of memory. You need more working memory (RAM) in order to do what you are trying to do. So if you add RAM memory to the machine you should be good to go... Unless you have a 32-bit-machine and run into the 3GB practical RAM limit. In that case you would need to upgrade to a 64-bit-machine where this memory limit is not an issue.
But if you are generating Excel files, you may want to look at ClosedXML instead of using the Excel object model. This is a library that doesn't require Excel on your machine. Have a look at http://www.campusmvp.net/blog/generating-excel-files-like-a-pro-with-closedxml.
I have create a WCF Service that allows uploading large files via BasicHttpBinding using streaming and it is working great! I would like to extended this to show a progress bar (UIProgressView) so that when a large file is being uploaded in 65k chunks, the user can see that it is actively working.
The client code calling the WCF Service is:
BasicHttpBinding binding = CreateBasicHttp ();
BTSMobileWcfClient _client = new BTSMobileWcfClient (binding, endPoint);
_client.UploadFileCompleted += ClientUploadFileCompleted;
byte[] b = File.ReadAllBytes (zipFileName);
using (new OperationContextScope(_client.InnerChannel)) {
OperationContext.Current.OutgoingMessageHeaders.Add(System.ServiceModel.Channels.MessageHeader.CreateHeader("SalvageId","",iBTSSalvageId.ToString()));
OperationContext.Current.OutgoingMessageHeaders.Add(System.ServiceModel.Channels.MessageHeader.CreateHeader("FileName","",Path.GetFileName(zipFileName)));
OperationContext.Current.OutgoingMessageHeaders.Add(System.ServiceModel.Channels.MessageHeader.CreateHeader("Length","",b.LongLength));
_client.UploadFileAsync(b);
}
On the server side, I read the file stream in 65k chuncks and do report back to the calling routine "bytes read", etc. A snippet of code for that is:
using (FileStream targetStream = new FileStream(filePath, FileMode.CreateNew,FileAccess.Write)) {
//read from the input stream in 65000 byte chunks
const int chunkSize = 65536;
byte[] buffer = new byte[chunkSize];
do {
// read bytes from input stream
int bytesRead = request.FileData.Read(buffer, 0, chunkSize);
if (bytesRead == 0) break;
// write bytes to output stream
targetStream.Write(buffer, 0, bytesRead);
} while (true);
targetStream.Close();
}
But I don't know how to hook into the callback on the Xamarin side to receive the "bytes read" versus "total bytes to send" so I can update the UIProgressView.
Has anyone tried this or is this even possible?
Thanks In Advance,
Bo
I saw the sample APIas below
public static byte[] compress( byte[] data )
{
try
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream gzipStream = new GZIPOutputStream( baos, 6, GZIPOutputStream.MAX_LOG2_WINDOW_LENGTH );
gzipStream.write( data );
gzipStream.close();
}
catch(IOException ioe)
{
return null;
}
return baos.toByteArray();
}
But when I tried to compress with a large file with Curve 8900 OS 4.6, I got a "OutOfMemoryError" so I would like to know that how to compress as a chunk small data?
I already tried with this code as below but it doesn't work, compressed file cannot decompress...
file = (FileConnection)Connector.open(_fileOutputPath, Connector.READ_WRITE);
if (!file.exists()) {
file.create();
}
os = file.openOutputStream();
is = FileUtil.getInputStream(_fileInputPath, 0);
int tmpSize = 1024;
byte[] tmp = new byte[tmpSize];
int len = -1;
gzipStream = new GZIPOutputStream( os, 6, GZIPOutputStream.MAX_LOG2_WINDOW_LENGTH );
while((len = is.read(tmp, 0, tmpSize)) != -1) {
gzipStream.write(tmp, 0, len);
}
GZIPOutputStream does not produce a file suitable for use with the gzip command line tool. This is because it doesn't produce the necessary file headers. How did you test decompressing it? You should write a similar Java program that makes use of GZIPInputStream to test, as 'gunzip' is not going to recognize the input.
The problem of the first code sample is that the ByteArrayOutputStream is getting too big for the limited memory of a mobile device.
An option could be to first write to a file (for instance) on SD card.
The second code sample seems fine, but see Michael's answer.
I'm working on a .NET WinForms app that needs to print a FEDEX shipping label. As part of the FedEx api, I can get raw label data for the printer.
I just don't know how to send that data to the printer through .NET (I'm using C#). To be clear, the data is already pre formatted into ZPL (Zebra printer language) I just need to send it to the printer without windows mucking it up.
C# doesn't support raw printing, you'll have to use the win32 spooler, as detailed in this KB article How to send raw data to a printer by using Visual C# .NET.
Hope this helps.
-Adam
I think you just want to send the ZPL (job below) directly to your printer.
private void SendPrintJob(string job)
{
TcpClient client = null;
NetworkStream ns = null;
byte[] bytes;
int bytesRead;
IPEndPoint remoteIP;
Socket sock = null;
try
{
remoteIP = new IPEndPoint( IPAddress.Parse(hostName), portNum );
sock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
sock.Connect(remoteIP);
ns = new NetworkStream(sock);
if (ns.DataAvailable)
{
bytes = new byte[client.ReceiveBufferSize];
bytesRead = ns.Read(bytes, 0, bytes.Length);
}
byte[] toSend = Encoding.ASCII.GetBytes(job);
ns.Write(toSend, 0, toSend.Length);
if (ns.DataAvailable)
{
bytes = new byte[client.ReceiveBufferSize];
bytesRead = ns.Read(bytes, 0, bytes.Length);
}
}
finally
{
if( ns != null )
ns.Close();
if( sock != null && sock.Connected )
sock.Close();
if (client != null)
client.Close();
}
}
A little late, but you can use this CodePlex Project for easy ZPL printing
http://sharpzebra.codeplex.com/
Zebra printers don't use a spooler, it isn't raw printing. It's a markup called ZPL. It's text based, not binary.
I've been working with a printer and ZPL for a while now, but with a Ruby app. Sending the ZPL out to the printer via socket works fine.
To check that it works, I often telnet to the printer and type ^XA^PH^XZ to feed a single label. Hope that helps.