It ended up that I had to force-transmit a carriage return after the ReadFile to "kick" the device using TransmitCommChar. After the "kick" it responds to the next WriteFile with the appropriate response. Using a second PC was going to be my next course of action.
You will have an error which will be a Readtimeout. Why because you set the read timeout to
1 second and execute a read and there won't be any data because you haven't yet sent another
From that moment on you are toast as your code does not ever clear the error condition and
ReadFile will always return with reading zero bytes because you haven't cleared the error.
The big obvious is there isn't even a single GetLastError in your code much less dealing
with the error. The reason the terminal program fixes the problem is at some point they go
and clear the error.
You could try brutal and SetLastError to zero just before the ReadFile .. I don't like it
but it will probably work
While the thread error variable has an error value I am pretty sure that none of the IO
functions will work so I am pretty sure WriteFile will also bail always writing zero
bytes while it's set. It should also return success but the actual bytes written will
always be zero because the fail out is for pre-existing error that hasn't been cleared.
I don't particually like the way you are using the com port but probably the easiest way
to fix you problem is make the ReadFile timeout bail immediately .. so set no timeout on
the read. How to do that is given in the documentation COMMTIMEOUTS structure (Windows)[^]
Quote => "A value of MAXDWORD, combined with zero values for both the ReadTotalTimeoutConstant
and ReadTotalTimeoutMultiplier members, specifies that the read operation is to return
immediately with the bytes that have already been received, even if no bytes have been
That should stop you getting a read timeout which should fix your problem with your current code
and it getting into a block condition. It just means it will spin around your do loop like a crazy
person rather than slow 1 second pace it currently is.
On the plus side it will be more responsive
However you really need to actually put in code to deal with errors, you set the com timeouts
but do nothing if the timeout or any other error actually occurs.
Excellent points and suggestions, and I've implemented much of what you suggested. In the end it turned out the device was waiting for a response from the computer to indicate the read was completed, which I accomplished with a TransmitCommChar. Clunky but it works.
If anyone has a minute can they confirm a weird behaviour of _tcscpy_s which caught me totally off guard that it trashes the unused part of the return buffer.
The code I would like you to test follows, you will need include TCHAR.H for the standard _tcscpy_s function
memset(szFilter, 0, sizeof(szFilter)); // Zero szFilter
_tcscpy_s(szFilter, _countof(szFilter), _T("All files"));
int i = _tcslen(szFilter);
TCHAR Ch1 = szFilter[i + 2]; // Place a debug here .. Ch1 will be trash .. my nice zeroed buffer is toast
memset(szFilter, 0, sizeof(szFilter)); // Zero szFilter
_tcscpy_s(szFilter, _tcslen(_T("All files"))+1, _T("All files"));
TCHAR Ch2 = szFilter[i + 2]; // Place a debug here .. Ch2 will be 0 as expected
What I am interested in is the part of the buffer the result is not written in. What stunned me was it was all trashed.
Okay the function does not define what it does with the unused parts of the buffer but it seems a waste of time to play with it.
The stranger part is if you lie to the function and make it have just the right size buffer it doesn't trash the buffer.
It's so quirky I am trying to work out if it is a machine/processor dependent implementation of the function.
I have seen this before and I think it is to do with the fact that the _s variants are "safe" mode functions. The first thing they do is to overwrite the buffer with some known pattern (hex FEFE in my Unicode test), before doing the copy - at least in Debug mode. You could try a Release mode version and add some code to examine the buffer at each point. A 16 character buffer will be big enough.
Yes it's hex FEFE pattern for me as well. I tried release and it's not there .. must be something to do with debug mode.
That is what was doing my head in a code that would run in release mode but not in debug mode ... now that is a turn up.
Update: David Crowe got the weirdness there is a FILL_STRING call put on the balance of the buffer. I can't for the life of me think why they do it so have referred it to Microsoft as to why debug mode does it, and will work around the behaviour.
You are correct the FILL_STRING is the culprit and no I need the function so will just do the buffer fill long handed. As Richard worked out it isn't there in release mode so it's something to do with debug mode display functions. My guess is it's a pattern for there watch for change implementation.
It did however totally catch me out
Update: Chris correctly identified why it's doing it and how you control it.
It's not a great structure from MS and it look something like this "DXF Files\0*.dxf\0PLT Files\0*.plt\0\0 "
You can't string copy that in because of the terminating 0 characters in it.
For me it's worse "DXF files", "PLT files" is the English version I have German, French etc strings
to replace it so the string changes.
So I have to build that structure and the old code basically relied on the buffer being zeroed
and it just wrote the string bits in without having to track all the string lengths. It was assumed
strcpy doesn't play with parts of the buffer it isn't writing the result into.
So the correct way to write it would be strcpy + strcat + strcat + strcat + strcat(\0).... which I did.
The safe functions mean you have to track the amount of buffer left to pass in and so it becomes
a lot of code for a very trivial thing ... BUT IT'S GUARANTEED TO WORK
So basically while I was trying to debug the program the code was failing because the code relied
on something not guaranteed. For such a simple string structure its a pain to have to make code
track multiple string pointers just to create it but I should have done it .. lesson 1 never assume
anything not actually specified!!!!
The bigger issue for me and why I went after it was performance. If they are playing around with
stuff they don't need to they are wasting time. String functions are used often and everywhere
and on very large memory blocks and I was concerned about the impact.
But yes that is a static create but my strings are coming from memory the user can switch language on the fly and the number of types of file that can be loaded depends on version purchased. Bascially I can't possible do it with static strings I have to build the string into an array and pass the pointer to the array. The array is created and disposed of by the dialog and all very normal when doing multilingual dialog functions.
Many of the string bits are coming from windows via the locale API and heaven only knows how long they are and where they are coming from in memory.
I need the array because I have to assemble all the string somewhere.
I would like to see a dynamic form of your code without allocating an array on the heap or local stack
Anyhow it's all working now, the performance was more the issue to me and that is resolved.
_tcscpy_s and it's variants only guarantee that the string will be copied IF it fits. I suspect that the compiler "figured out" that it could safely optimize the copy using 32 or 64 bit chunks. This would result in satisfying the condition that the string be null terminated, but would also end up copying random data stored after the original string.
I am new in MFC vc++ Please help me to come out from an major issue.
I want to move an object(Image,Rectangle) ..etc in Canvas buy using Arrow Key(left,right,up,down) in MFC VC++ application.only i get OnKeyDown()function I am not able to use this OnKeyDown()function to get keyboard event.
I am learning how to use ellipsis in function.
Started with putting "int" as parameters, with first entry being count of parameters passed to he function.
Now I want to pass multiple types , not just int , to the function.
The following snippet will do, but...
How do you get "type" from passing a char * - in this case "format" variable?
What did I missed ?
That code looks like it should broadly work, but you are assuming any 's', 'c', or 'd' in the string is a format identifier. Your main loop should iterate the characters of the format string, copying them to the output until you see a format specifier. When you see a '%' character then you know that is the start of a formatting sequence so you need to get the width, precision and type details. Once you have extracted all those values, then you can process the next argument according to the type field character.