进程相关(一)

创建进程
BOOL CreateProcess(
  LPCTSTR lpAppName,  //可执行的映像文件名。如果没有指定lpAppName参数,那么lpCommandLine参数(也就是第二个参数)的第一个空白定界标记前面的字符串。
  LPTSTR  lpCommandLine,  //用于执行应用程序的命令行,整个命令行可以用于GetCommandLine函数的新进程。
  LPSECURITY_ATTRIBUTES lpProcessAttributes,  //可选参数,新进程的属性。如果不指定,那么函数创建的进程没有安全描述符,且产生的句柄在进程创建时不被继承。
  LPSECURITY_ATTRIBUTES lpThreadAttributes,  //可选参数,用来指定新线程的属性。其他同上
  BOOL bInheritHandles,  //指定此新进程是否将继承调用进程可见对象的句柄。
  DWORD dwCreationFlags,  //控制进程创建时候的一些标志
  LPVOID lpEnvironment,  //可选参数。指向环境数据区的指针,如果没有指定该参数,那么当前执行进程的环境数据区。对使用EnvironmentStrings的函数来说可以使用此环境数据区。
  LPCTCTR lpCurrentDirectory,  //可选参数。(这个参数主要是为需要启动一个应用程序并指定其初始驱动好工作目录的外壳(shell)提供的)如果指定该参数,那么可以为新进程提供表示当前驱动器和目录的字符串(该字符串必须包括驱动器字母在内的全限定路径名)。如果没有指定,那么新进程就被建立在当前所在的同一驱动器和目录里。
  LPSTARTUPINFO lpStartupInfo,  //指定如何显示应用程序窗口的数据结构
  LPPROCESS_INFORMATION lpProcessInformation  //接收有关新进程的标识信息
);

这个函数创建一个进程和一个主线程对象,并打开每个对象的句柄。

注意:

  • 对于lpAppName参数(或者是lpCommandLine参数的文件名部分)来说,如果文件名不包含扩展名,那么默认采用.EXE作为扩展名;如果文件名不包含目录路径,那么Windows将会在以下目录中寻找:

    1. 当前目录
    2. Windows目录
    3. Windows系统目录
    4. 路径变量中所列出来的目录
  • dwCreationFlags,提供控制进程创建时的一些标识:

    1. DEBUG_PROCESS, 如果它被置位,就说明正在创建进程的进程被当做调试进程,被创建的进程当做被调试程序,所有出现在被调试程序中的调试事件都要报告给调试程序
    2. DEBUG_ONLY_THIS_PROCESS, 如果它没有被置位,并且调试进程处于被调试状态,则这个进程成为调用进程的调试程序的另一个被调试进程;如果调用进程不是一个正在被调试的进程,则不出现与调试程序有关的活动。
    3. CREATE_SUSPENDED, 此进程被创建,但该进程的初始线程仍被挂起。创建此进程的程序可以调用ResumeThread函数来重新使用该线程。直到完成这些操作后,才执行此进程。
    4. CREATE_NEW_CONSOLE, 所创建的程序将有一个新的控制台,而不是继承父控制台。
    5. DETACHED_PROCESS, 所创建的进程没有控制台。从一个没有控制台的函数中调用一个控制台函数会导致出错。如果次进程以后想拥有一个控制台的话,可以调用AllocateConsole函数得到。如果设置了CREATE_NEW_CONSOLE和DETACHED_PROOCESS两个值,则将返回一个出错信息。
    6. CREATE_UNICODE_ENVIRONMENT, 如果设置了该标志位,那么lpEnvironment指针指向的环境变量块使用Unicode字符;如果没有,那么使用ANSI字符。
    7. CREATE_SHARED_WOW_VDM,
    8. CREATE_NEW_PROCESS_GROUP, 新创建的进程是一个进程组的根进程,该进程组包括所有该进程的后代进程。该进程组的ID和该进程的ID相同。
    9. CREATE_DEFAULT_ERROR_MODE, 新创建的进程将不继承调用者的出错模式,而是为新创建的进程创建缺省出错模式。
  • STARTUPINFO 结构:

typedef struct _STARTUPINFOA {
    DWORD   cb;
    LPSTR   lpReserved;
    LPSTR   lpDesktop;
    LPSTR   lpTitle;
    DWORD   dwX;
    DWORD   dwY;
    DWORD   dwXSize;
    DWORD   dwYSize;
    DWORD   dwXCountChars;
    DWORD   dwYCountChars;
    DWORD   dwFillAttribute;
    DWORD   dwFlags;
    WORD    wShowWindow;
    WORD    cbReserved2;
    LPBYTE  lpReserved2;
    HANDLE  hStdInput;
    HANDLE  hStdOutput;
    HANDLE  hStdError;
} STARTUPINFOA, *LPSTARTUPINFOA;
typedef struct _STARTUPINFOW {
    DWORD   cb;
    LPWSTR  lpReserved;
    LPWSTR  lpDesktop;
    LPWSTR  lpTitle;
    DWORD   dwX;
    DWORD   dwY;
    DWORD   dwXSize;
    DWORD   dwYSize;
    DWORD   dwXCountChars;
    DWORD   dwYCountChars;
    DWORD   dwFillAttribute;
    DWORD   dwFlags;
    WORD    wShowWindow;
    WORD    cbReserved2;
    LPBYTE  lpReserved2;
    HANDLE  hStdInput;
    HANDLE  hStdOutput;
    HANDLE  hStdError;
} STARTUPINFOW, *LPSTARTUPINFOW;
#ifdef UNICODE
typedef STARTUPINFOW STARTUPINFO;
typedef LPSTARTUPINFOW LPSTARTUPINFO;
#else
typedef STARTUPINFOA STARTUPINFO;
typedef LPSTARTUPINFOA LPSTARTUPINFO;
#endif // UNICODE
  • PROCESS_INFORMATION结构:
typedef struct _PROCESS_INFORMATION {
    HANDLE hProcess;
    HANDLE hThread;
    DWORD dwProcessId;
    DWORD dwThreadId;
} PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION;
创建进程(指定用户运行)
BOOL CreateProcessAsUser(
  HANDLE hToken,  //指定一个代表用户的句柄,该句柄必须有TOKEN_QUERY、TOKEN_DUPLICATE和TOKEN_ASSIGN_PRIARY属性。
  LPCTSTR lpAppName, 
  LPTSTR  lpCommandLine,  
  LPSECURITY_ATTRIBUTES lpProcessAttributes,  
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  BOOL bInheritHandles, 
  DWORD dwCreationFlags,  
  LPVOID lpEnvironment,  
  LPCTCTR lpCurrentDirectory,  
  LPSTARTUPINFO lpStartupInfo, 
  LPPROCESS_INFORMATION lpProcessInformation
);

这个函数与CreateProcess类似,具体参数也可以参照CreateProcess的参数,只是该函数创建的进程只能在hToken参数所指定用户的安全上下文中运行。缺省情况下,新创建的进程是非交互式的,也就是说,它不接受用户的输入,同样的,新进程将继承调用者进程的环境变量,而不继承与指定用户相联系的环境变量。

  • 函数成功返回非零值,否则返回零值
  • 关于Token的内容还没有学习,有时间补
结束进程
VOID ExitProcess(
    UNIT uExitCode
);

当前进程可以使用ExitProcess函数退出,并附带退出其所有的线程。。这个API函数提供了应用程序彻底终止的方法,这包括在所有附加的DLL的实例终止入口调用他们。
在将进程终止情况通知给所有的DLL以后,此API会终止这个当前进程。

终止子进程
BOOL TerminateProcess(
  HANDLE hProcess,  //要终止的进程的句柄
  UINT uExitCode
);

这个函数用于终止特定进程以及它的所有线程

  • 它不通知DLL进程被附着在要终止的进程上。
  • 使用TerminateProcess而不使用ExitProcess会影响由DLL得到的全局数据的状态。
  • 进程的终止态会从STILL_ACTIVE改为进程中最后一个终止线程的终止态(通常和函数的退出值相同)。
    = 终止一个进程不会从系统中删掉该进程。它只是终止其所有线程的执行,并关闭所有由该进程打开的对象句柄。一个进程只有在其最后一个句柄被关闭时才会从系统中删除。
一个小实验:
// testProcess.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include<iostream>  
#include<Windows.h>  
#include <atlstr.h>
#include <strsafe.h>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    char cWindowsDirectory[MAX_PATH];

    //LPTSTR 与 wchar_t* 等价(Unicode环境下)  
    LPTSTR cWinDir = new TCHAR[MAX_PATH];
    GetCurrentDirectory(MAX_PATH, cWinDir);

    CString str(cWinDir);

    wcscat_s(cWinDir, str.GetLength()*sizeof(WCHAR) / sizeof(char), _T("\\Debug\\test2.exe"));

    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory(&si, sizeof(si));
    ZeroMemory(&pi, sizeof(pi));

    //创建一个新进程  
    if (CreateProcess(
        NULL,   //  指向一个NULL结尾的、用来指定可执行模块的宽字节字符串  
        cWinDir, // 命令行字符串  
        NULL, //    指向一个SECURITY_ATTRIBUTES结构体,这个结构体决定是否返回的句柄可以被子进程继承。  
        NULL, //    如果lpProcessAttributes参数为空(NULL),那么句柄不能被继承。<同上>  
        false,//    指示新进程是否从调用进程处继承了句柄。   
        CREATE_NEW_CONSOLE,  //  指定附加的、用来控制优先类和进程的创建的标  
        //  CREATE_NEW_CONSOLE  新控制台打开子进程  
        //  CREATE_SUSPENDED    子进程创建后挂起,直到调用ResumeThread函数  
        NULL, //    指向一个新进程的环境块。如果此参数为空,新进程使用调用进程的环境  
        NULL, //    指定子进程的工作路径  
        &si, // 决定新进程的主窗体如何显示的STARTUPINFO结构体  
        &pi  // 接收新进程的识别信息的PROCESS_INFORMATION结构体  
        ))
    {
        cout << "create process success" << endl;

        //下面两行关闭句柄,解除本进程和新进程的关系
        //关掉句柄之后再下面的TerminateProcess调用中会找不到相应的句柄,导致调用失败
        //CloseHandle(pi.hProcess);  
        //CloseHandle(pi.hThread);  
    }
    else{
        cerr << "failed to create process" << endl;
    }

    Sleep(100);

    //终止子进程  
    BOOL bRet = TerminateProcess(pi.hProcess, 300);

    //终止本进程,状态码  
    ExitProcess(1001);

    return 0;
}


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353

推荐阅读更多精彩内容