admin 发表于 2024-7-13 22:19:57

获取所有的CAD的进程号,窗口句柄,类名,窗口标题

#include "stdafx.h"
#include "TlHelp32.h"
#include "GetProcess.h"
#include "Psapi.h"
#include "winver.h"
#include "MSCorEE.h"

CString strWindows = _T("");
#pragma comment(lib, "version.lib")
#pragma comment(lib, "Psapi.lib")
#pragma comment(lib, "mscoree.lib")

struct LANGANDCODEPAGE
{
        WORD wLanguage;
        WORD wCodePage;
} *lpTranslate;

//----------------------------------------------------------------------------------
//另外方法
//枚举回调函数
BOOL CALLBACK EnumWindowsProc(HWND hWnd,LPARAM lParam)
{
        DWORD dwProcessId(0);
        LPWNDINFO pInfo = (LPWNDINFO)lParam;
        //通过窗口句柄获取进程ID
        GetWindowThreadProcessId(hWnd, &dwProcessId);
        TCHAR szText;
        ::GetWindowText(hWnd,szText,MAX_PATH);
        //匹配遍历窗口进程号与通过进程名得到的进程号
        TRACE( _T("EnumWindowsProc..hWnd=0x%x, ProcessID=%d, WindowsText=%s \n"), hWnd, dwProcessId, szText );
        if(dwProcessId == pInfo->dwProcessId && IsWindowVisible(hWnd))
        {
                TCHAR szClassName;
                GetClassName(hWnd,szClassName,80);
                HWND hParent = (HWND)::GetWindowLong(hWnd,-8);   //GWL_HWNDPARENT ;_WIN64,GWLP_HWNDPARENT
                if (hParent == 0 && _tcsncmp(szClassName,_T("Afx"),3) == 0 )
                {
                        strWindows +=_T("\n");
                        strWindows += szText;
                        //CString strTemp;
                        //strTemp.Format(_T("窗口句柄:%ld,父窗口句柄:%ld,窗口文本%s,窗口类别:%s"),hWnd,hParent,szText,szClassName);
                        //AfxMessageBox(strTemp);
                        pInfo->hWnd = hWnd;
                        pInfo->strClassName = szClassName;
            pInfo->strWindowText = szText;
                        return FALSE;
                }
        }
        return TRUE;
}

//获取所有的CAD的进程号,窗口句柄,类名,窗口标题,
int GFindWindows(LPCTSTR proc_name,vector<WNDINFO>&WndSet)
{
        int num=0;//返回的窗口句柄数目
        WndSet.clear();

        DWORD dwPID = 0;//一个临时PID
        int a;//存放进程PID的数组
        DWORD Proc_num=0;//进程数量
        CString procname(proc_name);
        //匹配进程名是否含 exe
        if (_tcscmp(procname.Right(procname.GetLength() - procname.ReverseFind('.') - 1),_T("exe")))
        {       
                return -1;//参数错误返回-1
        }
        //************************根据进程名称获取进程ID***********//
        HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
        if (INVALID_HANDLE_VALUE == hSnapshot)
        {
                return 0;
        }
        PROCESSENTRY32 pe = { sizeof(pe) };
        BOOL fOk;
        for (fOk = Process32First(hSnapshot, &pe); fOk; fOk = Process32Next(hSnapshot, &pe))
        {
                CString temp;
                TRACE(_T("当前查找进程的名称是: %s\n"),pe.szExeFile);
                TRACE(_T("当前进程PID: %d \n"),pe.th32ProcessID);
                if (!_tcscmp(pe.szExeFile, proc_name))
                {
                        //CloseHandle(hSnapshot);
                        temp.Format(_T("当前进程PID: %d \n"),pe.th32ProcessID);
                        TRACE(_T("当前匹配的进程PID: %d \n"),pe.th32ProcessID);
                        a = pe.th32ProcessID;
                        Proc_num++;
                }
        }
        //进程数量为0 提示找不到进程 返回为0;
        if (Proc_num==0)
        {
                return 0;
        }
        else//找到一个匹配进程
        {
                strWindows.Empty();
                WNDINFO wi;
                //对一个进程名有多个相同进程ID的全部数组进行处理
                for (DWORD j=0;j<Proc_num;j++)
                {
                        wi.hWnd = NULL;
                        wi.dwProcessId =a;//将获取到的进程ID传给结构体
                        wi.strAppPath = GetProcessPath(a);
                        wi.strVersion = GetAppVersion(wi.strAppPath);
              //遍历顶层窗口获取窗口句柄
                        EnumWindows(EnumWindowsProc,(LPARAM)&wi);
                        //判断当前进程是否无窗口 无窗口句柄则不保存
                        if (wi.hWnd!=NULL)
                        {
                                WndSet.push_back(wi);                //如果是需要的进程,则加入!!!!!!
                        }
                }
                //AfxMessageBox(strWindows);
                return num;//返回句柄个数
        }
}

//获取文件版本号
CString GetAppVersion(LPCTSTR pcszFileName)
{
        if (_tcscmp(pcszFileName,_T("X64")) == 0)
        {
                return pcszFileName;
        }
    //上面的小段为我加

        DWORD dwSize = 0;
        DWORD uiSize = GetFileVersionInfoSize(pcszFileName,&dwSize);
        if (0 == uiSize)
        {
                //0 意味着GetFileVersionInfoSize 函数调用失败
                return _T("");
        }

        PTSTR pBuffer = new TCHAR;

        if (NULL == pBuffer)
        {
                //分配内存失败:)
                return _T("");
        }

        memset((void*)pBuffer,0,uiSize);

        //获取exe 或 DLL 的资源信息,存放在pBuffer内
        if(!GetFileVersionInfo(pcszFileName,0,uiSize,(PVOID)pBuffer))
        {
                //GetFileVersionInfo 调用失败.
                delete []pBuffer;
                return _T("");
        }


        LANGANDCODEPAGE *pLanguage = NULL;//这里这样设置没关系了。

        UINTuiOtherSize = 0;
        //获取资源相关的 codepage 和language
        if (!VerQueryValue(pBuffer,_T("\\VarFileInfo\\Translation"),
                (PVOID*)&pLanguage,&uiOtherSize))
        {
                //出错
                delete []pBuffer;
                return _T("");
        }

        //////////////////////////////////////////////////////////////////////////
        //////////////////////////////////////////////////////////////////////////
        //超级重点

        LPVOID pTmp = NULL;   //一定要把pTmp这个变量设置成PVOID或LPVOID型的
        //否则无法获取信息。你不信可以试。
        //TCHAR *pTmp = NULL;
        //或下面这样的设置
        //TCHAR pTmp;
        //memset((void*)pTmp,0,sizeof(pTmp));

        //////////////////////////////////////////////////////////////////////////
        //////////////////////////////////////////////////////////////////////////

        TCHAR SubBlock;
        memset((void*)SubBlock,0,sizeof(SubBlock));

        CString strVersion;
       
        for(UINT i=0; i < (uiOtherSize / sizeof(LANGANDCODEPAGE)); i++ )
        {
                //获取每种 CodePage 和 Language 资源的相关信息
                wsprintf(SubBlock,
                        TEXT("\\StringFileInfo\\%04x%04x\\FileVersion"),
                        pLanguage.wLanguage,
                        pLanguage.wCodePage);

                //   Comments InternalName ProductName
                //   CompanyName LegalCopyright ProductVersion
                //   FileDescription LegalTrademarks PrivateBuild
                //   FileVersion OriginalFilename SpecialBuild
                //       OriginalFilename 可由上面的各种代替。
                //   Retrieve file description for language and code page "i".
               
                int nRet = VerQueryValue(pBuffer,SubBlock, (LPVOID*)&pTmp, &uiOtherSize);
                if (nRet != 0)
                {
                        strVersion.Format(_T("%s"),(TCHAR*)pTmp);
                }
        }
        delete []pBuffer;
        pBuffer = NULL;
        return strVersion;
}

//获取进程路径
CString GetProcessPath( DWORD idProcess )
{
        // 获取进程路径
        TCHAR szProcessName = _T("");
        // 打开进程句柄,需要管理员权限
        HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, idProcess );
        if( NULL != hProcess )
        {
                HMODULE hMod;
                DWORD cbNeeded;
                // 获取路径
                if( EnumProcessModules( hProcess, &hMod, (DWORD)sizeof( hMod ), (LPDWORD)&cbNeeded ) )
                {
                        DWORD dw = GetModuleFileNameEx( hProcess, hMod, szProcessName, MAX_PATH );
                }
                else
                {
                        //此处最可能碰到299错误,即如果编译成32位程序,去调用64位CAD
                        TRACE(_T("出错代码是:%d"),GetLastError());
                        int nError = GetLastError();//WSAGetLastError
                        if (nError == 299)
                        {
                                CloseHandle(hProcess);
                                return _T("X64");                        //64位的CAD
                        }
                }
                CloseHandle( hProcess );
        }
        return (szProcessName);
}


//将wchar_t* 转成char*的实现函数如下:
char *w2c(const wchar_t *pwstr)
{
        //size_t nlength=wcslen(pwstr);
        //获取转换后的长度
        size_t nbytes = WideCharToMultiByte( 0, // specify the code page used to perform the conversion
                0,         // no special flags to handle unmapped characters
                pwstr,   // wide character string to convert
                -1,//nlength,   // the number of wide characters in that string
                NULL,      // no output buffer given, we just want to know how long it needs to be
                0,
                NULL,      // no replacement character given
                NULL );    // we don't want to know if a character didn't make it through the translation
        // make sure the buffer is big enough for this, making it larger if necessary
        //if( nbytes > len)   
                //nbytes=len;

        char *pcstr = new char;
        // 通过以上得到的结果,转换unicode 字符为ascii 字符
        WideCharToMultiByte( 0, // specify the code page used to perform the conversion
                0,         // no special flags to handle unmapped characters
                pwstr,   // wide character string to convert
                -1,//nlength,   // the number of wide characters in that string
                pcstr, // put the output ascii characters at the end of the buffer
                nbytes,                           // there is at least this much space there
                NULL,      // no replacement character given
                NULL );
        return pcstr ;
}

//把ascii 字符转换为unicode字符
wchar_t* c2w(wchar_t *pwstr, const char *str)
{
        wchar_t* buffer=NULL;
        if(str != NULL)
        {
                size_t nu = strlen(str);
                size_t n =(size_t)MultiByteToWideChar(CP_ACP,0,(const char *)str,int(nu),NULL,0);
                buffer = new wchar_t;
                ::MultiByteToWideChar(CP_ACP,0,(const char *)str,int(nu),buffer,int(n));   
        }
        return buffer;
}
页: [1]
查看完整版本: 获取所有的CAD的进程号,窗口句柄,类名,窗口标题