Windows獲取進程完整路徑


#include <stdio.h>
#include <locale.h>
#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <Psapi.h>
#pragma comment (lib,"Psapi.lib")


BOOL DosPathToNtPath(LPTSTR pszDosPath, LPTSTR pszNtPath)
{
    TCHAR            szDriveStr[500];
    TCHAR            szDrive[3];
    TCHAR            szDevName[100];
    INT                iDevName;
    INT                i;

    //檢查參數
    if (!pszDosPath || !pszNtPath)
        return FALSE;

    //獲取本地磁盤所有盤符,以'\0'分隔,所以下面+4
    if (GetLogicalDriveStrings(sizeof(szDriveStr), szDriveStr))
    {
        for (i = 0; szDriveStr[i]; i += 4)
        {
            if (!lstrcmpi(&(szDriveStr[i]), _T("A:\\")) || !lstrcmpi(&(szDriveStr[i]), _T("B:\\")))
                continue;    //從C盤開始

            //盤符
            szDrive[0] = szDriveStr[i];
            szDrive[1] = szDriveStr[i + 1];
            szDrive[2] = '\0';
            if (!QueryDosDevice(szDrive, szDevName, 100))//查詢 Dos 設備名(盤符由NT查詢DOS)
                return FALSE;

            iDevName = lstrlen(szDevName);
            if (_tcsnicmp(pszDosPath, szDevName, iDevName) == 0)//是否為此盤
            {
                lstrcpy(pszNtPath, szDrive);//復制驅動器
                lstrcat(pszNtPath, pszDosPath + iDevName);//復制路徑

                return TRUE;
            }
        }
    }

    lstrcpy(pszNtPath, pszDosPath);

    return FALSE;
}
//獲取進程完整路徑
BOOL GetProcessFullPath(DWORD dwPID)
{
    TCHAR        szImagePath[MAX_PATH];
    TCHAR        pszFullPath[MAX_PATH];
    HANDLE        hProcess;
    if (!pszFullPath)
        return FALSE;

    pszFullPath[0] = '\0';

    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, 0, dwPID);    //由線程ID獲得線程信息
    if (!hProcess)
        return FALSE;

    if (!GetProcessImageFileName(hProcess, szImagePath, MAX_PATH))    //得到線程完整DOS路徑
    {
        CloseHandle(hProcess);
        return FALSE;
    }
    if (!DosPathToNtPath(szImagePath, pszFullPath))    //DOS路徑轉NT路徑
    {
        CloseHandle(hProcess);
        return FALSE;
    }



    CloseHandle(hProcess);

    _tprintf(_T("%5d  %s \r\n"), dwPID, pszFullPath);
    return TRUE;
}
int main(int argc, char* argv[])
{
    setlocale(LC_ALL, "chs");    //不設置解析中文字符時可能會出問題
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);    //得到系統所有線程快照
    if (INVALID_HANDLE_VALUE == hSnapshot)
    {
        return NULL;
    }
    PROCESSENTRY32 pe = { 0 };
    pe.dwSize = sizeof(PROCESSENTRY32);

    BOOL fOk;
    for (fOk = Process32First(hSnapshot, &pe); fOk; fOk = Process32Next(hSnapshot, &pe))    //遍歷
    {
        GetProcessFullPath(pe.th32ProcessID);
    }
    return 0;
}

為什么要使用setlocal呢(非本例)

在 VC2005 中 std::fstream 的打開文件的函數實現里,傳入的 char const* 文件名作為多字節首先被mbstowcs 轉換成寬字節后,再轉發給 Unicode 版本的 API 進行實際的打開文件操作

_MRTIMP2_NCEEPURE FILE *__CLRCALL_PURE_OR_CDECL _Fiopen(const char *filename, ios_base::openmode mode, int prot) 
{ // open wide-named file with byte name wchar_twc_name[FILENAME_MAX];   if (mbstowcs_s(NULL, wc_name, FILENAME_MAX, filename,FILENAME_MAX - 1) != 0)
    return (0); 
return _Fiopen(wc_name, mode, prot); 
}

問題的關鍵在於,對於 mbstowcs 函數來說,它需要知道多字節的編碼類型才能正確的將其轉換成寬字節的 unicode,很可惜這個編碼類型並沒有體現在函數的參數列表里,而是隱含依賴全局的 locale 。更加不幸的是,全局 locale 默認沒有使用系統當前語言,而是設置為沒什么用處的 "C" locale 。於是 GBK 編碼的文件名在 "C" locale 下轉換錯誤

 

在本機上vs2017運行本例時出現了無法打印中文字符串的現象


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM