cout<<"getting in issue read operation"<<endl;
ReadFile(hSerial, readbuff, dwBytesRead, &dwBytesRead, NULL);
cout<<"error: "<<GetLastError()<<endl;
if (!ReadFile(hSerial, readbuff, dwBytesRead, &dwBytesRead, NULL))
{
if (GetLastError() != ERROR_IO_PENDING)
cout << "Error in communications; report it.";
else
fWaitingOnRead = TRUE;
}
else
{
cout << "no waiting\n";
cout << "no. of bytes read: " <<dwBytesRead << endl;
cout<<"read buff: ";
for (DWORD i = 0; i < sizeof(writebuff); i++)
{
cout<< readbuff[i];`enter code here`
}
cout<<endl;
}
i cant understand whats going wrong coz each tym i have 0 bytes read.....
help me plzzz.....
You must check the value returned by ReadFile. Call GetLastError only if ReadFile returns zero.
ReadFile parameter 3 should be the size of your buffer. Parameter 4 should be a separate variable that will receive the number of bytes actually read.
Since you are passing NULL for Parameter 5 you will not get overlapped operation, so ReadFile will never return ERROR_IO_PENDING.
You may have more success if you use a proven library for serial port operations, such as this one:
http://www.naughter.com/serialport.html
Related
I am trying to read data all of the data in a PCAPNG file in chunks only using the Windows API's.
I have the first read of the file working with ReadFile and the data that is being returned is correct but on our subsequent call, we are failing the ReadFile with INVALID_HANDLE.
HANDLE hFile;
DWORD dwBytesToRead = 32;
DWORD dwBytesRead = 0;
DWORD ReadBuffer[2] = {0};
hFile = CreateFile(LogPath.c_str(),
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(hFile == INVALID_HANDLE_VALUE)
return false;
while(ReadFile(hFile, ReadBuffer, dwBytesToRead, &dwBytesRead, NULL) && dwBytesRead > 0)
{
std::cout << "Data from ReadBuffer[0]: " << ReadBuffer[0] << std::endl;
std::cout << "Data from ReadBuffer[1]: " << ReadBuffer[1] << std::endl;
}
std::cout << "Failed with: " << GetLastError() << std::endl;
CloseHandle(hFile);
During the first iteration of the ReadFile, we are able to successfully read the content of the file but on the second iteration of the loop we run into an error of INVALID_HANDLE.
Basing this ReadFile loop on this documentation: https://learn.microsoft.com/en-us/windows/win32/fileio/appending-one-file-to-another-file
I am not sure what our failure reason is.
I've done some testing with SetFilePointer and the OVERLAPPED structure but I haven't had much success with either.
Am I misunderstanding the ReadFile API or is this not the right way to do what I am looking for?
You're reading 32 bytes into a buffer that is only 8 bytes long.
You need to either change ReadBuffer to be larger, change the type from a DWORD to something that is 16 bytes long, or change dwBytesToRead to be the appropriate size (sizeof(ReadBuffer), and change the declaration order).
I`m struggling for the past many hours with the following problem: I try to read a file using CreateFile and ReadFile methods.
Here is the code:
char* Utils::ReadFromFile(wchar_t* path) {
HANDLE hFile = CreateFile(
path, // long pointer word string file path (16 bit UNICODE char pointer)
GENERIC_READ, // access to file
0, // share mode ( 0 - prevents others from opening/readin/etc)
NULL, // security attributes
OPEN_EXISTING, // action to take on file -- returns ERROR_FILE_NOT_FOUND
FILE_ATTRIBUTE_READONLY, // readonly and offset possibility
NULL // when opening an existing file, this parameter is ignored
);
if (hFile == INVALID_HANDLE_VALUE) {
std::cout << "File opening failed" << endl;
std::cout << "Details: \n" << Utils::GetLastErrorMessage() << endl;
CloseHandle(hFile);
hFile = NULL;
return nullptr;
}
LARGE_INTEGER largeInteger;
GetFileSizeEx(hFile, &largeInteger);
LONGLONG fileSize = largeInteger.QuadPart;
if (fileSize == 0) {
std::cout << "Error when reading file size" << endl;
std::cout << "Details: \n" << Utils::GetLastErrorMessage() << endl;
CloseHandle(hFile);
hFile = NULL;
return nullptr;
}
cout << "File size: " << fileSize << endl;
char* bytesRead;
bytesRead = new char(fileSize);
int currentOffset = 0;
int attempts = 0;
int nBytesToBeRead = BYTES_TO_READ;
//DWORD nBytesRead = 0;
OVERLAPPED overlap{};
errno_t status;
while (currentOffset < fileSize) {
overlap.Offset = currentOffset;
if (fileSize - currentOffset < nBytesToBeRead)
nBytesToBeRead = fileSize - currentOffset;
status = ReadFile(
hFile, // file handler
bytesRead + currentOffset, // byted read from file
nBytesToBeRead, // number of bytes to read
NULL, // number of bytes read
&overlap // overlap parameter
);
if (status == 0) {
std::cout << "Error when reading file at offset: " << currentOffset << endl;
std::cout << "Details: \n" << Utils::GetLastErrorMessage() << endl;
attempts++;
std::cout << "Attempt: " << attempts << endl;
if (attempts == 3) {
cout << "The operation could not be performed. Closing..." << endl;
CloseHandle(hFile);
hFile = NULL;
return nullptr;
}
continue;
}
else {
cout << "Read from offset: " << currentOffset;// << " -- " << overlap.InternalHigh << endl;
currentOffset += nBytesToBeRead;
if (currentOffset == fileSize) {
cout << "File reading completed" << endl;
break;
}
}
}
CloseHandle(hFile);
return bytesRead;
}
When running this method I get some weird results:
One time it worked perfectly
Very often I get Access violation reading location for currentOffset variable and overlap.InternalHigh ( I commented last one), with last method from CallStack being
msvcp140d.dll!std::locale::locale(const std::locale & _Right) Line 326 C++
Sometimes the function runs perfectly, but I get access violation reading location when trying to exit main function with last method from CallStack being
ucrtbased.dll!_CrtIsValidHeapPointer(const void * block) Line 1385 C++
I read the windows documentation thoroughly regarding the methods I use and checked the Internet for any solution I could find, but without any result. I don't understand this behaviour, getting different errors when running cod multiple times, and therefore I can`t get to a solution for this problem.
Note: The reason I am reading the file in repeated calls is not relevant. I tried reading with a single call and the result is the same.
Thank you in advance
You are allocating a single char for bytesRead, not an array of fileSize chars:
char* bytesRead;
bytesRead = new char(fileSize); // allocate a char and initialize it with fileSize value
bytesRead = new char[fileSize]; // allocate an array of fileSize chars
I created 2 functions to read and write across a serial port, I am coding in c++ with visual studios 2012, windows 7, 64 bit operating system, and using RS-232 serial cord. The board I'm connecting to is supposed to send 5 characters, TRG 1, upon pressing a button, the code works, however the output isn't always the correct values.
char serialRead()
{
char input[5];
DCB dcBus;
HANDLE hSerial;
DWORD bytesRead, eventMask;
COMMTIMEOUTS timeouts;
hSerial = CreateFile (L"\\\\.\\COM13", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hSerial == INVALID_HANDLE_VALUE)
{
cout << "error opening handle\n";
}
else
{
cout << "port opened\n";
}
dcBus.DCBlength = sizeof(dcBus);
if ((GetCommState(hSerial, &dcBus) == 0))
{
cout << "error getting comm state\n";
}
dcBus.BaudRate = CBR_9600;
dcBus.ByteSize = DATABITS_8;
dcBus.Parity = NOPARITY;
dcBus.StopBits = ONESTOPBIT;
if ((GetCommState(hSerial, &dcBus) == 0))
{
cout << "error setting comm state\n";
}
if ((GetCommTimeouts(hSerial, &timeouts) == 0))
{
cout << "error getting timeouts\n";
}
timeouts.ReadIntervalTimeout = 10;
timeouts.ReadTotalTimeoutMultiplier = 1;
timeouts.ReadTotalTimeoutConstant = 500;
timeouts.WriteTotalTimeoutMultiplier = 1;
timeouts.WriteTotalTimeoutConstant = 500;
if (SetCommTimeouts(hSerial, &timeouts) == 0)
{
cout << "error setting timeouts\n";
}
if (SetCommMask(hSerial, EV_RXCHAR) == 0)
{
cout << "error setting comm mask\n";
}
if (WaitCommEvent(hSerial, &eventMask, NULL))
{
if (ReadFile(hSerial, &input, 5, &bytesRead, NULL) !=0)
{
for (int i = 0; i < sizeof(input); i++)
{
cout << input[i];
}
cout << endl;
}
else
{
cout << "error reading file\n";
}
}
else
{
cout << "error waiting for comm event\n";
}
switch (input[4])
{
case '1' :
CloseHandle(hSerial);
return '1';
break;
case '2' :
CloseHandle(hSerial);
return '2';
break;
case '3' :
CloseHandle(hSerial);
return '3';
break;
case '4' :
CloseHandle(hSerial);
return '4';
break;
case '5':
CloseHandle(hSerial);
return '5';
break;
default :
CloseHandle(hSerial);
return '9';
break;
}
}
The code runs successfully in the sense that the port is configured correctly and data is being transmitted. The output varies, most of the time the output will print the whole "TRG 1", but randomly (it seems), the output will be "TRG|}|}" or "T|}|}|}|}", i.e. it will be part of the string and every character missing will be replaced with a "|}" instead of the correct characters. This is a problem because I want to be able to send it different values for trigger and run the switch of that variable.
I'm relatively new to serial communication and not an expert programmer so I'm wondering what's going on?
Serial communication is not packet-based. The information doesn't come to you in packages where the entire message can necessarily be read in one go; instead, it's a stream, so you could read half a message, a whole message, more than one message, etc.
As zdan said in the comments, you need to check the number bytes read from ReadFile and use that to compose 5-character packages which are your messages.
Specifically, only the first couple of characters up to the returned number of bytes read are valid; the rest are garbage.
At the time we are trying to create an interface for serial communication, to be able to communicate with a microprocessor.
Actually - everything works fine. Almost!
To be able to communicate with our controller, we need to sync up with it. To do this, we write a string: "?0{SY}13!", and the controller should then reply with "!0{SY}F5?" to accept the request for sync.
To do this, we use a writeData function (that works - we know that by using echo), and after that we use a readData to read the answer.
The problem is that, for some reason, it will not read anything. Though it returns 1 for success, the chars it reads is constanly " " (nothing).
Now comes the weird part - if we use an external terminal program to initialize the port (like putty), and then close the program, then everything works fine. It accepts the sync request, answers (and we can read it), and then we can do all that we want. But unless we use an external program to initialize the port, it doesn't work.
The constructor for the initializing the interface looks like this:
SerialIF::SerialIF(int baud, int byteSize, int stopBits, char* parity, int debug)
{
string coutport = getPort();
wstring wideport;
debug_ = debug; //Debuglevel
sync = false; //sync starts with false
error = false; //Error false as beginnging
//this is just for converting to the right type
for (int i = 0; i < coutport.length(); i++)
{
wideport += wchar_t(coutport[i]);
}
const wchar_t* port = wideport.c_str();
SerialIF::hserial = CreateFile(port,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if (hserial == INVALID_HANDLE_VALUE)
{
if (GetLastError() == ERROR_FILE_NOT_FOUND)
{
if (debug_ != LOW)
{
cout << "[-] Port " << coutport << "doesn't exist." << endl;
}
}
if (debug_ != LOW)
{
cout << "[-] Handle error - is there another terminal active?" << endl;
}
error = true;
}
DCB dcbParms = { 0 };
dcbParms.DCBlength = sizeof(dcbParms);
if (!GetCommState(hserial, &dcbParms))
{
if (debug_ != LOW)
{
cout << "[-] Couldn't get status from port " << coutport << endl;
}
error = true;
}
if (!error)
{
setBaud(dcbParms, baud);
setParity(dcbParms, parity);
setByteSize(dcbParms, byteSize);
setStopbits(dcbParms, stopBits);
if (debug_ == HIGH)
{
cout << "[+] Serial port " << coutport << " has been activated. \nBaud-rate: " << baud << "\nParity: "
<< parity << "\nStop bits: " << stopBits << endl;
}
}
else if (debug_ != LOW)
{
cout << "[-] Port not initialized" << endl;
}
}
This should work - I really don't know why it shouldn't. It returns no errors, I've tried A LOT of error searching the last couple of days, I tried timeouts, I tried other ways of building it, but it all boils down to the same problem.
Why wont this initialize the port?
EDIT:
The output when trying to sync:
Can't post pictures due to lack of reputation. though it outputs as follows:
[+] Serial port COM1 has been activated.
Baud-rate: 9600
Parity: NONE
Stop bits: 1
[+] -> ?0{SY}13! is written to the port.
((And this is where it goes in to the infinite loop reading " "))
EDIT: code for read:
const int bytesToRead = 1; //I byte pr læsning
char buffer[bytesToRead + 1] = { 0 }; //Bufferen til data
DWORD dwBytesRead = 0; //Antal bytes læst
string store; //Store - den vi gemmer den samlede streng i
bool end = false; //Kontrolvariabel til whileloop.
while (end == false)
{
if (ReadFile(hserial, buffer, bytesToRead, &dwBytesRead, NULL))
/*Readfile læser fra interfacet vha. hserial som vi oprettede i constructoren*/
{
if (buffer[0] == '?') //Da protokollen slutter en modtaget streng med "?", sætter vi end til true
{ //Hvis denne læses.
end = true;
}
store += buffer[0];
}
else
{
if (debug_ != LOW)
{
cout << "[-] Read fail" << endl; //Hvis readfile returnerer false, så er der sket en fejl.
}
end = true;
}
}
if (debug_ == HIGH)
{
cout << "[+] Recieved: " << store << endl; //I forbindelse med debug, er det muligt at få udsrkevet det man fik ind.
}
recentIn = store; //RecentIN brugES i andre funktioner
if (verify()) //Som f.eks. her, hvor vi verificerer dataen
{
if (debug_ == HIGH)
{
cout << "[+] Verification success!" << endl;
}
return convertRecData(store);
}
else
{
if (debug_ != LOW)
{
cout << "[-] Verification failed." << endl;
}
vector <string> null; //Returnerer en string uden data i, hvis der er sket en fejl.
return null;
}
You never call SetCommState.
I'm not sure where your functions setBaud,setParity etc. come from, but I can't see how they can actually modify the serial port, as they don't have access to the comm device's handle.
ReadFile() can return success even when zero bytes are read. Use dwBytesRead to find the actual number of received characters.
while (ReadFile(hserial, buffer, 1, &dwBytesRead, NULL))
{
if (dwBytesRead != 0)
{
store += buffer[0];
if (buffer[0] == '?')
{
end = true;
break;
}
}
}
Had a similar problem between a PC and an arduino nano clone including a CH340. This post was the only one which discribes my problem very good.
I solved it by switching off DTR (data-terminal-ready) and RTS (request-to-send) flow control, which is normaly activated after (re)start the PC or plugging in the arduino. I found a descrition of this parameters in the documentation of DCB
I know that shis post is very old but maybe i can help somebody else with this idea/solution.
I am using ReadFile to read a simple string that I wrote to a file using WriteFile.
Have a simple string: "Test string, testing windows functions".
Used WriteFile to write that to a file.
Now I want to use ReadFile to confirm that it was written to the file. I need to compare what I read to the original string above. To Read from the file I have
DWORD dwBytesRead;
char buff[128];
if(!ReadFile(hFile, buff, 128, &dwBytesRead, NULL))
//Fail
The function returns true so it is reading from the file. The problem is buff is full of just ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ. I've never come across LPVOID before so I don't know if it is something there or what. Is there a way to do this string comparison?
EDIT: The code i use to write to the file is quite simple:
if(!WriteFile(hFile, sentence.c_str(), sentence.length(), &bytesWritten, NULL))
{
//FAIL
}
The file pointer needs rewound after the WriteFile() and before the ReadFile(). As it stands, ReadFile() does not fail but reads zero bytes thus buff is unchanged. As buff is uninitialised it contains junk. To rewind the file pointer to the beginning of the file use SetFilePointer():
#include <windows.h>
#include <iostream>
#include <string>
int main()
{
HANDLE hFile = CreateFile ("myfile.txt",
GENERIC_WRITE | GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile)
{
std::string sentence("a test");
DWORD bytesWritten;
if (WriteFile(hFile,
sentence.c_str(),
sentence.length(),
&bytesWritten,
NULL))
{
if (INVALID_SET_FILE_POINTER != SetFilePointer(hFile,
0,
0,
FILE_BEGIN))
{
char buf[128] = { 0 }; /* Initialise 'buf'. */
DWORD bytesRead;
/* Read one less char into 'buf' to ensure null termination. */
if (ReadFile(hFile, buf, 127, &bytesRead, NULL))
{
std::cout << "[" << buf << "]\n";
}
else
{
std::cerr << "Failed to ReadFile: " <<
GetLastError() << "\n";
}
}
else
{
std::cerr << "Failed to SetFilePointer: " <<
GetLastError() << "\n";
}
}
else
{
std::cerr << "Failed to WriteFile: " << GetLastError() << "\n";
}
CloseHandle(hFile);
}
else
{
std::cerr << "Failed to open file: " << GetLastError() << "\n";
}
return 0;
}
The function returns true so it is reading from the file. The problem is buff is full of just ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ.
ReadFile only fills the buffer up to the value of dwBytesRead. If you're trying to work with a string, you'll have to null terminate it yourself after ReadFile returns:
buff [dwBytesRead] = 0;
You should not use 128 as the nNumberOfBytesToRead, since you can get out of bounds while printing the string (or otherwise considering buff as a 0-terminated string). Also check dwBytesRead if it really reads that many bytes, and 0-terminate the string as suggested by #James McLaughlin.