예제 #1
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="terminalParameter">Terminal parameter</param>
        /// <param name="socket">PipeSocket object</param>
        /// <param name="pipedProcess">Process data (or null)</param>
        public PipeTerminalConnection(PipeTerminalParameter terminalParameter, PipeSocket socket, PipedProcess pipedProcess) {
            _terminalOutput = new PipeTerminalOutput();
            _terminalParameter = terminalParameter;
            _socket = socket;
            _pipedProcess = pipedProcess;

            if (_pipedProcess != null) {
                _pipedProcess.Exited += delegate(object sender, EventArgs e) {
                    _socket.ProcessExited();
                };
            }
        }
예제 #2
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="terminalParameter">Terminal parameter</param>
        /// <param name="socket">PipeSocket object</param>
        /// <param name="pipedProcess">Process data (or null)</param>
        public PipeTerminalConnection(PipeTerminalParameter terminalParameter, PipeSocket socket, PipedProcess pipedProcess)
        {
            _terminalOutput    = new PipeTerminalOutput();
            _terminalParameter = terminalParameter;
            _socket            = socket;
            _pipedProcess      = pipedProcess;

            if (_pipedProcess != null)
            {
                _pipedProcess.Exited += delegate(object sender, EventArgs e) {
                    _socket.ProcessExited();
                };
            }
        }
예제 #3
0
        /// <summary>
        /// Start exe file and create a new PipeTerminalConnection
        /// </summary>
        /// <param name="param">Terminal parameter</param>
        /// <returns>created object</returns>
        /// <exception cref="Win32Exception">Error in Win32 API</exception>
        private static PipeTerminalConnection OpenExeFile(PipeTerminalParameter param)
        {
            // System.Diagnostics.Process has functionality that creates STDIN/STDOUT/STDERR pipe.
            // But we need two pipes. One connects to STDIN and another one connects to STDOUT and STDERR.
            // So we use Win32 API to invoke a new process.

            SafeFileHandle parentReadHandle  = null;
            SafeFileHandle parentWriteHandle = null;
            SafeFileHandle childReadHandle   = null;
            SafeFileHandle childWriteHandle  = null;
            SafeFileHandle childStdInHandle  = null;
            SafeFileHandle childStdOutHandle = null;
            SafeFileHandle childStdErrHandle = null;

            FileStream parentReadStream  = null;
            FileStream parentWriteStream = null;

            try {
                // Create pipes
                CreateAsyncPipe(out parentReadHandle, true, out childWriteHandle, false);
                CreateAsyncPipe(out childReadHandle, false, out parentWriteHandle, true);

                // Duplicate handles as inheritable handles.
                childStdOutHandle = DuplicatePipeHandle(childWriteHandle, true, "ChildWrite");
                childStdInHandle  = DuplicatePipeHandle(childReadHandle, true, "ChildRead");
                childStdErrHandle = DuplicatePipeHandle(childWriteHandle, true, "ChildWrite");

                // Close non-inheritable handles
                childWriteHandle.Dispose();
                childWriteHandle = null;
                childReadHandle.Dispose();
                childReadHandle = null;

                // Create parent side streams
                parentReadStream  = new FileStream(parentReadHandle, FileAccess.Read, 4096, true /*Async*/);
                parentWriteStream = new FileStream(parentWriteHandle, FileAccess.Write, 4096, true /*Async*/);

                // Prepare command line
                string commandLine = GetCommandLine(param.ExeFilePath, param.CommandLineOptions);

                // Determine character encoding of the environment variables
                bool unicodeEnvironment = (Environment.OSVersion.Platform == PlatformID.Win32NT) ? true : false;

                // Prepare flags
                // Note:
                //  We use CREATE_NEW_CONSOLE for separating console.
                //  It disables CREATE_NO_WINDOW, so we use setting below
                //  to hide the console window.
                //    STARTUPINFO.dwFlags |= STARTF_USESHOWWINDOW
                //    STARTUPINFO.wShowWindow = SW_HIDE
                int creationFlags = CREATE_NEW_CONSOLE /*| CREATE_NO_WINDOW*/;
                if (unicodeEnvironment)
                {
                    creationFlags |= CREATE_UNICODE_ENVIRONMENT;
                }

                // Prepare environment variables
                Dictionary <String, String> envDict = new Dictionary <String, String>();
                foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables())
                {
                    string key   = entry.Key as string;
                    string value = entry.Value as string;
                    if (key != null && value != null)
                    {
                        envDict.Add(key.ToLowerInvariant(), key + "=" + value);
                    }
                }

                if (param.EnvironmentVariables != null)
                {
                    foreach (PipeTerminalParameter.EnvironmentVariable ev in param.EnvironmentVariables)
                    {
                        string expandedValue = Environment.ExpandEnvironmentVariables(ev.Value);
                        string key           = ev.Name.ToLowerInvariant();
                        envDict.Remove(key);
                        envDict.Add(key, ev.Name + "=" + expandedValue);
                    }
                }

                byte[] environmentByteArray = GetEnvironmentBytes(envDict, unicodeEnvironment);

                // Prepare current directory
                string currentDirectory = Path.GetDirectoryName(param.ExeFilePath);

                // Prepare STARTUPINFO
                STARTUPINFO startupInfo = new STARTUPINFO();
                startupInfo.dwFlags    |= STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
                startupInfo.hStdInput   = childStdInHandle;
                startupInfo.hStdOutput  = childStdOutHandle;
                startupInfo.hStdError   = childStdErrHandle;
                startupInfo.wShowWindow = SW_HIDE;

                // Prepare PROCESS_INFORMATION
                PROCESS_INFORMATION processInfo = new PROCESS_INFORMATION();

                // Start process
                GCHandle environmentGCHandle = GCHandle.Alloc(environmentByteArray, GCHandleType.Pinned);
                bool     apiret = CreateProcess(
                    null,
                    commandLine,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    true,
                    creationFlags,
                    environmentGCHandle.AddrOfPinnedObject(),
                    currentDirectory,
                    startupInfo,
                    ref processInfo
                    );
                environmentGCHandle.Free();

                if (!apiret)
                {
                    throw new Win32Exception("CreateProcess", Marshal.GetLastWin32Error(), "commandLine=" + commandLine);
                }

                Process process = Process.GetProcessById(processInfo.dwProcessId);

                PipedProcess           pipedProcess = new PipedProcess(process, childStdInHandle, childStdOutHandle, childStdErrHandle);
                PipeSocket             socket       = new PipeSocket(parentReadStream, parentWriteStream);
                PipeTerminalConnection connection   = new PipeTerminalConnection(param, socket, pipedProcess);

                return(connection);
            }
            catch (Exception) {
                if (parentReadStream != null)
                {
                    parentReadStream.Dispose();
                }

                if (parentWriteStream != null)
                {
                    parentWriteStream.Dispose();
                }

                if (parentReadHandle != null)
                {
                    parentReadHandle.Dispose();
                }

                if (parentWriteHandle != null)
                {
                    parentWriteHandle.Dispose();
                }

                if (childReadHandle != null)
                {
                    childReadHandle.Dispose();
                }

                if (childWriteHandle != null)
                {
                    childWriteHandle.Dispose();
                }

                if (childStdInHandle != null)
                {
                    childStdInHandle.Dispose();
                }

                if (childStdOutHandle != null)
                {
                    childStdOutHandle.Dispose();
                }

                if (childStdErrHandle != null)
                {
                    childStdErrHandle.Dispose();
                }

                throw;
            }
        }
예제 #4
0
        /// <summary>
        /// Start exe file and create a new PipeTerminalConnection
        /// </summary>
        /// <param name="param">Terminal parameter</param>
        /// <returns>created object</returns>
        /// <exception cref="Win32Exception">Error in Win32 API</exception>
        private static PipeTerminalConnection OpenExeFile(PipeTerminalParameter param) {

            // System.Diagnostics.Process has functionality that creates STDIN/STDOUT/STDERR pipe.
            // But we need two pipes. One connects to STDIN and another one connects to STDOUT and STDERR.
            // So we use Win32 API to invoke a new process.

            SafeFileHandle parentReadHandle = null;
            SafeFileHandle parentWriteHandle = null;
            SafeFileHandle childReadHandle = null;
            SafeFileHandle childWriteHandle = null;
            SafeFileHandle childStdInHandle = null;
            SafeFileHandle childStdOutHandle = null;
            SafeFileHandle childStdErrHandle = null;

            FileStream parentReadStream = null;
            FileStream parentWriteStream = null;

            try {
                // Create pipes
                CreateAsyncPipe(out parentReadHandle, true, out childWriteHandle, false);
                CreateAsyncPipe(out childReadHandle, false, out parentWriteHandle, true);

                // Duplicate handles as inheritable handles.
                childStdOutHandle = DuplicatePipeHandle(childWriteHandle, true, "ChildWrite");
                childStdInHandle = DuplicatePipeHandle(childReadHandle, true, "ChildRead");
                childStdErrHandle = DuplicatePipeHandle(childWriteHandle, true, "ChildWrite");

                // Close non-inheritable handles
                childWriteHandle.Dispose();
                childWriteHandle = null;
                childReadHandle.Dispose();
                childReadHandle = null;

                // Create parent side streams
                parentReadStream = new FileStream(parentReadHandle, FileAccess.Read, 4096, true /*Async*/);
                parentWriteStream = new FileStream(parentWriteHandle, FileAccess.Write, 4096, true /*Async*/);

                // Prepare command line
                string commandLine = GetCommandLine(param.ExeFilePath, param.CommandLineOptions);

                // Determine character encoding of the environment variables
                bool unicodeEnvironment = (Environment.OSVersion.Platform == PlatformID.Win32NT) ? true : false;

                // Prepare flags
                // Note:
                //  We use CREATE_NEW_CONSOLE for separating console.
                //  It disables CREATE_NO_WINDOW, so we use setting below
                //  to hide the console window.
                //    STARTUPINFO.dwFlags |= STARTF_USESHOWWINDOW
                //    STARTUPINFO.wShowWindow = SW_HIDE
                int creationFlags = CREATE_NEW_CONSOLE /*| CREATE_NO_WINDOW*/;
                if (unicodeEnvironment)
                    creationFlags |= CREATE_UNICODE_ENVIRONMENT;

                // Prepare environment variables
                Dictionary<String, String> envDict = new Dictionary<String, String>();
                foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables()) {
                    string key = entry.Key as string;
                    string value = entry.Value as string;
                    if (key != null && value != null) {
                        envDict.Add(key.ToLowerInvariant(), key + "=" + value);
                    }
                }

                if (param.EnvironmentVariables != null) {
                    foreach (PipeTerminalParameter.EnvironmentVariable ev in param.EnvironmentVariables) {
                        string expandedValue = Environment.ExpandEnvironmentVariables(ev.Value);
                        string key = ev.Name.ToLowerInvariant();
                        envDict.Remove(key);
                        envDict.Add(key, ev.Name + "=" + expandedValue);
                    }
                }

                byte[] environmentByteArray = GetEnvironmentBytes(envDict, unicodeEnvironment);

                // Prepare current directory
                string currentDirectory = Path.GetDirectoryName(param.ExeFilePath);

                // Prepare STARTUPINFO
                STARTUPINFO startupInfo = new STARTUPINFO();
                startupInfo.dwFlags |= STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
                startupInfo.hStdInput = childStdInHandle;
                startupInfo.hStdOutput = childStdOutHandle;
                startupInfo.hStdError = childStdErrHandle;
                startupInfo.wShowWindow = SW_HIDE;

                // Prepare PROCESS_INFORMATION
                PROCESS_INFORMATION processInfo = new PROCESS_INFORMATION();

                // Start process
                GCHandle environmentGCHandle = GCHandle.Alloc(environmentByteArray, GCHandleType.Pinned);
                bool apiret = CreateProcess(
                               null,
                               commandLine,
                               IntPtr.Zero,
                               IntPtr.Zero,
                               true,
                               creationFlags,
                               environmentGCHandle.AddrOfPinnedObject(),
                               currentDirectory,
                               startupInfo,
                               ref processInfo
                           );
                environmentGCHandle.Free();

                if (!apiret)
                    throw new Win32Exception("CreateProcess", Marshal.GetLastWin32Error(), "commandLine=" + commandLine);

                Process process = Process.GetProcessById(processInfo.dwProcessId);

                PipedProcess pipedProcess = new PipedProcess(process, childStdInHandle, childStdOutHandle, childStdErrHandle);
                PipeSocket socket = new PipeSocket(parentReadStream, parentWriteStream);
                PipeTerminalConnection connection = new PipeTerminalConnection(param, socket, pipedProcess);

                return connection;
            }
            catch (Exception) {
                if (parentReadStream != null)
                    parentReadStream.Dispose();

                if (parentWriteStream != null)
                    parentWriteStream.Dispose();

                if (parentReadHandle != null)
                    parentReadHandle.Dispose();

                if (parentWriteHandle != null)
                    parentWriteHandle.Dispose();

                if (childReadHandle != null)
                    childReadHandle.Dispose();

                if (childWriteHandle != null)
                    childWriteHandle.Dispose();

                if (childStdInHandle != null)
                    childStdInHandle.Dispose();

                if (childStdOutHandle != null)
                    childStdOutHandle.Dispose();

                if (childStdErrHandle != null)
                    childStdErrHandle.Dispose();

                throw;
            }
        }