Reputation: 2417
I have inherited a printer helper class that can be used to send information directly to a printer. It can handle a file, string, or raw bytes. For files and strings it first converts them to bytes, and uses the bytes method to do the sending.
My problem is the file method is failing to set all the necessary variables for the bytes method to succeed. See the method below:
// Open the file.
FileStream fs = new FileStream(szFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
// Create a BinaryReader on the file.
BinaryReader br = new BinaryReader(fs);
// Dim an array of bytes big enough to hold the file's contents.
Byte[] bytes = new Byte[fs.Length];
bool bSuccess = false;
// Your unmanaged pointer.
IntPtr pUnmanagedBytes = new IntPtr(0);
int nLength;
nLength = Convert.ToInt32(fs.Length);
// Read the contents of the file into the array.
bytes = br.ReadBytes(nLength);
// Allocate some unmanaged memory for those bytes.
pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);
// Copy the managed byte array into the unmanaged array.
Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength);
// Send the unmanaged bytes to the printer.
bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength);
// Free the unmanaged memory that you allocated earlier.
Marshal.FreeCoTaskMem(pUnmanagedBytes);
return bSuccess;
The point of failure seems to be nLength = Convert.ToInt32(fs.length);
coming out as 0
, even though the stream itself has all the correct data. If I put a breakpoint at that point then it will always work. If I put it below at the SendBytesToPrinter
call, it nLength
will be 0
.
My workaround for now is to have use Thread.Sleep(1000);
right before the conversion, but that's too hacky for my taste.
Is there some characteristic of the FileStream that is causing this issue, or is something wrong with the code here?
EDIT: To clarify something, I'm fully aware of the difference between a long
and int
. The files used do not cause a problem with this. I can run the same file through a dozen times with and without the pause and it will always fail without the pause.
EDIT #2: Brandon's answer didn't solve the problem directly, but the new approach to working with the file revealed an issue with the download method used to get the file in the first place. I'm marking his answer as accepted because not only did it lead me to the real problem, but it's a cleaner way of handling the method in general.
Upvotes: 0
Views: 468
Reputation: 1330
Instead of relying on the filestream for length, maybe you can rely on the length of the returned byte array:
// Read bytes in from file, capture length of returned array
var bytes = File.ReadAllBytes(szFileName);
var nLength = bytes.Length;
// Your unmanaged pointer.
IntPtr pUnmanagedBytes = new IntPtr(0);
// Allocate some unmanaged memory for those bytes.
pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);
// Copy the managed byte array into the unmanaged array.
Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength);
// Send the unmanaged bytes to the printer.
var bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength);
// Free the unmanaged memory that you allocated earlier.
Marshal.FreeCoTaskMem(pUnmanagedBytes);
return bSuccess;
Upvotes: 1