[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;
}