I want to send mark to parallel port using C++ in winXP system. I checked the information and wrote the following code:
HANDLE parallelPort = CreateFile(L"LPT1", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if(parallelPort == INVALID_HANDLE_VALUE)
std::cout << "handle error" << std::endl;
int *data = new int[1];
data[0] = 4;
WriteFile(parallelPort, data, sizeof(int), NULL, NULL);
std::cout << "send success!" << std::endl;
CloseHandle(parallelPort);
I run this code, find parallelPort != INVALID_HANDLE_VALUE . But it doesn't print send success!. What's wrong with this code?
If you have used the software named "E-prime", I want to do the same as it:
WritePort &H378, 0
Related
I am working on an application which creates a Windows pseudoconsole (using the new ConPTY API).
It starts a PowerShell session (for test), and shows everything ConPTY sends from that session via the pseudoconsole, and everything works really well. Until I redirect the parent program output to anywhere.
Here's my full code listing for reference.
#include <string>
#include <stdexcept>
#include <iostream>
#include <vector>
#include <Windows.h>
using namespace std::string_literals;
void throwLastError(int number)
{
throw std::runtime_error("Error "s + std::to_string(number) + ": "s + std::to_string(GetLastError()));
}
STARTUPINFOEXW prepareStartupInformation(HPCON hPCon)
{
STARTUPINFOEXW startupInfo{sizeof(STARTUPINFOEXW)};
SIZE_T bytesRequired = 0;
if (InitializeProcThreadAttributeList(nullptr, 1, 0, &bytesRequired))
throw std::runtime_error("InitializeProcThreadAttributeList wasn't expected to succeed at that time.");
const auto threadAttributeList = static_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(calloc(bytesRequired, 1));
startupInfo.lpAttributeList = threadAttributeList;
if (!InitializeProcThreadAttributeList(threadAttributeList, 1, 0, &bytesRequired))
throwLastError(4);
if (!UpdateProcThreadAttribute(
threadAttributeList,
0,
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
hPCon,
sizeof(HPCON),
nullptr,
nullptr)
)
throwLastError(5);
return startupInfo;
}
PROCESS_INFORMATION startProcess(STARTUPINFOEXW startupInfo, const std::wstring &commandLine)
{
std::vector<wchar_t> cmdLineBuffer;
for (auto x : commandLine)
cmdLineBuffer.push_back(x);
cmdLineBuffer.push_back(L'\0');
PROCESS_INFORMATION processInfo{nullptr};
if (!CreateProcessW(
nullptr,
cmdLineBuffer.data(),
nullptr,
nullptr,
FALSE,
EXTENDED_STARTUPINFO_PRESENT,
nullptr,
nullptr,
&startupInfo.StartupInfo,
&processInfo)
)
throwLastError(6);
return processInfo;
}
int main()
{
auto h = GetStdHandle(STD_OUTPUT_HANDLE);
auto type = GetFileType(h);
std::cout << "STD_OUTPUT_HANDLE " << h << " " << type << std::endl;
try
{
HANDLE inPipeRead = nullptr, inPipeWrite = nullptr;
if (!CreatePipe(&inPipeRead, &inPipeWrite, nullptr, 0))
throwLastError(1);
HANDLE outPipeRead = nullptr, outPipeWrite = nullptr;
if (!CreatePipe(&outPipeRead, &outPipeWrite, nullptr, 0))
throwLastError(2);
HPCON hPCon = nullptr;
if (CreatePseudoConsole(COORD { 80, 25 }, inPipeRead, outPipeWrite, 0, &hPCon) != S_OK)
throwLastError(3);
CloseHandle(inPipeRead);
CloseHandle(outPipeWrite);
auto startupInfo = prepareStartupInformation(hPCon);
auto processInfo = startProcess(startupInfo, L"powershell.exe");
std::cout << "PID: " << processInfo.dwProcessId << "\nTID: " << processInfo.dwThreadId << "\n";
char buffer[1024];
DWORD readBytes = 0;
while (ReadFile(
outPipeRead,
buffer,
sizeof buffer - 1,
&readBytes,
nullptr
))
{
buffer[readBytes] = 0;
std::cout << "Read bytes: " << readBytes << "\n";
std::cout << buffer << "\n";
}
}
catch (const std::runtime_error &x)
{
std::cerr << x.what() << "\n";
}
}
So, if I start this program from terminal or from an IDE, it works (and tells how much data it has read from the PTY pipe). But if I start it with output redirected (e.g. myprogram.exe > C:\Temp\somefile.txt, or even myprogram.exe | out-host in pwsh), then it stops working: the PowerShell then somehow inherits the stdin and stdout and doesn't write anything to the PTY pipe.
For diagnostics, I've added output of GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)), which helps to detect if the output has been redirected (since it's not always obvious in practice). For pristine stdout, it should write 2, and other numbers for other output modes.
How can I overcome this issue? Is it possible for my program to work even if its own stdout/stderr were redirected somewhere? I thought one of the points of PTY was to create a separate isolated environment, which won't interfere with the parent one.
This got answered dy Dustin L. Howett on Microsoft Terminal issue tracker:
A-ha! We did do some work to improve handle inheritance, but only if the inherited handles were console handles (so: the spawned application would connect to its parent's stdin/stdout even if it was supposed to be using a pseudoconsole)
//
// If we are establishing a Pseudoterminal Connection, close
// any in/out/err handles that may have been copied from the parent.
// We will re-make new connections to the given PTY instead of
// using the automatically inherited handles.
//
if ((ProcessParameters->ConsoleFlags & CONSOLE_USING_PTY_REFERENCE) != 0)
{
ConsoleCloseIfConsoleHandle(&ProcessParameters->StandardInput);
ConsoleCloseIfConsoleHandle(&ProcessParameters->StandardOutput);
ConsoleCloseIfConsoleHandle(&ProcessParameters->StandardError);
}
We didn't do the same for all other inherited handles, so... I'm going to file a bug on the docs to make sure we document the need for STARTF_USESTDHANDLES.
So, for such cases, it's required to pass STARTF_USESTDHANDLES in startupInfo.StartupInfo.dwFlags.
I am trying to learn how named pipes work, and created 2 consoles to test the connectivity between server and client. Client will send a message to the server and the server will display the message, but instead of the message, it returns a value of "nullptr" as shown in the error exception break from VS.
below are my codes, do enlighten me if you found any problem with my code, and I am still learning..
Server.cpp
#include "cust_ostream.hpp"
#include <Windows.h>
#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
LPVOID buffer = NULL;
DWORD readbyte;
cout << "---Named Pipe Server Test---" << endl << endl;
cout << "Creating named pipe: \\\\.\\pipe\\mypipe" << endl;
HANDLE hPipe = CreateNamedPipeA("\\\\.\\pipe\\mypipe", PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES, 1024, 1024, 0, NULL);
if (!hPipe || hPipe == INVALID_HANDLE_VALUE)
{
cout << "Pipe creation failed." << endl;
return 0;
}
cout << "Connecting pipe to client..." << endl;
BOOL connect = ConnectNamedPipe(hPipe, NULL);
if (!connect)
{
cout << "Connect named pipe failed" << endl;
}
cout << "Success! Reading pipe message from client..." << endl;
ReadFile(hPipe, buffer, sizeof(buffer), &readbyte, NULL);
c_cout << "Pipe message = " << *(int *)buffer << endl;
_getch();
return 0;
}
cust_ostream.hpp
#include <Windows.h>
#include <iostream>
#include <sstream>
using namespace std;
#define endl "\n"
class cust_ostream
{
public:
~cust_ostream()
{
cout << m_buffer.str();
}
template <typename T>
cust_ostream &operator<<(T const &value)
{
m_buffer << value;
return *this;
}
private:
ostringstream m_buffer;
};
#define c_cout cust_ostream()
and my client
#include <Windows.h>
#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
LPVOID data;
DWORD writebyte;
int i = 2;
cout << "---Named Pipe Client---" << endl << endl;
cout << "Creating pipe file: \\\\.\\pipe\\mypipe" << endl;
HANDLE pipe = CreateFileA("\\\\.\\pipe\\mypipe", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (!pipe || pipe == INVALID_HANDLE_VALUE)
{
cout << "Pipe client failed." << endl;
return 0;
}
cout << "Pipe connected to server, sending data..." << endl;
WriteFile(pipe, &i, sizeof(i), &writebyte, NULL);
_getch();
return 0;
}
You need to wait for the NamedPipe to have a ConnectPipeReady event on it. As it stands, you are trying to create the pipe without actually seeing if it was succesfull. See the MSDN documentation for Named Pipes here: https://msdn.microsoft.com/en-ca/library/windows/desktop/aa365592(v=vs.85).aspx
Specifically, this block:
while (1)
{
hPipe = CreateFile(
lpszPipename, // pipe name
GENERIC_READ | // read and write access
GENERIC_WRITE,
0, // no sharing
NULL, // default security attributes
OPEN_EXISTING, // opens existing pipe
0, // default attributes
NULL); // no template file
// Break if the pipe handle is valid.
if (hPipe != INVALID_HANDLE_VALUE)
break;
// Exit if an error other than ERROR_PIPE_BUSY occurs.
if (GetLastError() != ERROR_PIPE_BUSY)
{
_tprintf( TEXT("Could not open pipe. GLE=%d\n"), GetLastError() );
return -1;
}
// All pipe instances are busy, so wait for 20 seconds.
if ( ! WaitNamedPipe(lpszPipename, 20000))
{
printf("Could not open pipe: 20 second wait timed out.");
return -1;
}
}
Also you shouldn't use #define endl "\n", use std::endl
You have initialized your buffer as NULL which means that by default its length is zero. Now when you use the sizeof operator in your read function in server (to retrieve the message received by server from client), what happens is that you are asking the sizeof operator in Read function to read 0 bytes! which means that nothing will be read.
To solve this, you can declare a char array of size 100 or a size of a message which you are sure that won't be exceeded by client. Like if you are assuming that message by client is not going to be longer than lets say 60 characters, then you can create your char buffer to be of size 100 just to make sure that you do accommodate all the message by client.
And one more thing, if problem still persists, instead of using sizeof in read, use 100 or whatever the size of of your char buffer array. This should solve your problem.
I'm running the following code with administrator privileges:
HANDLE hDevice = INVALID_HANDLE_VALUE; // handle to the drive to be examined
BOOL bResult = FALSE; // results flag
DWORD junk = 0; // discard results
hDevice = CreateFileW(L"\\\\.\\PhysicalDrive0", // drive to open
0, // no access to the drive
FILE_SHARE_READ | // share mode
FILE_SHARE_WRITE,
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
NULL); // do not copy file attributes
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
std::cout << "invalid handle" << std::endl;
return -1;
}
std::cout << "handle " << hDevice << std::endl;
DRIVE_LAYOUT_INFORMATION_EX drv_layout_info_ex;
CREATE_DISK disk;
INT n;
ZeroMemory(&disk, sizeof(CREATE_DISK));
disk.PartitionStyle = PARTITION_STYLE_MBR;
disk.Mbr.Signature = 0x7B060725;
bResult = ::DeviceIoControl(hDevice, IOCTL_DISK_CREATE_DISK, &disk,
sizeof(CREATE_DISK), NULL,
0, &junk, NULL);
if (!bResult)
{
std::cout << "IOCTL_DISK_CREATE_DISK failed due to " << GetLastError() << std::endl;
return FALSE;
}
I get the output:
handle 00000048
IOCTL_DISK_CREATE_DISK failed due to 5
Which is access denied. What is the problem?
I created a program to read serial data from a COM port using C++, however due to changes in my project I have to read data from a BT port. Since Im using a bluetooth adapter to connect my computer to the device I expected the reading process to be the same but apparently it is not. Since Im using the Window OS to perform this task GetLastError() returns 2 which means the specified file is not found. However when I use Arduino's serial monitor the data is read just fine. Does anyone know how to read from a BT port in C++? Im using Windows 8 by the way, here is my code:
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
///-----------------------------Open port-----------------------------------------------------------------
// Name of port where device is found
LPCWSTR port = L"COM40";
// Open port for reading
HANDLE hComm = ::CreateFile(port, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
// Check if port has been opened succesfully
if (hComm == INVALID_HANDLE_VALUE) std::cout << "Failed to open " << port << " error: " << GetLastError() << std::endl;
else std::cout << port << " has been opened succesfully\n";
///-----------------------------Configure port------------------------------------------------------------
// Create DCB structure
DCB dcb = { 0 };
// Get Comm state
if (!::GetCommState(hComm, &dcb)) std::cout << "Failed to get Comm state, error: " << GetLastError() << std::endl;
// Configure strcutre
dcb.DCBlength = sizeof(DCB);
// Set Baud rate
dcb.BaudRate = CBR_9600;
// Set number of bytes in bits that are recieved through the port
dcb.ByteSize = 8;
dcb.StopBits = ONESTOPBIT;
// Check if port has been configured correctly
if (!::SetCommState(hComm, &dcb)) std::cout << "\nFailed to set Comm State, error: " << GetLastError();
else std::cout << "Comm state has been set succesfully\n";
///-----------------------------Read data-------------------------------------------------------------------
char buffer;
DWORD maxBytes = 1;
if (!::ReadFile(hComm, &buffer, maxBytes, NULL, NULL)) std::cout << "\nFailed to read from " << port << " error: " << GetLastError() << std::endl;
else std::cout << "File has been read succesfully\n";
///-----------------------------Write to text file----------------------------------------------------------
std::fstream file;
int counter = 0;
// Writing to text file will be done later
while (ReadFile(hComm, &buffer, maxBytes, NULL, NULL))
{
std::cout << buffer;
}
///-----------------------------Close port------------------------------------------------------------------
CloseHandle(hComm);
file.close();
std::cout << "\nCOM40 has been closed!\n";
return 0;
}
I am trying to make RS-232 communication between the PC and the PC MCU PIC. So I started making the PC program first in C++, and it was errorless, and according to the cout I made to output the status it should be working, but I wanted to be sure. So I downloaded Hyperterminal and connected Tx to Rx pin in serial com port, but whenever I try to connect the hyperterminal it gives an error, saying access denied (error 5) when I try to run my C++ program. I don't understand where the problem really is. Here's the full code, if the problem was the code's, just to make sure:
main.c:
#include <windows.h>
#include <winbase.h>
#include <iostream>
PDWORD sent;
char buf;
int main(){
DCB serial;
HANDLE hserial = CreateFile("\\\\.\\COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
serial.DCBlength = sizeof(DCB);
serial.BaudRate = CBR_9600;
serial.fBinary = true;
serial.fParity = false;
serial.ByteSize = 8;
serial.Parity = NOPARITY;
serial.StopBits = ONESTOPBIT;
char result = BuildCommDCB("baud=9600 parity=N data=8 stop=1", &serial);
if(result != 0){
std::cout << "DCB Structure Successfully Created!" << std::endl;
}else{
std::cout << "DCB Structure Creation Failed!" << std::endl;
}
if(hserial != INVALID_HANDLE_VALUE){
std::cout << "COM Port Handle Successfully Created!" << std::endl;
}else{
std::cout << "COM Port Handle Creation Failed!" << std::endl;
std::cout << GetLastError() << std::endl;
}
char res = WriteFile(hserial, "0xFF", 1, sent, NULL);
if(res != 0){
std::cout << "Writing to COM Port Successfull!" << std::endl;
}else{
std::cout << "Writing to COM Port Failed!" << std::endl;
std::cout << GetLastError() << std::endl;
}
CloseHandle(&hserial);
return 0;
}
Only one program at a time can open a particular COM port. You can do your test if you have two COM ports available.