GetProcessImageFileName

GetProcessImageFileNameで、そのプロセスのプロセス名というか、実行ファイルのパスを取得できる。

GetProcessImageFileNameA function (psapi.h) - Win32 apps | Microsoft Docs
C++でプロセス名からプロセスIDを取得する - 備忘録
GetProcessImageFileName()で取得できるパス名について – プログラミング – Home

最初、QueryFullProcessImageNameを使ってたのだが、どうも失敗する。
しかもなぜかERROR_INSUFFICIENT_BUFFERで。
管理者権限かなとも思ったが、関係ない模様。
なので、

GetProcessImageFileNameでやってみた。

sizeof(dwProcessIds) = 4096
cbNeeded = 196
dwNum = 49
dwProcessIds[0] = 0, OpenProcess failed!
dwProcessIds[1] = 4, OpenProcess failed!
dwProcessIds[2] = 236, OpenProcess failed!
dwProcessIds[3] = 308, OpenProcess failed!
dwProcessIds[4] = 356, OpenProcess failed!
dwProcessIds[5] = 364, OpenProcess failed!
dwProcessIds[6] = 392, OpenProcess failed!
dwProcessIds[7] = 452, OpenProcess failed!
dwProcessIds[8] = 460, OpenProcess failed!
dwProcessIds[9] = 468, OpenProcess failed!
dwProcessIds[10] = 556, OpenProcess failed!
dwProcessIds[11] = 632, OpenProcess failed!
dwProcessIds[12] = 716, OpenProcess failed!
dwProcessIds[13] = 764, OpenProcess failed!
dwProcessIds[14] = 800, OpenProcess failed!
dwProcessIds[15] = 840, OpenProcess failed!
dwProcessIds[16] = 280, OpenProcess failed!
dwProcessIds[17] = 1056, OpenProcess failed!
dwProcessIds[18] = 1088, OpenProcess failed!
dwProcessIds[19] = 1208, OpenProcess failed!
dwProcessIds[20] = 1348, OpenProcess failed!
dwProcessIds[21] = 1380, OpenProcess failed!
dwProcessIds[22] = 1480, OpenProcess failed!
dwProcessIds[23] = 1524, OpenProcess failed!
dwProcessIds[24] = 1572, OpenProcess failed!
dwProcessIds[25] = 912, hProcess = 56, tszProcessName = \Device\HarddiskVolume2\
Windows\System32\taskhost.exe
dwProcessIds[26] = 2068, hProcess = 56, tszProcessName = \Device\HarddiskVolume2
\Windows\System32\dwm.exe
dwProcessIds[27] = 2116, hProcess = 56, tszProcessName = \Device\HarddiskVolume2
\Windows\explorer.exe
dwProcessIds[28] = 2556, hProcess = 56, tszProcessName = \Device\HarddiskVolume2
\Program Files\TortoiseGit\bin\TGitCache.exe
dwProcessIds[29] = 2700, hProcess = 56, tszProcessName = \Device\HarddiskVolume2
\Program Files (x86)\HTC\HTC Sync Manager\HTC Sync\adb.exe
dwProcessIds[30] = 2860, OpenProcess failed!
dwProcessIds[31] = 3504, OpenProcess failed!
dwProcessIds[32] = 3692, OpenProcess failed!
dwProcessIds[33] = 1564, OpenProcess failed!
dwProcessIds[34] = 3056, hProcess = 56, tszProcessName = \Device\HarddiskVolume2
\Program Files (x86)\Dropbox\Client\Dropbox.exe
dwProcessIds[35] = 2108, hProcess = 56, tszProcessName = \Device\HarddiskVolume2
\Program Files (x86)\Dropbox\Client\Dropbox.exe
dwProcessIds[36] = 2364, hProcess = 56, tszProcessName = \Device\HarddiskVolume2
\Program Files (x86)\Dropbox\Client\Dropbox.exe
dwProcessIds[37] = 1468, hProcess = 56, tszProcessName = \Device\HarddiskVolume2
\Program Files (x86)\Dropbox\Client\102.4.431\QtWebEngineProcess.exe
dwProcessIds[38] = 1072, hProcess = 56, tszProcessName = \Device\HarddiskVolume2
\Program Files (x86)\Dropbox\Client\102.4.431\QtWebEngineProcess.exe
dwProcessIds[39] = 836, hProcess = 56, tszProcessName = \Device\HarddiskVolume2\
Program Files (x86)\Microsoft Visual Studio 8\Common7\IDE\devenv.exe
dwProcessIds[40] = 3932, hProcess = 56, tszProcessName = \Device\HarddiskVolume2
\Program Files (x86)\TeraPad\TeraPad.exe
dwProcessIds[41] = 4032, hProcess = 56, tszProcessName = \Device\HarddiskVolume2
\Windows\System32\notepad.exe
dwProcessIds[42] = 3964, OpenProcess failed!
dwProcessIds[43] = 2540, hProcess = 56, tszProcessName = \Device\HarddiskVolume2
\Program Files (x86)\Microsoft Visual Studio 8\Common7\IDE\mspdbsrv.exe
dwProcessIds[44] = 3624, OpenProcess failed!
dwProcessIds[45] = 2176, OpenProcess failed!
dwProcessIds[46] = 828, hProcess = 56, tszProcessName = \Device\HarddiskVolume2\
Windows\SysWOW64\cmd.exe
dwProcessIds[47] = 4004, hProcess = 56, tszProcessName = \Device\HarddiskVolume2
\Windows\System32\conhost.exe
dwProcessIds[48] = 1008, hProcess = 56, tszProcessName = \Device\HarddiskVolume2
\Project\Cloud\github.com\Sample\winapi\GetProcessImageFileName\GetProcessImageF
ileName\src\GetProcessImageFileName\release\GetProcessImageFileName.exe
続行するには何かキーを押してください . . .

まあ、開けないのはしょうがないとして、開けるものは取得できた。
ただし、パスがデバイス形式なのは注意。

Sample/winapi/GetProcessImageFileName/GetProcessImageFileName/src/GetProcessImageFileName at master · bg1bgst333/Sample · GitHub

OpenProcess

OpenProcessで、指定のプロセスIDのプロセスをオープンし、ハンドルを取得する。

OpenProcess function (processthreadsapi.h) - Win32 apps | Microsoft Docs
C++でプロセス名からプロセスIDを取得する - 備忘録

プロセス情報取得のため、PROCESS_QUERY_INFORMATIONを指定。

このように書いて、実行。

sizeof(dwProcessIds) = 4096
cbNeeded = 236
dwNum = 59
dwProcessIds[0] = 0, OpenProcess failed!
dwProcessIds[1] = 4, OpenProcess failed!
dwProcessIds[2] = 236, OpenProcess failed!
dwProcessIds[3] = 308, OpenProcess failed!
dwProcessIds[4] = 356, OpenProcess failed!
dwProcessIds[5] = 364, OpenProcess failed!
dwProcessIds[6] = 392, OpenProcess failed!
dwProcessIds[7] = 452, OpenProcess failed!
dwProcessIds[8] = 460, OpenProcess failed!
dwProcessIds[9] = 468, OpenProcess failed!
dwProcessIds[10] = 556, OpenProcess failed!
dwProcessIds[11] = 632, OpenProcess failed!
dwProcessIds[12] = 720, OpenProcess failed!
dwProcessIds[13] = 764, OpenProcess failed!
dwProcessIds[14] = 796, OpenProcess failed!
dwProcessIds[15] = 836, OpenProcess failed!
dwProcessIds[16] = 280, OpenProcess failed!
dwProcessIds[17] = 1076, OpenProcess failed!
dwProcessIds[18] = 1108, OpenProcess failed!
dwProcessIds[19] = 1184, OpenProcess failed!
dwProcessIds[20] = 1232, OpenProcess failed!
dwProcessIds[21] = 1372, OpenProcess failed!
dwProcessIds[22] = 1396, OpenProcess failed!
dwProcessIds[23] = 1468, OpenProcess failed!
dwProcessIds[24] = 1540, OpenProcess failed!
dwProcessIds[25] = 1604, OpenProcess failed!
dwProcessIds[26] = 304, hProcess = 56
dwProcessIds[27] = 2032, hProcess = 56
dwProcessIds[28] = 2060, hProcess = 56
dwProcessIds[29] = 2440, hProcess = 56
dwProcessIds[30] = 2460, hProcess = 56
dwProcessIds[31] = 2492, hProcess = 56
dwProcessIds[32] = 2524, hProcess = 56
dwProcessIds[33] = 2644, hProcess = 56
dwProcessIds[34] = 2796, OpenProcess failed!
dwProcessIds[35] = 2340, OpenProcess failed!
dwProcessIds[36] = 2856, hProcess = 56
dwProcessIds[37] = 2676, hProcess = 56
dwProcessIds[38] = 3544, OpenProcess failed!
dwProcessIds[39] = 4056, OpenProcess failed!
dwProcessIds[40] = 4068, hProcess = 56
dwProcessIds[41] = 2436, hProcess = 56
dwProcessIds[42] = 3536, hProcess = 56
dwProcessIds[43] = 3600, hProcess = 56
dwProcessIds[44] = 3580, hProcess = 56
dwProcessIds[45] = 4216, hProcess = 56
dwProcessIds[46] = 5244, hProcess = 56
dwProcessIds[47] = 1476, hProcess = 56
dwProcessIds[48] = 5512, hProcess = 56
dwProcessIds[49] = 5924, hProcess = 56
dwProcessIds[50] = 5708, hProcess = 56
dwProcessIds[51] = 4028, hProcess = 56
dwProcessIds[52] = 5660, hProcess = 56
dwProcessIds[53] = 4508, OpenProcess failed!
dwProcessIds[54] = 4860, OpenProcess failed!
dwProcessIds[55] = 4400, OpenProcess failed!
dwProcessIds[56] = 2860, hProcess = 56
dwProcessIds[57] = 5840, hProcess = 56
dwProcessIds[58] = 2192, hProcess = 56
続行するには何かキーを押してください . . .

オープンに失敗するプロセスも割とある。

Sample/winapi/OpenProcess/OpenProcess/src/OpenProcess at master · bg1bgst333/Sample · GitHub

EnumProcesses

EnumProcessesで、プロセスIDを列挙する。

EnumProcesses function (psapi.h) - Win32 apps | Microsoft Docs
C++でプロセス名からプロセスIDを取得する - 備忘録

psapi.libをリンク
psapi.libをリンク

psapi.libをリンク。

cbNeededで得られるのは必要な配列の全体サイズなので、要素数となるとDWORDのサイズで割るのがちょっとめんどくさい。

sizeof(dwProcessIds) = 4096
cbNeeded = 236
dwNum = 59
dwProcessIds[0] = 0
dwProcessIds[1] = 4
dwProcessIds[2] = 236
dwProcessIds[3] = 308
dwProcessIds[4] = 356
dwProcessIds[5] = 364
dwProcessIds[6] = 392
dwProcessIds[7] = 452
dwProcessIds[8] = 460
dwProcessIds[9] = 468
dwProcessIds[10] = 556
dwProcessIds[11] = 632
dwProcessIds[12] = 720
dwProcessIds[13] = 764
dwProcessIds[14] = 796
dwProcessIds[15] = 836
dwProcessIds[16] = 280
dwProcessIds[17] = 1076
dwProcessIds[18] = 1108
dwProcessIds[19] = 1184
dwProcessIds[20] = 1232
dwProcessIds[21] = 1372
dwProcessIds[22] = 1396
dwProcessIds[23] = 1468
dwProcessIds[24] = 1540
dwProcessIds[25] = 1604
dwProcessIds[26] = 304
dwProcessIds[27] = 2032
dwProcessIds[28] = 2060
dwProcessIds[29] = 2440
dwProcessIds[30] = 2460
dwProcessIds[31] = 2492
dwProcessIds[32] = 2524
dwProcessIds[33] = 2644
dwProcessIds[34] = 2796
dwProcessIds[35] = 2340
dwProcessIds[36] = 2856
dwProcessIds[37] = 2676
dwProcessIds[38] = 3544
dwProcessIds[39] = 4056
dwProcessIds[40] = 3956
dwProcessIds[41] = 4068
dwProcessIds[42] = 2436
dwProcessIds[43] = 3536
dwProcessIds[44] = 3600
dwProcessIds[45] = 3580
dwProcessIds[46] = 1964
dwProcessIds[47] = 4216
dwProcessIds[48] = 4452
dwProcessIds[49] = 4568
dwProcessIds[50] = 5156
dwProcessIds[51] = 1180
dwProcessIds[52] = 5588
dwProcessIds[53] = 5284
dwProcessIds[54] = 4108
dwProcessIds[55] = 5720
dwProcessIds[56] = 3904
dwProcessIds[57] = 1532
dwProcessIds[58] = 5960
続行するには何かキーを押してください . . .

とりあえずプロセスIDは列挙できた。

Sample/winapi/EnumProcesses/EnumProcesses/src/EnumProcesses at master · bg1bgst333/Sample · GitHub

ControlService

サービスの停止は、StopService・・・とおもったら、そういうものはなく、ControlServiceで、SERVICE_CONTROL_STOPを指定する。

ControlService function (winsvc.h) - Win32 apps | Microsoft Docs
Win32 Windowsサービスを制御する ControlService - s-kita’s blog

実行中の状態
実行中の状態

実行中の状態。

SERVICE_CONTROL_STOPで停止。

デバッグなしで開始
デバッグなしで開始

デバッグなしで開始。

UACが反応
UACが反応

UACが反応

停止成功
停止成功

停止成功。

停止してる
停止してる

停止してる。

Sample/winapi/ControlService/ControlService/src/ControlService at master · bg1bgst333/Sample · GitHub

StartService

StartServiceで、サービスを開始する。

StartServiceA function (winsvc.h) - Win32 apps | Microsoft Docs
Win32 Windowsサービスを開始する StartService - s-kita’s blog

"Irmon"をいったんサービス停止する
"Irmon"をいったんサービス停止する

"Irmon"をいったんサービス停止する。

停止状態
停止状態

停止状態。


デバッガなし起動
デバッガなし起動

デバッガなし起動。

UACが反応
UACが反応

UACが反応。

StartService成功
StartService成功

StartService成功。

終了
終了

終了。

実行中になっている
実行中になっている

実行中になっている。

Sample/winapi/StartService/StartService/src/StartService at master · bg1bgst333/Sample · GitHub

OpenService

OpenServiceで、既存のサービスをオープンし、ハンドルを取得する。

OpenServiceA function (winsvc.h) - Win32 apps | Microsoft Docs
Win32 Windowsサービスを開始する StartService - s-kita’s blog

今回は、赤外線通信を管理するサービス"Irmon"、

赤外線通信を管理する"Irmon"
赤外線通信を管理する"Irmon"

こちらをオープンする。

一応、メニューからサービスを停止
一応、メニューからサービスを停止

一応、メニューからサービスを停止。

停止状態になっている
停止状態になっている

停止状態になっている。
コンソールアプリケーションの空プロジェクトで、

// ヘッダファイルのインクルード
#include <windows.h>	// 標準WindowsAPI
#include <tchar.h>		// TCHAR型
#include <stdio.h>		// 標準入出力

// _tmain関数の定義
int _tmain(int argc, TCHAR *argv[]){	// main関数のTCHAR版.

	// 変数の宣言と初期化.
	SC_HANDLE hSCM = NULL;	// SC_HANDLE型hSCMをNULLで初期化.
	SC_HANDLE hService = NULL;	// SC_HANDLE型hServiceをNULLで初期化.
	LPCTSTR lpctszService = _T("Irmon");	// サービス名lpctszServiceを"Irmon"で初期化.

	// SCManagerのオープン
	hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);	// OpenSCManagerでSCManagerを開き, ハンドルをhSCMに格納.
	if (hSCM != NULL){	// NULLでない時.

		// hSCMの出力.
		_tprintf(_T("hSCM = 0x%08x\n"), (unsigned long)hSCM);	// hSCMの値を出力.

		// Serviceのオープン
		hService = OpenService(hSCM, lpctszService, SERVICE_START);	// OpenServiceで"Irmon"を開く.
		if (hService != NULL){	// NULLでない時.

			// hServiceの出力.
			_tprintf(_T("hService = 0x%08x\n"), (unsigned long)hService);	// hServiceの値を出力.
			CloseServiceHandle(hService);	// CloseServiceHandleでhServiceを閉じる.

		}
		else{	// NULLの時.
			_tprintf(_T("OpenService failed!\n"));	// "OpenService failed!"と出力.
		}

		// hSCMを閉じる.
		CloseServiceHandle(hSCM);	// CloseServiceHandleでhSCMを閉じる.

	}
	else{	// NULLの時.
		_tprintf(_T("OpenSCManager failed!\n"));	// "OpenSCManager failed!"と出力.
	}

	// プログラムの終了
	return 0;	// 0を返して正常終了.

}

SERVICE_STARTで、開始権限を取得しようとしたが、

hSCM = 0x002d4c18
OpenService failed!
続行するには何かキーを押してください .

失敗した。

アプリケーション実行時に常にAdministratorとして実行する

VSからデバッガなし起動で管理者権限になっていないからダメなのかも。

app.manifestをrequireAdministratorに変更
app.manifestをrequireAdministratorに変更

app.manifestをrequireAdministratorに変更。

VSからデバッガなし起動でUACが反応するので管理者権限になれそう
VSからデバッガなし起動でUACが反応するので管理者権限になれそう

VSからデバッガなし起動でUACが反応するので管理者権限になれそう。

あれ?何も出ない。
あれ?何も出ない。

あれ?何も出ない。
ただ、一瞬何か見えたので、別コンソールになってるかもしれない。

hServiceを出力の後、Sleepで5秒待つ。

UACが出る
UACが出る

UACが出る。

やっぱり別コンソールで出力されてた
やっぱり別コンソールで出力されてた

やっぱり別コンソールで出力されてた。

Sample/winapi/OpenService/OpenService/src/OpenService at master · bg1bgst333/Sample · GitHub

OpenSCManager

サービスを制御するには、まずOpenSCManagerで、SCManagerをオープンして、ハンドルを取得する。

OpenSCManagerA function (winsvc.h) - Win32 apps | Microsoft Docs
Win32 Windowsサービスを開始する StartService - s-kita’s blog

コンソールアプリ
コンソールアプリ

コンソールアプリ。

空のプロジェクト
空のプロジェクト

空のプロジェクト。

OpenSCManagerで、SC_HANDLEのhSCMを取得する。
SC_MANAGER_CONNECTは、接続権限を持つハンドルといったところかな。

基本的にサービスは管理者権限が要りそうなのでマニフェストを用意しておく
基本的にサービスは管理者権限が要りそうなのでマニフェストを用意しておく

基本的にサービスは管理者権限が要りそうなのでマニフェストを用意しておく。
(ただし、ここではまだasInvokerにしてる。)

app.manifestを登録
app.manifestを登録

app.manifestを登録。

hSCM = 0x00544c98
続行するには何かキーを押してください . . .

hSCMを取得できた。

Sample/winapi/OpenSCManager/OpenSCManager/src/OpenSCManager at master · bg1bgst333/Sample · GitHub