「仕事」をするものの下にここにあります。以下のコードは概念実証です。これを関数に入れて、埋め込まれたすべてのスクリプトの最初に呼び出す必要があります。
#TestJob.ps1
$CreateJobObjectSignature = @"
using System;
using System.Text;
using System.Runtime.InteropServices;
public class ClsNativ
{
public enum JOBOBJECTINFOCLASS
{
AssociateCompletionPortInformation = 7,
BasicLimitInformation = 2,
BasicUIRestrictions = 4,
EndOfJobTimeInformation = 6,
ExtendedLimitInformation = 9,
SecurityLimitInformation = 5,
GroupInformation = 11
}
[StructLayout(LayoutKind.Sequential)]
struct JOBOBJECT_BASIC_LIMIT_INFORMATION
{
public Int64 PerProcessUserTimeLimit;
public Int64 PerJobUserTimeLimit;
public UInt32 LimitFlags;
public UIntPtr MinimumWorkingSetSize;
public UIntPtr MaximumWorkingSetSize;
public UInt32 ActiveProcessLimit;
public Int64 Affinity;
public UInt32 PriorityClass;
public UInt32 SchedulingClass;
}
[StructLayout(LayoutKind.Sequential)]
struct IO_COUNTERS
{
public UInt64 ReadOperationCount;
public UInt64 WriteOperationCount;
public UInt64 OtherOperationCount;
public UInt64 ReadTransferCount;
public UInt64 WriteTransferCount;
public UInt64 OtherTransferCount;
}
[StructLayout(LayoutKind.Sequential)]
struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
public IO_COUNTERS IoInfo;
public UIntPtr ProcessMemoryLimit;
public UIntPtr JobMemoryLimit;
public UIntPtr PeakProcessMemoryUsed;
public UIntPtr PeakJobMemoryUsed;
}
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr CreateJobObject(IntPtr lpJobAttributes, string lpName);
[DllImport("kernel32.dll")]
public static extern bool AssignProcessToJobObject(IntPtr hJob, IntPtr hProcess);
[DllImport("kernel32.dll")]
public static extern bool SetInformationJobObject(IntPtr hJob, JOBOBJECTINFOCLASS JobObjectInfoClass, IntPtr lpJobObjectInfo, uint cbJobObjectInfoLength);
[DllImport("kernel32.dll")]
public static extern IntPtr GetCurrentProcess();
private const UInt32 JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x2000;
public ClsNativ()
{
IntPtr hJob = CreateJobObject(IntPtr.Zero, "JobName");
JOBOBJECT_BASIC_LIMIT_INFORMATION info = new JOBOBJECT_BASIC_LIMIT_INFORMATION();
info.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();
extendedInfo.BasicLimitInformation = info;
int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length);
Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);
SetInformationJobObject(hJob, JOBOBJECTINFOCLASS.ExtendedLimitInformation, extendedInfoPtr, (uint)length);
IntPtr hProcess = GetCurrentProcess();
bool blRc = AssignProcessToJobObject(hJob, hProcess);
Marshal.FreeHGlobal(extendedInfoPtr);
}
}
"@
Add-Type -TypeDefinition $CreateJobObjectSignature
$a = New-Object ClsNativ
& notepad.exe
Start-Process -FilePath "c:\windows\system32\calc.exe"
Read-Host "Push return key !"
コンセプト:スケジュールされたジョブや PowerShell ジョブではなく、ジョブ、システム オブジェクトを作成します。「JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE」で構成して、ジョブの最後のハンドルが閉じられると、内部のすべてのプロセスが閉じられるようにします。次に、PowerShell プロセスをジョブに割り当てます。すべてのサブ プロセスはジョブに属し、唯一のジョブ ハンドルが PowerShell プロセス内にあるため、この 1 つが終了すると、他のすべてが消えます。それで、それはトリックを行います。
x64 PowerShellを使用してSevenでテストしました。問題は、既にジョブに属しているプロセスにジョブを追加できないことです (これは、VS 2010 の通常の起動の場合です)。
x64 PowerShellを使用してWindows 8でテストします。
これをテストする方法は次のとおりです。
powershell -file "C:\temp\TestJob.ps1"
Windows Seven を使用して、Visual Studio を正常に起動すると、次のスクリーンショットでわかるように、既にジョブ内にあります。
ただし、次のように WMI を使用して Visual Studio 2010 を起動すると:
Invoke-WmiMethod -path win32_process -name create -argumentlist "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe"
それはもはや Job に属していません:
したがって、サブプロセスを使用してデバッグで PowerShell を開始すると、PowerShell が停止すると、それらはすべて停止します。