C++ API常用函數簡單例子大全四

第三十個CreateToolhelp32Snapshot給當前進程拍一個照

HANDLE hProcessSnap=::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);

//記住這種格式就行了,返回的句柄,存儲有進程信息,可以Process32Firs函數找出來。

第三十一個Process32First根據CreateToolhelp32Snapshot函數返回的句柄獲取進程信息

結合Process32Next函數使用,有點像文件尋找函數。

看完整例子:顯示系統進程名,以及進程ID號

#include<windows.h>
#include<tlhelp32.h>//聲明快照函數的頭文件
#include<stdio.h>
int main()
{
 PROCESSENTRY32 pe32;//進程的信息將會存儲在這個結構裏
 //在使用這個結構之前,先設置它的大小
 pe32.dwSize=sizeof(pe32);
 //給系統內的所有進程拍一個快照
 HANDLE hProcessSnap=::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
 BOOL bMore=::Process32First(hProcessSnap,&pe32);//第一次查找
 while(bMore)
 {
  printf("進程名稱:%s/n",pe32.szExeFile);//szExeFile是進程名
  printf("進程ID號:%u/n/n",pe32.th32ProcessID);//th32ProcessID是進程ID號
  bMore=::Process32Next(hProcessSnap,&pe32);//尋找下個進程,函數返回0,則沒有進程可尋
 }
 return 0;
}

第三十二個OpenProcess根據進程ID號獲得進程句柄,句柄通過函數返回

函數定義:HANDLE OpenProcess( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId);

第一個參數不要管它,填PROCESS_ALL_ACCESS,第二個參數也一樣,填FALSE,那最後一個參數就是進程ID號。

第三十三個TerminateProcess結束一個進程(需進程句柄做參數

該函數只有兩個參數,第一個是進程句柄,第二個填0就行了。

現在給個例子:假設當前有一個進程名爲abc.exe的進程正在運行,編一個程序結束它。

#include<windows.h>
#include<tlhelp32.h>//聲明快照函數的頭文件
int main(int argc,char *argv[])


 PROCESSENTRY32 pe32;
 //在使用這個結構之前,先設置它的大小
 pe32.dwSize=sizeof(pe32);
 //給系統內的所有進程拍一個快照
 HANDLE hProcessSnap=::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
 //遍歷進程快照,輪流顯示每個進程的信息
 BOOL bMore=::Process32First(hProcessSnap,&pe32);
 while(bMore)
 {

      if(strcmp("abc.exe",pe32.szExeFile)==0)//如果找到進程名爲abc.exe
   {
    HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pe32.th32ProcessID);//獲取句柄
     ::TerminateProcess(hProcess,0);//結束它
   }
  bMore=::Process32Next(hProcessSnap,&pe32);//尋找下一個
 }
 return 0;
}

上面的這個例子,只能結束普通權限進程,如果爲系統進程的話,則沒有用,結束不了。在後面的提升權限函數,會有例子說明如何結束系統進程。

第三十四個CreatePen創建一個畫筆(返回畫筆句柄)

函數定義:BOOL CreatePen(int nPenStyle, int nWidth, COLORREF crColor);

第一個參數,表示是什麼類型的線,取值有以下:

 如創建一個畫筆:HPEN pen=CreatePen(PS_SOLID,3,RGB(255,78,99));

PS_SOLID  畫筆畫出的是實線   PS_DASH 畫筆畫出的是虛線(nWidth必須是1) PS_DOT 畫筆畫出的是點線(nWidth必須是1)
PS_DASHDOT 畫筆畫出的是點劃線(nWidth必須是1) PS_DASHDOTDOT 畫筆畫出的是點-點-劃線(nWidth必須是1)
第二個參數是畫筆的寬度,第三個參數是畫筆的顏色,COLORREF類型可以RGB來獲得如RGB(233,128,88);分別是紅綠藍。

第三十五個CreateSolidBrush建一個畫刷

只有一個COLORREF類型的參數

HBRUSH brush=CreateSolidBrush(RGB(22,182,111));

第三十六個SelectObject把GDI對象選入相應的DC中

像畫筆(句柄HPEN),畫刷(HBURSH),位圖(HBITMAP)等都是GID對象。因爲畫圖函數,如畫圓,畫矩形,畫直線,它們所畫出圖形,默認屬性都是不變的,如線的寬度。那麼想要改變畫出來時線的寬度,比如我想畫出來的圖形它的線條寬度爲5(像素),那麼就要創建一個寬度爲5的畫筆,然後再通過SelectObject函數,給這個畫筆選入,就可以了.

接下舉個例子:SelectObject應用


#include "stdafx.h"
#include<windows.h>
LRESULT CALLBACK WinSunProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
 static HPEN pen=CreatePen(PS_SOLID,3,RGB(255,78,99));//創建畫筆
 static HBRUSH brush=CreateSolidBrush(RGB(22,182,111));//創建畫刷
 if(uMsg==WM_PAINT)//窗口需要重畫的時候
 {
    HDC hDC;
    PAINTSTRUCT ps;
    hDC=BeginPaint(hwnd,&ps);    //BeginPaint只能在響應WM_PAINT,不能用GetDC獲取設備上下文
 SelectObject(hDC,pen);//選入畫筆
 SelectObject(hDC,brush);//選入畫刷
 Rectangle(hDC,100,100,200,200);
    EndPaint(hwnd,&ps);
}
else if(uMsg==WM_CLOSE)//用戶關閉了窗口
 DestroyWindow(hwnd);//銷燬窗口,併發送WM_DESTROY消息
else if(uMsg==WM_DESTROY)//如果窗口被銷燬
 PostQuitMessage(0);//讓進程退出
 return DefWindowProc(hwnd,uMsg,wParam,lParam); //未處理的消息通過DefWindowProc函數交給系統處理
}
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{

  WNDCLASS wndcls; //定義一個存儲窗口信息WNDCLASS變量
  wndcls.cbClsExtra=0; //默認爲0
  wndcls.cbWndExtra=0; //默認爲0
  wndcls.hbrBackground=(HBRUSH)GetStockObject(GRAY_BRUSH); //背景畫刷
  wndcls.hCursor=LoadCursor(NULL,IDC_ARROW); //光標
  wndcls.hIcon=LoadIcon(NULL,IDI_ERROR); //窗口圖標
  wndcls.hInstance=hInstance;   //應用程序實例句柄由WinMain函數傳進來
  wndcls.lpfnWndProc=WinSunProc; //窗口消息處理函數
  wndcls.lpszClassName="windowclass"; //窗口類名
  wndcls.lpszMenuName=NULL; //窗口菜單名,沒有菜單,爲NULL
  wndcls.style=CS_HREDRAW | CS_VREDRAW;//窗口類型,CS_HREDRAW和CS_VERDRAW 表明
  //當窗口水平方向垂直方向的寬度變化時重繪整個窗口
  RegisterClass(&wndcls); //把窗口信息提交給系統,註冊窗口類
  HWND hwnd; //用以存儲CreateWindow函數所創建的窗口句柄
   hwnd=CreateWindow("windowclass","first windows",
  WS_OVERLAPPEDWINDOW,0,0,600,400,NULL,NULL,hInstance,NULL);//創建窗口
   ShowWindow(hwnd,SW_SHOWNORMAL);//窗口創建完了,顯示它
   UpdateWindow(hwnd); //更新窗口,讓窗口毫無延遲的顯示
   MSG msg;//消息結構類型
   while(GetMessage(&msg,NULL,0,0))//獲取消息
   {
    //TranslateMessage(&msg); //此函數用於把鍵盤消息(WM_KEYDOWN,WM_KEYUP)轉換成字符消息WM_CHAR
    DispatchMessage(&msg); //這個函數調用窗口過程處理函數,並把MSG裏的信息處理後傳給過程函數的四個參數
 }
  return 0;
}

第三十七個 ReadProcessMemory根據進程句柄讀取相應的一段內存(讀其它進程裏的內存)

函數定義:BOOL ReadProcessMemory(HANDLE hProcess,PVOID pvAddressRemote,PVOID pvBufferLocal,DWORD dwSize,

PDWORD pdwNumBytesRead);總共四個參數

第一個參數hProcess是遠程進程句柄,被讀取者 。第二個pvAddressRemote是遠程進程中內存地址。 從具體何處讀取

pvBufferLocal是本地進程中內存地址. 函數將讀取的內容寫入此處 ,dwSize是要讀取字節數。要讀取多少 

pdwNumBytesRead是實際讀取的內容(函數執行後,實際讀了多少字節,將存儲在該變量裏)

遠程進程的內存地址是什麼意思呢,比如我現在定義一個變量a,int a;就是了,大家知道int型是佔四個字節的,也就是說如果a變量所佔的內存起始地址是0x1234,那麼變量a就佔用0x1234,0x1235,0x1236,0x1237這四個字節,這四個字節的內容決定了a變量的值。

好了知道了這個,我們就來舉個例子,讀取另一個進程裏一個變量的值:需設計兩個程序,一個用於讀(Read)一個用於被讀(BeRead);

那麼要如何獲得另一個進程中一個變量的地址呢?這裏我們用一個簡單的方法,讓另一個進程自己去獲取,然後輸出地址值。

被讀的程序代碼如下:假設該進程名爲:BeRead.exe
#include<stdio.h>
int main()
{
 int a=10;//要讀取的變量。
  printf("%x/n",&a);//輸出這個變量的起始地址,假設輸出爲12ff7c
  while(1)
  {
   Sleep(1000);
  }

 return 0;
}

必須先讓這個程序運行,然後根據輸出的地址值,才能在下面的程序填入地址值。

讀取的程序代碼如下:

#include<windows.h>
#include<stdio.h>
#include<tlhelp32.h>
int main()
{

//先要獲取進程句柄,如何獲取,參照TerminateProcess函數,結束一個進程

 HANDLE ReProcess;
 PROCESSENTRY32 pe32;
 pe32.dwSize=sizeof(pe32);
 HANDLE hProcessSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
 BOOL bMore=::Process32First(hProcessSnap,&pe32);
 while(bMore)
 {
  if(strcmp(pe32.szExeFile,"BeRead.exe")==0)//如果是BeRead.exe
  {
   ReProcess=::OpenProcess(PROCESS_ALL_ACCESS,FALSE,pe32.th32ProcessID);//獲取該進程句柄
   break;
  }
  bMore=Process32Next(hProcessSnap,&pe32);
 }
 int *ReAddress=(int *)0x12ff7c;//要讀取的內存的地址值
 int  *p=new int;
    unsigned long size;
 ReadProcessMemory(ReProcess,ReAddress,p,4,&size);//讀取BeRead進程的內存
 printf("%d/n",*p);//輸出讀取來的值
 return 0;
}

第三十八個WriteProcessMemory根據進程句柄寫入相應的一段內存(寫入其它進程裏的內存)

這個函數裏的參數跟ReadProcessMemory函數參數意思一樣,只不過一個是寫,一個是讀。

下面直接舉個例子,形式跟讀內存函數的例子一樣。

被寫的程序代碼如下:假設該進程名爲:BeWrite.exe

#include<stdio.h>
int main()
{
 int a=10;
  printf("%x/n",&a);//假設輸出爲12ff7c
  while(1)
  {
   printf("%d/n",a);//每隔一秒輸出,查看值有沒有改變
   Sleep(1000);
  }

 return 0;
}

寫入的代碼如下:

#include<windows.h>
#include<stdio.h>
#include<tlhelp32.h>
int main()
{
 HANDLE ReProcess;
 PROCESSENTRY32 pe32;
 pe32.dwSize=sizeof(pe32);
 HANDLE hProcessSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
 BOOL bMore=::Process32First(hProcessSnap,&pe32);
 while(bMore)
 {
  if(strcmp(pe32.szExeFile,"BeWrite.exe")==0)
  {
   ReProcess=::OpenProcess(PROCESS_ALL_ACCESS,FALSE,pe32.th32ProcessID);
   break;
  }
  bMore=Process32Next(hProcessSnap,&pe32);
 }
 int *ReAddress=(int *)0x12ff7c;
 int  *p=new int;
 *p=300;
    unsigned long size;
 WriteProcessMemory(ReProcess,ReAddress,p,4,&size);

 return 0;
}

第三十九個CreateThread創建一個線程(多線程)

線程是什麼意思呢,代碼是由線程來執行的,一個程序默認只有一個線程(主線程),打個比方,線程就好比一個人,而不同功能的代碼或函數就好是一件件不同的事情,如洗碗,洗衣服,擦地。一個人要把這幾種事情做完,可以有好幾種方案,第一種就是,洗完碗,就去洗衣服,衣服洗完了,再去擦地。第二種就是:洗一分鐘碗,再去洗一分鐘衣服,再去擦一分鐘,然後又去洗一分鐘衣服.......直到做完。好了,現在你可以再創造一個人幫你做事,創造這個人後,你就叫他洗衣服,而你就洗碗,這樣兩件事就可以同時被做了。而這裏的創造一個人指的就是CreateThread函數。

函數定義:HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,DWORD dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter,DWORD dwCreationFlags,LPDWORD lpThreadId);

該函數有六個參數,第一個參數不用管它,填NULL,第二個參數dwStackSize用於新線程的初始堆棧大小,默認爲0,第三個lpStartAddress填函數名(指標),但這個函數必須是這種固定格式的DWORD _stdcall ThreadProc(LPVOID lpParameter),新的線程將會執行這個函數裏面的代碼,直到函數結束,線程死亡。第四個lpParameter是一自定義參數,用戶可以通過這個參數,傳遞需要的類型,這個參數與線程函數的參數相對應。第五個dwCreationFlags填0表示立即執行,如果是CREATE_SUSPENDED表示掛起,直到用ResumeThread函數喚醒。第六個lpThreadId填NULL就行了。

現舉個例子,兩個線程同時每隔一秒輸出一個數字,也就是一秒會有兩數字輸出。

#include<windows.h>
#include<stdio.h>
DWORD _stdcall ThreadProc(LPVOID lpParameter)//線程執行函數
{
 int si=100;
 while(si>0)
 {
  printf("子線程輸出數字:%d/n",si--);
  Sleep(1000);
 }
 return 0;
}

int main()
{
 int mi=0;
 CreateThread(NULL,0,ThreadProc,NULL,0,NULL);//創建一個線程,去執行ThreadProc函數
 while(mi<100)
 {
  printf("主線程輸出數字:%d/n",mi++);
  Sleep(1000);
 }
 return 0;
}

第四十個GetCurrentProcessId獲得當前進程ID

 DWORD currentPID;
 currentPID=::GetCurrentProcessId();//返回進程ID號
 cout<<currentPID<<endl;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章