Выполнение rundll32.exe с помощью CreateProcess
Я создал DLL и хотел бы выполнить одну из функций с помощью команды rundll32.exe в Windows.
Используя rundll32.exe, он работает правильно из командной строки; Тем не менее, я хотел бы назвать его (rundll32.exe) из отдельной программы. Я не могу напрямую вызвать функцию из своего кода из-за проблем совместимости 32/64 бит в используемых мной базовых библиотеках (Easyhook).
Ниже приведено то, что я использую при попытке запустить функцию dll:
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi));
LPCTSTR application = "C:\\Windows\\system32\\rundll32.exe";
LPTSTR cmd = "C:\\Projects\\Test\\mydll.dll,MyFunc";
BOOL cpRes = CreateProcess(application,
cmd,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&si,
&pi);
if(cpRes == 0) {
cout << "ERROR\n";
cout << GetLastError() << endl;
} else {
cout << "DLL Launched!" << endl;
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
Выход на мою консоль всегда DLL Launched
; однако я не вижу эффекта от того, что моя DLL на самом деле вызывается (в настоящее время отключена таким образом, что команда записывает в файл).
Если я поменяю приложение чем-то вроде C:\\Windows\\system32\\notepad.exe
, программа успешно запускается.
Для завершения вот тело MyFunc
:
ofstream file;
file.open("C:\\Projects\\Test\\test.txt");
file << "I wrote to a file!";
file.close();
Есть ли какая-то причина, по которой CreateProcess нельзя использовать с rundll32? Читая об этом, я нашел несколько предупреждений о LoadLibrary()
а также DLLMain
но не похоже, что они имеют к этому отношение.
Больше разъяснений:
В настоящее время это 32-разрядное приложение (предположительно), запускающее 32-разрядное rundll32.exe
(Логика будет добавлена позже для вызова 32- или 64-битной версии).
Моя библиотека выглядит следующим образом:
extern "C" __declspec(dllexport) void CALLBACK MyFunc(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
void CALLBACK MyFunc(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) { ... }
Который также имеет .def
файл с:
EXPORTS
MyFunc
Бег
C:\Windows\system32\rundll32.exe C:\Projects\Test\mydll.dll,MyFunc
дает ожидаемые результаты.
Обновить
настройка application
в NULL
и в том числе rundll32.exe
в cmd, как упомянуто в комментариях, кажется, работает.
Соответствующие документы:
CreateProcess
rundll32.exe
1 ответ
В соответствии с CreateProcess()
документация:
Если оба
lpApplicationName
а такжеlpCommandLine
не NULL, строка с нулевым символом в конце, указаннаяlpApplicationName
указывает модуль для выполнения, и строка с нулевым символом в конце, указаннаяlpCommandLine
определяет командную строку. Новый процесс может использоватьGetCommandLine
чтобы получить всю командную строку. Консольные процессы, написанные на C, могут использоватьargc
а такжеargv
аргументы для разбора командной строки. Так какargv[0]
это имя модуля, программисты на C обычно повторяют имя модуля в качестве первого токена в командной строке.
Вы не повторяете rundll32.exe
в качестве первого токена командной строки.
Итак, если вы продолжите использовать lpApplicationName
параметр, затем измените это:
LPCTSTR application = "C:\\Windows\\system32\\rundll32.exe";
LPTSTR cmd = "C:\\Projects\\Test\\mydll.dll,MyFunc";
На это вместо этого:
LPCTSTR application = TEXT("C:\\Windows\\system32\\rundll32.exe");
LPTSTR cmd = TEXT("C:\\Windows\\system32\\rundll32.exe C:\\Projects\\Test\\mydll.dll,MyFunc");
Обратите внимание, что вы в настоящее время компилируете для ANSI/MBCS (в силу того, что вы передаете узкие строки CreateProcess()
). Если вы когда-нибудь обновите проект для компиляции для Unicode, используйте вместо этого:
TCHAR cmd[] = TEXT("C:\\Windows\\system32\\rundll32.exe C:\\Projects\\Test\\mydll.dll,MyFunc");
Это потому, что в документации говорится:
lpCommandLine [in, out, необязательно]
...
Unicode-версия этой функции,CreateProcessW
, может изменить содержимое этой строки. Следовательно, этот параметр не может быть указателем на постоянную память (такую как переменная const или литеральная строка). Если этот параметр является константной строкой, функция может вызвать нарушение прав доступа.
Вы могли бы рассмотреть возможность изменения cmd
в TCHAR[]
массив в любом случае, даже в ANSI/MBCS, так что вы можете сделать что-то вроде этого:
LPCTSTR application = TEXT("C:\\Windows\\system32\\rundll32.exe");
TCHAR cmd[(MAX_PATH*2)+10];
wsprintf(cmd, TEXT("%s %s,%s"), application, TEXT("C:\\Projects\\Test\\mydll.dll"), TEXT("MyFunc"));
В любом случае, передавая имя файла модуля в качестве первого токена в lpCommandLine
параметр, вы можете установить lpApplicationName
параметр в NULL:
lpApplicationName
параметр может быть НЕДЕЙСТВИТЕЛЕН. В этом случае имя модуля должно быть первым токеном с пробелами вlpCommandLine
строка.
Позволять CreateProcess()
установить правильную командную строку для передачи rundll32.exe
для тебя:
TCHAR cmd[] = TEXT("C:\\Windows\\system32\\rundll32.exe C:\\Projects\\Test\\mydll.dll,MyFunc");
BOOL cpRes = CreateProcess(NULL, cmd, ...);