如何获得进程句柄和进程其他模块的句柄:(和进程内核对象的句柄区分开来)也可以叫做模块句柄
每个可执行文件或者DLL文件被装入到某个进程的地址空间,都会有一个唯一的实例句柄,来表示装入后的可执行文件,或者DLL
此时我们把这个可执行文件或者DLL叫做进程地址空间中的一个模块!
进程句柄的本质,就是当前模块的起始地址。
进程句柄(HINSTANCE),在程序中很多地方,都被使用,尤其是在装入某一个资源的时候:
LoadIcon(HINSTANCE hInstance;PCTSTR pszIcon);
获取进程句柄的两种方法:
- WinMain函数的参数;
- GetProcessModule函数;
获得进程中,模块对应的文件名
DWORD GetModuleFileName(HMODULE hInstance,//进程句柄PTSTR pszPath,//文件名DWORD cchPath);//pszPath指向的内存的大小
进程句柄的本质是什么?就是进程模块在进程地址空间中的首地址!这个函数的使用注意事项:
- 如果这个函数的参数是NULL的话,那么这个函数只返回当前进程的模块地址!!
- 在DLL中,调用GetModuleHandle,返回的不是DLL模块的地址,而是当前进程的模块地址!
- 这个函数只检查本进程地址空间,不检查别的进程的地址空间。
如果自己的代码位于一个DLL文件中,那么想知道这个DLL文件被装入进程控件后的模块地址怎么办?
第一种方法:
extern “C” HANDLE __ImageBase;int main(){printf(“%x\n”,&__ImaggeBase);return 0;}
第二种方法:
void fun(HMODULE* hModule){GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,(PCTSTR)fun,&hModule);}
获得进程句柄的方式:
- GetModuleHandle函数;
- WinMain函数中的第一个参数hInstance;
HMODULE WINAPI GetModuleHandle(__in_opt LPCTSTR lpModuleName //模块名称,其实就是可执行文件的名称。);
如何获得一个进程或者执行模块的文件名呢?
通过:GetModuleFileName函数。
如果我们使用WinMain函数的话,这个函数的第一个参数,就是当前可执行程序的进程句柄。
进程的命令行:
在控制台程序中,有专门的机制,例如:
int main(int argc,char* argv[]);
在图形接口程序中,可以有一个函数:GetCommandLine,还有WinMain函数有一个参数:pszCmdLine,另外,还有一个分析命令行的函数CommandLineToArgvW(这个函数获得的)。
该函数原型如下:
LPWSTR CommandLinetoArgvW(LPCWSTR,int);
返回的字符串数组所使用的内存,用LocalFree来释放!
#include <windows.h>#include <stdio.h>#include <shellapi.h>int __cdecl main(){LPWSTR *szArglist;int nArgs;int i;szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);if( NULL == szArglist ){wprintf(L"CommandLineToArgvW failed\n");return 0;}else for( i=0; i<nArgs; i++) printf("%d: %ws\n", i, szArglist[i]);// Free memory allocated for CommandLineToArgvW arguments.LocalFree(szArglist);return(1);}
环境变量:
获取环境变量的一种方法:
#include <windows.h>#include<stdio.h>int main(){char** p=_environ;while(*p){printf("%s\n",*p);p++;}getchar();return(1);}#define UNICODE#define _UNICODE#include <windows.h>#include<tchar.h>int _tmain(){TCHAR** p=_wenviron;while(*p){_tprintf(L"%s\n",*p);p++;}_gettchar();return(1);}
环境变量保存位置
放在注册表中:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
这个注册表键下放的是系统环境变量。
HKEY_CURRENT_USER\Environment
这个注册表键下放的是当前登陆用户自己的环境变量。
注意,在你的程序中,如果你改变了环境变量,那么最好你发送一个消息:WM_SETTINGCHANGE!!!
注意:发这个消息时,不要使用某一个窗口的句柄,应该使用:HWND_BROADCAST作为窗口句柄!!使用SendMessage或者SendMessageTimeout函数来发送这个消息,lParam参数应该设置成”Environment”。
单个环境变量的获取和修改:
GetEnvironmentVariable;SetEnvironmentVariable;//只能改变当前进程的环境变量!对系统内的环境变量没有影响。对于%%之间的字符串,将被系统扩展!ExpandEnvironmentStrings函数。#include<Windows.h>#include<tchar.h>int _tmain(){DWORD length=ExpandEnvironmentStrings(L"%SystemRoot%",NULL,0);TCHAR* str=new TCHAR[length+1];ExpandEnvironmentStrings(L"%SystemRoot%",str,length);_tprintf(L"%s\n",str);_gettchar();return 0;}
最后一种获得环境变量的方法是:GetEnvironmentString()函数。
我们可以控制我们进程中的线程,只运行在某个CPU上,这个属性叫:Affinity
进程的错误模式:
一个函数:SetErrorMode(UINT uMode);
| Value | Meaning |
|---|---|
| 0 | 系统缺省模式,将所有错误都显示在错误窗口上。 |
| SEM_FAILCRITICALERRORS 0x0001 |
系统不在显示关键错误句柄信息给用户,而是将错误信息返回给进程 |
| SEM_NOALIGNMENTFAULTEXCEPT 0x0004 |
系统自动解决内存对齐缺陷,这种错误将不再报告给应用程序。进程的子进程也会具有这种特性。但有些CPU不支持这种方式。 这个标志一旦被设置,将不能再被取消。 |
| SEM_NOGPFAULTERRORBOX 0x0002 |
系统不在显示general-protection-default消息框。这个框只在调试模式下被显示。 |
| SEM_NOOPENFILEERRORBOX 0x8000 |
程序找不到文件时,不再显示消息框,这个错误被返回给进程。 |
获取进程的当前目录
GetCurrentDirectory函数//获取进程当前目录
DWORD WINAPI GetCurrentDirectory(__in DWORD nBufferLength,__out LPTSTR lpBuffer);
nBufferLength:lpBuffer指针指向内存块的大小(单位TCHAR);
lpBuffer:接收当前路径的内存块。
SetCurrentDirectory函数//设置进程当前目录
_chdir:设置当前目录
获取制定文件的当前路径
GetFullPathName(L”E:”,MAX_PATH,str,NULL);
::::这个函数为什么能获得当前目录?因为这个函数,就是用当前目录来补齐你的文件名,不管你这个文件真正在那里!!!没啥用!!!
transacted operation:事件操作,指这个操作不能被打断。
DWORD WINAPI GetFullPathName(__in LPCTSTR lpFileName,__in DWORD nBufferLength,__out LPTSTR lpBuffer,__out LPTSTR *lpFilePart);
lpFileName:文件名
nBufferLength:获取全路径的内存大小(TCHAR)
lpBuffer:内存指针
lpFilePart:文件名最后一个元素,在lpBuffer中的位置。
注意:这个函数,只是将当前路径,粘贴到你给的文件上,其他什么也没有做。
获取系统版本:
DWORD GetVersion();HIBYTE(GetVersion());LOBYTE(GetVersion());BOOL WINAPI GetVersionEx(__inout LPOSVERSIONINFO lpVersionInfo);// 获取当前系统版本信息//LpVersionInfo:这个参数执行OSVERSIONINFO或者OSVERSIONINFOEX这个结构体。//OSVERSIONIINFOEX结构体是OSVERSIONINFO结构体的扩展,所以这个函数可以传递这两个参数的任意一个,//前提条件是,必须设置结构体的大小,让GetVersionEx函数能够知道你传递的是那个结构体。typedef struct _OSVERSIONINFOEX {DWORD dwOSVersionInfoSize;DWORD dwMajorVersion;DWORD dwMinorVersion;DWORD dwBuildNumber;DWORD dwPlatformId;TCHAR szCSDVersion[128];WORD wServicePackMajor;WORD wServicePackMinor;WORD wSuiteMask;BYTE wProductType;BYTE wReserved;} OSVERSIONINFOEX, *POSVERSIONINFOEX, *LPOSVERSIONINFOEX;typedef struct _OSVERSIONINFO {DWORD dwOSVersionInfoSize;DWORD dwMajorVersion;DWORD dwMinorVersion;DWORD dwBuildNumber;DWORD dwPlatformId;TCHAR szCSDVersion[128];} OSVERSIONINFO;BOOL WINAPI VerifyVersionInfo(__in LPOSVERSIONINFOEX lpVersionInfo,__in DWORD dwTypeMask,__in DWORDLONG dwlConditionMask);//确认当前系统版本是否满足版本需求,其中lpVersionInfo是需要的系统版本,//dwTypeMask测试项,也就是说,lpVersioinInfo结构体中,那些参数被设置;//dwlConditionMask:比较条件ULONGLONG VER_SET_CONDITION(ULONGLONG dwlConditionMask,DWORD dwTypeBitMask,BYTE dwConditionMask);
