[C] 반디집 자동설치 프로그램

Windows에서의 wget , 다른 프로세스 제어

나는 운영체제를 자주 설치하는 편이다. 뭐 이런저런 이유가 있지만 하드카피기기가 없는것이 가장 큰 이유이다.

Linux야 bash나 perl로 설치 명령어만 써주면 자동으로 인스톨이 슥슥 되지만,

CLI 기반의 설치가 아닌 Windows에서는 그것이 쉽지가 않다….

따라서 먼저 wget과 같은 함수로 installer 파일을 받아야한다.

다행이 이 함수는 존재한다.

#include<urlmon.h>            //URLDownloadToFileA
#pragma comment(lib,"urlmon.lib")
static char* url = "http://www.bandisoft.co.kr/bandizip/dl.php?web";
static char* file = "BANDIZIP-SETUP-KR.EXE";
int main(){
    ...
    if (URLDownloadToFileA(NULL, url, file, 0, 0) == S_OK){
        InstallBandiZip();
    }
    ...
    return 0;
}

사용법은 위의 소스를 보면 쉽게 알 수 있다.

이제 WinExec로 해당 프로그램을 실행 시킨후 spy++로 해당 윈도우의 class나 name을 알아온후
FindWindow함수로 HWND을 얻어온다.

자식 HWND를 알고싶다면 FindWindowEx 함수를 사용한다.

아래는 전체 소스이다.

#include<stdio.h>	//puts , printf , remove
#include<stdlib.h>	//EXIT_FAILURE
#include<time.h>

#include<stdbool.h>

#include<urlmon.h>			//URLDownloadToFileA
#pragma comment(lib,"urlmon.lib")

#include<shellapi.h>		//SHELLEXECUTEINFOA
#include<synchapi.h>		//WaitForSingleObject	Sleep

#include<winnt.h>			//SID_IDENTIFIER_AUTHORITY , PSID 
#include<securitybaseapi.h>	//AllocateAndInitializeSid, CheckTokenMembership, FreeSid

#include<windef.h>			//HWND
#include<WinUser.h>			//FindWindowA , FindWindowEx , SendMessageA

#define PRINT_HWND(H)	printf("%x\n",(H))
void InstallBandiZip() {
	char* url = "http://www.bandisoft.co.kr/bandizip/dl.php?web";
	char* file = "BANDIZIP-SETUP-KR.EXE";
	if (URLDownloadToFileA(NULL, url, file, 0, 0) == S_OK) {
		HWND hwnd;
		//If the function succeeds, the return value is greater than 31.
		if (WinExec(file, SW_SHOW) <= 31) {
			puts("[ERROR] 반디집 설치프로그램 실행 실패");
			return;
		}
		puts("반디집 설치 프로그램 실행...");
		if ((hwnd = FindWindowA("#32770", "반디집 설치")) == 0) {
			puts("[ERROR] 반디집 자동설치 실패. 수동으로 설치하세요");
			return;
		}
		HWND view = 0;
		HWND lp = 0;
		do {		//핸들을 순회하면서 inner form을 찾습니다.
			view = lp;
			lp = FindWindowExA(hwnd, lp, NULL, NULL);
		} while (lp);
		char* option[2] = { "프로그램 그룹 생성", "압축 파일 확장자 연결" };
		HWND combo1 = FindWindowExA(view, NULL, "Button", option[0]);
		HWND combo2 = FindWindowExA(view, NULL, "Button", option[1]);
		SendMessageA(combo1, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
		SendMessageA(combo2, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
		printf("%s 설치옵션 체크\n", option[0]);
		printf("%s 설치옵션 체크\n", option[1]);
		HWND ok = FindWindowExA(hwnd, NULL, "Button", "설치");
		SendMessageA(ok, BM_CLICK, (WPARAM)0, (LPARAM)0);
		WaitForSingleObject(hwnd, INFINITE);
		//반디집은 설치후에 프로그램이 뜨나 필요없기에 뜰때까지 기다렸다가 닫아준다.
		while ((hwnd = FindWindowA("BandiZipClass", NULL)) == 0) {
			Sleep(100);
		}
		SendMessageA(hwnd, WM_CLOSE, (WPARAM)0, (LPARAM)0);
		puts("[SUCCESS] 반디집 설치 완료");
		remove(file);
	}
	else {
		puts("[ERROR] 반디집 다운로드 실패");
	}
}
BOOL IsUserAdmin(void) {
	BOOL b;
	SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
	PSID AdministratorsGroup;
	b = AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID
		, DOMAIN_ALIAS_RID_ADMINS
		, 0, 0, 0, 0, 0, 0, &AdministratorsGroup);
	if (b) {
		if (!CheckTokenMembership(NULL, AdministratorsGroup, &b)) {
			b = FALSE;
		}
		FreeSid(AdministratorsGroup);
	}
	return b;
}
int main(void) {
	if (IsUserAdmin() == FALSE) {
		puts("[ERROR] : 관리자 권한으로 실행 하세요");
		Sleep(1000);
		exit(EXIT_FAILURE);
	}
	InstallBandiZip();
	return 0;
}