如何获得进程句柄和进程其他模块的句柄:(和进程内核对象的句柄区分开来)也可以叫做模块句柄
每个可执行文件或者DLL文件被装入到某个进程的地址空间,都会有一个唯一的实例句柄,来表示装入后的可执行文件,或者DLL
此时我们把这个可执行文件或者DLL叫做进程地址空间中的一个模块!
进程句柄的本质,就是当前模块的起始地址。

进程句柄(HINSTANCE),在程序中很多地方,都被使用,尤其是在装入某一个资源的时候:

  1. LoadIcon(
  2. HINSTANCE hInstance;
  3. PCTSTR pszIcon);

获取进程句柄的两种方法:

  1. WinMain函数的参数;
  2. GetProcessModule函数;

获得进程中,模块对应的文件名

  1. DWORD GetModuleFileName(
  2. HMODULE hInstance,//进程句柄
  3. PTSTR pszPath,//文件名
  4. DWORD cchPath);//pszPath指向的内存的大小

进程句柄的本质是什么?就是进程模块在进程地址空间中的首地址!这个函数的使用注意事项:

  • 如果这个函数的参数是NULL的话,那么这个函数只返回当前进程的模块地址!!
  • 在DLL中,调用GetModuleHandle,返回的不是DLL模块的地址,而是当前进程的模块地址!
  • 这个函数只检查本进程地址空间,不检查别的进程的地址空间。

如果自己的代码位于一个DLL文件中,那么想知道这个DLL文件被装入进程控件后的模块地址怎么办?
第一种方法:

  1. extern C HANDLE __ImageBase;
  2. int main()
  3. {
  4. printf(“%x\n”,&__ImaggeBase);
  5. return 0;
  6. }

第二种方法:

  1. void fun(HMODULE* hModule)
  2. {
  3. GetModuleHandleEx(
  4. GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
  5. (PCTSTR)fun,&hModule);
  6. }


获得进程句柄的方式:

  1. GetModuleHandle函数;
  2. WinMain函数中的第一个参数hInstance;
  1. HMODULE WINAPI GetModuleHandle(
  2. __in_opt LPCTSTR lpModuleName //模块名称,其实就是可执行文件的名称。
  3. );

如何获得一个进程或者执行模块的文件名呢?
通过:GetModuleFileName函数。
如果我们使用WinMain函数的话,这个函数的第一个参数,就是当前可执行程序的进程句柄。

进程的命令行:

在控制台程序中,有专门的机制,例如:
int main(int argc,char* argv[]);
在图形接口程序中,可以有一个函数:GetCommandLine,还有WinMain函数有一个参数:pszCmdLine,另外,还有一个分析命令行的函数CommandLineToArgvW(这个函数获得的)。

该函数原型如下:
LPWSTR CommandLinetoArgvW(LPCWSTR,int);
返回的字符串数组所使用的内存,用LocalFree来释放!

  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <shellapi.h>
  4. int __cdecl main()
  5. {
  6. LPWSTR *szArglist;
  7. int nArgs;
  8. int i;
  9. szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
  10. if( NULL == szArglist )
  11. {
  12. wprintf(L"CommandLineToArgvW failed\n");
  13. return 0;
  14. }
  15. else for( i=0; i<nArgs; i++) printf("%d: %ws\n", i, szArglist[i]);
  16. // Free memory allocated for CommandLineToArgvW arguments.
  17. LocalFree(szArglist);
  18. return(1);
  19. }

环境变量:

获取环境变量的一种方法:

  1. #include <windows.h>
  2. #include<stdio.h>
  3. int main()
  4. {
  5. char** p=_environ;
  6. while(*p)
  7. {
  8. printf("%s\n",*p);
  9. p++;
  10. }
  11. getchar();
  12. return(1);
  13. }
  14. #define UNICODE
  15. #define _UNICODE
  16. #include <windows.h>
  17. #include<tchar.h>
  18. int _tmain()
  19. {
  20. TCHAR** p=_wenviron;
  21. while(*p)
  22. {
  23. _tprintf(L"%s\n",*p);
  24. p++;
  25. }
  26. _gettchar();
  27. return(1);
  28. }

环境变量保存位置

放在注册表中:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
这个注册表键下放的是系统环境变量。

HKEY_CURRENT_USER\Environment
这个注册表键下放的是当前登陆用户自己的环境变量。

注意,在你的程序中,如果你改变了环境变量,那么最好你发送一个消息:WM_SETTINGCHANGE!!!

注意:发这个消息时,不要使用某一个窗口的句柄,应该使用:HWND_BROADCAST作为窗口句柄!!使用SendMessage或者SendMessageTimeout函数来发送这个消息,lParam参数应该设置成”Environment”。

单个环境变量的获取和修改:

  1. GetEnvironmentVariable;
  2. SetEnvironmentVariable;//只能改变当前进程的环境变量!对系统内的环境变量没有影响。
  3. 对于%%之间的字符串,将被系统扩展!
  4. ExpandEnvironmentStrings函数。
  5. #include<Windows.h>
  6. #include<tchar.h>
  7. int _tmain()
  8. {
  9. DWORD length=ExpandEnvironmentStrings(L"%SystemRoot%",NULL,0);
  10. TCHAR* str=new TCHAR[length+1];
  11. ExpandEnvironmentStrings(L"%SystemRoot%",str,length);
  12. _tprintf(L"%s\n",str);
  13. _gettchar();
  14. return 0;
  15. }

最后一种获得环境变量的方法是: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函数//获取进程当前目录

  1. DWORD WINAPI GetCurrentDirectory(
  2. __in DWORD nBufferLength,
  3. __out LPTSTR lpBuffer
  4. );

nBufferLength:lpBuffer指针指向内存块的大小(单位TCHAR);
lpBuffer:接收当前路径的内存块。
SetCurrentDirectory函数//设置进程当前目录
_chdir:设置当前目录
获取制定文件的当前路径
GetFullPathName(L”E:”,MAX_PATH,str,NULL);
::::这个函数为什么能获得当前目录?因为这个函数,就是用当前目录来补齐你的文件名,不管你这个文件真正在那里!!!没啥用!!!

transacted operation:事件操作,指这个操作不能被打断。

  1. DWORD WINAPI GetFullPathName(
  2. __in LPCTSTR lpFileName,
  3. __in DWORD nBufferLength,
  4. __out LPTSTR lpBuffer,
  5. __out LPTSTR *lpFilePart
  6. );

lpFileName:文件名
nBufferLength:获取全路径的内存大小(TCHAR)
lpBuffer:内存指针
lpFilePart:文件名最后一个元素,在lpBuffer中的位置。

注意:这个函数,只是将当前路径,粘贴到你给的文件上,其他什么也没有做

获取系统版本:

  1. DWORD GetVersion();
  2. HIBYTE(GetVersion());
  3. LOBYTE(GetVersion());
  4. BOOL WINAPI GetVersionEx(
  5. __inout LPOSVERSIONINFO lpVersionInfo
  6. );
  7. // 获取当前系统版本信息
  8. //LpVersionInfo:这个参数执行OSVERSIONINFO或者OSVERSIONINFOEX这个结构体。
  9. //OSVERSIONIINFOEX结构体是OSVERSIONINFO结构体的扩展,所以这个函数可以传递这两个参数的任意一个,
  10. //前提条件是,必须设置结构体的大小,让GetVersionEx函数能够知道你传递的是那个结构体。
  11. typedef struct _OSVERSIONINFOEX {
  12. DWORD dwOSVersionInfoSize;
  13. DWORD dwMajorVersion;
  14. DWORD dwMinorVersion;
  15. DWORD dwBuildNumber;
  16. DWORD dwPlatformId;
  17. TCHAR szCSDVersion[128];
  18. WORD wServicePackMajor;
  19. WORD wServicePackMinor;
  20. WORD wSuiteMask;
  21. BYTE wProductType;
  22. BYTE wReserved;
  23. } OSVERSIONINFOEX, *POSVERSIONINFOEX, *LPOSVERSIONINFOEX;
  24. typedef struct _OSVERSIONINFO {
  25. DWORD dwOSVersionInfoSize;
  26. DWORD dwMajorVersion;
  27. DWORD dwMinorVersion;
  28. DWORD dwBuildNumber;
  29. DWORD dwPlatformId;
  30. TCHAR szCSDVersion[128];
  31. } OSVERSIONINFO;
  32. BOOL WINAPI VerifyVersionInfo(
  33. __in LPOSVERSIONINFOEX lpVersionInfo,
  34. __in DWORD dwTypeMask,
  35. __in DWORDLONG dwlConditionMask
  36. );
  37. //确认当前系统版本是否满足版本需求,其中lpVersionInfo是需要的系统版本,
  38. //dwTypeMask测试项,也就是说,lpVersioinInfo结构体中,那些参数被设置;
  39. //dwlConditionMask:比较条件
  40. ULONGLONG VER_SET_CONDITION(
  41. ULONGLONG dwlConditionMask,
  42. DWORD dwTypeBitMask,
  43. BYTE dwConditionMask
  44. );