獲取程式全路徑方法(支援xp、win7、win10系統)

byxdaz發表於2018-06-14
獲取程式全路徑方法(支援xp、win7、win10系統)

獲取程式的全路徑的函式包括GetModuleFileNameEx、GetProcessImageFileName、QueryFullProcessImageName。
這三個函式的原型:
DWORD GetModuleFileNameEx(HANDLE hProcess,HMODULE hModule,LPTSTR lpFilename,DWORD nSize)
      hProcess是目標程式的控制程式碼、hModule是目標模組的控制程式碼(當此引數為NULL時函式返回的是程式可執行檔案的路徑)、lpFilename是存放路徑的字串緩衝區、nSize表示緩衝區的大小。函式呼叫失敗將返回0。注:程式的控制程式碼須有PROCESS_QUERY_INFORMATION和PROCESS_VM_READ許可權。
 
DWORD GetProcessImageFileName(HANDLE hProcess,LPTSTR lpImageFileName,DWORD nSize)
      hProcess是目標程式的控制程式碼、lpImageFileName是存放路徑的字串緩衝區、nSize表示緩衝區的大小。函式失敗將返回0。注:程式控制程式碼需要有PROCESS_QUERY_INFORMATION的許可權。
 
BOOL QueryFullProcessImageName(HANDLE hProcess,DWORD dwFlags,LPTSTR lpExeName,PDWORD lpdwSize)
      hProcess是目標程式的控制程式碼、dwFlags一般設為0(表示返回的路徑是Win32的路徑格式,如"C:/...",如將其設為PROCESS_NAME_NATIVE將返回"/Device/HarddiskVolume1/..."這樣的格式路徑)、lpExeName是存放路徑的字串緩衝區、lpdwSize表示緩衝區的大小。函式失敗將返回FALSE。注:呼叫此函式的控制程式碼須有PROCESS_QUERY_INFORMATION或這是PROCESS_QUERY_LIMITED_INFORMATION的許可權,並且只能在Vista或更高版本的系統中使用。
 
      呼叫GetModuleFileNameEx和GetProcessImageFileName需要包含Psapi.h標頭檔案,並連結到Psapi.lib
#include <Psapi.h>
#pragma comment (lib,"Psapi.lib")

在win10 64位系統上呼叫GetModuleFileNameEx()遍歷獲取64位程式的全路徑失敗,得到的路徑都為空。

根據官方的說法:
For the best results use the following table to convert paths.
Windows 2000 = GetModuleFileNameEx()
Windows XP/Server2003 = GetProcessImageFileName()
Windows Vista/7/8/10/Server2008/Server2012 = QueryFullProcessImageName()
如果在win10系統中呼叫GetModuleFileNameEx 返回錯誤299 GetLastError();需要呼叫QueryFullProcessImageName()函式。

例項:

DWORD dwMajorVersion = 0;
	DWORD dwMinorVersion = 0;
	OSVERSIONINFOEX osver = { 0 };
	osver.dwOSVersionInfoSize = sizeof(osver);
	::GetVersionEx((OSVERSIONINFO*)&osver);
	dwMajorVersion = osver.dwMajorVersion;
	dwMinorVersion = osver.dwMinorVersion;
	
	//開啟程式
	//dwPID,程式ID
	char  szFileName[MAX_PATH] = {0};//檔名
	char  szPathName[MAX_PATH] = {0};//路徑名
	HANDLE hProcess = NULL;
	HMODULE hModule = NULL;
	hProcess=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,//訪問許可權,win7以上系統需要提升許可權EnablePrivilege
		false,//是否允許得到的程式控制程式碼被後建立的子程式繼承
		dwPID);//程式ID
  	DWORD dwError = 0;
		//BOOL bSuccessProcess = pEnumProcessModules(hProcess,&hModule,sizeof(hModule),&cbReturn);
		BOOL bSuccessProcess = EnumProcessModules(hProcess, &hModule, sizeof(hModule), &cbReturn);
		if (!bSuccessProcess)
		{
			dwError = GetLastError();
		}
		memset(szFileName, 0, sizeof(szFileName));
		memset(szPathName, 0, sizeof(szPathName));
		if (hModule != NULL)
		{
			//獲得程式模組檔名(包含路徑)
			if (dwMajorVersion < 5)		//2000
			{
				//儲存檔名
				DWORD dwGetModuleBaseName = GetModuleFileNameEx(hProcess, hModule, szPathName, sizeof(szPathName));
				GetFileNameWithoutExtendName(szPathName, pAll[i].szFileName);
			}
			if (dwMajorVersion == 5)  //x或Windows Server2003
			{
				GetProcessImageFileName(hProcess, szPathName, sizeof(szPathName));
				GetFileNameWithoutExtendName(szPathName, pAll[i].szFileName);
			}
			else if (osver.dwMajorVersion >= 6)		//win7或win7以上
			{
				DWORD dwPathNameSize = sizeof(szPathName);
				bSuccessProcess = QueryFullProcessImageName(hProcess, 0, szPathName, &dwPathNameSize);
				GetFileNameWithoutExtendName(szPathName, pAll[i].szFileName);
			}
			if (!bSuccessProcess)
			{
				dwError = GetLastError();
			}
			strcpy(pAll[i].szPathName, szPathName);
		}
		if(hProcess)
			CloseHandle(hProcess);
				

//得到檔名(不含副檔名)  
void GetFileNameWithoutExtendName(const char* pFile,char *pFileDest)
{
	if (NULL == pFile || 0 == strlen(pFile) || NULL == pFileDest)
		return;

	char *pPos = (char *)strrchr(pFile, '\\');
	if (NULL == pPos)
	{
		pPos = (char *)strrchr(pFile, '/');
	}
	if (NULL == pPos)
	{
		pPos = (char *)pFile;
	}
	if (pPos != NULL)
	{
		char *pSplitFlag = strrchr(pPos, '.');
		if (pSplitFlag != NULL)
		{
			int nLenTemp = pSplitFlag - pPos - 1;
			strncpy(pFileDest, pPos + 1, nLenTemp);
			pFileDest[nLenTemp] = '\0';
		}
		else
		{
			strcpy(pFileDest, pPos + 1);
		}
	}
	else
	{
		strcpy(pFileDest, pFile);
	}
}

//提權函式
BOOL EnablePrivilege(HANDLE hToken,LPCSTR szPrivName)
{
	TOKEN_PRIVILEGES tkp;//訪問令牌許可權結構變數
	LUID  luid;//本地唯一識別符號結構變數

	//查詢SE_DEBUG_NAME許可權所對應的luid值
	if(!LookupPrivilegeValue(NULL,szPrivName,&luid))
	{
	//	TRACE("Lookup Privilege Value Failed...\nErrorCode:%d\n",GetLastError());
		return 0;
	}

	//填充Token_Privileges結構
	tkp.PrivilegeCount=1;
	tkp.Privileges[0].Luid=luid;
	tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;

	//提升許可權
	if(!AdjustTokenPrivileges(hToken,FALSE,&tkp,sizeof(tkp),NULL,NULL))
	{
//		TRACE("Adjust Token Privileges Failed...\nErrorCode:%d\n",GetLastError());
		return 0;
	}

	return(GetLastError()==ERROR_SUCCESS);
}

相關文章