Переключатели CLI - не единственное, что может контролировать поведение процессов Windows.
Вызов процесса через CLI и через диспетчер задач на самом деле сильно отличается, и этот след может быть использован несколькими способами.
CWD (ответ)
Причина, по которой Explorer не запускает панель задач, заключается в том, что при запуске из CLI его рабочий каталог отличается от того, когда он выполняется из диспетчера задач.
В опубликованном GIF CWD установлен в Z:\
, в то время как taskmgr
устанавливает в C:\Windows
. Он знает, что ему следует установить его в C:\Windows
, поскольку C:\Windows\
- это первая папка в переменной среды PATH
которая содержит explorer.exe
. Этой детали достаточно, чтобы изменить ситуацию - смоделируйте это в cmd
:
C:\> cd /d C:\windows
C:\windows> explorer
... действительно восстанавливает панель задач, как и ожидалось.
CreateProcess
Выполнение процессов также можно контролировать с помощью структуры Windows STARTUPINFO
, которая используется функцией CreateProcess
WinAPI, основной функцией для открытия новых процессов в Windows.
Я написал программу для проверки различий между STARTUPINFO
для программ, запускаемых CMD, и для программ, запускаемых диспетчером задач:
#include <stdio.h>
#include <Windows.h>
int main(int argc, char ** argv)
{
STARTUPINFO si;
memset(&si, 0, sizeof(si));
GetStartupInfo(&si);
FILE *fp = fopen("Z:\\output.txt", "a");
if (!fp) {
return 1;
}
fprintf(fp, "cb: %08x\n", si.cb);
fprintf(fp, "lpDesktop: %s\n", si.lpDesktop);
fprintf(fp, "dwX: %d\n", si.dwX);
fprintf(fp, "dwY: %d\n", si.dwY);
fprintf(fp, "dwXSize: %d\n", si.dwXSize);
fprintf(fp, "dwYSize: %d\n", si.dwYSize);
fprintf(fp, "dwXCountChars: %d\n", si.dwXCountChars);
fprintf(fp, "dwYCountChars: %d\n", si.dwYCountChars);
fprintf(fp, "dwFillAttribute: %d\n", si.dwFillAttribute);
fprintf(fp, "dwFlags: %d\n", si.dwFlags);
fprintf(fp, "wShowWindow: %d\n", si.wShowWindow);
fprintf(fp, "hStdInput: %08x\n", si.hStdInput);
fprintf(fp, "hStdOutput: %08x\n", si.hStdOutput);
fprintf(fp, "hStdError: %08x\n", si.hStdError);
fclose(fp);
return 0;
}
Я быстро получил следующие результаты - запуск тестовой программы через CMD приводит к следующим результатам:
cb: 00000044
lpDesktop: Winsta0\Default
dwX: 0
dwY: 0
dwXSize: 0
dwYSize: 0
dwXCountChars: 0
dwYCountChars: 0
dwFillAttribute: 0
dwFlags: 256
wShowWindow: 0
hStdInput: 000001d8
hStdOutput: 000001dc
hStdError: 000001dc
при запуске через taskmgr
получается следующее:
cb: 00000044
lpDesktop: Winsta0\Default
dwX: 0
dwY: 0
dwXSize: 0
dwYSize: 0
dwXCountChars: 0
dwYCountChars: 0
dwFillAttribute: 0
dwFlags: 1
wShowWindow: 1
hStdInput: ffffffff
hStdOutput: ffffffff
hStdError: ffffffff
Мы можем видеть, что они явно отличаются друг от друга - например, CLI не хочет, чтобы программа показывала какое-либо окно, и taskmgr закрывает все стандартные дескрипторы ввода / вывода. Любая программа может использовать эту информацию для управления своим поведением - даже если она не интуитивна для конечного пользователя, это вполне возможно.
ShellExecute
Другим стандартным способом запуска процессов является функция ShellExecute
WinAPI.
Согласно этому сообщению, ShellExecute
делает следующее:
- Определяет тип файла путем поиска в реестре Windows.
- Перечисляет разрешенные команды оболочки (глаголы).
- Получает командную строку для указанного глагола.
- Создает ключи командной строки.
- Вызывает
CreateProcess()
для запуска процесса, на который указывает полученная командная строка.
Эта функция полностью способна манипулировать параметрами CLI данного процесса - фактически, вы можете попытаться порождать процесс для текстового файла ... и ShellExecute
запустит приложение по умолчанию, отвечающее за открытие текстовых файлов, используя параметры в соответствии с инструкциями Windows Реестр. Вот что делает Task Manager: если вы пытаетесь запустить новую задачу, указывающую на текстовый файл, он обнаруживает, что должен открыть ваш текстовый редактор по умолчанию.