如何获得进程句柄和进程其他模块的句柄:(和进程内核对象的句柄区分开来)也可以叫做模块句柄
每个可执行文件或者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
);