PoEdu培训 Windows班 第十五课 Windows进程及线程(二)
文章类别: 培训笔记 0 评论

PoEdu培训 Windows班 第十五课 Windows进程及线程(二)

文章类别: 培训笔记 0 评论

Windows 进程及线程(二)

进程路径

总结

环境变量
在我们的进程中, 我们有一些环境变量:
=C: =D: =E: =F: ... (有几个盘符就有几个)
它是我们进程默认的当前目录设置

所在目录*
启动的时候分配的, 默认是在exe所在目录下
可以进行修改
修改的同时, 会将当前盘符下的当前目录同时更改

当前目录
当前目录是针对盘符的
它会因为我们修改所在目录而发生改变

例子

#include <Windows.h>
#include <tchar.h>

int _tmain(int, TCHAR**)
{
    // 获取所在目录
    TCHAR szCurrDir[MAX_PATH] = {0};
    GetCurrentDirectory(MAX_PATH, szCurrDir);
    _tprintf(TEXT("所在目录:[%s]\n"), szCurrDir);

    // 获取Module目录
    TCHAR szModulePath[MAX_PATH] = {0};
    GetModuleFileName(NULL, szModulePath, MAX_PATH);
    _tprintf(TEXT("Module目录:[%s]\n"), szModulePath);


    // 获取当前目录
    TCHAR szFullPathName[MAX_PATH] = {0};
    GetFullPathName(TEXT("C:"), MAX_PATH, szFullPathName, NULL);
    _tprintf(TEXT("原始FullPathName-C:[%s]\n"), szFullPathName);
    GetFullPathName(TEXT("D:"), MAX_PATH, szFullPathName, NULL);
    _tprintf(TEXT("原始FullPathName-D:[%s]\n"), szFullPathName);

    // 获取环境变量
    TCHAR szEnvValue[MAX_PATH] = {0};
    GetEnvironmentVariable(TEXT("=C:"), szEnvValue, MAX_PATH);
    _tprintf(TEXT("环境变量C:[%s]\n"), szEnvValue);
    GetEnvironmentVariable(TEXT("=D:"), szEnvValue, MAX_PATH);
    _tprintf(TEXT("环境变量D:[%s]\n"), szEnvValue);

    // 更改所在目录
    SetCurrentDirectory(TEXT("C:\\"));
    GetCurrentDirectory(MAX_PATH, szCurrDir);
    _tprintf(TEXT("修改后的所在目录:[%s]\n"), szCurrDir);
    GetFullPathName(TEXT("C:"), MAX_PATH, szFullPathName, NULL);
    _tprintf(TEXT("修改后的FullPathName-C:[%s]\n"), szFullPathName);
    GetFullPathName(TEXT("D:"), MAX_PATH, szFullPathName, NULL);
    _tprintf(TEXT("修改后的FullPathName-D:[%s]\n"), szFullPathName);

    // 获取环境变量
    GetEnvironmentVariable(TEXT("=C:"), szEnvValue, MAX_PATH);
    _tprintf(TEXT("环境变量C:[%s]\n"), szEnvValue);
    GetEnvironmentVariable(TEXT("=D:"), szEnvValue, MAX_PATH);
    _tprintf(TEXT("环境变量D:[%s]\n"), szEnvValue);

    // 更改环境变量
    SetEnvironmentVariable(TEXT("=D:"), TEXT("D:\\"));
    GetFullPathName(TEXT("D:"), MAX_PATH, szFullPathName, NULL);
    _tprintf(TEXT("修改环境变量后的FullPathName-D:[%s]\n"), szFullPathName);


    return 0;
}

CreateProcess

它可以创建一个进程

注意: 
内核对象都有`使用计数`
当被使用的时候, 使用计数会加一
当不被使用的时候, 使用计数会减一
当使用计数为0的时候, 操作系统会丢内核对象进行回收

成功创建了新进程和主线程, 函数会返回TRUE
被创建出来的进程会形成父子关系, 启动的进程为父进程, 被启动的进程为子进程
但是, 父进程和子进程是独立的两个进程
它们是不能直接进行通信的

参数解析

BOOL WINAPI CreateProcess(
  _In_opt_    LPCTSTR               lpApplicationName,
  _Inout_opt_ LPTSTR                lpCommandLine,
  _In_opt_    LPSECURITY_ATTRIBUTES lpProcessAttributes,
  _In_opt_    LPSECURITY_ATTRIBUTES lpThreadAttributes,
  _In_        BOOL                  bInheritHandles,
  _In_        DWORD                 dwCreationFlags,
  _In_opt_    LPVOID                lpEnvironment,
  _In_opt_    LPCTSTR               lpCurrentDirectory,
  _In_        LPSTARTUPINFO         lpStartupInfo,
  _Out_       LPPROCESS_INFORMATION lpProcessInformation
);

lpApplicationName

指定新进程要使用的执行体的文件名

当在lpApplicationName传一个文件路径时, 如果给的是一个相对路径
那么它只会在exe所在目录下来进行查找
当它不是NULL时, lpCommandLine会被作为命令行参数传递

lpCommandLine

传递给新进程的命令行字符串

如果lpApplicationName为NULL, 可以在lpCommandLine中传递一个文件路径
如果传递的是一个相对路径, 它会按照如下顺序进行查找:

  1. 所在目录
  2. 当前目录
  3. Windows系统目录(System32)
  4. Windows目录
  5. Path环境变量中列出的目录
    注意, lpCommandLine会被CreateProcess内部修改, 所以我们不应该传递一个常量指针

lpProcessAttributes

设置进程内核对象的安全属性

可以设置为NULL.

lpThreadAttributes

设置主线程内核对象的安全属性

可以设置为NULL.

bInheritHandles

是否有被继承

可以设置为FALSE.

dwCreationFlags

进程创建方式的标识

lpEnvironment

它指向一个内存块, 其中包含了新进程要会用的环境变量字符串
大多数时候, 这个参数的值都为NULL
这使得子进程继承父进程使用的一组环境变量字符串
还可以使用GetEnvironmentStrings函数来进行传递

lpCurrentDirectory

允许父进程设置子进程的当前驱动器和目录
如果参数为NULL, 新进程的工作目录与生成新进程的应用程序相同

lpStartupInfo
此结构体一定要清零, 否则成员间包含主调线程对站上的垃圾数据

typedef struct _STARTUPINFO {
  DWORD  cb;                // 初始化为sizeof(STARTUPINFO)
  LPTSTR lpReserved;        // 保留, 必须初始化为NULL
  LPTSTR lpDesktop;         // 启动应用程序的桌面名称
  LPTSTR lpTitle;           // 控制台下可用, 指定控制台的窗口标题
  DWORD  dwX;               // 屏幕的位置 X坐标
  DWORD  dwY;               // 屏幕的位置 Y坐标
  DWORD  dwXSize;           // 屏幕宽度
  DWORD  dwYSize;           // 屏幕高度
  DWORD  dwXCountChars;     // 控制台下可用, 控制台的宽度
  DWORD  dwYCountChars;     // 控制台下可用, 控制台的高度
  DWORD  dwFillAttribute;   // 控制台下可用, 控制台的文本和背景色
  DWORD  dwFlags;           // 组合值, 详情见下方
  WORD   wShowWindow;       // GUI可用, 窗口如何显示
  WORD   cbReserved2;       // 保留
  LPBYTE lpReserved2;       // 保留
  HANDLE hStdInput;         // 标准输入
  HANDLE hStdOutput;        // 标准输出
  HANDLE hStdError;         // 标准错误输出
} STARTUPINFO, *LPSTARTUPINFO;

Flags的取值

Value Meaning
<dl> <dt> <span style="font-weight:bold">STARTF_FORCEONFEEDBACK</span></dt> <dt>0x00000040</dt></dl> <p>Indicates that the cursor is in feedback mode for two seconds after <span style="font-weight:bold">CreateProcess</span> is called. The Working in Background cursor is displayed (see the Pointers tab in the Mouse control panel utility).</p> <p>If during those two seconds the process makes the first GUI call, the system gives five more seconds to the process. If during those five seconds the process shows a window, the system gives five more seconds to the process to finish drawing the window.</p> <p>The system turns the feedback cursor off after the first call to <span style="font-weight:bold">GetMessage</span>, regardless of whether the process is drawing.</p>
<dl> <dt> <span style="font-weight:bold">STARTF_FORCEOFFFEEDBACK</span></dt> <dt>0x00000080</dt></dl> <p>Indicates that the feedback cursor is forced off while the process is starting. The Normal Select cursor is displayed.</p>
<dl> <dt> <span style="font-weight:bold">STARTF_PREVENTPINNING</span></dt> <dt>0x00002000</dt></dl> <p>Indicates that any windows created by the process cannot be pinned on the taskbar.</p> <p>This flag must be combined with STARTF_TITLEISAPPID.</p>
<dl> <dt> <span style="font-weight:bold">STARTF_RUNFULLSCREEN</span></dt> <dt>0x00000020</dt></dl> <p> Indicates that the process should be run in full-screen mode, rather than in windowed mode.</p> <p>This flag is only valid for console applications running on an x86 computer.</p>
<dl> <dt> <span style="font-weight:bold">STARTF_TITLEISAPPID</span></dt> <dt>0x00001000</dt></dl> <p>The <span style="font-weight:bold">lpTitle</span> member contains an AppUserModelID. This identifier controls how the taskbar and <span style="font-weight:bold">Start</span> menu present the application, and enables it to be associated with the correct shortcuts and Jump Lists. Generally, applications will use the <span style="font-weight:bold">SetCurrentProcessExplicitAppUserModelID</span> and <span style="font-weight:bold">GetCurrentProcessExplicitAppUserModelID</span> functions instead of setting this flag. For more information, see Application User Model IDs.</p> <p>If STARTF_PREVENTPINNING is used, application windows cannot be pinned on the taskbar. The use of any AppUserModelID-related window properties by the application overrides this setting for that window only.</p> <p>This flag cannot be used with STARTF_TITLEISLINKNAME.</p>
<dl> <dt> <span style="font-weight:bold">STARTF_TITLEISLINKNAME</span></dt> <dt>0x00000800</dt></dl> <p>The <span style="font-weight:bold">lpTitle</span> member contains the path of the shortcut file (.lnk) that the user invoked to start this process. This is typically set by the shell when a .lnk file pointing to the launched application is invoked. Most applications will not need to set this value.</p> <p>This flag cannot be used with STARTF_TITLEISAPPID.</p>
<dl> <dt> <span style="font-weight:bold">STARTF_UNTRUSTEDSOURCE</span></dt> <dt>0x00008000</dt></dl> <p>The command line came from an untrusted source. For more information, see Remarks.</p>
<dl> <dt> <span style="font-weight:bold"></span></dt> <dt></dt></dl>
<dl> <dt> <span style="font-weight:bold">STARTF_USECOUNTCHARS</span></dt> <dt>0x00000008</dt></dl> <p> The <span style="font-weight:bold">dwXCountChars</span> and <span style="font-weight:bold">dwYCountChars</span> members contain additional information.</p>
<dl> <dt> <span style="font-weight:bold">STARTF_USEFILLATTRIBUTE</span></dt> <dt>0x00000010</dt></dl> <p>The <span style="font-weight:bold">dwFillAttribute</span> member contains additional information.</p>
<dl> <dt> <span style="font-weight:bold">STARTF_USEHOTKEY</span></dt> <dt>0x00000200</dt></dl> <p>The <span style="font-weight:bold">hStdInput</span> member contains additional information.</p> <p>This flag cannot be used with <span style="font-weight:bold">STARTF_USESTDHANDLES</span>.</p>
<dl> <dt> <span style="font-weight:bold">STARTF_USEPOSITION</span></dt> <dt>0x00000004</dt></dl> <p>The <span style="font-weight:bold">dwX</span> and <span style="font-weight:bold">dwY</span> members contain additional information.</p>
<dl> <dt> <span style="font-weight:bold">STARTF_USESHOWWINDOW</span></dt> <dt>0x00000001</dt></dl> <p>The <span style="font-weight:bold">wShowWindow</span> member contains additional information.</p>
<dl> <dt> <span style="font-weight:bold">STARTF_USESIZE</span></dt> <dt>0x00000002</dt></dl> <p>The <span style="font-weight:bold">dwXSize</span> and <span style="font-weight:bold">dwYSize</span> members contain additional information.</p>
<dl> <dt> <span style="font-weight:bold">STARTF_USESTDHANDLES</span></dt> <dt>0x00000100</dt></dl> <p>The <span style="font-weight:bold">hStdInput</span>, <span style="font-weight:bold">hStdOutput</span>, and <span style="font-weight:bold">hStdError</span> members contain additional information.</p> <p>If this flag is specified when calling one of the process creation functions, the handles must be inheritable and the function's <span style="font-style:italic">bInheritHandles</span> parameter must be set to TRUE. For more information, see Handle Inheritance.</p> <p>If this flag is specified when calling the <span style="font-weight:bold">GetStartupInfo</span> function, these members are either the handle value specified during process creation or INVALID_HANDLE_VALUE.</p> <p>Handles must be closed with <span style="font-weight:bold">CloseHandle</span> when they are no longer needed.</p> <p>This flag cannot be used with <span style="font-weight:bold">STARTF_USEHOTKEY</span>.</p>

一些需要注意的FLAG:
Alt Flag中文解释

lpProcessInformation

typedef struct _PROCESS_INFORMATION {
  HANDLE hProcess;
  HANDLE hThread;
  DWORD  dwProcessId;
  DWORD  dwThreadId;
} PROCESS_INFORMATION, *LPPROCESS_INFORMATION;

输出参数, 会设置结构体的值

未完待续...

如有错误,请提出指正!谢谢.

回复