카테고리 없음

C/C++ Windows 특정 프로그램 실행하고 그 프로그램을 원하는 위치에 배치하기

hyuckkim 2023. 12. 10. 09:51

바로가기에 이 프로그램을 입력해서, 바로가기 A를 누르면 왼쪽에, 바로가기 B를 누르면 오른쪽에 프로그램이 켜지게 만들고 싶었다.

 

핵심은 프로그램이 켜지게 하는 것과 특정 위치로 이동시키는 것이다.

 


프로그램이 켜지게 하기

 

#include <processthreadsapi.h>

...

STARTUPINFOA si;
PROCESS_INFORMATION pi;
// set the size of the structures
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
int c = CreateProcessA(argv[1], NULL,
	NULL,
	NULL,
	FALSE,
	CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
	NULL,
	NULL,
	&si,
	&pi
);
    
...
   
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

 

processthreadsapi.h에 있는 CreateProcess를 사용하면 된다.

실행시킨 프로세스의 정보도 충분히 전달해줘서 다른 방식보다 할 수 있는 게 많다.

여기서는 실행시킨 프로세스의 pid만 가져와서 사용한다. (pi.dwThreadId)

 

프로그램 이동시키기

 

EnumWindows(enumWindowCallback, NULL);
static BOOL CALLBACK enumWindowCallback(HWND hWnd, LPARAM lparam) {
	DWORD cur = GetWindowThreadProcessId(hWnd, NULL);
	if (pid != cur) return TRUE;

	bool res = SetWindowPos(hWnd, NULL, dat.x, dat.y, 0, 0, SWP_NOSIZE);
	return TRUE;
}

 

핵심은 두 가지다.

창을 움직이려면 pid를 HWND로 변환해 줄 필요가 있다.

Hwnd를 찾았으면 움직이면 된다.

 

EnumWindows 함수는 지금 있는 모든 프로세스의 HWND를 가져와 callback을 실행한다. pid를 HWND로 바꾸는 편리한 함수는 없기 때문에, 모든 HWND에 대해 pid를 물어보고 (GetWindowThreadProcessId) 비교해준다.

 

아까 찾았던 pid와 지금 찾은 pid가 같다면, 그 창을 옮겨주면 된다. (SetWindowPos)

 

그 밖에

 

CreateProcess가 실행되고 나서 실제로 그 창을 움직일 수 있게 되기까지는 꽤 오래 걸린다.

나는 sleep 함수를 사용해 0.1초동안 대기하게 했다.

아마도 CreateProcess에서 받은 정보들을 가지고 더 우아하게 대기할 방법이 있을 것이다. 있을 거긴 한데 안 찾아봤다.

 

큰 프로그램들은 프로세스를 열심히 나눠서 쓴다.

그래서 그런 프로그램들은 창을 이동시키는 게 안 먹힌다. 아마 CreateProcess에서 찾은 건 메인 프로세스인데, 실제로 표시되는 창은 서브 프로세스라서 그럴 거다.

이 큰 프로그램은 대표적으로 Chrome이 있다. 원래 크롬 시작할 때 오른쪽 모니터에 띄워두려고 만든 건데 이래버려서 개발의욕이 떨어졌다.

아마 서브 프로세스를 찾아서 전부 이동시키면 되긴 할 것이다. 그래서 얘도 있을 거긴 한데, 안 찾아 봤다. 이 프로그램은 그냥 버릴 것이다.

 

전체 소스
#include <iostream>
#include <Windows.h>
#include <processthreadsapi.h>

struct wh {
	DWORD x;
	DWORD y;
} dat;
static DWORD pid;


static BOOL CALLBACK enumWindowCallback(HWND hWnd, LPARAM lparam) {
	DWORD cur = GetWindowThreadProcessId(hWnd, NULL);
	if (pid != cur) return TRUE;

	bool res = SetWindowPos(hWnd, NULL, dat.x, dat.y, 0, 0, SWP_NOSIZE);
	return TRUE;
}

int main(int argc, char** argv) {
	if (argc <= 3) return -1;
	dat.x = std::strtoul(argv[2], NULL, 10);
	dat.y = std::strtoul(argv[3], NULL, 10);
	DWORD sleeps = (argc > 4) ? std::strtoul(argv[4], NULL, 10) : 100;

	// additional information
	STARTUPINFOA si;
	PROCESS_INFORMATION pi;
	// set the size of the structures
	ZeroMemory(&si, sizeof(si));
	si.cb = sizeof(si);
	ZeroMemory(&pi, sizeof(pi));
	int c = CreateProcessA(argv[1], NULL,
		NULL,
		NULL,
		FALSE,
		CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
		NULL,
		NULL,
		&si,
		&pi
	);
	pid = pi.dwThreadId;
	Sleep(sleeps);
	EnumWindows(enumWindowCallback, NULL);


	// Close process and thread handles. 
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);

	return 0;
}

 

사용 방법 (굳이 사용한다면)

 

./Program "C:\Program Files\Bandizip\Bandizip.exe" 400 400

 

원래 Path에 넣어 놓고 바로가기 앞뒤에 글자 붙여서 쓰려고 했었다.

 

첫 번째 인자는 원래 실행하려던 파일이다. 바로가기 만들면 나오는 그 주소다.

두 번째, 세 번째 인자는 각각 모니터에서의 x좌표, y좌표이다. 1번 모니터의 왼쪽 위 끝이 0, 0이다.

내 모니터 설정은 이렇게 되어 있는데, 2번 모니터에서 실행하려면 1920, -200 정도로 넣으면 됐다.

 

 

 

끝.

 

 

레퍼런스

 

How do I call ::CreateProcess in c++ to launch a Windows executable? - Stack Overflow

 

How do I call ::CreateProcess in c++ to launch a Windows executable?

Looking for an example that: Launches an EXE Waits for the EXE to finish. Properly closes all the handles when the executable finishes.

stackoverflow.com

 

Get hwnd by process id c++ - Stack Overflow

 

Get hwnd by process id c++

How can I get the HWND of application, if I know the process ID? Anyone could post a sample please? I'm using MSV C++ 2010. I found Process::MainWindowHandle but I don't know how to use it.

stackoverflow.com

 

time - How do you add a timed delay to a C++ program? - Stack Overflow

 

How do you add a timed delay to a C++ program?

I am trying to add a timed delay in a C++ program, and was wondering if anyone has any suggestions on what I can try or information I can look at? I wish I had more details on how I am implementin...

stackoverflow.com

 

...그리고 여러 msdn 문서들