Автозапуск программы на чистом Windows API
18 декабря 2013
Конечно же, вы видели множество программ, запускающихся автоматически во время загрузки системы. В Windows есть немало способов добавить программу в автозагрузку. Сегодня мы рассмотрим наиболее простой и популярный способ, который заключается в добавлении специальной записи в реестр. Разумеется, как и ранее, мы будем писать программу на Си и Windows API.
Для решения задачи нам понадобятся следующие процедуры.
GetModuleFileName записывает в буфер szFileName полный путь до файла, содержащего заданный модуль, загруженный текущим процессом. Если hModule == NULL, возвращается полный путь до исполняемого файла текущего процесса. Аргумент dwChars должен быть равен размеру буфера в TCHAR’ах. В случае ошибки процедура возвращает ноль, в случае успеха — значение, отличное от нуля.
GetWindowsDirectory записывает в буфер szWinPath путь до каталога Windows, который «C:\WINDOWS», «Z:\WINNT» и так далее. Аргумент dwChars должен быть равен размеру буфера в TCHAR’ах. В случае ошибки процедура возвращает ноль, в случае успеха — значение, отличное от нуля.
Процедура CopyFile копирует файл szFrom в szTo. Если файл с именем szTo уже существует, то процедура перезаписывает его в случае, если bFailIfExists == FALSE, и завершается с ошибкой иначе. В случае ошибки возвращается ноль, в случае успеха — значение, отличное от нуля.
RegOpenKey открывает заданный ключ реестра и записывает хэндл открытого ключа в hKey. Первый аргумент — это либо хэндл открытого или созданного ранее ключа, либо одно из предопределенных значений, например, HKEY_USERS, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE и так далее. В аргументе szSubKey передается имя ключа, который требуется открыть. Это должен быть подключ ключа, переданного первым аргументом. В случае успеха процедура возвращает ERROR_SUCCESS. В случае ошибки возвращается одно из значений, определенных в Winerror.h. В отличие от процедур, с которыми мы работали до этого момента, RegOpenKey никак не связана с GetLastError.
Процедура RegSetValueEx устанавливает значение, а также тип, заданного ключа реестра и принимает следующие аргументы. Слева направо — хэндл ключа реестра, имя устанавливаемого значения, зарезервированный аргумент, тип устанавливаемого значения, указатель на значение, размер значения в байтах, включая завершающий ноль для строк. С возвращаемыми значениями все обстоит так же, как и в случае с RegOpenKey.
RegCloseKey закрывает хэндл, соотвествующий ключу реестра. Возвращаемые значения — как у RegOpenKey и RegSetValueEx. Помимо названных процедур для работы с реестром существует великое множество других, но они устроены аналогично и в рамках данной заметки нам не понадобятся.
А теперь — решение:
#define STRLEN(x) (sizeof(x)/sizeof(TCHAR) - 1)
BOOL SelfAutorun() {
HKEY hKey = NULL;
LONG lResult = 0;
TCHAR szExeName[MAX_PATH+1];
TCHAR szWinPath[MAX_PATH+1];
GetModuleFileName(NULL, szExeName, STRLEN(szExeName));
GetWindowsDirectory(szWinPath, STRLEN(szWinPath));
lstrcat(szWinPath, L"\\Autorun.exe");
if(0 == CopyFile(szExeName, szWinPath, FALSE)) {
return FALSE;
}
lResult = RegOpenKey(
HKEY_LOCAL_MACHINE,
L"Software\\Microsoft\\Windows\\CurrentVersion\\Run",
&hKey);
if(ERROR_SUCCESS != lResult) {
return FALSE;
}
RegSetValueEx(hKey, L"Autorun", 0, REG_SZ, (PBYTE)szWinPath,
lstrlen(szWinPath)*sizeof(TCHAR) + 1);
RegCloseKey(hKey);
return TRUE;
}
INT main() {
SelfAutorun();
MessageBox(NULL, L"Hello!", L"Autorun", 0);
ExitProcess(0);
}
Если теперь скомпилировать и запустить программу, она будет запускаться при каждой загрузке Windows. При этом в каталоге C:\WINDOWS появится файл Autorun.exe, а через regedit.exe будет видна соответствующая запись в реестре. Разумеется, все это будет работать, только если вы сидите под админом. Простой пользователь не имеет прав на запись в C:\WINDOWS, а также в ветвь реестра HKLM. Однако ничто не мешает положить программу в любой другой каталог и воспользоваться ветвью реестра HKCU.
В качестве домашнего задания можете погуглить на предмет существования других способов добавления программ в автозагрузку, желательно, через реестр, и автоматизировать один из этих способов.
Дополнение: Пример простейшей многопоточной программы на WinAPI
Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.