社区
进程/线程/DLL
帖子详情
已经获得当前所有运行进程的句柄,获得后怎么操作?
不想干IT
2010-01-28 12:22:09
1,怎么获得当前所有进程的句柄。
2,获得后我怎么能实现对这个线程的操作。
我现在,在用全局钩子中把鼠标给隐藏了。但是程序结束后,我设置显示鼠标的时候只是当前线程的鼠标给设置成现实了。别的线程的鼠标依然是隐藏状态。
希望高手指教。
...全文
619
2
打赏
收藏
已经获得当前所有运行进程的句柄,获得后怎么操作?
1,怎么获得当前所有进程的句柄。 2,获得后我怎么能实现对这个线程的操作。 我现在,在用全局钩子中把鼠标给隐藏了。但是程序结束后,我设置显示鼠标的时候只是当前线程的鼠标给设置成现实了。别的线程的鼠标依然是隐藏状态。 希望高手指教。
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
2 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
IcyPlayer
2010-01-28
打赏
举报
回复
方法三:利用系统收集的性能数据(Performance Data)
这也是一种Windows NT/2000下的方法。首先,我们需要介绍一些关于性能监视(Performance Monitoring)的背景知识。
所谓性能监视,实际上是Windows NT/2000提供的一种系统功能,它能实时采集、分析系统内的应用程序、服务、驱动程序等的性能数据,以此来分析系统的瓶颈、监视组件的表现,最终帮助用户进行系统的合理调配。这里,还要引入一个性能对象(Performance Object)的概念,即被监视者。一般系统中的性能对象包括处理器(Processor)、进程(Process)、线程(Thread)、网络通讯(如TCP、UDP、ICMP、IP等)、系统服务(如ACS/RSVP Service)等。(本文我们关心的是进程,即名为“Process”的对象。)
性能对象有两种:一种只支持一个实例,另一种支持多个实例。(我们关心的进程对象支持多个实例,而每个实例对应系统中的一个进程。)一个对象可以有多个性能指标;每个性能指标都用一个计数器(Counter)来记录。就进程对象而言,它拥有的计数器种类包括ID Process(进程的PID)、Thread Count(线程数)、Priority Base(进程优先级)、IO Read Bytes/sec(每秒IO读取字节数)、IO Writer Bytes/sec(每秒IO写出字节数)等。(本文我们只关心ID Process计数器的值。)
知道了性能数据结构,接下去我们怎么来读取它们呢?最基本的方法就是通过注册表函数,如RegOpenKeyEx、RegQueryValueEx、RegCloseKey等。值得注意的是,这里虽然使用的是注册表函数,但性能数据并不存储在注册表数据库中;读取性能数据时调用函数RegOpenKeyEx,主键值应该是HKEY_PERFORMANCE_DATA。而当性能数据获得之后,根据各部分数据结构的定义,计算偏移量,我们就能获取我们感兴趣的数据了。
我们的演示程序提供了完整的代码实现:
#define INITIAL_SIZE 51200
#define EXTEND_SIZE 25600
#define REGKEY_PERF _T("Software\\Microsoft\\Windows NT\\Currentversion\\Perflib")
#define REGSUBKEY_COUNTERS _T("Counters")
#define PROCESS_COUNTER _T("process")
#define PROCESSID_COUNTER _T("id process")
BOOL CPerformanceSpy::BuildProcessList(void)
{
// 步骤一:从特定的注册表路径下获取系统中所有的对象、计数器的名字
LANGID lid = MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL);
TCHAR szSubKey[1024];
_stprintf(szSubKey, _T("%s\\%03x"), REGKEY_PERF, lid);
HKEY hSubKey;
DWORD rt = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSubKey, 0,
KEY_READ, &hSubKey);
if (rt != ERROR_SUCCESS)
{
return FALSE;
}
DWORD dwType = 0;
DWORD dwSize = 0;
LPBYTE buffer = NULL;
BOOL pass = FALSE;
// 获得装载所有计数器名字的缓冲大小
rt = RegQueryValueEx(hSubKey, REGSUBKEY_COUNTERS, NULL,
&dwType, NULL, &dwSize);
if (rt == ERROR_SUCCESS)
{
buffer = (LPBYTE) malloc(dwSize);
memset(buffer, 0, dwSize);
rt = RegQueryValueEx(hSubKey, REGSUBKEY_COUNTERS, NULL,
&dwType, buffer, &dwSize);
}
LPSTR p, p2;
DWORD dwProcessIdTitle;
DWORD dwProcessIdCounter;
PPERF_DATA_BLOCK pPerf;
PPERF_OBJECT_TYPE pObj;
PPERF_INSTANCE_DEFINITION pInst;
PPERF_COUNTER_BLOCK pCounter;
PPERF_COUNTER_DEFINITION pCounterDef;
if (rt == ERROR_SUCCESS)
{
pass = TRUE;
// 步骤二:查找名为“Process”的对象以及名为“ID Process”的计数器
// 获取它们的索引值(因为对象、计数器在性能数据中是靠索引来标识的)
p = (LPSTR) buffer;
while (*p)
{
if (p > (LPSTR) buffer)
{
for (p2 = p - 2; _istdigit(*p2); p2--)
;
}
if (_tcsicmp(p, PROCESS_COUNTER) == 0)
{
// 获取“Process”对象的索引
for (p2 = p - 2; _istdigit(*p2); p2--)
;
_tcscpy(szSubKey, p2+1);
}
else if (stricmp(p, PROCESSID_COUNTER) == 0)
{
// 获取“ID Process”计数器的索引
for (p2 = p - 2; _istdigit(*p2); p2--)
;
dwProcessIdTitle = atol(p2 + 1);
}
// Point to the next string
p += (_tcslen(p) + 1);
}
// 步骤三:获取进程对象的所有性能数据
free(buffer);
buffer = NULL;
dwSize = INITIAL_SIZE;
buffer = (LPBYTE) malloc(dwSize);
memset(buffer, 0, dwSize);
while (pass)
{
rt = RegQueryValueEx(HKEY_PERFORMANCE_DATA, szSubKey, NULL,
&dwType, buffer, &dwSize);
pPerf = (PPERF_DATA_BLOCK) buffer;
// 性能数据块开头以四个字符“PERF”标识
if ((rt == ERROR_SUCCESS) && (dwSize > 0) &&
pPerf->Signature[0] == (WCHAR)'P' &&
pPerf->Signature[1] == (WCHAR)'E' &&
pPerf->Signature[2] == (WCHAR)'R' &&
pPerf->Signature[3] == (WCHAR)'F')
{
break;
}
// 如果缓冲不够大,扩大缓冲后再试
if (rt == ERROR_MORE_DATA)
{
dwSize += EXTEND_SIZE;
buffer = (LPBYTE) realloc(buffer, dwSize );
memset(buffer, 0, dwSize );
}
else
{
pass = FALSE;
}
}
}
if (pass)
{
pObj = (PPERF_OBJECT_TYPE) ((DWORD)pPerf + pPerf->HeaderLength);
// 步骤四:在进程对象数据的计数器定义部分寻找“ID Process”计数器
pCounterDef = (PPERF_COUNTER_DEFINITION) ((DWORD)pObj + pObj->HeaderLength);
for (DWORD i = 0; i < (DWORD)pObj->NumCounters; i++)
{
if (pCounterDef->CounterNameTitleIndex == dwProcessIdTitle)
{
dwProcessIdCounter = pCounterDef->CounterOffset;
break;
}
pCounterDef++;
}
// 步骤五:遍历所有实例,获取实例的名字(即进程名)以及PID
TCHAR szProcessName[MAX_PATH];
pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pObj + pObj->DefinitionLength);
for (i = 0; i < (DWORD)pObj->NumInstances; i++)
{
// 获取进程名
p = (LPSTR) ((DWORD)pInst + pInst->NameOffset);
rt = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)p, -1, szProcessName,
sizeof(szProcessName), NULL, NULL);
// 获取进程PID
pCounter = (PPERF_COUNTER_BLOCK) ((DWORD)pInst + pInst->ByteLength);
DWORD processId = *((LPDWORD) ((DWORD)pCounter + dwProcessIdCounter));
if (strcmp(szProcessName, "System") && processId)
{
CProcessItem processItem;
processItem.SetProcessId(processId);
processItem.SetProcessName(szProcessName);
mProcList.AddTail(processItem);
}
// Point to the next process
pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pCounter + pCounter->ByteLength);
}
}
if (buffer)
{
free(buffer);
buffer = NULL;
}
RegCloseKey(hSubKey);
RegCloseKey(HKEY_PERFORMANCE_DATA);
return pass;
}
注:方法三用到的仅仅是注册表操作函数,而这些函数在advapi32.dll中实现。程序开发中,我们需要包含头文件winperf.h。另外,该方法中各个进程所调用的模块,仍然使用方法二的PSAPI函数获得,这里就不再列出。
方法四:使用PDH (Performance Data Helper)函数
这种方法的底层实现跟方法三其实是一样的。但我们看到,方法三实现起来非常繁琐。为了简化应用,PDH函数对方法三的实现进行了一层封装。我们这里的进程枚举,主要使用PdhEnumObjectItems函数,它的函数原型如下:
PDH_STATUS PdhEnumObjectItems(
LPCTSTR szDataSource, // 数据源
LPCTSTR szMachineName, // 机器名
LPCTSTR szObjectName, // 对象名
LPTSTR mszCounterList, // 计数器列表
LPDWORD pcchCounterListLength, // 计数器列表长度
LPTSTR mszInstanceList, // 实例列表
LPDWORD pcchInstanceListLength, // 实例列表长度
DWORD dwDetailLevel, // 获取信息的级别
DWORD dwFlags // 保留为0
);
对于每一个获得的进程实例,我们还要得到它的PID,也就是得到“ID Process”计数器的值。这时,我们会用到其他的PDH函数,包括:PdhOpenQuery、PdhAddCounter、PdhCollectQueryData、PdhGetFormattedCounterValue、PdhCloseQuery等。
我们的演示程序提供了完整的代码实现:
BOOL CPDHSpy::BuildProcessList(void)
{
LPTSTR szCounterListBuffer = NULL;
DWORD dwCounterListSize = 0;
LPTSTR szInstanceListBuffer = NULL;
DWORD dwInstanceListSize = 0;
BOOL pass = FALSE;
// 第一次调用PdhEnumObjectItems以获取需要的列表长度
PDH_STATUS pdhStatus = PdhEnumObjectItems(NULL, NULL, TEXT("Process"),
szCounterListBuffer, &dwCounterListSize, szInstanceListBuffer,
&dwInstanceListSize, PERF_DETAIL_WIZARD, 0);
if (pdhStatus == ERROR_SUCCESS)
{
szCounterListBuffer = (LPTSTR) malloc((dwCounterListSize * sizeof (TCHAR)));
szInstanceListBuffer = (LPTSTR) malloc((dwInstanceListSize * sizeof (TCHAR)));
// 第二次调用PdhEnumObjectItems
// 获得“Process”对象的所有计数器和实例
pdhStatus = PdhEnumObjectItems(NULL, NULL, TEXT("Process"),
szCounterListBuffer, &dwCounterListSize, szInstanceListBuffer,
&dwInstanceListSize, PERF_DETAIL_WIZARD, 0);
if (pdhStatus == ERROR_SUCCESS)
{
pass = TRUE;
LPTSTR pInst = szInstanceListBuffer;
// 获得每个实例名,也就是进程名
for (; *pInst != 0; pInst += lstrlen(pInst) + 1)
{
if (strcmp(pInst, "System") && strcmp(pInst, "Idle") &&
strcmp(pInst, "_Total"))
{
CProcessItem processItem;
// 获得进程的PID
processItem.SetProcessId(GetPIDCounterValue(pInst));
processItem.SetProcessName(pInst);
mProcList.AddTail(processItem);
}
}
}
}
if (szCounterListBuffer != NULL)
{
free(szCounterListBuffer);
szCounterListBuffer = NULL;
}
if (szInstanceListBuffer != NULL)
{
free(szInstanceListBuffer);
szInstanceListBuffer = NULL;
}
return pass;
}
DWORD CPDHSpy::GetPIDCounterValue(LPTSTR inInstanceName)
{
// 打开一个查询对象
HQUERY hQuery = NULL;
PDH_STATUS pdhStatus = PdhOpenQuery (0, 0, &hQuery);
HCOUNTER hCounter = NULL;
char szPathBuffer[MAX_PATH];
sprintf(szPathBuffer, "\\Process(%s)\\ID Process", inInstanceName);
pdhStatus = PdhAddCounter(hQuery, szPathBuffer, 0, &hCounter);
pdhStatus = PdhCollectQueryData(hQuery);
// 获得当前实例的“ID Process”计数器的值
DWORD ctrType;
PDH_FMT_COUNTERVALUE fmtValue;
pdhStatus = PdhGetFormattedCounterValue(hCounter, PDH_FMT_LONG,
&ctrType, &fmtValue);
// 关闭查询对象
pdhStatus = PdhCloseQuery (hQuery);
return fmtValue.longValue;
}
注:PDH函数在Pdh.dll中实现。程序开发中,我们需要包含头文件Pdh.h,连接库文件Pdh.lib。
IcyPlayer
2010-01-28
打赏
举报
回复
方法一:使用工具库(Tool Help Library)函数
这是一种历史最悠久、也是最基本的方法(从Windows 95开始就支持这种方法)。这些API函数中,最重要的当属CreateToolhelp32Snapshot,它的函数原型如下:
HANDLE WINAPI CreateToolhelp32Snapshot(
DWORD dwFlags,
DWORD th32ProcessID
);
这个函数的功能就是给系统拍“快照”。拍照的对象由参数dwFlags决定,比如dwFlags值为TH32CS_SNAPPROCESS表示对象为系统中的所有进程,值为TH32CS_SNAPMODULE表示对象为由th32ProcessID参数指定的进程调用的所有模块(也就是DLL)。
当调用CreateToolhelp32Snapshot函数给指定的对象拍完快照之后,我们就可以使用Process32First、Process32Next、Module32First、Module32Next等函数进行“取片”工作了,就是遍历刚才拍下来的所有进程、进程调用的所有模块。
我们的演示程序提供了完整的代码实现:
BOOL CToolHelpSpy::BuildProcessList(void)
{
// 给系统中所有进程拍快照
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
return FALSE;
}
PROCESSENTRY32 pe32 = {0};
pe32.dwSize = sizeof(PROCESSENTRY32);
// 遍历拍下来的所有进程
if (Process32First(hProcessSnap, &pe32))
{
do
{
if (pe32.th32ProcessID && strcmp(pe32.szExeFile, "System"))
{
// 保存进程的名字、PID
CProcessItem processItem;
processItem.SetProcessName(pe32.szExeFile);
processItem.SetProcessId(pe32.th32ProcessID);
// 加入列表保存
mProcList.AddTail(processItem);
}
} while (Process32Next(hProcessSnap, &pe32));
}
CloseHandle(hProcessSnap);
return TRUE;
}
BOOL CToolHelpSpy::BuildModuleList(CProcessItem& inProcess)
{
// 给指定的进程调用的所有模块拍快照
HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,
inProcess.GetProcessId());
if (hModuleSnap == INVALID_HANDLE_VALUE)
{
return FALSE;
}
MODULEENTRY32 me32 = {0};
me32.dwSize = sizeof(MODULEENTRY32);
inProcess.CleanupModuleList();
// 遍历所有模块
if (Module32First(hModuleSnap, &me32))
{
do
{
// 保存模块文件全路径
inProcess.AddModuleItem(me32.szExePath);
} while (Module32Next(hModuleSnap, &me32));
}
CloseHandle(hModuleSnap);
return TRUE;
}
注:工具库函数在Kernel32.dll中实现。程序开发中,我们需要包含头文件Tlhelp32.h,连接库文件Kernel32.lib。
注:我们这里使用自定义类CProcessItem来描述一个进程,它保存了进程的名字、PID等信息,另外还维持一个该进程调用的所有模块的列表。相应地,我们也使用一个自定义类CModuleItem来描述模块,它保存模块文件的全路径、版本号、文件大小、说明信息、所属产品名等。(下同)
方法二:使用PSAPI (Process Status API)函数
这是一种Windows NT/2000下的方法。核心是使用EnumProcesses函数。它的原型如下:
BOOL EnumProcesses(
DWORD *lpidProcess, // 用于保存所有进程的PID的数组
DWORD cb, // 上述数组的大小
DWORD *cbNeeded // PID数组中实际返回的(有效)字节数
);
当获得系统中所有进程的PID后,我们就可以使用OpenProcess函数打开指定的进程,再调用GetModuleBaseName获得该进程的名字,调用EnumProcessModules枚举该进程调用的所有模块,调用GetModuleFileNameEx获得模块文件的全路径。
我们的演示程序提供了完整的代码实现:
BOOL CPSApiSpy::BuildProcessList(void)
{
// 枚举获得系统中的所有进程的PID
DWORD processes[1024], needed;
if (!EnumProcesses(processes, sizeof(processes), &needed))
{
return FALSE;
}
char szName[MAX_PATH] = "";
DWORD actualProcessCount = needed / sizeof(DWORD);
for (DWORD i = 0; i < actualProcessCount; i++)
{
// 保存进程的PID
CProcessItem processItem;
processItem.SetProcessId(processes[i]);
// 打开当前进程以获得进程操作句柄
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE, processes[i]);
if (hProcess)
{
HMODULE hModule;
DWORD needed;
// 枚举当前进程调用的所有模块
if (EnumProcessModules(hProcess, &hModule, sizeof(hModule), &needed))
{
// 获得并保存进程的名字
GetModuleBaseName(hProcess, hModule, szName, sizeof(szName));
processItem.SetProcessName(szName);
mProcList.AddTail(processItem);
}
CloseHandle(hProcess);
}
}
return TRUE;
}
BOOL CPSApiSpy::BuildModuleList(CProcessItem& inProcess)
{
// 根据PID打开该进程,获得一个进程操作句柄
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE, inProcess.GetProcessId());
if (hProcess)
{
HMODULE modules[1024];
DWORD needed;
// 枚举当前进程调用的所有模块
if (EnumProcessModules(hProcess, modules, sizeof(modules), &needed))
{
char szName[MAX_PATH] = "";
inProcess.CleanupModuleList();
DWORD actualModuleCount = needed / sizeof(DWORD);
// 获得各个模块文件的全路径
for (DWORD i = 1; i < actualModuleCount; i++)
{
GetModuleFileNameEx(hProcess, modules[i], szName, sizeof(szName));
inProcess.AddModuleItem(szName);
}
}
CloseHandle(hProcess);
}
return TRUE;
}
注:PSAPI函数在Psapi.dll中实现。程序开发中,我们需要包含头文件Psapi.h,连接库文件Psapi.lib。这些文件在安装了微软的Platform SDK后就可获得。
C#通过
进程
名获取窗口
句柄
C#通过
进程
名获取窗口
句柄
,也可以获取
当前
窗口
句柄
。本人在c#2013测试通过。
VB Spy获取
进程
句柄
源码实例.rar
VB Spy获取
进程
句柄
源码实例,列出出
当前
运行
程序的窗口信息、子
进程
信息和鼠标坐标、
句柄
信息,程序可设置窗口总在最前端显示。
MT5 非区间均线回归刷单EA教学
1.主要面向有一定基础的学员;2.想编写EA苦于不知道如何下手的学员!3.能看懂代码的学员!4.不啰嗦直接上干货!5.固定框架式编程!6.面向对象,面向函数式编程!//--- 交易.追踪止损(Symbol(),追踪点值,magic号码); 指标.
句柄
至数组(指标.
句柄
A,小均值,0,iBars(Symbol(),应用周期),true); 指标.
句柄
至数组(指标.
句柄
B,大均值,0,iBars(Symbol(),应用周期),true);//---非区间 double 区间最高价= 数据.求区间最高价(Symbol(),应用周期,MODE_CLOSE,0,区间根数); double 区间最低价= 数据.求区间最低价(Symbol(),应用周期,MODE_CLOSE,0,区间根数); bool 包裹均线=小均值[0]区间最低价&&大均值[0]区间最低价;
EnumProcessHandle.rar(枚举
进程
句柄
)MFC
通过调用ProcessHandleEnumDll实现遍历某一个
进程
的所有
句柄
,需要管理员身份
运行
,显示
当前
系统
进程
列表,可通过右键选择要查看的
进程
项,或在下方Edit输入10进制PID查看
句柄
,适用场景:需要查看进场
当前
句柄
项,又无法进行调试器调试时,相对于使用调试器附加查看
句柄
,更快更高效也更安全
操作
系统实验实验
进程
管理
实验二
进程
管理 Windows所创建的每个
进程
都从调用CreateProcess() API函数开始,该函数的任务是在对象管理器子系统内初始化
进程
对象。每一
进程
都以调用ExitProcess() 或TerminateProcess() API函数终止。通常应用程序的框架负责调用 ExitProcess() 函数。对于C++
运行
库来说,这一调用发生在应用程序的main() 函数返回之后。 1. 创建
进程
CreateProcess() 调用的核心参数是可执行文件
运行
时的文件名及其命令行。表 2-1详细地列出了每个参数的类型和名称。 表2-1 CreateProcess() 函数的参数 参数名称 使用目的 LPCTSTR lpApplivationName 全部或部分地指明包括可执行代码的EXE文件的文件名 LPCTSTR lpCommandLine 向可执行文件发送的参数 LPSECURIITY_ATTRIBUTES lpProcessAttributes 返回
进程
句柄
的安全属性。主要指明这一
句柄
是否应该由其他子
进程
所继承 LPSECURIITY_ATTRIBUTES lpThreadAttributes 返回
进程
的主线程的
句柄
的安全属性 BOOL bInheritHandle 一种标志,告诉系统允许新
进程
继承创建者
进程
的
句柄
DWORD dwCreationFlage 特殊的创建标志 (如CREATE_SUSPENDED) 的位标记 LPVOID lpEnvironment 向新
进程
发送的一套环境变量;如为null值则发送调用者环境 LPCTSTR lpCurrentDirectory 新
进程
的启动目录 STARTUPINFO lpStartupInfo STARTUPINFO结构,包括新
进程
的输入和输出配置的详情 LPPROCESS_INFORMATION lpProcessInformation 调用的结果块;发送新应用程序的
进程
和主线程的
句柄
和ID 可以指定第一个参数,即应用程序的名称,其中包括相对于
当前
进程
的
当前
目录的全路径或者利用搜索方法找到的路径;lpCommandLine参数允许调用者向新应用程序发送数据;接下来的三个参数与
进程
和它的主线程以及返回的指向该对象的
句柄
的安全性有关。 然后是标志参数,用以在dwCreationFlags参数中指明系统应该给予新
进程
什么行为。经常使用的标志是CREATE_SUSPNDED,告诉主线程立刻暂停。当准备好时,应该使用ResumeThread() API来启动
进程
。另一个常用的标志是CREATE_NEW_CONSOLE,告诉新
进程
启动自己的控制台窗口,而不是利用父窗口。这一参数还允许设置
进程
的优先级,用以向系统指明,相对于系统中所有其他的活动
进程
来说,给此
进程
多少CPU时间。 接着是CreateProcess() 函数调用所需要的三个通常使用缺省值的参数。第一个参数是lpEnvironment参数,指明为新
进程
提供的环境;第二个参数是lpCurrentDirectory,可用于向主创
进程
发送与缺省目录不同的新
进程
使用的特殊的
当前
目录;第三个参数是STARTUPINFO数据结构所必需的,用于在必要时指明新应用程序的主窗口的外观。 CreateProcess() 的最后一个参数是用于新
进程
对象及其主线程的
句柄
和ID的返回值缓冲区。以PROCESS_INFORMATION结构中返回的
句柄
调用CloseHandle() API函数是重要的,因为如果不将这些
句柄
关闭的话,有可能危及主创
进程
终止之前的任何未释放的资源。 2. 正在
运行
的
进程
如果一个
进程
拥有至少一个执行线程,则为正在系统中
运行
的
进程
。通常,这种
进程
使用主线程来指示它的存在。当主线程结束时,调用ExitProcess() API函数,通知系统终止它所拥有的所有正在
运行
、准备
运行
或正在挂起的其他线程。当
进程
正在
运行
时,可以查看它的许多特性,其中少数特性也允许加以修改。 首先可查看的
进程
特性是系统
进程
标识符 (PID) ,可利用GetCurrentProcessId() API函数来查看,与GetCurrentProcess() 相似,对该函数的调用不能失败,但返回的PID在整个系统中都可使用。其他的可显示
当前
进程
信息的API函数还有GetStartupInfo()和GetProcessShutdownParameters() ,可给出
进程
存活期内的配置详情。 通常,一个
进程
需要它的
运行
期环境的信息。例如API函数GetModuleFileName() 和GetCommandLine() ,可以给出用在CreateProcess() 中的参数以启动应用程序。在创建应用程序时可使用的另一个
进程/线程/DLL
15,471
社区成员
49,182
社区内容
发帖
与我相关
我的任务
进程/线程/DLL
VC/MFC 进程/线程/DLL
复制链接
扫一扫
分享
社区描述
VC/MFC 进程/线程/DLL
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章