Send commands to Python console opened with CreateProcessW (Windows, C++) [duplicate] - python

I try to redirect in windows the cmd.exe stdout&stdin (with CreateProcess()). It works fine as long as I run simple commands or open GUI apps, but if I try running a software like python, it does not give me it's output anymore (nor getting the input through stdin).
Code example:
#include <windows.h>
#include <iostream>
#include <string>
#include <thread>
using namespace std;
HANDLE child_input_read;
HANDLE child_input_write;
HANDLE child_output_read;
HANDLE child_output_write;
void writeToPipe()
{
while (true)
{
DWORD bytes_written;
string msg;
getline(cin, msg);
msg += '\n';
BOOL success = WriteFile(child_input_write, msg.c_str(), msg.size(), &bytes_written, NULL);
if (!success)
{
break;
}
}
}
void readFromPipe()
{
while (true)
{
DWORD bytes_read;
char buffer[512];
BOOL success = ReadFile(child_output_read, buffer, sizeof(buffer)-1, &bytes_read, NULL);
buffer[bytes_read] = 0;
if (!success)
{
break;
}
cout << buffer;
}
}
void createCmdProcess()
{
PROCESS_INFORMATION process_info;
STARTUPINFO startup_info;
SECURITY_ATTRIBUTES security_attributes;
// Set the security attributes for the pipe handles created
security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
security_attributes.bInheritHandle = TRUE;
security_attributes.lpSecurityDescriptor = NULL;
CreatePipe(&child_output_read, &child_output_write, &security_attributes, 0);
CreatePipe(&child_input_read, &child_input_write, &security_attributes, 0);
// Create the child process
ZeroMemory(&process_info, sizeof(PROCESS_INFORMATION));
ZeroMemory(&startup_info, sizeof(STARTUPINFO));
startup_info.cb = sizeof(STARTUPINFO);
startup_info.hStdInput = child_input_read;
startup_info.hStdOutput = child_output_write;
startup_info.hStdError = child_output_write;
startup_info.dwFlags |= STARTF_USESTDHANDLES;
CreateProcess(NULL, "cmd.exe", NULL, NULL, TRUE, 0, NULL, NULL, &startup_info, &process_info);
}
int main()
{
createCmdProcess();
thread t(writeToPipe);
thread t2(readFromPipe);
t.join();
t2.join();
system("pause");
}

It's not a bug, it's a feature. :-)
From Python Setup & Usage, section 1.1.1, Interface options (emphasis added):
The interpreter interface resembles that of the UNIX shell, but provides some additional methods of invocation:
When called with standard input connected to a tty device, it prompts for commands and executes them until an EOF (an end-of-file character, you can produce that with Ctrl-D on UNIX or Ctrl-Z, Enter on Windows) is read.
When called with a file name argument or with a file as standard input, it reads and executes a script from that file.
A pipe is neither a file nor a tty device, but it looks like a file as far as the C standard library (and hence Python) is concerned. So the second behaviour kicks in, and Python attempts to read to the end of file. Since we never close our end of the pipe, that never happens.
This behaviour isn't particularly sensible in my opinion (or at least not in Windows) and you could file a bug if you wanted. I would guess that such a proposal would be rejected, since any change would break backwards compatibility, but I could be wrong.
You can work around the problem by providing the -i option on the command line:
python -i
That makes Python enter interactive mode, despite the fact that stdin isn't a terminal.
Unfortunately, there is no known way to make a pipe that looks like a terminal on Windows.

Related

Diverting the output of a c++ that calls python mangles it

I have a c++ (VS2019) app
#include <stdio.h>
#include <Python.h>
void main(int argc, char *argv[])
{
printf( "- before\n" );
FILE* file;
Py_SetPath( L"c:\\Python37\\Lib" );
Py_Initialize();
file = fopen( "abc.py", "r" );
PyRun_SimpleFile( file, "abc.py" );
Py_Finalize();
printf( "- after\n" );
return;
}
that calls a python (3.10) script abc.py
print( "hi" );
When run (on Win11) from cmd (main.exe), the output is:
- before
hi
- after
However, when diverted into a file (main.exe > out.txt, or used in a pipe to tee), I get:
hi
- before
- after
In my real app, where I interleave python with c++, the python output is printed after the script terminates (again, only when diverting the app's output).
Adding
setbuf( stdout, NULL );
, like #retired-ninja suggested, resolves the simple example above. However, in my more complicated app, it doesn't. I need to find a new simple example.
I only needed to add auto-flush to my python script to resolve the issue:
sys.stdout.reconfigure(line_buffering=True)

How to compile python 3.4.3 script to exe?

How to compile python 3.4.3 script with the module tkinter and ttk to an self-executable exe (standalone)? (py2exe, pyinstaller, freeze doesn't work.) any suggestions? Thank You
What I do is
download Portable Python
create an file in an other language that can be compiled to exe
make that executable call portable Python with my Python file.
Structure:
application_folder # the folder where everything is in
+--my_python_folder # the folder where your python files are in
| +--my_program.py # the python file that you want to start
+--Portable Python 3 # the Python version that you use
+--program.exe # the compiled program
The C++ source code:
// based on https://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
int _tmain( int argc, TCHAR *argv[] )
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
// choose between pythonw.exe and python.exe
TCHAR command[] = "\"Portable Python 3\\App\\pythonw.exe\" \"my_program.py\"";
// the directory where you start the Python program in
TCHAR directory[] = "my_python_folder";
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
// Start the child process.
if( !CreateProcess( NULL, // No module name (use command line)
command, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
directory, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi ) // Pointer to PROCESS_INFORMATION structure
)
{
printf( "CreateProcess failed (%d).\n", GetLastError() );
return 1;
}
/*
// Wait until child process exits.
WaitForSingleObject( pi.hProcess, INFINITE );
// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
*/
return 0;
}
You can compile the file with devc++.
Evaluation
Pros:
An other way to do it.
Cons:
Needs whole Portable Python.
No command line arguments are passed.
You can do it with a .bat file and it works, too.
The current working directory is different than the caller's one.

Python - How can I read input from a device using ioctl or spidev?

I have a hardware device and the vendor that supplied it gave a bit of C code to listen for button presses which uses ioctl. The device has an SSD1289 controller.
Push buttons require no additional pins, their status canbe read over SPI.
That's what I want, to read which push button was pressed.
I am trying to replicate this script in Python for my own application, but the _IOR and ioctl requirements are throwing me off.
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#define SSD1289_GET_KEYS _IOR('keys', 1, unsigned char *)
void get_keys(int fd)
{
unsigned char keys;
if (ioctl(fd, SSD1289_GET_KEYS, &keys) == -1)
{
perror("_apps ioctl get");
}
else
{
printf("Keys : %2x\n", keys);
}
}
int main(int argc, char *argv[])
{
char *file_name = "/dev/fb1";
int fd;
fd = open(file_name, O_RDWR);
if (fd == -1)
{
perror("_apps open");
return 2;
}
while(1)
get_keys(fd);
printf("Ioctl Number: (int)%d (hex)%x\n", SSD1289_GET_KEYS, SSD1289_GET_KEYS);
close (fd);
return 0;
}
Now I know that Python has an ioctl module, and at some point I should be calling
file = open("/dev/fb1")
buf = array.array('h', [0])
fcntl.ioctl(file, ????, buf, 1)
I can't figure out what the SSD1289_GET_KEYS is supposed to be. How do I get this and what is _IOR?
Also, if this is the wrong approach, knowing that would be a help too. There are libraries such as spidev which are supposedly for SPI, but I don't know what to read using it.
#alexis provided some useful steps below, which got me to this point:
import fcntl
import array
file = open("/dev/fb1")
buf = array.array('h', [0])
fcntl.ioctl(file, -444763391, buf, 1)
Now, pressing a button changes the value of buf if I keep the above in a loop.
You're on the right track, you just need to figure out the constant to use. Your vendor's program will actually print it out, in decimal and hex-- if you would just edit main() and move the printf line above the endless while loop:
printf("Ioctl Number: (int)%d (hex)%x\n", SSD1289_GET_KEYS, SSD1289_GET_KEYS);
while(1)
get_keys(fd);
Explanation:
_IOR is a macro defined in sys/ioctl.h. Its definition is as follows:
#define _IOC(inout,group,num,len) \
(inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num))
#define _IO(g,n) _IOC(IOC_VOID, (g), (n), 0)
#define _IOR(g,n,t) _IOC(IOC_OUT, (g), (n), sizeof(t))
#define _IOW(g,n,t) _IOC(IOC_IN, (g), (n), sizeof(t))
I have included the relevant context lines. You can see that this macro constructs a bit mask that (we can tell from the name) deals with read operations. But your goal is to figure out the bitmask you need, which you can do without too much trouble: Run your vendor's C program through cc -E, and you'll see the source after preprocessor commands have applied. Track down the definition of get_keys (there'll be a whole lot of header files first, so it'll be at the very end of the output), and pull out the second argument.
The result just might be system-dependent, so you should really try it yourself. On my box, it comes out as
((__uint32_t)0x40000000 | ((sizeof(unsigned char *) & 0x1fff) << 16) | ((('keys')) << 8) | ((1)))
Not eager to translate that into python, I added the following lines at the very start of main():
printf("%d", ((__uint32_t)0x40000000 | ((sizeof(unsigned char *) & 0x1fff) << 16) |
((('keys')) << 8) | ((1))));
exit(0);
I ran the program and it gave me the output 1702458113, which may be the value you need. It should be the same as the decimal output from the printf command that was already there (but hidden below the endless while loop). But check it yourself and don't blame me if you blow out your hardware or something!

Segfault on calling standard windows .dll from python ctypes with wine

I'm trying to call some function from Kernel32.dll in my Python script running on Linux. As Johannes Weiß pointed How to call Wine dll from python on Linux? I'm loading kernel32.dll.so library via ctypes.cdll.LoadLibrary() and it loads fine. I can see kernel32 loaded and even has GetLastError() function inside. However whenever I'm trying to call the function i'm gettings segfault.
import ctypes
kernel32 = ctypes.cdll.LoadLibrary('/usr/lib/i386-linux-gnu/wine/kernel32.dll.so')
print kernel32
# <CDLL '/usr/lib/i386-linux-gnu/wine/kernel32.dll.so', handle 8843c10 at b7412e8c>
print kernel32.GetLastError
# <_FuncPtr object at 0xb740b094>
gle = kernel32.GetLastError
# OK
gle_result = gle()
# fails with
# Segmentation fault (core dumped)
print gle_result
First I was thinking about calling convention differences but it seems to be okay after all. I'm ending with testing simple function GetLastError function without any params but I'm still getting Segmentation fault anyway.
My testing system is Ubuntu 12.10, Python 2.7.3 and wine-1.4.1 (everything is 32bit)
UPD
I proceed with my testing and find several functions that I can call via ctypes without segfault. For instance I can name Beep() and GetCurrentThread() functions, many other functions still give me segfault. I created a small C application to test kernel32.dll.so library without python but i've got essentially the same results.
int main(int argc, char **argv)
{
void *lib_handle;
#define LOAD_LIBRARY_AS_DATAFILE 0x00000002
long (*GetCurrentThread)(void);
long (*beep)(long,long);
void (*sleep)(long);
long (*LoadLibraryExA)(char*, long, long);
long x;
char *error;
lib_handle = dlopen("/usr/local/lib/wine/kernel32.dll.so", RTLD_LAZY);
if (!lib_handle)
{
fprintf(stderr, "%s\n", dlerror());
exit(1);
}
// All the functions are loaded e.g. sleep != NULL
GetCurrentThread = dlsym(lib_handle, "GetCurrentThread");
beep = dlsym(lib_handle, "Beep");
LoadLibraryExA = dlsym(lib_handle, "LoadLibraryExA");
sleep = dlsym(lib_handle, "Sleep");
if ((error = dlerror()) != NULL)
{
fprintf(stderr, "%s\n", error);
exit(1);
}
// Works
x = (*GetCurrentThread)();
printf("Val x=%d\n",x);
// Works (no beeping, but no segfault too)
(*beep)(500,500);
// Segfault
(*sleep)(5000);
// Segfault
(*LoadLibraryExA)("/home/ubuntu/test.dll",0,LOAD_LIBRARY_AS_DATAFILE);
printf("The End\n");
dlclose(lib_handle);
return 0;
}
I was trying to use different calling conventions for Sleep() function but got no luck with it too. When I comparing function declarations\implementation in Wine sources they are essentially the same
Declarations
HANDLE WINAPI GetCurrentThread(void) // http://source.winehq.org/source/dlls/kernel32/thread.c#L573
BOOL WINAPI Beep( DWORD dwFreq, DWORD dwDur ) // http://source.winehq.org/source/dlls/kernel32/console.c#L354
HMODULE WINAPI DECLSPEC_HOTPATCH LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags) // http://source.winehq.org/source/dlls/kernel32/module.c#L928
VOID WINAPI DECLSPEC_HOTPATCH Sleep( DWORD timeout ) // http://source.winehq.org/source/dlls/kernel32/sync.c#L95
WINAPI is defined to be __stdcall
However some of them works and some don't. As I can understand this sources are for kernel32.dll file and kernel32.dll.so file is a some kind of proxy that supposed to provide access to kernel32.dll for linux code. Probably I need to find exact sources of kernel32.dll.so file and take a look on declarations.
Is there any tool I can use to take a look inside .so file and find out what functions and what calling conventions are used?
The simplest way to examine a DLL is to use the nm command, i.e.
$ nm kernel32.dll.so | grep GetLastError
7b86aae0 T _GetLastError
As others have pointed out, the default calling convention for Windows C DLLs is stdcall. It has nothing to do with using Python. On the Windows platform, ctypes.windll is available.
However, I am not even sure what you are trying to do is at all possible. Wine is a full-blown Windows emulator and it is safe to guess that at least you would have to start it with wine_init before loading any other functions. The Windows API probably have some state (set when Windows boots).
The easiest way to continue is probably to install a Windows version of Python under Wine and run your script from there.

KeyboardHookProc in DLL doesn't do anything when called from python

I've been trying to write a DLL in C.
Install hook sets up the KeyboardProc. Calling the InstallHook() and UninstallHook() functions from Python always returns a 0, which I guess is because my callback function KeyboardProc isn't working.
The following is my C code for the DLL:
#include "stdafx.h"
#include <windows.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include "ourdll.h"
//#pragma comment(linker, "/SECTION:.SHARED,RWS")
//#pragma data_seg(".SHARED")
HHOOK hKeyboardHook = 0;
int keypresses = 0;
HMODULE hInstance = 0;
//#pragma data_seg()
BOOL WINAPI DllMain (HANDLE hModule, DWORD dwFunction, LPVOID lpNot)
{
hInstance = hModule; //Edit
return TRUE;
}
LRESULT CALLBACK KeyboardProc(int hookCode, WPARAM vKeyCode, LPARAM flags)
{
if(hookCode < 0)
{
return CallNextHookEx(hKeyboardHook, hookCode, vKeyCode, flags);
}
keypresses++;;
return CallNextHookEx(hKeyboardHook, hookCode, vKeyCode, flags);
}
__declspec(dllexport) void InstallHook(void)
{
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, hInstance, 0);
}
__declspec(dllexport) int UninstallHook(void)
{
UnhookWindowsHookEx(hKeyboardHook);
hKeyboardHook = 0;
return keypresses;
}
The Python code to use this is as follows:
>>> from ctypes import *
>>> dll = CDLL('C:\...\OurDLL.dll')
>>> dll.InstallHook()
[Type something at this point]
>>> result = dll.UninstallHook()
>>> result
0
EDIT: I should probably mention that I've also tried out a LowLevelKeyboardHook. I understand that the LowLevel hook is global and will catch all keystrokes, but that just caused my dll.InstallHook() Python code to freeze for a second or two before returning zero.
I am no expert in C, so any help would be greatly appreciated. Thanks.
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, NULL, 0);
SetWindowsHookEx requires a hModule - save the hModule from DllMain and pass it here. (You can pass NULL only if the thread id is your own thread.)
One exception to this is for the _LL hook types; these don't need a hmodule param since these hook don't inject into the target process - that's why your code using KEYBOARD_LL is 'succeeding'.
As for why it might be blocking when you use KEYBOARD_LL - docs for LowLevelKeyboardHookProc mention that the thread that installs the hook (ie. calls SetWindowsHookEx) must have a message loop, which you might not have in your python code.
Debugging tips: it looks like SetWindowsHookEx should be returning NULL (with GetLastError() returning a suitable error code); while developing code, using some combination of assert/printf/OutputDebugString as appropriate to check these return values is a good way to ensure that your assumptions are correct and give you some clues as to where things are going wrong.
BTW, one other thing to watch for with KEYBOARD vs KEYBOARD_LL: the KEYBOARD hook gets loaded into the target process - but only if it's the same bitness - so a 32-bit hook only sees keys pressed by other 32-bit processes. OTOH, KEYBOARD_LL is called back in your own process, so you get to see all keys - and also don't need to deal with the shared segment (though as far as I know it's also less efficient as a KEYBOARD hook).

Categories