进程ID和窗口间相互获得和转换

2015-04-27 16:35:25  访问(1812) 赞(0) 踩(0)

#pragma once

#define  SEM_OBJECT            TEXT("C_CHECK_OBJECT")
#define  STR_TARGET_PROCNAME   TEXT("Mp.exe")

enum {FLAG_CLOSE,FLAG_DATE_RESTART,FLAG_MIN_RESTART,FLAG_BACKUP,FLAG_ERROR_RESTART,FLAG_HANDLE};

class CCheckObject
{
public:
	CCheckObject(void);
	~CCheckObject(void);
private:
	HANDLE m_hEvent;
	HWND m_hWnd;
public:
	TCHAR m_szPath[MAX_PATH+1];
	BOOL IsProcessExist(LPCTSTR strName);//通过进程名,判断进程是否存在
	DWORD GetProcessId(LPCTSTR strName);//通过进程名,返回进程ID
	DWORD GetThreadId(LPCTSTR strName);//通过进程名,返回主线程ID
	DWORD GetThreadId(DWORD dwProcessID);//通过进程ID得到主线程ID
	HWND  GetTargetWindowHanle(LPCTSTR strName);//通过进程名,得到主窗口句柄.
	BOOL IsExeExist();                  //判断当前程序是否已经在运行.
	BOOL chSetProp(HWND hWnd);          //设置程序唯一性标记
	BOOL chRemoveProp();                //移除程序唯一性标记
	BOOL RunExe(LPCTSTR lpAppPathName,LPTSTR lpCmdLine);//传入exe完整路径,和命令行参数,运行一个外部程序.
};


#include "StdAfx.h"
#include "CheckObject.h"



#include <Tlhelp32.h>//方法1,toolhelp32

#include <Psapi.h> //方法2 ,EnumProcesses
#pragma comment(lib,"psapi.lib")

#include <WtsApi32.h>
#pragma comment(lib,"wtsapi32.lib")//WTSOpenServer  WTSEnumProcessInfo

#include <LM.h>
#pragma comment(lib,"netapi32.lib")//NetServerGetInfo 获得NetBios

#include <shlwapi.h>
#pragma comment(lib,"shlwapi.lib") //EnumThreadWindows



CCheckObject::CCheckObject(void)
{

	m_hEvent=NULL;
	m_hWnd=NULL;

	//获得当前工程路径
	memset(m_szPath,0,(MAX_PATH+1)*sizeof(TCHAR));
	GetModuleFileName(NULL,m_szPath,MAX_PATH);
	TCHAR *pChar=_tcsrchr(m_szPath,'\\');
	int len=_tcslen(pChar);
	memset(pChar,0,len*sizeof(TCHAR));
}

CCheckObject::~CCheckObject(void)
{
	chRemoveProp();
	CloseHandle(m_hEvent);
}

void PrintProcessNameAndID( DWORD processID )
{
	TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");

	// 获得进程句柄

	HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
		PROCESS_VM_READ,
		FALSE, processID );

	//获得进程名.

	if (NULL != hProcess )
	{
		HMODULE hMod;
		DWORD cbNeeded;

		//枚举进程中的模块
		if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), 
			&cbNeeded) )
		{
			//得到模块相关信息
			GetModuleBaseName( hProcess, hMod, szProcessName, sizeof(szProcessName)/sizeof(TCHAR) );
			/*if(0==GetModuleFileName(hMod,szProcessName,sizeof(szProcessName)/sizeof(TCHAR)))
			{
				TCHAR ebuf[20]={0};
				_stprintf(ebuf,TEXT("错误号:%d"),GetLastError());
				OutputDebugString(ebuf);

				GetModuleBaseName( hProcess, hMod, szProcessName, sizeof(szProcessName)/sizeof(TCHAR) );
			}*/
		}
	}

	// 输出进程名和进程ID.
	TCHAR buf[MAX_PATH]={0};
	_stprintf(buf, TEXT("%s  (PID: %u)\n"), szProcessName, processID );
	OutputDebugString(buf);//输出到DebugView中.
	CloseHandle( hProcess );
}


BOOL CCheckObject::IsProcessExist(LPCTSTR strName)
{
	if(strName==NULL)
	{
		return FALSE;
	}

	//遍历进程的方法
	//方法一,ToolHelp32遍历
	HANDLE hProcess=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
	BOOL bHave=FALSE;
	PROCESSENTRY32 pe32;
	pe32.dwSize=sizeof(pe32);
	if(hProcess)
	{
		bHave=Process32First(hProcess,&pe32);
		while(bHave)
		{
			bHave=Process32Next(hProcess,&pe32);
			//OutputDebugString(pe32.szExeFile);
			if(_tcsicmp(strName,pe32.szExeFile)==0)
			{
				return TRUE;
			}
		}
	}

	//方法二  进程枚举函数EnumProcesses
	/*DWORD aProcesses[1024], cbNeeded, cProcesses;
	unsigned int i;

	if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
		return FALSE;

	// Calculate how many process identifiers were returned.

	cProcesses = cbNeeded / sizeof(DWORD);

	// Print the name and process identifier for each process.

	for ( i = 0; i < cProcesses; i++ )
		if( aProcesses[i] != 0 )
			PrintProcessNameAndID( aProcesses[i] );
			*/

	//方法三  WTSEnumerateProcesses

	//获得远程计算机的NetBios
	/*DWORD dwLevel = 101;
	LPSERVER_INFO_101 pBuf = NULL;
	NET_API_STATUS nStatus;
	LPTSTR pszServerName = NULL;//
	nStatus = NetServerGetInfo(pszServerName,
		dwLevel,
		(LPBYTE *)&pBuf);
	if (nStatus == NERR_Success)
	{
		if ((pBuf->sv101_type & SV_TYPE_DOMAIN_CTRL) ||
			(pBuf->sv101_type & SV_TYPE_DOMAIN_BAKCTRL) ||
			(pBuf->sv101_type & SV_TYPE_SERVER_NT))
			OutputDebugString(TEXT("This is a server\n"));
		else
			OutputDebugString(TEXT("This is a workstation\n"));
	}
	//打开对应名字服务.
	HANDLE hWtsServer = WTSOpenServer(pBuf->sv101_name);

	//释放
	if (pBuf != NULL)
		NetApiBufferFree(pBuf);*/ 


	//以下可完成获得本机的,不需要以上获得的数据.
	/*PWTS_PROCESS_INFO pWtspi;
	DWORD dwCount=0;

	//枚举进程信息.
	if(!WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, //当前机子,HANDLE直接用WTS_CURRENT_SERVER_HANDLE就可以了
		0, 
		1, 
		&pWtspi, 
		&dwCount)) 
	{ 
		return FALSE; 
	}; 
	TCHAR buf[MAX_PATH]={0};
	for(int i=0; i<dwCount; i++) 
	{ 
		memset(buf,0,MAX_PATH*sizeof(TCHAR));
		_stprintf(buf,TEXT("ps_Id: %d ps_name: %s "), pWtspi[i].ProcessId, pWtspi[i].pProcessName); 
		OutputDebugString(buf);
	} */


	

	return FALSE;
}

DWORD CCheckObject::GetProcessId(LPCTSTR strName)
{
	if(strName==NULL)
	{
		return 0;
	}
	HANDLE hProcess=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
	BOOL bHave=FALSE;
	PROCESSENTRY32 pe32;
	pe32.dwSize=sizeof(pe32);
	TCHAR buf[100]={0};
	if(hProcess)
	{
		bHave=Process32First(hProcess,&pe32);
		while(bHave)
		{
			bHave=Process32Next(hProcess,&pe32);
			//OutputDebugString(pe32.szExeFile);
			//memset(buf,0,100*sizeof(TCHAR));
			//_stprintf(buf,TEXT("进程ID:%04d  线程数量:%d"),pe32.th32ProcessID,pe32.cntThreads);
			//OutputDebugString(buf);
			//GetThreadId(pe32.th32ProcessID);
			if(_tcsicmp(strName,pe32.szExeFile)==0)
			{
				//memset(buf,0,100*sizeof(TCHAR));
				//_stprintf(buf,TEXT("进程名:%s 进程ID:%04d  线程数量:%d"),pe32.szExeFile,pe32.th32ProcessID,pe32.cntThreads);
				//OutputDebugString(buf);
				return pe32.th32ProcessID;
			}
		}
	}
	return 0;
}

DWORD CCheckObject::GetThreadId(DWORD dwProcessID)
{
	if(dwProcessID==0)
	{
		return 0;
	}
	HANDLE hThread=CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);
	BOOL bHave=FALSE;
	THREADENTRY32 pe32;
	pe32.dwSize=sizeof(pe32);
	TCHAR buf[100]={0};
	if(hThread)
	{
		bHave=Thread32First(hThread,&pe32);
		while(bHave)
		{
			bHave=Thread32Next(hThread,&pe32);
			if(pe32.th32OwnerProcessID==dwProcessID)//第一个一般就是主线程ID.
			{
				//memset(buf,0,100*sizeof(TCHAR));
				//_stprintf(buf,TEXT("    线程ID:%04d"),pe32.th32ThreadID);
				//OutputDebugString(buf);
				return pe32.th32ThreadID;
			}
		}
	}
	return 0;
}


DWORD CCheckObject::GetThreadId(LPCTSTR strName)
{
	if(strName==NULL)
	{
		return 0;
	}
	return GetThreadId(GetProcessId(strName));
}


BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam )
{
	TCHAR buf[100]={0};
	GetWindowText(hwnd,buf,100);
	OutputDebugString(buf);
	if(::GetProp(hwnd,SEM_OBJECT))
	{
		::ShowWindow(hwnd,SW_RESTORE);
		::SetForegroundWindow(hwnd);
		return FALSE;
	}
	return  TRUE;
}



BOOL CCheckObject::IsExeExist()
{
	//让本程序只远行一个实例
	//方法1
	HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS,TRUE,SEM_OBJECT);
	if(NULL != hEvent)
	{
		//TCHAR buf[MAX_PATH]={0};
		//GetModuleFileName(NULL,buf,MAX_PATH);
		//CCheckObject ch;
		//DWORD dwThreadId=ch.GetThreadId(PathFindFileName(buf));
		//EnumThreadWindows(dwThreadId,EnumThreadWndProc,NULL);

		CloseHandle(hEvent);
		//OutputDebugString(TEXT("该程序已经在运行,不能打开另一个副本!"));
		return TRUE;
	}
	m_hEvent = CreateEvent(NULL,TRUE,TRUE,SEM_OBJECT);

	//方法2
	/*HANDLE hSem=CreateSemaphore(NULL,1,1,SEM_OBJECT);
	if(hSem)
	{
		if(ERROR_ALREADY_EXISTS==GetLastError())//如果是已经存在,则说明程序已经运行过.
		{
			EnumWindows(EnumWindowsProc,NULL);
			return TRUE;
		}
	}*/

	return FALSE;
}

BOOL CCheckObject::chSetProp(HWND hWnd)
{
	if(hWnd)
	{
		if(::SetProp(hWnd,SEM_OBJECT,(HANDLE)112233))
		{
			m_hWnd=hWnd;
			return TRUE;
		}
	}
	return FALSE;
}

BOOL CCheckObject::chRemoveProp()
{
	if(m_hWnd)
	{
		::RemoveProp(m_hWnd,SEM_OBJECT);
		return TRUE;
	}
	return FALSE;
}


//加强枚举;
BOOL CALLBACK EnhanceEnumProcWnd(HWND hWnd,LPARAM lParam)
{
	DWORD ProcID=0;
	DWORD pId=*(PDWORD)lParam;
	DWORD dwThreadId=GetWindowThreadProcessId(hWnd,&ProcID);
	if(dwThreadId==pId)
	{
		DWORD Style=GetWindowLong(hWnd,GWL_STYLE);
		
		if( !(Style&WS_CHILDWINDOW) && GetParent(hWnd)==NULL && GetWindow(hWnd,GW_CHILD)!=NULL)//非子 无父 并且 有子
		{

			/*OutputDebugString(TEXT("find wnd"));
			*(PDWORD)lParam=(DWORD)hwnd;
			return FALSE;*/
			/*CString Str;
			Str.Format(TEXT("%08X--%X"),hWnd,Style);
			Str+=TEXT("  -------MainWnd-----");
			TCHAR buf[0x30]={0};
			GetClassName(hWnd,buf,0x30);
			Str+=buf;
			OutputDebugString(Str);*/
			*(PDWORD)lParam=(DWORD)hWnd;
			return FALSE;
			
		}
		

	}
	return  TRUE;
}
//
BOOL CALLBACK EnumProcHwnd(HWND hwnd, LPARAM lParam )
{
	DWORD ProcID=0;
	DWORD pId=*(PDWORD)lParam;
	DWORD dwThreadId=GetWindowThreadProcessId(hwnd,&ProcID);
	if(dwThreadId==pId)
	{
		DWORD Style=GetWindowLong(hwnd,GWL_STYLE);
		
		
		if( !(Style&WS_CHILDWINDOW) && GetParent(hwnd)==NULL )//非子窗口 并且 无父窗口
		{

			/*OutputDebugString(TEXT("find wnd"));
			*(PDWORD)lParam=(DWORD)hwnd;
			return FALSE;*/
			/*CString Str;
			Str.Format(TEXT("%08X--%X"),hwnd,Style);
			Str+=TEXT("  -------MainWnd-----");
			TCHAR buf[0x30]={0};
			GetClassName(hwnd,buf,0x30);
			Str+=buf;
			OutputDebugString(Str);*/
			*(PDWORD)lParam=(DWORD)hwnd;
			return FALSE;
		}
		
		
	}
	return  TRUE;
}

//加强枚举.
BOOL CALLBACK EnEnumThreadWndProc(HWND hwnd,LPARAM lParam)
{
	if(GetParent(hwnd)==NULL && GetWindow(hwnd,GW_CHILD)!=NULL)//无父窗口 并且 有子窗口
	{
		
		*(PDWORD)lParam=(DWORD)hwnd;
		return FALSE;
	}
	return TRUE;
}

BOOL CALLBACK EnumThreadWndProc(HWND hwnd,LPARAM lParam)
{
	if(GetParent(hwnd)==NULL)//无父窗口
	{
		*(PDWORD)lParam=(DWORD)hwnd;//返回找到的窗口句柄
		return FALSE;
	}
	return TRUE;
}

HWND CCheckObject::GetTargetWindowHanle(LPCTSTR strName)
{

	DWORD ProcId=GetThreadId(strName);
	DWORD Handle=ProcId;

	//方法1
	/*EnumWindows(EnhanceEnumProcWnd,(LPARAM)&Handle);
	if(Handle==ProcId)//如果加强枚举没有得到,则降低条件
	{
		EnumWindows(EnumProcHwnd,(LPARAM)&Handle);
	}*/

	//方法2;
	EnumThreadWindows(ProcId,EnEnumThreadWndProc,(LPARAM)&Handle);
	if(Handle==ProcId)
	{
		EnumThreadWindows(ProcId,EnumWindowsProc,(LPARAM)&Handle);
	}
	//MoveWindow(HWND(*ProcId),0,0,100,100);
	return Handle==ProcId?NULL:(HWND)Handle;
}

BOOL CCheckObject::RunExe(LPCTSTR lpAppPathName,LPTSTR lpCmdLine)
{
	STARTUPINFO si;
	memset(&si,0,sizeof(STARTUPINFO));
	si.cb=sizeof(STARTUPINFO);//这一步一定要有.不然程序不能运行.
	PROCESS_INFORMATION pi;
	if(CreateProcess(lpAppPathName,lpCmdLine,NULL,NULL,FALSE,CREATE_SUSPENDED,NULL,NULL,&si,&pi))
	{
		::ResumeThread(pi.hThread);
		CloseHandle(pi.hProcess);
		CloseHandle(pi.hThread);
		return TRUE;
	}
	return FALSE;
}


标签:进程ID和窗口间相互获得和转换 

上一条:

下一条:


 

相关评论

评论加载中……
 

发表评论

类型:
内容:
  (Alt+Enter)