/// <summary> /// Disposes of resources used for the process. If <see cref="ProcessStartInfo.KillOnClose"/> was set, this also terminates the process. /// </summary> public void Dispose() { if (_stdin != null) { _stdin.Dispose(); } if (_stdout != null) { _stdout.Dispose(); } if (_stderr != null) { _stderr.Dispose(); } if (_killOnClose) { Kill(); } _watcher.Dispose(); if (_p != IntPtr.Zero) { HcsFunctions.ProcessHcsCall(HcsFunctions.HcsCloseProcess(_p), null); _p = IntPtr.Zero; } }
/// <summary> /// Find a container network that uses a NAT for connectivity. /// </summary> /// <returns>The ID of the network.</returns> public static Guid FindNatNetwork() { string result; HcsFunctions.HNSCall("GET", "/networks/", "", out result); var response = JsonHelper.FromJson <Schema.HNSNetworkResponse>(result); if (!response.Success) { throw new Win32Exception(response.Error); } string networkId = null; foreach (var network in response.Output) { if (network.Type == Schema.NetworkMode.NAT) { networkId = network.ID; break; } } if (networkId == null) { throw new Exception("could not find NAT network"); } return(Guid.Parse(networkId)); }
/// <summary> /// Gets an existing process object from the container. /// </summary> /// <param name="pid">The process ID.</param> /// <returns></returns> public Process GetProcess(int pid) { IntPtr process; string result; HcsFunctions.ProcessHcsCall(HcsFunctions.HcsOpenProcess(_cs, (uint)pid, out process, out result), result); return(new Process(process, null, null, null, false)); }
/// <summary> /// Retrieves an existing container. /// </summary> /// <param name="id">The ID of the container.</param> /// <returns>A Container object that can be used to manipulate the container.</returns> public static Container GetComputeSystem(string id) { IntPtr computeSystem; string result; HcsFunctions.ProcessHcsCall(HcsFunctions.HcsOpenComputeSystem(id, out computeSystem, out result), result); return(Container.Initialize(id, computeSystem, false)); }
public async Task StartAsync() { string result; if (HcsFunctions.ProcessHcsCall(HcsFunctions.HcsStartComputeSystem(_cs, null, out result), result)) { await _watcher.WatchAsync(HCS_NOTIFICATIONS.HcsNotificationSystemStartCompleted); } }
public async Task KillAsync() { string result; if (!_killed && !_exited && HcsFunctions.ProcessHcsCall(HcsFunctions.HcsTerminateProcess(_p, out result), result)) { await _watcher.WatchAsync(HCS_NOTIFICATIONS.HcsNotificationProcessExited); } _killed = true; }
public async Task ShutdownAsync() { string result; if (!_dead && HcsFunctions.ProcessHcsCall(HcsFunctions.HcsShutdownComputeSystem(_cs, null, out result), result)) { await _watcher.WatchAsync(HCS_NOTIFICATIONS.HcsNotificationSystemExited); } _dead = true; }
/// <summary> /// Resizes the console that was allocated for the process if <see cref="ProcessStartInfo.EmulateConsole"/> was set. /// </summary> /// <param name="height">The new height, in character cells.</param> /// <param name="width">The new width, in character cells.</param> public void ResizeConsole(ushort height, ushort width) { Schema.ProcessConsoleSize procSize = new Schema.ProcessConsoleSize(); procSize.Height = height; procSize.Width = width; Schema.ProcessModifyRequest procModReq = new Schema.ProcessModifyRequest(); procModReq.Operation = Schema.ProcessModifyOperation.ConsoleSize; procModReq.ConsoleSize = procSize; string result; HcsFunctions.ProcessHcsCall(HcsFunctions.HcsModifyProcess(_p, JsonHelper.ToJson(procModReq), out result), result); }
public HcsNotificationWatcher(IntPtr handle, RegisterHcsNotificationCallback register, UnregisterHcsNotificationCallback unregister, HCS_NOTIFICATIONS[] notificationList) { _unreg = unregister; foreach (var notificationType in notificationList) { var entry = new TaskCompletionSource <NotificationResult>(); _n.Add(notificationType, entry); } _callbackFunc = (uint nType, IntPtr ctx, int nStatus, string nData) => { var key = (HCS_NOTIFICATIONS)nType; if (key == HCS_NOTIFICATIONS.HcsNotificationServiceDisconnect) { // Service disconnect should fail all outstanding notifications. foreach (var entry in _n.Values) { entry.TrySetException(new HcsException(HcsException.E_ABORT, null)); } return; } if (key == HCS_NOTIFICATIONS.HcsNotificationSystemExited && _n.ContainsKey(HCS_NOTIFICATIONS.HcsNotificationSystemStartCompleted)) { // Special handling for exit received while waiting for start. _n[HCS_NOTIFICATIONS.HcsNotificationSystemStartCompleted].TrySetException(new HcsException(HcsException.UNEXPECTED_EXIT, null)); } if (_n.ContainsKey(key)) { var result = new NotificationResult() { Status = nStatus, Data = nData }; if (HcsException.Failed(result.Status)) { _n[key].SetException(new HcsException(result.Status, result.Data)); } else { _n[key].SetResult(result); } } }; HcsFunctions.ProcessHcsCall(register(handle, _callbackFunc, IntPtr.Zero, out _h), null); }
/// <summary> /// Helper function to call into HNS to modify/query a network endpoint. /// </summary> /// <param name="method">The request method type</param> /// <param name="path">The path of the request</param> /// <param name="request">The request data</param> /// <returns>The queried endpoint.</returns> public static HNSEndpoint HNSEndpointRequest(string method, string path, string request) { string result; HcsFunctions.HNSCall(method, "/endpoints/" + path, request, out result); var response = JsonHelper.FromJson <Schema.HNSEndpointResponse>(result); if (!response.Success) { throw new Win32Exception(response.Error); } return(response.Output); }
/// <summary> /// Disposes of the container object. /// </summary> public void Dispose() { if (_killOnClose && !_dead) { Kill(); } _watcher.Dispose(); if (_cs != IntPtr.Zero) { HcsFunctions.ProcessHcsCall(HcsFunctions.HcsCloseComputeSystem(_cs), null); _cs = IntPtr.Zero; } }
/// <summary> /// Creates (but does not start) a new container. /// </summary> /// <param name="id">The ID of the new container. Must be unique on the machine.</param> /// <param name="settings">The settings for the container.</param> /// <returns>A Container object that can be used to manipulate the container.</returns> public static Container CreateContainer(string id, ContainerSettings settings) { var hcsSettings = new Schema.ContainerSettings { SystemType = Schema.SystemType.Container, LayerFolderPath = settings.SandboxPath, Layers = settings.Layers.Select(x => new Schema.Layer { Id = x.Id, Path = x.Path }).ToArray(), HvPartition = settings.HyperVContainer, TerminateOnLastHandleClosed = settings.KillOnClose, }; if (settings.MappedDirectories != null) { hcsSettings.MappedDirectories = settings.MappedDirectories.Select(x => new Schema.MappedDirectory { HostPath = x.HostPath, ContainerPath = x.ContainerPath }).ToArray(); } if (settings.NetworkId != Guid.Empty) { hcsSettings.NetworkEndpoints = new Schema.NetworkEndpoint[] { new Schema.NetworkEndpoint { NetworkId = settings.NetworkId, EndpointName = id, } }; } if (settings.UtilityVmPath != null) { hcsSettings.HvRuntime = new Schema.UtilityVmSettings { ImagePath = settings.UtilityVmPath }; } IntPtr computeSystem; string result; HcsFunctions.ProcessHcsCall(HcsFunctions.HcsCreateComputeSystem(id, JsonHelper.ToJson(hcsSettings), IntPtr.Zero, out computeSystem, out result), result); return(Container.Initialize(id, computeSystem, settings.KillOnClose)); }
/// <summary> /// Starts a process in the container. /// </summary> /// <param name="startInfo">Process start parameters.</param> /// <returns></returns> public Process CreateProcess(ProcessStartInfo startInfo) { // Use UTF-8 encoding on the streams by default (without a BOM). The user can override this with whatever they // want by using .BaseStream, but this is a good default. var encoding = new UTF8Encoding(false); var parameters = new Schema.ProcessParameters { ApplicationName = startInfo.ApplicationName, CommandLine = startInfo.CommandLine, EmulateConsole = startInfo.EmulateConsole, RestrictedToken = startInfo.RestrictedToken, User = startInfo.User, WorkingDirectory = startInfo.WorkingDirectory, CreateStdInPipe = startInfo.RedirectStandardInput, CreateStdOutPipe = startInfo.RedirectStandardOutput, CreateStdErrPipe = startInfo.RedirectStandardError, }; IntPtr process; string result; HCS_PROCESS_INFORMATION procInfo; HcsFunctions.ProcessHcsCall(HcsFunctions.HcsCreateProcess(_cs, JsonHelper.ToJson(parameters), out procInfo, out process, out result), result); StreamWriter stdinHandle = null; StreamReader stdoutHandle = null, stderrHandle = null; if (startInfo.RedirectStandardInput) { stdinHandle = new StreamWriter(new FileStream(new SafeFileHandle(procInfo.StdInput, true), FileAccess.Write), encoding); } if (startInfo.RedirectStandardOutput) { stdoutHandle = new StreamReader(new FileStream(new SafeFileHandle(procInfo.StdOutput, true), FileAccess.Read), encoding); } if (startInfo.RedirectStandardError) { stderrHandle = new StreamReader(new FileStream(new SafeFileHandle(procInfo.StdError, true), FileAccess.Read), encoding); } return(new Process(process, stdinHandle, stdoutHandle, stderrHandle, startInfo.KillOnClose)); }