/// <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;
     }
 }
Пример #2
0
        /// <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));
        }
Пример #3
0
        /// <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));
        }
Пример #4
0
        /// <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));
        }
Пример #5
0
        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;
        }
Пример #7
0
        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);
        }
Пример #9
0
        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);
        }
Пример #10
0
        /// <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);
        }
Пример #11
0
        /// <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;
            }
        }
Пример #12
0
        /// <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));
        }
Пример #13
0
        /// <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));
        }