i try to create a client written in c++ and a server using python flask. The task is simple, client connect and get data from server, then display it on console. I have two piece of code:
Server:
from flask import Flask
app = Flask(__name__)
#app.route('/hello')
def hello():
return "hello".encode("utf-16")
if __name__ == "__main__":
app.run(debug=True,host="127.0.0.1")
Client:
BOOL bResults = FALSE;
bool ret = false;
DWORD dwDownloaded = 0;
WCHAR wDataRecv[1024] = {0};
HINTERNET hConnect = NULL;
HINTERNET hRequest = NULL;
DWORD dwSize = 0;
HINTERNET hSession = WinHttpOpen(L"WinHTTP Example/1.0",
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, 0); # open session to connect
hConnect = WinHttpConnect(hSession, L"localhost", (port == 0) ? INTERNET_DEFAULT_HTTP_PORT : port, 0); # connect to localhost with port 80 or custom port (this time i use port 5000)
if (!hConnect)
goto Free_And_Exit;
hRequest = WinHttpOpenRequest(hConnect, L"GET", L"/hello", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
if (hRequest) {
bResults = WinHttpSendRequest(hRequest, NULL, 0,WINHTTP_NO_REQUEST_DATA, 0,0, 0);# send GET request
}
if (bResults)
bResults = WinHttpReceiveResponse(hRequest, NULL);
if (bResults)
{
dwSize = 0;
if (!WinHttpQueryDataAvailable(hRequest, &dwSize)) {
std::cout << "WinHttpQueryDataAvailable failed with code: " << GetLastError();
}
if (!WinHttpReadData(hRequest, wDataRecv, dwSize, &dwDownloaded)) {
std::cout << "WinHttpReadData failed with code: " << GetLastError();
}
std::wcout << wDataRecv; # wcout wont print anything to console
}
Free_And_Exit: #clean up
if (hRequest) WinHttpCloseHandle(hRequest);
if (hConnect) WinHttpCloseHandle(hConnect);
return ret;
I noticed that the data return from server like:
b'\xfe\xff\hello'
Why 0xFEFF is there ?
Its is BOM (byte order mark). I just need to decode from the client or use:
return "hello".encode('UTF-16LE') # not UTF-16
I have a c function that publish data to a c++ subscriber, now I want to migrate this c function to Python:
void setup_msg_publish() {
int r;
zmqcontext = zmq_ctx_new();
datasocket = zmq_socket(zmqcontext, ZMQ_PUB);
r = zmq_bind(datasocket, "tcp://*:44000");
if (r == -1) {
printf(zmq_strerror(errno));
}
}
void publishdata(int x, int y) {
if (datasocket == 0) {
setup_msg_publish();
}
zmq_data zd;
zd.msgType = int 0;
zd.x = x;
zd.y = y;
size_t len = sizeof(zd);
int res = zmq_send(datasocket, &zd, len, NULL);
assert(res == len);
}
I've tried to implement this in Python:
import zmq
import pickle
from collections import namedtuple
Data = namedtuple("Data", "msgType x y")
def send_zmq():
data = Data("0", "1", "2")
msg = pickle.dumps(data)
context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect("tcp://127.0.0.1:44000")
socket.send(msg)
For debug purposes I can recive the data with Python like this:
import zmq
import pickle
context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind("tcp://127.0.0.1:44000")
while True:
message = socket.recv()
data = pickle.loads(message)
print(data)
But I don't receive anything in my c++ code (it just prints no data):
#include "View.h"
#include <iostream>
#include <thread>
#include <chrono>
View::View() :
viewSubscriber(zmqcontext, ZMQ_SUB)
{
unsigned _int16 msgType = 0;
viewSubscriber.connect("tcp://127.0.0.1:44000");
//viewSubscriber.setsockopt(ZMQ_SUBSCRIBE, &msgType, sizeof(msgType));
viewSubscriber.setsockopt(ZMQ_SUBSCRIBE, "", 0);
std::cout << msgType;
}
void View::run() {
using namespace std;
bool received_view_data = false;
bool checkForMore = true;
zmq_view data;
while (checkForMore) {
zmq::message_t msg;
//cout << &msg;
if (viewSubscriber.recv(&msg, ZMQ_NOBLOCK)) {
received_view_data = true;
memcpy(&data, msg.data(), sizeof(data));
cout << &data.x;
}
else {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
cout << "no data \n";
}
}
}
int main(){
View *app = new View();
app -> run();
return 0;
}
Any ideas what to fix so I receive the data in the namedTuple on the c++ side? Could it be that the c++ "needs to know more" about the type of each attribute of the namedTuple (if that is the case how do I specify whether the data is a double or int etc?)?
The solution was found after testing to go from C++ -> Python thank you J_H for the idea. Instead of using a namedtuple a packed struct was used.
import zmq
import struct
def send_zmq():
struct_format = 'Idd'
msg_type = 0
x = 1.0
y = 1.0
msg = struct.pack(struct_format, msg_type, x, y)
context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect("tcp://127.0.0.1:44000")
socket.send(msg)
I would like to call a python script in my C# project , I'm using this function to do the job but unfortunately I didn't get any result and the result variable shows always an empty output. I would like to know what's the reason of this
public string RunFromCmd(string rCodeFilePath, string args)
{
string file = rCodeFilePath;
string result = string.Empty;
try
{
var info = new ProcessStartInfo(pythonPath);
info.Arguments = #"C:\Users\MyPc\ExternalScripts\HelloWorld.py" + " " + args;
info.RedirectStandardInput = false;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
info.CreateNoWindow = true;
using (var proc = new Process())
{
proc.StartInfo = info;
proc.Start();
proc.WaitForExit();
if (proc.ExitCode == 0)
{
result = proc.StandardOutput.ReadToEnd();
}
}
return result;
}
catch (Exception ex)
{
throw new Exception("R Script failed: " + result, ex);
}
}
Click Event ( Calling funtion )
private void Button1_Click(object sender, RoutedEventArgs e)
{
pythonPath = Environment.GetEnvironmentVariable("PYTHON_PATH");
RunFromCmd(pythonPath, "");
}
Python Script :
import sys
def main():
text = "Hello World"
return text
result = main()
I've fixed the issue by setting Copy if newer instead of Do Not Copy to HelloWorld.py Script
I've decided to bite more than I could chew here. I've spent the past day attempting this through trial and error however I have yet to figure out the correct way to interact with the Windows API.
I would like to retrieve the full path for the focused window on my Windows 10 PC using Python. So far I have hot glued this together:
from ctypes import *
import sys
import time
try:
while True:
# Retrieve the handle for the foreground window
hwnd = windll.user32.GetForegroundWindow()
# Create a buffer for the GetWindowThreadProcessId function
buffer = create_string_buffer(260)
# Retrieve the full path and file name of the foreground window
windll.user32.GetWindowModuleFileName(hwnd, buffer, sizeof(buffer))
# Print the full path and file name of the foreground window
print(buffer.value)
# Sleep for 100 milliseconds
time.sleep(0.1)
except KeyboardInterrupt:
sys.exit(0)
Unfortunatly this doesn't have my desired output. When I have Command Prompt open I would expect the path to be C:\Windows\system32\cmd.exe however I get C:\Users\John\AppData\Local\Programs\Python\Python39\python.exe instead. When I open any other window I get an empty output.
GetWindowModuleFileName calls GetModuleFileName from which the MSDN doc says :
The module must have been loaded by the current process.
So you can't get the full path you want directly by calling GetWindowModuleFileName.
You can refer to this thread : How to get the Executable name of a window.
And here is an example implemented in C++, you can refer to it:
#include <Windows.h>
#include <psapi.h>
#include <iostream>
#include <tlhelp32.h>
BOOL SetPrivilege(HANDLE hToken, LPCTSTR Privilege,BOOL bEnablePrivilege)
{
TOKEN_PRIVILEGES tp = { 0 };
// Initialize everything to zero
LUID luid;
DWORD cb = sizeof(TOKEN_PRIVILEGES);
if (!LookupPrivilegeValue(NULL, Privilege, &luid))
{
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege) {
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
}
else {
tp.Privileges[0].Attributes = 0;
}
AdjustTokenPrivileges(hToken, FALSE, &tp, cb, NULL, NULL);
if (GetLastError() != ERROR_SUCCESS)
{
std::cout << "err = " << GetLastError() << std::endl;
return FALSE;
}
return TRUE;
}
int main()
{
HANDLE curHandle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
OpenProcessToken(curHandle, TOKEN_ADJUST_PRIVILEGES, &curHandle);
SetPrivilege(curHandle, SE_DEBUG_NAME, TRUE);
while (1)
{
TCHAR buf[MAX_PATH] = L"";
HWND hwnd = GetForegroundWindow();
DWORD pid = 0;
GetWindowThreadProcessId(hwnd, &pid);
HANDLE handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
if (handle)
{
GetModuleFileNameEx(handle, 0, buf, MAX_PATH);
std::wcout << buf << std::endl;
}
else
{
std::cout << "error = " << GetLastError() << std::endl;
}
if (handle) CloseHandle(handle);
Sleep(100);
}
return 0;
}
I have managed to get C code calling Python scripts happily on Unix using PIPES within the C code. I now need to do the same on Windows.
Essentially I would like to write scripts in different scripting languages like Python / Lua etc on Windows and be able to execute them using STDIN / STDOUT etc.
I have been looking at the "CreateProcess" call at:
http://msdn.microsoft.com/en-us/library/ms682425(VS.85).aspx
and although I can get it to work with a "child written in C", I cannot get it to call a Python script.
Below is the "parent / sender code" on my windows box:
#include<windows.h>
#include <stdio.h>
#include <stdlib.h>
#pragma comment(lib, "User32.lib")
void DisplayError(char *pszAPI);
void readFromPipe(HANDLE hPipeRead);
void createChildProcess(char *commandLine,
HANDLE hChildStdOut,
HANDLE hChildStdIn,
HANDLE hChildStdErr);
DWORD WINAPI writeToPipe(LPVOID lpvThreadParam);
HANDLE hChildProcess = NULL;
HANDLE hStdIn = NULL;
BOOL bRunThread = TRUE;
char *inputStream;
int main(int argc, char *argv[]){
HANDLE hOutputReadTmp,hOutputRead,hOutputWrite;
HANDLE hInputWriteTmp,hInputRead,hInputWrite;
HANDLE hErrorWrite;
HANDLE hThread;
DWORD ThreadId;
SECURITY_ATTRIBUTES sa;
int streamLen;
sa.nLength= sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
if (!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0))
return 1;
if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite,
GetCurrentProcess(),&hErrorWrite,0,
TRUE,DUPLICATE_SAME_ACCESS))
return 1;
if (!CreatePipe(&hInputRead,&hInputWriteTmp,&sa,0))
return 1;
if (!DuplicateHandle(GetCurrentProcess(),hOutputReadTmp,
GetCurrentProcess(),
&hOutputRead,
0,FALSE,
DUPLICATE_SAME_ACCESS))
return 1;
if (!DuplicateHandle(GetCurrentProcess(),hInputWriteTmp,
GetCurrentProcess(),
&hInputWrite,
0,FALSE,
DUPLICATE_SAME_ACCESS))
return 1;
if (!CloseHandle(hOutputReadTmp)) return 1;;
if (!CloseHandle(hInputWriteTmp)) return 1;;
if ( (hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE )
return 1;
if (argc == 2){
createChildProcess(argv[1], hOutputWrite,hInputRead,hErrorWrite);
}else{
puts("No process name / input stream specified\n");
return 1;
}
if (!CloseHandle(hOutputWrite)) return 1;;
if (!CloseHandle(hInputRead )) return 1;;
if (!CloseHandle(hErrorWrite)) return 1;;
hThread = CreateThread(NULL,0,writeToPipe,
(LPVOID)hInputWrite,0,&ThreadId);
if (hThread == NULL)
return 1;;
readFromPipe(hOutputRead);
if (!CloseHandle(hStdIn))
return 1;
bRunThread = FALSE;
if (WaitForSingleObject(hThread,INFINITE) == WAIT_FAILED)
return 1;;
if (!CloseHandle(hOutputRead)) return 1;;
if (!CloseHandle(hInputWrite)) return 1;;
}
void createChildProcess(char *commandLine,
HANDLE hChildStdOut,
HANDLE hChildStdIn,
HANDLE hChildStdErr){
PROCESS_INFORMATION pi;
STARTUPINFO si;
ZeroMemory(&si,sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdOutput = hChildStdOut;
si.hStdInput = hChildStdIn;
si.hStdError = hChildStdErr;
if (!CreateProcess(NULL,commandLine,NULL,NULL,TRUE,
NULL,NULL,NULL,&si,&pi))
hChildProcess = pi.hProcess;
if (!CloseHandle(pi.hThread)) return 1;;
}
void readFromPipe(HANDLE hPipeRead)
{
CHAR lpBuffer[256];
DWORD nBytesRead;
DWORD nCharsWritten;
while(TRUE)
{
if (!ReadFile(hPipeRead,lpBuffer,sizeof(lpBuffer),
&nBytesRead,NULL) || !nBytesRead)
{
if (GetLastError() == ERROR_BROKEN_PIPE)
break; // pipe done - normal exit path.
else
return 1; // Something bad happened.
}
if (!WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),lpBuffer,
nBytesRead,&nCharsWritten,NULL))
return 1;;
}
}
DWORD WINAPI writeToPipe(LPVOID lpvThreadParam)
{
CHAR read_buff[256];
DWORD nBytesRead,nBytesWrote;
HANDLE hPipeWrite = (HANDLE)lpvThreadParam;
while (bRunThread){
nBytesRead = 21;
strncpy(read_buff, "hello from the paren\n",21);
read_buff[nBytesRead] = '\0';
if (!WriteFile(hPipeWrite,read_buff,nBytesRead,&nBytesWrote,NULL)){
if (GetLastError() == ERROR_NO_DATA)
break; //Pipe was closed (normal exit path).
else
return 1;;
}
}
return 1;
}
Quite a bit of the above code is "hardcoded" just for testing purposes...essentially I passing some text like "hello from the paren" to be sent to a "child.exe"....
Here is the code for the child.c...a simple ECHO of what is sent to it
#include<windows.h>
#include<stdio.h>
#include<string.h>
void main (){
CHAR szInput[1024];
ZeroMemory(szInput,1024);
gets(szInput);
puts(szInput);
fflush(NULL);
}
To run the app I send "CallSubProcess.exe Child.exe" and it works 100%
Next I want to change "child.c" to be a PYTHON SCRIPT...
import sys
if __name__ == "__main__":
inStream = sys.stdin.read()
outStream = inStream
sys.stdout.write(outStream)
sys.stdout.flush()
So how can I change the CreateProcess call to execute this script?
if (!CreateProcess("C:\\Python26\\python.exe", "echo.py",NULL, NULL,FALSE, 0,NULL,NULL,&si,&pi)){
But it never works.
Any ideas how I can get this to work? Any help will be greatly appreciated.
My application posts a string to a python script, and the python script posts the string back to the c
application. It works well.
//c code
#pragma comment(lib, "json_vc71_libmtd.lib")
#include <windows.h>
#include <iostream>
#include <io.h>
#include "./json/json.h"
using namespace std;
DWORD WINAPI threadproc(PVOID pParam);
HANDLE hRead, hWrite, hRead1, hWrite1;
int main()
{
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
if (!CreatePipe(&hRead, &hWrite, &sa, 0)){
::MessageBox(NULL, L"can't create pipe", L"error", MB_OK);
return -1;
}
if (!CreatePipe(&hRead1, &hWrite1, &sa, 0)){
::MessageBox(NULL, L"can't create pipe1", L"error", MB_OK);
return -1;
}
STARTUPINFO si;
PROCESS_INFORMATION pi;
GetStartupInfo(&si);
si.cb = sizeof(STARTUPINFO);
si.hStdError = hWrite;
si.hStdOutput = hWrite;
si.hStdInput = hRead1;
si.wShowWindow = SW_SHOW;
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
WCHAR szCmdLine[] = L"\"D:\\tools\\python\\python.exe\" D:\\code\\test\\pipeCallCore\\pipeCallCore\\json_wraper.py";
if (!CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)){
::MessageBox(NULL, L"can't create process", L"error", MB_OK);
return -1;
}
CloseHandle(hWrite);
CloseHandle(hRead1);
const int cBufferSize = 4096;
char buffer[cBufferSize] = {0};
DWORD bytes;
int i = 0;
while (true){
cout << "come !" << endl;
ZeroMemory(buffer, sizeof(buffer));
sprintf(buffer, "{\"write\":%d}\n", i ++);
if (NULL == WriteFile(hWrite1, buffer, strlen(buffer), &bytes, NULL)){
::MessageBox(NULL, L"write file failed!", L"error", MB_OK);
break;
}
ZeroMemory(buffer, sizeof(buffer));
if (NULL == ReadFile(hRead, buffer, cBufferSize - 1, &bytes, NULL)){
::MessageBox(NULL, L"readfile failed", L"error", MB_OK);
return -1;
}
cout <<"yes " << buffer << endl;
Sleep(2000);
}
return 0;
}
//python code
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
while True:
try:
s = sys.stdin.readline()
sys.stdout.write(s)
sys.stdout.flush()
except EOFError, KeyboardInterrupt:
break
Maybe
if (!CreateProcess("C:\\Python26\\python.exe",
"echo.py 'hello from parent'",
NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
CreateProcess is kind of tricky to use.
From the MSDN documentation:
If both lpApplicationName and lpCommandLine are non-NULL, ... lpApplicationName specifies the module to execute, and ... lpCommandLine specifies the command line.... Console processes written in C can use the argc and argv arguments to parse the command line. Because argv[0] is the module name, C programmers generally repeat the module name as the first token in the command line.
To avoid the weirdness, I recommend always passing NULL for the first argument and to pass the full command-line as the second:
CreateProcess(NULL, "\"C:\\Python26\\python.exe\" echo.py", ...);