AttachConsole in DLL
-
Hallo,
ich schreibe gerade eine DLL, die ich mit RunDll32.exe (über Batch) aufrufen kann.
Ich möchte allerdings in der gleichen Console bleiben (Console des Parent Process erben)
[cmd.exe] (Batch-Programm) <-- In die Console möchte ich... v [rundll32.exe] v [xxx.dll] <-- ...von dieser DLL aus schreiben
Wenn ich jetzt in der DLL AttachConsole(ATTACH_PARENT_PROCESS) aufrufe, dann wird der Fehler ERROR_INVALID_HANDLE (6) erzeugt.
void DLL_EXPORT Init(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) { AttachConsole(ATTACH_PARENT_PROCESS) freopen("conin$", "r", stdin); freopen("conout$", "w", stdout); freopen("conout$", "w", stderr); cout << "Hello World"; }
AllocConsole() funktioniert natürlich, weil das in dem RunDll32.exe-Prozess eine neue Console erstellt, aber das möchte ich ja nicht...
Wie kann ich das Problem lösen?
Vielen Dank schonmal
Gruß
Fabian
-
Ich habe herausgefunden, wie es geht:
DWORD GetParentProcessID(DWORD ProcessID) { DWORD result = 0; HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (INVALID_HANDLE_VALUE != snap) { PROCESSENTRY32 entry = {sizeof(entry)}; if (Process32First(snap, &entry)) { DWORD pid = ProcessID; do { if (pid == entry.th32ProcessID) { result = entry.th32ParentProcessID; break; } } while (Process32Next(snap, &entry)); } CloseHandle(snap); } return result; } void InitializeConsole() { if (!AttachConsole(GetParentProcessID/*cmd.exe*/((DWORD)GetParentProcessID/*rundll32.exe *32*/((DWORD)GetCurrentProcessId()/*rundll32.exe*/)))) { //Fehler } freopen("conin$", "r", stdin); freopen("conout$", "w", stdout); freopen("conout$", "w", stderr); } void DLL_EXPORT EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) { InitializeConsole(); cout << "Hello World!"; }
Allerdings sieht die Prozess-Struktur bei meinem x64-Vista so aus:
[cmd.exe] v [rundll.exe] v [rundll.exe *32] v [xxx.dll]
Und bei meinem x84-XP wie im ersten Posting.
Wie kann ich herausfinden, ob ein Prozess ein 64 Bit oder 32 Bit-Prozess ist?
Oder hat jmd. vllt. eine andere Lösung?Gruß
Fabian
-
Falls es jmd. interressiert, ich habe es hingekommen.
Die Dll muss eine x86-Dll sein.
Aufrufen kann man es so:
rundll32 xxx.dll,EntryPoint Hello World
#define _WIN32_WINNT 0x0501 #include <windows.h> #include <tlhelp32.h> #include <stdio.h> #include <iostream> using namespace std; #include "main.h" DWORD GetParentProcessID(DWORD ProcessID) { DWORD result = 0; HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (INVALID_HANDLE_VALUE != snap) { PROCESSENTRY32 entry = {sizeof(entry)}; if (Process32First(snap, &entry)) { DWORD pid = ProcessID; do { if (pid == entry.th32ProcessID) { result = entry.th32ParentProcessID; break; } } while (Process32Next(snap, &entry)); } CloseHandle(snap); } return result; } typedef UINT (WINAPI* GETSYSTEMWOW64DIRECTORY)(LPTSTR, UINT); bool IsWow64(void) { GETSYSTEMWOW64DIRECTORY getSystemWow64Directory; HMODULE hKernel32; TCHAR Wow64Directory[MAX_PATH]; hKernel32 = GetModuleHandle(TEXT("kernel32.dll")); if (hKernel32 == NULL) { return false; } getSystemWow64Directory = (GETSYSTEMWOW64DIRECTORY) GetProcAddress(hKernel32, "GetSystemWow64DirectoryW"); if (getSystemWow64Directory == NULL) { return false; } if ((getSystemWow64Directory(Wow64Directory, sizeof(Wow64Directory)/sizeof(TCHAR)) == 0) && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) { return false; } return true; } void InitializeConsole() { if (IsWow64()) { if (!AttachConsole(GetParentProcessID((DWORD)GetParentProcessID((DWORD)GetCurrentProcessId())))) { //Fehler } } else { if (!AttachConsole((DWORD)GetParentProcessID((DWORD)GetCurrentProcessId()))) { //Fehler } } freopen("conin$", "r", stdin); freopen("conout$", "w", stdout); freopen("conout$", "w", stderr); } void DLL_EXPORT EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) { InitializeConsole(); cout << lpszCmdLine << endl; }
Ich glaube das ist aber ziemlich unperformant, also sollte ich wohl einfach eine exe erstellen, die man dann aufruft