上编文章已经说明如果,子进程不加入到作业中需要设置进程的flag字段为CREATE_BREAKAWAY_FROM_JOB
    在创建进程的flag字段中找到CREATE_BREAKAWAY_FROM_JOB,其描述中说明如果进程关联了job,子进程不想关联就必须设置JOB_OBJECT_LIMIT_BREAKAWAY_OK。
    image.png

    JOBOBJECT_LIMIT_BREAKAWAY_OK 位于JOBOBJECT_BASIC_LIMIT_INFORMATION_结构体中

    1. typedef struct _JOBOBJECT_BASIC_LIMIT_INFORMATION {
    2. LARGE_INTEGER PerProcessUserTimeLimit;
    3. LARGE_INTEGER PerJobUserTimeLimit;
    4. DWORD LimitFlags;
    5. SIZE_T MinimumWorkingSetSize;
    6. SIZE_T MaximumWorkingSetSize;
    7. DWORD ActiveProcessLimit;
    8. ULONG_PTR Affinity;
    9. DWORD PriorityClass;
    10. DWORD SchedulingClass;
    11. } JOBOBJECT_BASIC_LIMIT_INFORMATION, *PJOBOBJECT_BASIC_LIMIT_INFORMATION;

    如果要使用jobobject_limit_breakaway标记必须使用[**_JOBOBJECT_EXTENDED_LIMIT_INFORMATION**](https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-jobobject_extended_limit_information)结构体
    image.png
    结构体如下:

    1. typedef struct _JOBOBJECT_EXTENDED_LIMIT_INFORMATION {
    2. JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
    3. IO_COUNTERS IoInfo;
    4. SIZE_T ProcessMemoryLimit;
    5. SIZE_T JobMemoryLimit;
    6. SIZE_T PeakProcessMemoryUsed;
    7. SIZE_T PeakJobMemoryUsed;
    8. } JOBOBJECT_EXTENDED_LIMIT_INFORMATION, *PJOBOBJECT_EXTENDED_LIMIT_INFORMATION;

    因此要使子进程不加入到作业中需要如下的代码设置

    1. DWORD re;
    2. BOOL Result;
    3. HANDLE hJob1=CreateJobObject(NULL,L"hello");
    4. _tprintf(L"hJob1 = %X GetLastError = %d\n",hJob1,GetLastError());
    5. //创建对象
    6. JOBOBJECT_EXTENDED_LIMIT_INFORMATION info={0};
    7. //设置为JOB_OBJECT_LIMIT_BREAKAWAY_OK
    8. info.BasicLimitInformation.LimitFlags=JOB_OBJECT_LIMIT_BREAKAWAY_OK;
    9. //查询作业对象的信息
    10. re =SetInformationJobObject(hJob1,JobObjectExtendedLimitInformation,(PVOID)&info,sizeof(info));

    完整的代码

    1. #include<Windows.h>
    2. #include<tchar.h>
    3. int _tmain()
    4. {
    5. /*
    6. 判断一个进程是否已经加入了一个作业的函数是:IsProcessInJob;
    7. BOOL WINAPI IsProcessInJob(
    8. __in HANDLE ProcessHandle,
    9. __in_opt HANDLE JobHandle,
    10. __out PBOOL Result
    11. );
    12. ProcessHandle: 要判断的进程句柄;
    13. JobHandle: 看看进程是否加入到JobHandle这个作业中;
    14. Result: 判断结果。
    15. */
    16. DWORD re;
    17. BOOL Result;
    18. HANDLE hJob1=CreateJobObject(NULL,L"hello");
    19. _tprintf(L"hJob1 = %X GetLastError = %d\n",hJob1,GetLastError());
    20. JOBOBJECT_EXTENDED_LIMIT_INFORMATION info={0};
    21. info.BasicLimitInformation.LimitFlags=JOB_OBJECT_LIMIT_BREAKAWAY_OK;
    22. re =SetInformationJobObject(hJob1,JobObjectExtendedLimitInformation,(PVOID)&info,sizeof(info));
    23. /*
    24. BOOL WINAPI IsProcessInJob(
    25. __in HANDLE ProcessHandle,
    26. __in_opt HANDLE JobHandle,
    27. __out PBOOL Result
    28. );
    29. ProcessHandle 需要检查确认的进程句柄 A。
    30. JobHandle 作业句柄 B
    31. Result 检查结果,如果是1,那么说明进程A已经被放入做也B,否则进程A没有被放到作业B中。
    32. Return 成功,返回1,否则返回1
    33. */
    34. re = IsProcessInJob(GetCurrentProcess(),NULL,&Result);
    35. _tprintf(L" re = %d Result = %d\n",re,Result);
    36. /////////////////////////////////////////////////////////
    37. STARTUPINFO si;
    38. PROCESS_INFORMATION pi;
    39. ZeroMemory( &si, sizeof(si) );
    40. si.cb = sizeof(si);
    41. ZeroMemory( &pi, sizeof(pi) );
    42. /*
    43. BOOL WINAPI AssignProcessToJobObject(
    44. __in HANDLE hJob,
    45. __in HANDLE hProcess
    46. );
    47. hJob: 要将进程hProcess加入的那个作业的句柄
    48. Process: 要加入到作业中的进程句柄
    49. return: 成功返回1,否则返回0
    50. */
    51. re=AssignProcessToJobObject(hJob1,GetCurrentProcess());
    52. _tprintf(L" re = %d \n",re);
    53. re = IsProcessInJob(GetCurrentProcess(),NULL,&Result);
    54. _tprintf(L" re = %d currentProcess__Result = %d\n",re,Result);
    55. // Start the child process.
    56. if( !CreateProcess(L"Reloz.exe", // No module name (use command line)
    57. NULL, // Command line
    58. NULL, // Process handle not inheritable
    59. NULL, // Thread handle not inheritable
    60. NULL, // Set handle inheritance to FALSE
    61. CREATE_BREAKAWAY_FROM_JOB, // No creation flags
    62. NULL, // Use parent's environment block
    63. NULL, // Use parent's starting directory
    64. &si, // Pointer to STARTUPINFO structure
    65. &pi ) // Pointer to PROCESS_INFORMATION structure
    66. )
    67. {
    68. _tprintf(L"CreateProcess failed (%d).\n", GetLastError() );
    69. return 0;
    70. }
    71. /////////////////////////////////////////
    72. re = IsProcessInJob(pi.hProcess,hJob1,&Result);
    73. _tprintf(L" re = %d pi.hProcess 子进程Result = %d\n",re,Result);
    74. _gettchar();
    75. CloseHandle(hJob1);
    76. CloseHandle(pi.hProcess);
    77. CloseHandle(pi.hThread);
    78. return 0;
    79. }