public static void DisposeLocalCopyOfClientHandle_BeforeServerRead()
        {
            using (AnonymousPipeServerStream server = new AnonymousPipeServerStream(PipeDirection.In))
            {
                using (AnonymousPipeClientStream client = new AnonymousPipeClientStream(PipeDirection.Out, server.ClientSafePipeHandle))
                {
                    byte[] sent = new byte[] { 123 };
                    byte[] received = new byte[] { 0 };
                    client.Write(sent, 0, 1);

                    server.DisposeLocalCopyOfClientHandle();

                    Assert.Equal(1, server.Read(received, 0, 1));
                    Assert.Equal(sent[0], received[0]);
                }
            }
        }
        public void PingPong()
        {
            // Create two anonymous pipes, one for each direction of communication.
            // Then spawn another process to communicate with.
            using (var outbound = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable))
            using (var inbound = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable))
            using (var remote = RemoteInvoke(PingPong_OtherProcess, outbound.GetClientHandleAsString(), inbound.GetClientHandleAsString()))
            {
                // Close our local copies of the handles now that we've passed them of to the other process
                outbound.DisposeLocalCopyOfClientHandle();
                inbound.DisposeLocalCopyOfClientHandle();

                // Ping-pong back and forth by writing then reading bytes one at a time.
                for (byte i = 0; i < 10; i++)
                {
                    outbound.WriteByte(i);
                    int received = inbound.ReadByte();
                    Assert.Equal(i, received);
                }
            }
        }
示例#3
0
        public R <(string, Thread, TimeSpan?), LocalStr> StreamSongToPipeHandle(string spotifyTrackUri)
        {
            var trackId = SpotifyApi.UriToTrackId(spotifyTrackUri);

            if (!trackId.Ok)
            {
                return(new LocalStr("Cannot stream this URI from spotify."));
            }

            if (state == State.NotSetUp)
            {
                return(new LocalStr("Spotify API access was not set up correctly. Cannot play from spotify."));
            }

            if (state != State.Idle)
            {
                throw new InvalidOperationException(
                          $"Tried to stream spotify song while the system was not idle (current state: {state})."
                          );
            }

            // Launch Librespot.
            state = State.LaunchingLibrespot;
            Log.Debug("Launching Librespot...");
            var processOption = LaunchLibrespot();

            if (!processOption.Ok)
            {
                return(processOption.Error);
            }

            void Fail(string msg)
            {
                Log.Debug("Failed to start song on spotify: " + msg);
            }

            TimeSpan duration = default;

            for (var i = 0; i < SongStartRetries; i++)
            {
                Log.Debug($"Starting to play song on spotify, try {i}...");

                // Start song.
                var playResult = api.Request(
                    () => api.Client.Player.ResumePlayback(new PlayerResumePlaybackRequest {
                    DeviceId = deviceId,
                    Uris     = new List <string> {
                        spotifyTrackUri
                    }
                })
                    );
                if (!playResult.Ok)
                {
                    Fail(playResult.Error.ToString());
                    continue;
                }

                // Check if the song actually started playing.
                for (var j = 0; j < 2; j++)
                {
                    if (j == 1)
                    {
                        // Wait before the second check.
                        Thread.Sleep(SongStartRecheckAfter);
                    }

                    var checkResult = api.Request(() => api.Client.Player.GetCurrentPlayback());
                    if (!checkResult.Ok)
                    {
                        Fail(checkResult.Error.ToString());
                        continue;
                    }

                    var currentlyPlaying = checkResult.Value;

                    if (currentlyPlaying.CurrentlyPlayingType != "track")
                    {
                        Fail("No track is currently playing.");
                        continue;
                    }

                    var track = (FullTrack)currentlyPlaying.Item;

                    if (
                        currentlyPlaying.IsPlaying &&
                        currentlyPlaying.Device.Id == deviceId &&
                        track.Id == trackId.Value
                        )
                    {
                        duration = TimeSpan.FromMilliseconds(track.DurationMs);
                        state    = State.StreamRunning;
                        break;
                    }

                    Fail(
                        $"Song not playing yet on spotify." +
                        $" IsPlaying: {currentlyPlaying.IsPlaying}," +
                        $" DeviceId: {currentlyPlaying.Device.Id} (should be {deviceId})," +
                        $" TrackId: {track.Id} (should be {trackId.Value})."
                        );
                }

                if (state == State.StreamRunning)
                {
                    Log.Trace("Song is playing on spotify now.");
                    break;
                }
            }

            // Start audio streaming to ffmpeg.
            Log.Debug("Starting stream...");
            var pipeServer = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable);
            var handle     = "pipe:" + pipeServer.GetClientHandleAsString();

            var totalBytesSent = 0;

            void ExitLibrespot(string message, bool stats = true)
            {
                pipeServer.Dispose();

                if (!process.HasExitedSafe())
                {
                    process.Kill();
                }
                process.Close();

                state = State.Idle;

                var msg = message;

                if (stats)
                {
                    msg += $" Sent {byteSizeFormatter.Format(totalBytesSent)} bytes in total.";
                }
                Log.Debug(msg);
            }

            if (state != State.StreamRunning)
            {
                var msg = $"Song did not start playing after {SongStartRetries} retries.";
                ExitLibrespot(msg, false);
                return(new LocalStr(msg));
            }

            var byteReaderThread = new Thread(() => {
                var buffer = new byte[BytesPerChunk];
                while (true)
                {
                    int bytesRead;
                    try {
                        bytesRead = process.StandardOutput.BaseStream.Read(buffer, 0, BytesPerChunk);
                    } catch (IOException e) {
                        ExitLibrespot($"Reading from Librespot failed: {e}.");
                        return;
                    }

                    if (bytesRead == 0)
                    {
                        // Librespot exited, no more data coming.
                        ExitLibrespot("All spotify streaming data sent to ffmpeg.");
                        return;
                    }

                    try {
                        pipeServer.Write(buffer, 0, bytesRead);
                    } catch (IOException) {
                        ExitLibrespot("Ffmpeg went away before all spotify stream data was sent.");
                        return;
                    }

                    if (totalBytesSent == 0)
                    {
                        // Necessary to dispose the handle after ffmpeg connected to receive notice when ffmpeg exits.
                        pipeServer.DisposeLocalCopyOfClientHandle();
                    }

                    totalBytesSent += bytesRead;
                }
            })
            {
                IsBackground = true
            };

            return(handle, byteReaderThread, duration);
        }
示例#4
0
        static void Main(string[] args)
        {
            Console.WriteLine("Started application (Process A)...");

            var result = new List <string>();

            // Create separate process
            var anotherProcess = new Process
            {
                StartInfo =
                {
                    FileName        = "SomeOtherApp.exe",
                    CreateNoWindow  = true,
                    UseShellExecute = false
                }
            };

            // Create 2 anonymous pipes (read and write) for duplex communications (each pipe is one-way)
            using (var pipeRead = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable))
                using (var pipeWrite = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable))
                {
                    // Pass to the other process handles to the 2 pipes
                    anotherProcess.StartInfo.Arguments = pipeRead.GetClientHandleAsString() + " " + pipeWrite.GetClientHandleAsString();
                    anotherProcess.Start();

                    Console.WriteLine("Started other process (Process B)...");
                    Console.WriteLine();

                    pipeRead.DisposeLocalCopyOfClientHandle();
                    pipeWrite.DisposeLocalCopyOfClientHandle();

                    try
                    {
                        using (var sw = new StreamWriter(pipeWrite))
                        {
                            // Send a 'sync message' and wait for the other process to receive it
                            sw.Write("SYNC");
                            pipeWrite.WaitForPipeDrain();

                            Console.WriteLine("Sending message to Process B...");

                            // Send message to the other process
                            sw.Write("Hello from Process A!");
                            sw.Write("END");
                        }

                        // Get message from the other process
                        using (var sr = new StreamReader(pipeRead))
                        {
                            string temp;

                            // Wait for 'sync message' from the other process
                            do
                            {
                                temp = sr.ReadLine();
                            } while (temp == null || !temp.StartsWith("SYNC"));

                            // Read until 'end message' from the other process
                            while ((temp = sr.ReadLine()) != null && !temp.StartsWith("END"))
                            {
                                result.Add(temp);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        //TODO Exception handling/logging
                        throw;
                    }
                    finally
                    {
                        anotherProcess.WaitForExit();
                        anotherProcess.Close();
                    }

                    if (result.Count > 0)
                    {
                        Console.WriteLine("Received message from Process B: " + result[0]);
                    }

                    Console.ReadLine();
                }
        }
        /// <summary>
        /// Finds or creates a child process which can act as a node.
        /// </summary>
        /// <returns>The pipe stream representing the node.</returns>
        protected NodeContext GetNode(string msbuildLocation, string commandLineArgs, int nodeId, INodePacketFactory factory, long hostHandshake, long clientHandshake, NodeContextTerminateDelegate terminateNode)
        {
#if DEBUG
            if (Execution.BuildManager.WaitForDebugger)
            {
                commandLineArgs += " /wfd";
            }
#endif

            if (String.IsNullOrEmpty(msbuildLocation))
            {
                msbuildLocation = _componentHost.BuildParameters.NodeExeLocation;
            }

            if (String.IsNullOrEmpty(msbuildLocation))
            {
                string msbuildExeName = Environment.GetEnvironmentVariable("MSBUILD_EXE_NAME");

                if (!String.IsNullOrEmpty(msbuildExeName))
                {
                    // we assume that MSBUILD_EXE_NAME is, in fact, just the name.
                    msbuildLocation = Path.Combine(msbuildExeName, ".exe");
                }
            }

#if FEATURE_NODE_REUSE
            // Try to connect to idle nodes if node reuse is enabled.
            if (_componentHost.BuildParameters.EnableNodeReuse)
            {
                var candidateProcesses = GetPossibleRunningNodes(msbuildLocation);

                CommunicationsUtilities.Trace("Attempting to connect to each existing msbuild.exe process in turn to establish node {0}...", nodeId);
                foreach (Process nodeProcess in candidateProcesses)
                {
                    if (nodeProcess.Id == Process.GetCurrentProcess().Id)
                    {
                        continue;
                    }

                    // Get the full context of this inspection so that we can always skip this process when we have the same taskhost context
                    string nodeLookupKey = GetProcessesToIgnoreKey(hostHandshake, clientHandshake, nodeProcess.Id);
                    if (_processesToIgnore.Contains(nodeLookupKey))
                    {
                        continue;
                    }

                    // We don't need to check this again
                    _processesToIgnore.Add(nodeLookupKey);

                    // Attempt to connect to each process in turn.
                    Stream nodeStream = TryConnectToProcess(nodeProcess.Id, 0 /* poll, don't wait for connections */, hostHandshake, clientHandshake);
                    if (nodeStream != null)
                    {
                        // Connection successful, use this node.
                        CommunicationsUtilities.Trace("Successfully connected to existed node {0} which is PID {1}", nodeId, nodeProcess.Id);
                        return(new NodeContext(nodeId, nodeProcess.Id, nodeStream, factory, terminateNode));
                    }
                }
            }
#endif

            // None of the processes we tried to connect to allowed a connection, so create a new one.
            // We try this in a loop because it is possible that there is another MSBuild multiproc
            // host process running somewhere which is also trying to create nodes right now.  It might
            // find our newly created node and connect to it before we get a chance.
            CommunicationsUtilities.Trace("Could not connect to existing process, now creating a process...");
            int retries = NodeCreationRetries;
            while (retries-- > 0)
            {
#if FEATURE_NET35_TASKHOST
                // We will also check to see if .NET 3.5 is installed in the case where we need to launch a CLR2 OOP TaskHost.
                // Failure to detect this has been known to stall builds when Windows pops up a related dialog.
                // It's also a waste of time when we attempt several times to launch multiple MSBuildTaskHost.exe (CLR2 TaskHost)
                // nodes because we should never be able to connect in this case.
                string taskHostNameForClr2TaskHost = Path.GetFileNameWithoutExtension(NodeProviderOutOfProcTaskHost.TaskHostNameForClr2TaskHost);
                if (Path.GetFileNameWithoutExtension(msbuildLocation).Equals(taskHostNameForClr2TaskHost, StringComparison.OrdinalIgnoreCase))
                {
                    if (FrameworkLocationHelper.GetPathToDotNetFrameworkV35(DotNetFrameworkArchitecture.Current) == null)
                    {
                        CommunicationsUtilities.Trace
                        (
                            "Failed to launch node from {0}. The required .NET Framework v3.5 is not installed or enabled. CommandLine: {1}",
                            msbuildLocation,
                            commandLineArgs
                        );

                        string nodeFailedToLaunchError = ResourceUtilities.GetResourceString("TaskHostNodeFailedToLaunchErrorCodeNet35NotInstalled");
                        throw new NodeFailedToLaunchException(null, nodeFailedToLaunchError);
                    }
                }
#endif
#if !FEATURE_NAMED_PIPES_FULL_DUPLEX
                var clientToServerStream = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable);
                var serverToClientStream = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable);

                commandLineArgs += $" /clientToServerPipeHandle:{clientToServerStream.GetClientHandleAsString()} /serverToClientPipeHandle:{serverToClientStream.GetClientHandleAsString()}";
#endif

                // Create the node process
                int msbuildProcessId = LaunchNode(msbuildLocation, commandLineArgs);
                _processesToIgnore.Add(GetProcessesToIgnoreKey(hostHandshake, clientHandshake, msbuildProcessId));

#if FEATURE_NAMED_PIPES_FULL_DUPLEX
                // Note, when running under IMAGEFILEEXECUTIONOPTIONS registry key to debug, the process ID
                // gotten back from CreateProcess is that of the debugger, which causes this to try to connect
                // to the debugger process. Instead, use MSBUILDDEBUGONSTART=1

                // Now try to connect to it.
                Stream nodeStream = TryConnectToProcess(msbuildProcessId, TimeoutForNewNodeCreation, hostHandshake, clientHandshake);
                if (nodeStream != null)
                {
                    // Connection successful, use this node.
                    CommunicationsUtilities.Trace("Successfully connected to created node {0} which is PID {1}", nodeId, msbuildProcessId);
                    return(new NodeContext(nodeId, msbuildProcessId, nodeStream, factory, terminateNode));
                }
#else
                if (WaitForConnectionFromProcess(clientToServerStream, serverToClientStream, msbuildProcessId, hostHandshake, clientHandshake))
                {
                    // Connection successful, use this node.

                    clientToServerStream.DisposeLocalCopyOfClientHandle();
                    serverToClientStream.DisposeLocalCopyOfClientHandle();

                    CommunicationsUtilities.Trace("Successfully connected to created node {0} which is PID {1}", nodeId, msbuildProcessId);
                    return(new NodeContext(nodeId, msbuildProcessId, clientToServerStream, serverToClientStream, factory, terminateNode));
                }
#endif
            }

            // We were unable to launch a node.
            CommunicationsUtilities.Trace("FAILED TO CONNECT TO A CHILD NODE");
            return(null);
        }
        private IReadOnlyList <Process> CreateProcessTree()
        {
            (Process Value, string Message)rootResult = ListenForAnonymousPipeMessage(rootPipeHandleString =>
            {
                Process root = CreateProcess(rhs =>
                {
                    (Process Value, string Message)child1Result = ListenForAnonymousPipeMessage(child1PipeHandleString =>
                    {
                        Process child1 = CreateProcess(c1hs =>
                        {
                            Process child2 = CreateProcess(() => WaitForever());
                            child2.Start();

                            SendMessage(child2.Id.ToString(), c1hs);

                            return(WaitForever());
                        }, child1PipeHandleString, autoDispose: false);

                        child1.Start();

                        return(child1);
                    });

                    var child1ProcessId = child1Result.Value.Id;
                    var child2ProcessId = child1Result.Message;
                    SendMessage($"{child1ProcessId};{child2ProcessId}", rhs);

                    return(WaitForever());
                }, rootPipeHandleString, autoDispose: false);

                root.Start();

                return(root);
            });

            IEnumerable <Process> childProcesses = rootResult.Message
                                                   .Split(';')
                                                   .Select(x => int.Parse(x))
                                                   .Select(pid => Process.GetProcessById(pid));

            return(new[] { rootResult.Value }
                   .Concat(childProcesses)
                   .ToList());

            int WaitForever()
            {
                Thread.Sleep(Timeout.Infinite);

                // never reaches here -- but necessary to satisfy method's signature
                return(RemoteExecutor.SuccessExitCode);
            }

            void SendMessage(string message, string handleAsString)
            {
                using (var client = new AnonymousPipeClientStream(PipeDirection.Out, handleAsString))
                {
                    using (var sw = new StreamWriter(client))
                    {
                        sw.WriteLine(message);
                    }
                }
            }

            (T Value, string Message) ListenForAnonymousPipeMessage <T>(Func <string, T> action)
            {
                using (var pipeServer = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable))
                {
                    string handleAsString = pipeServer.GetClientHandleAsString();

                    T result = action(handleAsString);

                    pipeServer.DisposeLocalCopyOfClientHandle();

                    using (var sr = new StreamReader(pipeServer))
                    {
                        return(result, sr.ReadLine());
                    }
                }
            }
        }
        private async static Task <InterfaceLists> GetInterfacesOOP(string command_line, bool runtime_class)
        {
            using (AnonymousPipeServerStream server = new AnonymousPipeServerStream(PipeDirection.In,
                                                                                    HandleInheritability.Inheritable, 16 * 1024, null))
            {
                string process = null;
                if (!Environment.Is64BitOperatingSystem || Environment.Is64BitProcess)
                {
                    process = COMUtilities.GetExePath();
                }
                else
                {
                    process = COMUtilities.Get32bitExePath();
                }

                Process          proc = new Process();
                ProcessStartInfo info = new ProcessStartInfo(process, string.Format("{0} {1} {2}",
                                                                                    runtime_class ? "-r" : "-e", server.GetClientHandleAsString(), command_line));
                info.UseShellExecute = false;
                info.CreateNoWindow  = true;
                proc.StartInfo       = info;
                proc.Start();
                try
                {
                    List <COMInterfaceInstance> interfaces         = new List <COMInterfaceInstance>();
                    List <COMInterfaceInstance> factory_interfaces = new List <COMInterfaceInstance>();
                    server.DisposeLocalCopyOfClientHandle();

                    using (StreamReader reader = new StreamReader(server))
                    {
                        while (true)
                        {
                            string line = await reader.ReadLineAsync();

                            if (line == null)
                            {
                                break;
                            }

                            if (line.StartsWith("ERROR:"))
                            {
                                uint errorCode;
                                try
                                {
                                    errorCode = uint.Parse(line.Substring(6), System.Globalization.NumberStyles.AllowHexSpecifier);
                                }
                                catch (FormatException ex)
                                {
                                    Debug.WriteLine(ex.ToString());
                                    errorCode = 0x80004005;
                                }

                                throw new Win32Exception((int)errorCode);
                            }
                            else
                            {
                                Guid g;
                                bool factory = false;

                                if (line.StartsWith("*"))
                                {
                                    factory = true;
                                    line    = line.Substring(1);
                                }

                                string[] parts = line.Split(new char[] { ',' }, 3);
                                if (Guid.TryParse(parts[0], out g))
                                {
                                    string module_path   = null;
                                    long   vtable_offset = 0;
                                    if (parts.Length == 3)
                                    {
                                        module_path = parts[1];
                                        long.TryParse(parts[2], out vtable_offset);
                                    }

                                    if (factory)
                                    {
                                        factory_interfaces.Add(new COMInterfaceInstance(g, module_path, vtable_offset));
                                    }
                                    else
                                    {
                                        interfaces.Add(new COMInterfaceInstance(g, module_path, vtable_offset));
                                    }
                                }
                            }
                        }

                        if (!proc.WaitForExit(5000))
                        {
                            proc.Kill();
                        }
                        int exitCode = proc.ExitCode;
                        if (exitCode != 0)
                        {
                            interfaces         = new List <COMInterfaceInstance>(new COMInterfaceInstance[] { new COMInterfaceInstance(COMInterfaceEntry.IID_IUnknown) });
                            factory_interfaces = new List <COMInterfaceInstance>(new COMInterfaceInstance[] { new COMInterfaceInstance(COMInterfaceEntry.IID_IUnknown) });
                        }
                        return(new InterfaceLists()
                        {
                            Interfaces = interfaces, FactoryInterfaces = factory_interfaces
                        });
                    }
                }
                finally
                {
                    proc.Close();
                }
            }
        }
示例#8
0
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIDocument uidoc = commandData.Application.ActiveUIDocument;
            Document   doc   = uidoc.Document;

            revitVersion = Convert.ToInt32(doc.Application.VersionName.Split(' ').Last());

            //The IFC Loader process
            string assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

            var ifcLoader = new Process
            {
                StartInfo =
                {
                    FileName        = Path.Combine(assemblyFolder, "IFCLoader.exe"),
                    CreateNoWindow  = true,
                    UseShellExecute = false
                }
            };

            Application.EnableVisualStyles();
            MainWindow main = new MainWindow();

            Label lbl = new Label();

            lbl.Location = new System.Drawing.Point(90, 110);
            lbl.AutoSize = true;
            lbl.Font     = new Font("Calibri", 12);
            lbl.Text     = $"Revit Version: {revitVersion}";
            main.Controls.Add(lbl);

            //Create an input server pipe to recieve the XML data from the IFC Loader
            using (var pipeRead = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable))
            {
                ifcLoader.StartInfo.Arguments = pipeRead.GetClientHandleAsString();
                void startLoader(object o, EventArgs e) => ifcLoader.Start();

                main.loaderBtn.Click += startLoader;
                Application.Run(main);


                //Lists of strings to recieve the XML data
                List <string> columnsResult  = new List <string>();
                List <string> storeysResult  = new List <string>();
                List <string> floorsResult   = new List <string>();
                List <string> beamsResult    = new List <string>();
                List <string> inclinesResult = new List <string>();

                List <string> columnsStResult = new List <string>();
                List <string> beamsStResult   = new List <string>();
                List <string> bracesResult    = new List <string>();

                if (main.isCancelled == true)
                {
                    ifcLoader.Close();
                    return(Result.Cancelled);
                }
                pipeRead.DisposeLocalCopyOfClientHandle();

                try
                {
                    using (var sr = new StreamReader(pipeRead))
                    {
                        string temp;
                        // Wait for 'sync message' from the other process
                        do
                        {
                            temp = sr.ReadLine();
                        } while (temp == null || !temp.StartsWith("SYNC"));

                        // Read Column data until 'COLSEND message' from the other process
                        while ((temp = sr.ReadLine()) != null && !temp.StartsWith("COLSEND"))
                        {
                            columnsResult.Add(temp);
                        }

                        // Read Inclines data until 'INCSEND message' from the other process
                        while ((temp = sr.ReadLine()) != null && !temp.StartsWith("INCSEND"))
                        {
                            inclinesResult.Add(temp);
                        }

                        // Read Beams data until 'BEAMSEND message' from the other process
                        while ((temp = sr.ReadLine()) != null && !temp.StartsWith("BEAMSEND"))
                        {
                            beamsResult.Add(temp);
                        }

                        // Read I-Column data until 'COLSTEELSEND message' from the other process
                        while ((temp = sr.ReadLine()) != null && !temp.StartsWith("COLSTEELSEND"))
                        {
                            columnsStResult.Add(temp);
                        }

                        // Read Braces data until 'BRACESEND message' from the other process
                        while ((temp = sr.ReadLine()) != null && !temp.StartsWith("BRACESEND"))
                        {
                            bracesResult.Add(temp);
                        }

                        // Read I-Beams data until 'BEAMSSTEELEND message' from the other process
                        while ((temp = sr.ReadLine()) != null && !temp.StartsWith("BEAMSSTEELEND"))
                        {
                            beamsStResult.Add(temp);
                        }

                        // Read Storeys data until 'END message' from the other process
                        while ((temp = sr.ReadLine()) != null && !temp.StartsWith("STORSEND"))
                        {
                            storeysResult.Add(temp);
                        }

                        // Read Floors data until 'END message' from the other process
                        while ((temp = sr.ReadLine()) != null && !temp.StartsWith("END"))
                        {
                            floorsResult.Add(temp);
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    ifcLoader.WaitForExit();
                    ifcLoader.Close();
                }


                //Joining XML data lines
                string columnsXMLData  = String.Join(Environment.NewLine, columnsResult.ToArray());
                string beamsXMLData    = String.Join(Environment.NewLine, beamsResult.ToArray());
                string inclinesXMLData = String.Join(Environment.NewLine, inclinesResult.ToArray());
                string storeysXMLData  = String.Join(Environment.NewLine, storeysResult.ToArray());
                string floorsXMLData   = String.Join(Environment.NewLine, floorsResult.ToArray());

                string bracesXMLData    = String.Join(Environment.NewLine, bracesResult.ToArray());
                string beamsStXMLData   = String.Join(Environment.NewLine, beamsStResult.ToArray());
                string columnsStXMLData = String.Join(Environment.NewLine, columnsStResult.ToArray());


                //XML Deserializers
                XmlSerializer columnsDeserializer  = new XmlSerializer(typeof(List <Column>));
                XmlSerializer beamsDeserializer    = new XmlSerializer(typeof(List <Beam>));
                XmlSerializer inclinesDeserializer = new XmlSerializer(typeof(List <Inclined>));
                XmlSerializer storeysDeserializer  = new XmlSerializer(typeof(List <double>));
                XmlSerializer floorsDeserializer   = new XmlSerializer(typeof(List <FloorSlab>));

                XmlSerializer columnsStDeserializer = new XmlSerializer(typeof(List <ColumnSt>));
                XmlSerializer beamsStDeserializer   = new XmlSerializer(typeof(List <BeamSt>));
                XmlSerializer bracesDeserializer    = new XmlSerializer(typeof(List <Brace>));


                //String Readers streams
                StringReader colsStringReader     = new StringReader(columnsXMLData);
                StringReader beamsStringReader    = new StringReader(beamsXMLData);
                StringReader inclinesStringReader = new StringReader(inclinesXMLData);
                StringReader storsStringReader    = new StringReader(storeysXMLData);
                StringReader floorsStringReader   = new StringReader(floorsXMLData);

                StringReader columnsStStringReader = new StringReader(columnsStXMLData);
                StringReader beamsStStringReader   = new StringReader(beamsStXMLData);
                StringReader bracesStringReader    = new StringReader(bracesXMLData);



                //Lists of required data

                List <Column>    cols       = columnsDeserializer.Deserialize(colsStringReader) as List <Column>;
                List <Inclined>  incss      = inclinesDeserializer.Deserialize(inclinesStringReader) as List <Inclined>;
                List <Beam>      beammms    = beamsDeserializer.Deserialize(beamsStringReader) as List <Beam>;
                List <double>    storeys    = storeysDeserializer.Deserialize(storsStringReader) as List <double>;
                List <FloorSlab> floorSlabs = floorsDeserializer.Deserialize(floorsStringReader) as List <FloorSlab>;

                List <ColumnSt> StCol   = columnsStDeserializer.Deserialize(columnsStStringReader) as List <ColumnSt>;
                List <BeamSt>   Stbeam  = beamsStDeserializer.Deserialize(beamsStStringReader) as List <BeamSt>;
                List <Brace>    StBrace = bracesDeserializer.Deserialize(bracesStringReader) as List <Brace>;


                //Disposing resources and closing the string readers
                colsStringReader.Dispose();
                inclinesStringReader.Dispose();
                beamsStringReader.Dispose();
                storsStringReader.Dispose();
                floorsStringReader.Dispose();

                columnsStStringReader.Dispose();
                beamsStStringReader.Dispose();
                bracesStringReader.Dispose();


                floorsStringReader.Close();
                storsStringReader.Close();
                beamsStringReader.Close();
                inclinesStringReader.Close();
                colsStringReader.Close();

                columnsStStringReader.Close();
                beamsStStringReader.Close();
                bracesStringReader.Close();


                //Creating Levels
                void createLevels() => levels = CreateLevels(doc, storeys);

                InitTransaction(doc, "Create Levels", createLevels);

                //Creating Columns
                void createColumns() => colInstances = CreateColumnInstance(doc, cols, "Concrete-Rectangular-Column", true, storeys);

                InitTransaction(doc, "Create Columns", createColumns);

                //Creating Inclined Columns
                void createInclines() => incInstances = CreateInclinedInstance(doc, incss, "Concrete-Rectangular-Column", true, storeys);

                InitTransaction(doc, "Create Inclined Columns", createInclines);

                //Creating Beams
                void createBeams() => beamInstances = CreateBeamInstance(doc, beammms, "Concrete-Rectangular Beam");

                InitTransaction(doc, "Create Beams", createBeams);

                //Creating steel Columns
                void createSteelColumns() => colStInstances = CreateSteelColumnInstance(doc, StCol, "W Shapes-Column", true, storeys);

                InitTransaction(doc, "Create Columns", createSteelColumns);

                //Creating Braces
                void createBraces() => BraceInstances = CreateBraceInstance(doc, StBrace, "L-Angle-Column", true, storeys);

                InitTransaction(doc, "Create Braces", createBraces);

                //Creating steel Beams
                void createSteelBeams() => beamStInstances = CreateSteelBeamInstance(doc, Stbeam, "W Shapes");

                InitTransaction(doc, "Create steel Beams", createSteelBeams);


                //Creating Grids
                List <FamilyInstance> allColumns = new List <FamilyInstance>();
                allColumns.AddRange(colInstances);
                allColumns.AddRange(colStInstances);
                allColumns.RemoveAll(col => col == null);
                List <XYZ>    gridsIntersections = GetGridsIntersections(allColumns);
                List <double> xGridLocations     = GetXGridsLocations(gridsIntersections);
                List <double> yGridLocations     = GetYGridsLocations(gridsIntersections);

                void creatGrids() => grids = CreateGrids(doc, xGridLocations, yGridLocations);

                InitTransaction(doc, "Create Grids", creatGrids);


                //Creating Floors
                void createFloors() => floors = CreateFloor(doc, floorSlabs);

                InitTransaction(doc, "Create Floors", createFloors);
            }

            return(Result.Succeeded);
        }
示例#9
0
        public static void StartServer()
        {
            Process pipeClient = new Process();

            pipeClient.StartInfo.FileName = "A0143_AnonymousPipeClient.exe";



            // 匿名管道.
            using (AnonymousPipeServerStream pipeServer =
                       new AnonymousPipeServerStream(PipeDirection.Out,
                                                     HandleInheritability.Inheritable))
            {
                // Show that anonymous pipes do not support Message mode.
                try
                {
                    Console.WriteLine("[SERVER] 尝试设置管道当前的传输模式为: \"Message\".");
                    pipeServer.ReadMode = PipeTransmissionMode.Message;
                }
                catch (NotSupportedException e)
                {
                    Console.WriteLine("[SERVER] 异常:\n    {0}", e.Message);
                }


                Console.WriteLine("[SERVER] 管道当前的传输模式: {0}.", pipeServer.TransmissionMode);



                // 提供命令行参数, 启动客户端.
                // Pass the client process a handle to the server.
                pipeClient.StartInfo.Arguments       = pipeServer.GetClientHandleAsString();
                pipeClient.StartInfo.UseShellExecute = false;
                pipeClient.Start();



                pipeServer.DisposeLocalCopyOfClientHandle();


                try
                {
                    // Read user input and send that to the client process.
                    using (StreamWriter sw = new StreamWriter(pipeServer))
                    {
                        sw.AutoFlush = true;


                        // Send a 'sync message' and wait for client to receive it.
                        sw.WriteLine("SYNC");
                        pipeServer.WaitForPipeDrain();


                        // Send the console input to the client process.
                        Console.Write("[SERVER] 输入需要发送给客户端的消息: ");
                        sw.WriteLine(Console.ReadLine());
                    }
                }
                // Catch the IOException that is raised if the pipe is broken
                // or disconnected.
                catch (IOException e)
                {
                    Console.WriteLine("[SERVER] Error: {0}", e.Message);
                }
            }


            pipeClient.WaitForExit();
            pipeClient.Close();
            Console.WriteLine("[SERVER] Client quit. Server terminating.");
        }
示例#10
0
        public static ReturningObject CallProcessingApp(DataContainer.PassingObject data)
        {
            string sProcessingAppLocation = Assembly.GetExecutingAssembly().Location;

            var lsResult = new List <string>();

            // Create separate process
            var newProcess = new Process
            {
                StartInfo =
                {
                    FileName        = sProcessingAppLocation,
                    CreateNoWindow  = true,
                    UseShellExecute = false,
                }
            };

            // Create 2 anonymous pipes (read and write) for duplex communications
            // (each pipe is one-way)
            using (var pipeRead = new AnonymousPipeServerStream(PipeDirection.In,
                                                                HandleInheritability.Inheritable))
                using (var pipeWrite = new AnonymousPipeServerStream(PipeDirection.Out,
                                                                     HandleInheritability.Inheritable))
                {
                    // Pass to the other process handles to the 2 pipes
                    newProcess.StartInfo.Arguments = pipeRead.GetClientHandleAsString() + " " +
                                                     pipeWrite.GetClientHandleAsString();

                    try
                    {
                        newProcess.Start();
                    }
                    catch { }

                    pipeRead.DisposeLocalCopyOfClientHandle();
                    pipeWrite.DisposeLocalCopyOfClientHandle();

                    try
                    {
                        using (var sw = new StreamWriter(pipeWrite))
                        {
                            // Send a 'sync message' and wait for the other process to receive it
                            sw.WriteLine("SYNC");
                            pipeWrite.WaitForPipeDrain();

                            sw.WriteLine(JsonConvert.SerializeObject(data));
                            sw.WriteLine("END");
                        }

                        // Get message from the other process
                        using (var sr = new StreamReader(pipeRead))
                        {
                            string sTempResult;

                            // Wait for 'sync message' from the other process
                            do
                            {
                                sTempResult = sr.ReadLine();
                            } while (sTempResult == null || !sTempResult.StartsWith("SYNC"));

                            // Read until 'end message' from the other process
                            while ((sTempResult = sr.ReadLine()) != null && !sTempResult.StartsWith("END"))
                            {
                                lsResult.Add(sTempResult);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                    }
                    finally
                    {
                        newProcess.WaitForExit();
                        newProcess.Close();
                    }
                }

            ReturningObject dataReturnObject;

            if (lsResult.Count == 0)
            {
                dataReturnObject = new ReturningObject()
                {
                    Error = "Error"
                };
            }
            else if (lsResult[0] != null)
            {
                dataReturnObject = JsonConvert.DeserializeObject <ReturningObject>(lsResult[0]);
            }
            else
            {
                dataReturnObject = new ReturningObject()
                {
                    Error = "Error"
                }
            };

            return(dataReturnObject);
        }
    }
示例#11
0
        public async static Task <COMEnumerateInterfaces> GetInterfacesOOP(COMCLSIDEntry ent)
        {
            using (AnonymousPipeServerStream server = new AnonymousPipeServerStream(System.IO.Pipes.PipeDirection.In,
                                                                                    HandleInheritability.Inheritable, 16 * 1024, null))
            {
                string process = null;
                if (!Environment.Is64BitOperatingSystem || Environment.Is64BitProcess)
                {
                    process = COMUtilities.GetExePath();
                }
                else
                {
                    process = COMUtilities.Get32bitExePath();
                }

                string apartment = "s";
                if (ent.DefaultThreadingModel == COMThreadingModel.Both ||
                    ent.DefaultThreadingModel == COMThreadingModel.Free)
                {
                    apartment = "m";
                }

                Process          proc = new Process();
                ProcessStartInfo info = new ProcessStartInfo(process, String.Format("{0} {1} {2} {3} \"{4}\"",
                                                                                    "-e", server.GetClientHandleAsString(), ent.Clsid.ToString("B"), apartment, ent.CreateContext));
                info.UseShellExecute = false;
                info.CreateNoWindow  = true;
                proc.StartInfo       = info;
                proc.Start();
                try
                {
                    server.DisposeLocalCopyOfClientHandle();

                    using (StreamReader reader = new StreamReader(server))
                    {
                        List <COMInterfaceInstance> interfaces         = new List <COMInterfaceInstance>();
                        List <COMInterfaceInstance> factory_interfaces = new List <COMInterfaceInstance>();
                        while (true)
                        {
                            string line = await reader.ReadLineAsync();

                            if (line == null)
                            {
                                break;
                            }

                            if (line.StartsWith("ERROR:"))
                            {
                                uint errorCode;
                                try
                                {
                                    errorCode = uint.Parse(line.Substring(6), System.Globalization.NumberStyles.AllowHexSpecifier);
                                }
                                catch (FormatException ex)
                                {
                                    Debug.WriteLine(ex.ToString());
                                    errorCode = 0x80004005;
                                }

                                throw new Win32Exception((int)errorCode);
                            }
                            else
                            {
                                Guid g;
                                bool factory = false;

                                if (line.StartsWith("*"))
                                {
                                    factory = true;
                                    line    = line.Substring(1);
                                }

                                string[] parts = line.Split(new char[] { ',' }, 3);
                                if (Guid.TryParse(parts[0], out g))
                                {
                                    string module_path   = null;
                                    long   vtable_offset = 0;
                                    if (parts.Length == 3)
                                    {
                                        module_path = parts[1];
                                        long.TryParse(parts[2], out vtable_offset);
                                    }

                                    if (factory)
                                    {
                                        factory_interfaces.Add(new COMInterfaceInstance(g, module_path, vtable_offset));
                                    }
                                    else
                                    {
                                        interfaces.Add(new COMInterfaceInstance(g, module_path, vtable_offset));
                                    }
                                }
                            }
                        }

                        if (!proc.WaitForExit(5000))
                        {
                            proc.Kill();
                        }
                        int exitCode = proc.ExitCode;
                        if (exitCode != 0)
                        {
                            interfaces         = new List <COMInterfaceInstance>(new COMInterfaceInstance[] { new COMInterfaceInstance(COMInterfaceEntry.IID_IUnknown) });
                            factory_interfaces = new List <COMInterfaceInstance>(new COMInterfaceInstance[] { new COMInterfaceInstance(COMInterfaceEntry.IID_IUnknown) });
                        }

                        return(new COMEnumerateInterfaces(ent.Clsid, ent.CreateContext, interfaces, factory_interfaces));
                    }
                }
                finally
                {
                    proc.Close();
                }
            }
        }
示例#12
0
        private async Task <Process> StartProcessAsync()
        {
            Debug.Assert(!_Process.IsValueCreated); // Can be called only once.
            Debug.Assert(disposables == null);
            Directory.CreateDirectory(WorkingDirectory);
            Process process          = null;
            var     localDisposables = new List <IDisposable>();

            try
            {
                var txPipe = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable);
                localDisposables.Add(txPipe);
                var rxPipe = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable);
                localDisposables.Add(rxPipe);
                process = StartExecutionProcess(txPipe, rxPipe);
                localDisposables.Add(process);
                txPipe.DisposeLocalCopyOfClientHandle();
                rxPipe.DisposeLocalCopyOfClientHandle();

                var procReader = new ByLineTextMessageReader(rxPipe);
                localDisposables.Add(procReader);
                localDisposables.Remove(rxPipe);
                var procWriter = new ByLineTextMessageWriter(txPipe);
                localDisposables.Add(procWriter);
                localDisposables.Remove(txPipe);
                // Wait for host to start up.
                using (var cts = new CancellationTokenSource(5000))
                {
                    Message startedMessage = null;
                    try
                    {
                        startedMessage = await procReader.ReadAsync(m =>
                                                                    m is RequestMessage rm && rm.Method == "NotifyStarted",
                                                                    cts.Token);
                    }
                    catch (OperationCanceledException)
                    {
                    }
                    if (startedMessage == null)
                    {
                        throw new ExecutionHostException(Prompts.CannotStartExecutionHost_MissingNotifyStarted);
                    }
                }

                //// HOST
                //var hostBuilder = new JsonRpcServiceHostBuilder();
                //// Currently this host does nothing.
                //var host = hostBuilder.Build();
                //var serverHandler = new StreamRpcServerHandler(host);
                //serverHandler.DefaultFeatures.Set<ISandboxContextFeature>(new SandboxContextFeature(this, null));
                //localDisposables.Add(serverHandler.Attach(procReader, procWriter));

                // CLIENT
                var clientHandler = new StreamRpcClientHandler();
                RpcClient = new JsonRpcClient(clientHandler);
                localDisposables.Add(clientHandler.Attach(procReader, procWriter));

                HostStub = ProxyBuilder.CreateProxy <IHostStub>(RpcClient);
                return(process);
            }
            catch (Exception ex)
            {
                if (process != null)
                {
                    try
                    {
                        if (!process.WaitForExit(1000))
                        {
                            process.Kill();
                        }
                    }
                    catch (Exception ex1)
                    {
                        throw new AggregateException(ex, ex1);
                    }
                }
                foreach (var d in localDisposables)
                {
                    try
                    {
                        d.Dispose();
                    }
                    catch (ObjectDisposedException)
                    {
                        // StreamWriter will attempt to flush before disposal,
                    }
                    catch (Exception ex1)
                    {
                        throw new AggregateException(ex, ex1);
                    }
                }
                localDisposables = null;
                if (ex is ExecutionHostException)
                {
                    throw;
                }
                throw new ExecutionHostException(Prompts.CannotStartExecutionHost, ex);
            }
            finally
            {
                if (localDisposables != null)
                {
                    disposables = localDisposables;
                }
            }
        }
示例#13
0
        // This solution utilizes a separate process for camera handling and uses an anonymous pipe to communicate with it to receive images from the camera
        // The Canon EOS handling is done separately to enable several connected cameras at the same time since the EDSDK DLL is loaded statically and only allows one connected camera
        public virtual void Start()
        {
            // An anonymous pipe is used to get the images from the camerahandler process
            using (var pipeServer = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable))
            {
                _process = new Process
                {
                    StartInfo =
                    {
                        FileName        = _settings.HandlerExecutableName,
                        UseShellExecute = false,
                        Arguments       = "--pipe=\"" + pipeServer.GetClientHandleAsString() + "\" " +
                                          "--device=" + _settings.DeviceIndex + " " +
                                          "--av=\"" + _settings.Av + "\" " +
                                          "--tv=\"" + _settings.Tv + "\" " +
                                          "--wb=\"" + _settings.WB + "\" " +
                                          "--iso=\"" + _settings.ISO + "\" "
                    }
                };
                _process.Start();

                //MSDN: The DisposeLocalCopyOfClientHandle method should be called after the client handle has been passed to the client.
                //      If this method is not called, the AnonymousPipeServerStream object will not receive notice when the client disposes of its PipeStream object.
                pipeServer.DisposeLocalCopyOfClientHandle();

                // Pipe reader (reads the camera images ad infinitum)
                using (var binaryReader = new BinaryReader(pipeServer))
                {
                    try
                    {
                        while (pipeServer.IsConnected)
                        {
                            // Data structure: image size in bytes as int32 and then the image size amount of data
                            var imgSize = binaryReader.ReadInt32();
                            if (imgSize <= 0)
                            {
                                continue;
                            }
                            byte[] buf = binaryReader.ReadBytes(imgSize);
                            unsafe
                            {
                                var memIntPtr = IntPtr.Zero;
                                try
                                {
                                    // Reserve unamanged memory for the image so that we can use it in another thread safely
                                    memIntPtr = Marshal.AllocHGlobal(imgSize);
                                    var writeStream = new UnmanagedMemoryStream((byte *)memIntPtr.ToPointer(), imgSize,
                                                                                imgSize, FileAccess.Write);
                                    writeStream.Write(buf, 0, imgSize);
                                    writeStream.Close();

                                    // The stream above could be opened using Read+Write permissions, but it's better to provide a read-only stream to the handler delegate
                                    var readStream = new UnmanagedMemoryStream((byte *)memIntPtr.ToPointer(), imgSize,
                                                                               imgSize, FileAccess.Read);
                                    // Pass the image to the delegate to call for image update
                                    if (ImageUpdated != null)
                                    {
                                        ImageUpdated(this, new ImageUpdateEventArgs {
                                            Image = readStream
                                        });
                                    }
                                    readStream.Close();
                                }
                                finally
                                {
                                    // Free the unmanaged memory
                                    if (memIntPtr != IntPtr.Zero)
                                    {
                                        Marshal.FreeHGlobal(memIntPtr);
                                    }
                                }
                            }
                        }
                    }
                    catch (ThreadAbortException)
                    {
                        CallClose();
                    }
                    catch (IOException ex)
                    {
                        Debug.WriteLine("CameraHandlerProcess pipe error: " + ex.Message);
                        CallClose();
                    }
                    Debug.WriteLine("CameraHandlerProcess: pipe is no longer connected.");
                }
            }
        }
示例#14
0
        /// <summary>
        /// Uses P/Invoke to start the process using the login token obtained for the user.
        /// </summary>
        /// <param name="token">The login token to use to create the process with.</param>
        private void StartWithCreateProcessAsUser(IntPtr token)
        {
            var  startinfo      = _process.StartInfo;
            var  path           = Path.GetFullPath(startinfo.FileName);
            var  dir            = Path.GetDirectoryName(path);
            bool processCreated = false;

            Win32NativeMethods.PROCESS_INFORMATION pi        = new Win32NativeMethods.PROCESS_INFORMATION();
            Win32NativeMethods.SECURITY_ATTRIBUTES saProcess = new Win32NativeMethods.SECURITY_ATTRIBUTES();
            saProcess.bInheritHandle = true;
            saProcess.nLength        = (uint)Marshal.SizeOf(saProcess);

            Win32NativeMethods.SECURITY_ATTRIBUTES saThread = new Win32NativeMethods.SECURITY_ATTRIBUTES();
            saThread.bInheritHandle = true;
            saThread.nLength        = (uint)Marshal.SizeOf(saThread);

            Win32NativeMethods.STARTUPINFO si = new Win32NativeMethods.STARTUPINFO();
            si.lpDesktop = string.Empty;
            si.cb        = (uint)Marshal.SizeOf(si);

            lock (createProcessLock)
            {
                _pipeServerToClient        = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable);
                _pipeServerFromClient      = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable);
                _pipeServerErrorFromClient = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable);

                try
                {
                    // although these are separate if statements, in reality all standard streams must be
                    // redirected otherwise it just won't work in SACS.
                    if (startinfo.RedirectStandardInput)
                    {
                        _standardInput           = new StreamWriter(_pipeServerToClient);
                        _standardInput.AutoFlush = true;
                    }

                    if (startinfo.RedirectStandardOutput)
                    {
                        Encoding encoding = (startinfo.StandardOutputEncoding != null) ? startinfo.StandardOutputEncoding : Console.OutputEncoding;
                        _standardOutput = new StreamReader(_pipeServerFromClient);
                    }

                    if (startinfo.RedirectStandardError)
                    {
                        Encoding encoding2 = (startinfo.StandardErrorEncoding != null) ? startinfo.StandardErrorEncoding : Console.OutputEncoding;
                        _standardError = new StreamReader(_pipeServerErrorFromClient);
                    }

                    ArgumentObject["pipeIn"]  = _pipeServerToClient.GetClientHandleAsString();
                    ArgumentObject["pipeOut"] = _pipeServerFromClient.GetClientHandleAsString();
                    ArgumentObject["pipeErr"] = _pipeServerErrorFromClient.GetClientHandleAsString();

                    processCreated = Win32NativeMethods.CreateProcessAsUser(
                        token,
                        path,
                        string.Format("\"{0}\" {1}", startinfo.FileName.Replace("\"", "\"\""), JsonConvert.SerializeObject(this.ArgumentObject)),
                        ref saProcess,
                        ref saThread,
                        true,
                        0,
                        IntPtr.Zero,
                        dir,
                        ref si,
                        out pi);

                    if (!processCreated)
                    {
                        throw new Win32Exception(Marshal.GetLastWin32Error());
                    }

                    // For the last step, since we're not using the in-build methods to start the process,
                    // we need to replace the now outdated process
                    _process = Process.GetProcessById((int)pi.dwProcessId);
                }
                finally
                {
                    _pipeServerToClient.DisposeLocalCopyOfClientHandle();
                    _pipeServerFromClient.DisposeLocalCopyOfClientHandle();
                    _pipeServerErrorFromClient.DisposeLocalCopyOfClientHandle();

                    if (pi.hProcess != IntPtr.Zero)
                    {
                        Win32NativeMethods.CloseHandle(pi.hProcess);
                    }

                    if (pi.hThread != IntPtr.Zero)
                    {
                        Win32NativeMethods.CloseHandle(pi.hThread);
                    }
                }
            }
        }
        public async Task Start()
        {
            int c = 0;

            while (!_cancellationToken.IsCancellationRequested)
            {
                // pause (let it finish current scrape)
                await _manualResetEvent.WaitAsync();

                CrawlDescription crawlDescription = await _scraperQueue.Dequeue();

                CrawlResult crawlResult = null;

                await _crawlLogger.LogCrawl(crawlDescription, new CrawlResult
                {
                    CrawlResultID = Shared.Enum.CrawlResultID.Success
                });

                c += 1;
                Log.Information("Crawled Keyword: {0}, Proxy: {1}, SearchString: {2}, Count: {3}",
                                crawlDescription.Keyword, crawlDescription.IP, crawlDescription.SearchString, c);

                continue;

                // pause (let it finish dequeue)
                await _manualResetEvent.WaitAsync();

                Process pipeClient = new Process
                {
                    StartInfo = new ProcessStartInfo
                    {
                        FileName         = "WebScraper.exe", // TODO(zvp): Don't hardcode this name
                        CreateNoWindow   = false,
                        UseShellExecute  = false,
                        WindowStyle      = ProcessWindowStyle.Hidden,
                        WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory
                    }
                };

                // For In-Out Inter-Process Communication
                using (AnonymousPipeServerStream pipeServerWriter =
                           new AnonymousPipeServerStream(PipeDirection.Out,
                                                         HandleInheritability.Inheritable))
                    using (AnonymousPipeServerStream pipeServerReader =
                               new AnonymousPipeServerStream(PipeDirection.In,
                                                             HandleInheritability.Inheritable))
                    {
                        // Start Pipe Client (WebScraper.exe)
                        pipeClient.StartInfo.Arguments =
                            $"{pipeServerWriter.GetClientHandleAsString()} {pipeServerReader.GetClientHandleAsString()}";
                        pipeClient.Start();

                        // release object handles
                        pipeServerWriter.DisposeLocalCopyOfClientHandle();
                        pipeServerReader.DisposeLocalCopyOfClientHandle();

                        try
                        {
                            using (StreamWriter sw = new StreamWriter(pipeServerWriter))
                            {
                                // flush after every write
                                sw.AutoFlush = true;

                                // write sync message
                                await sw.WriteLineAsync("SYNC");

                                pipeServerWriter.WaitForPipeDrain();

                                // write crawl description
                                string serializedCrawlDescription = JsonConvert.SerializeObject(crawlDescription);
                                await sw.WriteLineAsync(serializedCrawlDescription);
                            }

                            using (StreamReader sr = new StreamReader(pipeServerReader))
                            {
                                string message;

                                do
                                {
                                    // TODO(zvp) : have to exit eventually.
                                    message = await sr.ReadLineAsync();

                                    Log.Debug("Pipe Received Message: {0}", message);
                                } while (message == null || !message.StartsWith("SYNC"));

                                message = await sr.ReadLineAsync();

                                crawlResult = JsonConvert.DeserializeObject <CrawlResult>(message);
                                Log.Debug("Pipe Received Crawl Result: {0}", message);
                            }
                        }
                        catch (Exception ex)
                        {
                            Log.Error("WebScraper Exception({0}): {1}", ex.GetType(), ex.Message);
                        }
                        finally
                        {
                            // wait for client to shutdown
                            pipeClient.WaitForExit();
                            // free resources
                            pipeClient.Close();
                        }
                    }

                await _crawlLogger.LogCrawl(crawlDescription, new CrawlResult
                {
                    CrawlResultID = Shared.Enum.CrawlResultID.Success
                });

                c += 1;
                Log.Information("Crawled Keyword: {0}, Proxy: {1}, SearchString: {2}, Count: {3}",
                                crawlDescription.Keyword, crawlDescription.IP, crawlDescription.SearchString, c);
            }
        }
        /// <summary>
        /// Creates a child domain.
        /// </summary>
        public ChildDomain AddChildDomain(ProcessStartInfo startInfo, IAmASerializer serializer = null, IGenerateProxies proxyGenerator = null)
        {
            //if the path is missing then
            if (startInfo == null)
            {
                throw new ArgumentNullException(nameof(startInfo));
            }

            var childProcess = new Process
            {
                StartInfo = startInfo
            };

            proxyGenerator = proxyGenerator ?? DefaultProxyFactory.Instance;
            serializer     = serializer ?? DefaultSerializer.Instance;

            var debuggerEnabled = Debugger.IsAttached && DebuggingSupported;

            var read  = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable);
            var write = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable);

            startInfo.Environment[connectionStringVarName] =
                $"pid={Current.Process.Id}&" +
                $"write={write.GetClientHandleAsString()}&" +
                $"read={read.GetClientHandleAsString()}&" +
                $"debug={(debuggerEnabled ? 1 : 0)}&" +
                $"serializer={HttpUtility.UrlEncode(serializer.Name)}&" +
                $"proxyGenerator={HttpUtility.UrlEncode(proxyGenerator.Name)}";
            startInfo.UseShellExecute = false;

            childProcess.EnableRaisingEvents = true;

            childProcess.Start();

            read.DisposeLocalCopyOfClientHandle();
            write.DisposeLocalCopyOfClientHandle();

            if (debuggerEnabled)
            {
                if (!TryToAttachDebugger(childProcess.Id))
                {
                    debuggerEnabled = false;
                }

                //signal to the child process to continue now that the debugger is attached
                read.Write(new byte[1], 0, 1);
            }

            //NOTE: the read and write streams are switched for the server side
            var child = new ChildDomain(childProcess, debuggerEnabled, new Connection(this, serializer, proxyGenerator, write, read));

            children[childProcess.Id] = child;

            child.Process.Exited += (sender, eventArgs) => children.TryRemove(childProcess.Id, out _);

            if (child.Process.HasExited)
            {
                children.TryRemove(childProcess.Id, out _);
            }

            return(child);
        }
示例#17
0
        /// <summary>
        /// Main task thread for working with a single APSIMRunner.exe process using
        /// an anonymous pipe.
        /// </summary>
        private void PipeServerTaskThread()
        {
            // Create 2 anonymous pipes (read and write) for duplex communications
            // (each pipe is one-way)
            using (var pipeRead = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable))
                using (var pipeWrite = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable))
                {
                    var pipeHandles = pipeRead.GetClientHandleAsString() + " " + pipeWrite.GetClientHandleAsString();

                    // Run a APSIMRunner process passing the pipe read and write handles as arguments.
                    var runnerProcess = new ProcessUtilities.ProcessWithRedirectedOutput();
                    runnerProcess.Exited += OnExited;
                    var runnerExecutable = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "APSIMRunner.exe");
                    runnerProcess.Start(executable: runnerExecutable,
                                        arguments: pipeHandles,
                                        workingDirectory: Directory.GetCurrentDirectory(),
                                        redirectOutput: true,
                                        cancelToken: cancelToken.Token,
                                        writeToConsole: false);

                    // Release the local handles that were created with the above GetClientHandleAsString calls
                    pipeRead.DisposeLocalCopyOfClientHandle();
                    pipeWrite.DisposeLocalCopyOfClientHandle();

                    try
                    {
                        // Get the next job to run.
                        var job = GetJobToRun();

                        while (job != null)
                        {
                            var startTime = DateTime.Now;

                            DummyJob dummy = new DummyJob(job.RunnableJob);
                            if (!(job.RunnableJob is JobRunnerSleepJob))
                            {
                                lock (runningLock)
                                    SimsRunning.Add(dummy);
                            }

                            // Send the job to APSIMRunner.exe - this will run the simulation.
                            PipeUtilities.SendObjectToPipe(pipeWrite, job.JobSentToClient);

                            pipeWrite.WaitForPipeDrain();

                            // Get the output data back from APSIMRunner.exe
                            object response = PipeUtilities.GetObjectFromPipe(pipeRead);
                            while (!(response is JobOutput))
                            {
                                if (response == null)
                                {
                                    throw new Exception("Invalid response from APSIMRunner pipe: response was null");
                                }

                                if (response is ProgressReport progressResponse)
                                {
                                    dummy.Progress = progressResponse.Progress;
                                }

                                response = PipeUtilities.GetObjectFromPipe(pipeRead);
                            }

                            var endJob = response as JobOutput;

                            // Send the output data to storage.
                            endJob?.WriteOutput(job.DataStore);

                            if (!(job.RunnableJob is JobRunnerSleepJob))
                            {
                                lock (runningLock)
                                {
                                    NumJobsCompleted++;
                                    SimsRunning.Remove(dummy);
                                }
                            }

                            // Signal end of job.
                            InvokeJobCompleted(job.RunnableJob,
                                               job.JobManager,
                                               startTime,
                                               endJob?.ErrorMessage);

                            // Get the next job to run.
                            job = GetJobToRun();
                        }
                    }
                    catch (Exception err)
                    {
                        AddException(err);
                    }
                }
        }
        private string ProcessRsvg(string svgFileName)
        {
            var appDir = _optionSettings.RsvgDirectory;

            if (string.IsNullOrWhiteSpace(appDir) || Directory.Exists(appDir))
            {
                return(null);
            }
            var svgInputDir = _optionSettings.SvgDirectory;
            var workingDir  = _optionSettings.CacheDirectory;
            var toolsDir    = _optionSettings.ToolsDirectory;

            var testHandler = new RsvgTestHandler(svgInputDir, workingDir, appDir);

            testHandler.Initialize(svgFileName);
            if (!testHandler.IsInitialized)
            {
                return(null);
            }
            if (File.Exists(testHandler.OutputFile))
            {
                return(testHandler.OutputFile);
            }

            var     outputBuilder = new StringBuilder();
            Process pipeClient    = new Process();

            pipeClient.StartInfo.FileName = _optionSettings.TestRunnerFile;
            pipeClient.StartInfo.RedirectStandardError  = true;
            pipeClient.StartInfo.RedirectStandardOutput = true;
            pipeClient.StartInfo.WindowStyle            = ProcessWindowStyle.Hidden;
            pipeClient.StartInfo.CreateNoWindow         = true;
            pipeClient.StartInfo.UseShellExecute        = false;
            pipeClient.EnableRaisingEvents = false;

            pipeClient.OutputDataReceived += (sender, eventArgs) =>
            {
                if (!string.IsNullOrWhiteSpace(eventArgs.Data))
                {
                    outputBuilder.AppendLine(eventArgs.Data);
                }
            };
            pipeClient.ErrorDataReceived += (sender, eventArgs) =>
            {
                if (!string.IsNullOrWhiteSpace(eventArgs.Data))
                {
                    outputBuilder.AppendLine(eventArgs.Data);
                }
            };

            using (var pipeServer = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable))
            {
                // Pass the client process a handle to the server.
                pipeClient.StartInfo.Arguments = pipeServer.GetClientHandleAsString();
                pipeClient.Start();
                pipeClient.BeginOutputReadLine();
                pipeClient.BeginErrorReadLine();

                pipeServer.DisposeLocalCopyOfClientHandle();

                try
                {
                    // Read user input and send that to the client process.
                    using (StreamWriter writer = new StreamWriter(pipeServer))
                    {
                        writer.AutoFlush = true;
                        // Send a 'sync message' and wait for client to receive it.
                        writer.WriteLine(SvgTestHandler.KeySync);
                        pipeServer.WaitForPipeDrain();
                        // Send the console input to the client process.
                        testHandler.Marshal(writer);
                    }
                }
                catch (IOException ex)
                {
                    // Catch the IOException that is raised if the pipe is broken or disconnected.
                    Trace.TraceError("[Server] Error: {0}", ex.Message);
                }
            }

            var processExited = pipeClient.WaitForExit(WaitTime);

            if (processExited == false) // process is timed out...
            {
                pipeClient.Kill();
                pipeClient.Close();
                return(_optionSettings.CrashImageFile);
            }
            var exitCode = pipeClient.ExitCode;

            //Trace.WriteLine("ExitCode: " + pipeClient.ExitCode);

            pipeClient.Close();
            //Trace.WriteLine("[Server] Client quit. Server terminating.");

            var outputText = outputBuilder.ToString().Trim();

            if (outputText.Length != 0)
            {
                Trace.WriteLine(string.Empty);
                Trace.WriteLine("###***** LibRsvg *****");
                Trace.WriteLine(outputText);
            }

            if (exitCode == ExitSuccess && File.Exists(testHandler.OutputFile))
            {
                return(testHandler.OutputFile);
            }
            if (exitCode == ExitStackOverflow)
            {
                return(_optionSettings.CrashImageFile);
            }
            return(_optionSettings.EmptyImageFile);
        }
    public static async Task ServerPInvokeChecks()
    {
        // calling every API related to server and client to detect any bad PInvokes
        using (AnonymousPipeServerStream server = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.None, 4096))
        {
            Task clientTask = Task.Run(() => StartClient(PipeDirection.In, server.ClientSafePipeHandle));

            Assert.False(server.CanRead);
            Assert.False(server.CanSeek);
            Assert.False(server.CanTimeout);
            Assert.True(server.CanWrite);
            Assert.False(string.IsNullOrWhiteSpace(server.GetClientHandleAsString()));
            Assert.False(server.IsAsync);
            Assert.True(server.IsConnected);
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ||
                RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                Assert.True(server.OutBufferSize > 0);
            }
            else
            {
                Assert.Throws <PlatformNotSupportedException>(() => server.OutBufferSize);
            }
            Assert.Equal(PipeTransmissionMode.Byte, server.ReadMode);
            Assert.NotNull(server.SafePipeHandle);
            Assert.Equal(PipeTransmissionMode.Byte, server.TransmissionMode);

            server.Write(new byte[] { 123 }, 0, 1);
            await server.WriteAsync(new byte[] { 124 }, 0, 1);

            server.Flush();
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                server.WaitForPipeDrain();
            }
            else
            {
                Assert.Throws <PlatformNotSupportedException>(() => server.WaitForPipeDrain());
            }

            await clientTask;
            server.DisposeLocalCopyOfClientHandle();
        }

        using (AnonymousPipeServerStream server = new AnonymousPipeServerStream(PipeDirection.In))
        {
            Task clientTask = Task.Run(() => StartClient(PipeDirection.Out, server.ClientSafePipeHandle));

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                Assert.Equal(4096, server.InBufferSize);
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                Assert.True(server.InBufferSize > 0);
            }
            else
            {
                Assert.Throws <PlatformNotSupportedException>(() => server.InBufferSize);
            }
            byte[] readData = new byte[] { 0, 1 };
            Assert.Equal(1, server.Read(readData, 0, 1));
            Assert.Equal(1, server.ReadAsync(readData, 1, 1).Result);
            Assert.Equal(123, readData[0]);
            Assert.Equal(124, readData[1]);

            await clientTask;
        }
    }
示例#20
0
        static void Main()
        {
            Process pipeClient = new Process();

            pipeClient.StartInfo.FileName = "D:\\Session 2017\\OS\\Barkovskaya\\ping\\ping2\\bin\\Debug\\ping2.exe";

            using (AnonymousPipeServerStream pipeServer =
                       new AnonymousPipeServerStream(PipeDirection.Out,
                                                     HandleInheritability.Inheritable))
            {
                // Show that anonymous pipes do not support Message mode.
                try
                {
                    pipeServer.ReadMode = PipeTransmissionMode.Message;
                }
                catch (NotSupportedException e)
                {
                    Console.WriteLine("[SERVER] Exception:\n    {0}", e.Message);
                }

                // Pass the client process a handle to the server.
                pipeClient.StartInfo.Arguments       = pipeServer.GetClientHandleAsString();
                pipeClient.StartInfo.UseShellExecute = false;
                pipeClient.Start();
                pipeServer.DisposeLocalCopyOfClientHandle();

                try
                {
                    // Read user input and send that to the client process.
                    using (StreamWriter sw = new StreamWriter(pipeServer))
                    {
                        sw.AutoFlush = true;
                        // Send a 'sync message' and wait for client to receive it.
                        sw.WriteLine("SYNC");
                        pipeServer.WaitForPipeDrain();
                        // Send the console input to the client process.
                        // Console.Write("[SERVER] Enter text: ");
                        Ping      p       = new Ping();
                        string    s       = "google.com";
                        PingReply r       = p.Send(s);
                        var       results = "";
                        if (r.Status == IPStatus.Success)
                        {
                            results = "Ping to " + s.ToString() + "[" + r.Address.ToString() + "]" + " Successful"
                                      + " Response delay = " + r.RoundtripTime.ToString() + " ms" + "\n";
                        }
                        else
                        {
                            results = "ERROR PING " + s;
                        }
                        sw.WriteLine(results);
                    }
                }
                // Catch the IOException that is raised if the pipe is broken
                // or disconnected.
                catch (IOException e)
                {
                    Console.WriteLine("[SERVER] Error: {0}", e.Message);
                }
            }

            pipeClient.WaitForExit();
            pipeClient.Close();
            Console.ReadKey();
        }
        async public Task TestAsyncOutputStream_BeginCancelBeginOutputRead()
        {
            using (AnonymousPipeServerStream pipeWrite = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable))
                using (AnonymousPipeServerStream pipeRead = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable))
                {
                    using (Process p = CreateProcess(TestAsyncOutputStream_BeginCancelBeinOutputRead_RemotelyInvokable, $"{pipeWrite.GetClientHandleAsString()} {pipeRead.GetClientHandleAsString()}"))
                    {
                        var dataReceived = new BlockingCollection <int>();

                        p.StartInfo.RedirectStandardOutput = true;
                        p.OutputDataReceived += (s, e) =>
                        {
                            if (e.Data != null)
                            {
                                dataReceived.Add(int.Parse(e.Data));
                            }
                        };

                        // Start child process
                        p.Start();

                        pipeWrite.DisposeLocalCopyOfClientHandle();
                        pipeRead.DisposeLocalCopyOfClientHandle();

                        // Wait child process start
                        Assert.True(await WaitPipeSignal(pipeRead, WaitInMS), "Child process not started");

                        //Start listening and signal client to produce 1,2,3
                        p.BeginOutputReadLine();
                        await pipeWrite.WriteAsync(new byte[1], 0, 1);

                        // Wait child signal produce number 1,2,3
                        Assert.True(await WaitPipeSignal(pipeRead, WaitInMS), "Missing child signal for value 1,2,3");
                        using (CancellationTokenSource cts = new CancellationTokenSource(WaitInMS))
                        {
                            try
                            {
                                List <int> expectedValue123 = new List <int>()
                                {
                                    1, 2, 3
                                };
                                foreach (int value in dataReceived.GetConsumingEnumerable(cts.Token))
                                {
                                    expectedValue123.Remove(value);
                                    if (expectedValue123.Count == 0)
                                    {
                                        break;
                                    }
                                }
                            }
                            catch (OperationCanceledException)
                            {
                                Assert.False(cts.IsCancellationRequested, "Values 1,2,3 not arrived");
                            }
                        }

                        // Cancel and signal child
                        p.CancelOutputRead();
                        await pipeWrite.WriteAsync(new byte[1], 0, 1);

                        // Re-start listening and signal child
                        p.BeginOutputReadLine();
                        await pipeWrite.WriteAsync(new byte[1], 0, 1);

                        // Wait child process close
                        Assert.True(p.WaitForExit(WaitInMS), "Child process didn't close");

                        // Wait for value 7,8,9
                        using (CancellationTokenSource cts = new CancellationTokenSource(WaitInMS))
                        {
                            try
                            {
                                List <int> expectedValue789 = new List <int>()
                                {
                                    7, 8, 9
                                };
                                foreach (int value in dataReceived.GetConsumingEnumerable(cts.Token))
                                {
                                    expectedValue789.Remove(value);
                                    if (expectedValue789.Count == 0)
                                    {
                                        break;
                                    }
                                }
                            }
                            catch (OperationCanceledException)
                            {
                                Assert.False(cts.IsCancellationRequested, "Values 7,8,9 not arrived");
                            }
                        }
                    }
                }
        }
        /// <summary>
        /// Runs a child process, synchronously, with the specified input.
        /// This method should be called by the parent process. It starts the child process, providing it
        /// with specific command line arguments that will allow the child process to support cancellation
        /// and error handling.
        /// The child process should call <see cref="RunAndListenToParentAsync{TInput,TOutput}"/>, provide
        /// it with the command line arguments and the main method that receives the input object and returns
        /// an object of type <typeparamref name="TOutput"/>.
        /// </summary>
        /// <example>
        /// Parent process:
        /// <code>
        /// private async cTask&lt;OutputData&gt; RunInChildProcess(string childProcessName, InputData input, ITracer tracer, CancellationToken cancellationToken)
        /// {
        ///     IChildProcessManager childProcessManager = new ChildProcessManager();
        ///     OutputData output = await childProcessManager.RunChildProcessAsync&lt;OutputData&gt;(childProcessName, input, tracer, cancellationToken);
        ///     return output;
        /// }
        /// </code>
        /// Child process:
        /// <code>
        /// public static void Main(string[] args)
        /// {
        ///     ITracer tracer;
        ///     // Initialize tracer...
        ///
        ///     IChildProcessManager childProcessManager = new ChildProcessManager();
        ///     childProcessManager.RunAndListenToParentAsync&lt;InputData, OutputData&gt;(args, MainFunction, tracer).Wait();
        /// }
        ///
        /// private static OutputData MainFunction(InputData input, CancellationToken cancellationToken)
        /// {
        ///     // ...
        ///
        ///     return output;
        /// }
        /// </code>
        /// </example>
        /// <typeparam name="TOutput">The child process output type</typeparam>
        /// <param name="exePath">The child process' executable file path</param>
        /// <param name="input">The child process input</param>
        /// <param name="cancellationToken">The cancellation token</param>
        /// <exception cref="InvalidOperationException">The child process could not be started</exception>
        /// <exception cref="ChildProcessException">The child process failed - see InnerException for details</exception>
        /// <returns>A <see cref="Task{TResult}"/>, returning the child process output</returns>
        public async Task <TOutput> RunChildProcessAsync <TOutput>(string exePath, object input, CancellationToken cancellationToken)
        {
            this.CurrentStatus = RunChildProcessStatus.Initializing;
            this.tracer.TraceInformation($"Starting to run child process {exePath}");

            // Create a temporary folder for the child process
            string tempFolder = FileSystemExtensions.CreateTempFolder(TempSubFolderName);

            this.tracer.TraceInformation($"Created temporary folder for child process: {tempFolder}");

            try
            {
                // The pipe from the parent to the child is used to pass a cancellation instruction
                // The pipe from the child to the parent is used to pass the child process output
                using (AnonymousPipeServerStream pipeParentToChild = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable))
                {
                    using (AnonymousPipeServerStream pipeChildToParent = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable))
                    {
                        using (Process childProcess = new Process())
                        {
                            // Write the output to the pipe
                            await this.WriteToStream(input, pipeParentToChild, cancellationToken);

                            // Get pipe handles
                            string pipeParentToChildHandle = pipeParentToChild.GetClientHandleAsString();
                            string pipeChildToParentHandle = pipeChildToParent.GetClientHandleAsString();

                            // Prepare command line arguments
                            ChildProcessArguments arguments = new ChildProcessArguments(
                                pipeParentToChildHandle,
                                pipeChildToParentHandle,
                                this.tracer.SessionId,
                                this.tracer.GetCustomProperties(),
                                tempFolder);

                            // Setup the child process
                            childProcess.StartInfo = new ProcessStartInfo(exePath)
                            {
                                Arguments             = ChildProcessArguments.ToCommandLineArguments(arguments),
                                CreateNoWindow        = true,
                                UseShellExecute       = false,
                                RedirectStandardError = true
                            };

                            // Start the child process
                            Stopwatch sw = Stopwatch.StartNew();
                            childProcess.Start();
                            this.tracer.TraceInformation($"Started to run child process '{Path.GetFileName(exePath)}', process ID {childProcess.Id}");
                            this.CurrentStatus = RunChildProcessStatus.WaitingForProcessToExit;
                            this.ChildProcessIds.Add(childProcess.Id);

                            // Dispose the local copy of the client handle
                            pipeParentToChild.DisposeLocalCopyOfClientHandle();
                            pipeChildToParent.DisposeLocalCopyOfClientHandle();

                            // Wait for the child process to finish
                            bool         wasChildTerminatedByParent = false;
                            MemoryStream outputStream = new MemoryStream();
                            using (cancellationToken.Register(() => { this.CancelChildProcess(childProcess, pipeParentToChild, ref wasChildTerminatedByParent); }))
                            {
                                // Read the child's output
                                // We do not use the cancellation token here - we want to wait for the child to gracefully cancel
                                await pipeChildToParent.CopyToAsync(outputStream, 2048, default(CancellationToken));

                                // Ensure the child existed
                                childProcess.WaitForExit();
                            }

                            this.CurrentStatus = RunChildProcessStatus.Finalizing;
                            sw.Stop();
                            this.tracer.TraceInformation($"Process {exePath} completed, duration {sw.ElapsedMilliseconds / 1000}s, exit code {childProcess.ExitCode}");

                            // If the child process was terminated by the parent, throw appropriate exception
                            if (wasChildTerminatedByParent)
                            {
                                throw new ChildProcessTerminatedByParentException();
                            }

                            // If the child process has exited with an error code, throw appropriate exception
                            if (childProcess.ExitCode != 0)
                            {
                                // This read ignores the cancellation token - if there was a cancellation, the process output will contain the appropriate exception
                                outputStream.Seek(0, SeekOrigin.Begin);
                                string processOutput = await this.ReadFromStream <string>(outputStream, default(CancellationToken));

                                throw new ChildProcessFailedException(childProcess.ExitCode, processOutput);
                            }

                            // Read the process result from the stream
                            outputStream.Seek(0, SeekOrigin.Begin);
                            TOutput processResult = await this.ReadFromStream <TOutput>(outputStream, cancellationToken);

                            // Return process result
                            this.CurrentStatus = RunChildProcessStatus.Completed;
                            return(processResult);
                        }
                    }
                }
            }
            catch (Exception)
            {
                this.CurrentStatus = cancellationToken.IsCancellationRequested ? RunChildProcessStatus.Canceled : RunChildProcessStatus.Failed;
                throw;
            }
            finally
            {
                FileSystemExtensions.TryDeleteFolder(tempFolder, this.tracer);
                FileSystemExtensions.CleanupTempFolders(TempSubFolderName, tracer: this.tracer);
            }
        }
 protected override void WaitForChild()
 {
     childInputPipe.DisposeLocalCopyOfClientHandle();
     childOutputPipe.DisposeLocalCopyOfClientHandle();
 }
示例#24
0
        static void Main(string[] args)
        {
            Process pipeClient = new Process();

            pipeClient.StartInfo.FileName  = @"D:\temp\ffmpeg\bin\ffmpeg.exe";
            pipeClient.StartInfo.Arguments =
                @" -y -loglevel warning -loop 1 -f image2pipe -i pipe:.jpg -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100  -c:v libx264 -t 3000 -r 30 -pix_fmt yuvj420p  -g 60 -c:a aac d:\temp\out.mp4";

            using (AnonymousPipeServerStream pipeServer =
                       new AnonymousPipeServerStream(PipeDirection.Out,
                                                     HandleInheritability.Inheritable))
            {
                // Show that anonymous pipes do not support Message mode.
                try
                {
                    Console.WriteLine("[SERVER] Setting ReadMode to \"Message\".");
                    pipeServer.ReadMode = PipeTransmissionMode.Message;
                }
                catch (NotSupportedException e)
                {
                    Console.WriteLine("[SERVER] Exception:\n    {0}", e.Message);
                }

                Console.WriteLine("[SERVER] Current TransmissionMode: {0}.",
                                  pipeServer.TransmissionMode);

                // Pass the client process a handle to the server.
                //pipeClient.StartInfo.Arguments =
                //    pipeServer.GetClientHandleAsString();
                pipeClient.StartInfo.UseShellExecute = false;
                pipeClient.Start();
                pipeServer.DisposeLocalCopyOfClientHandle();

                try
                {
                    // Read user input and send that to the client process.
                    using (StreamWriter sw = new StreamWriter(pipeServer))
                    {
                        sw.AutoFlush = true;
                        // Send a 'sync message' and wait for client to receive it.
                        var    a      = File.ReadAllBytes(@"D:\temp\cover.jpg");
                        Stream stream = new MemoryStream(a);
                        sw.Write(stream);
                        pipeServer.WaitForPipeDrain();

                        // Send the console input to the client process.
                        //Console.Write("[SERVER] Enter text: ");
                        //sw.WriteLine(Console.ReadLine());
                    }
                }

                // Catch the IOException that is raised if the pipe is broken
                // or disconnected.
                catch (IOException e)
                {
                    Console.WriteLine("[SERVER] Error: {0}", e.Message);
                }
            }
            Console.ReadLine();

            pipeClient.WaitForExit();
            pipeClient.Close();
            Console.WriteLine("[SERVER] Client quit. Server terminating.");
        }
 public void DisposeLocalClientHandles()
 {
     _out.DisposeLocalCopyOfClientHandle();
     _in.DisposeLocalCopyOfClientHandle();
 }
示例#26
0
 public void AfterSubProcessStart()
 {
     _writePipeServerStream.DisposeLocalCopyOfClientHandle();
     _readPipeServerStream.DisposeLocalCopyOfClientHandle();
 }
示例#27
0
        /// <summary>
        /// Runs a child process, synchronously, with the specified input.
        /// This method should be called by the parent process. It starts the child process, providing it
        /// with specific command line arguments that will allow the child process to support cancellation
        /// and error handling.
        /// The child process should call <see cref="RunAndListenToParentAsync{TInput,TOutput}"/>, provide
        /// it with the command line arguments and the main method that receives the input object and returns
        /// an object of type <see cref="TOutput"/>.
        /// </summary>
        /// <example>
        /// Parent process:
        /// <code>
        /// private async cTask&lt;OutputData&gt; RunInChildProcess(string childProcessName, InputData input, ITracer tracer, CancellationToken cancellationToken)
        /// {
        ///     IChildProcessManager childProcessManager = new ChildProcessManager();
        ///     OutputData output = await childProcessManager.RunChildProcessAsync&lt;OutputData&gt;(childProcessName, input, tracer, cancellationToken);
        ///     return output;
        /// }
        /// </code>
        /// Child process:
        /// <code>
        /// public static void Main(string[] args)
        /// {
        ///     ITracer tracer;
        ///     // Initialize tracer...
        ///
        ///     IChildProcessManager childProcessManager = new ChildProcessManager();
        ///     childProcessManager.RunAndListenToParentAsync&lt;InputData, OutputData&gt;(args, MainFunction, tracer).Wait();
        /// }
        ///
        /// private static OutputData MainFunction(InputData input, CancellationToken cancellationToken)
        /// {
        ///     // ...
        ///
        ///     return output;
        /// }
        /// </code>
        /// </example>
        /// <typeparam name="TOutput">The child process output type</typeparam>
        /// <param name="exePath">The child process' executable file path</param>
        /// <param name="input">The child process input</param>
        /// <param name="cancellationToken">The cancellation token</param>
        /// <exception cref="InvalidOperationException">The child process could not be started</exception>
        /// <exception cref="ChildProcessException">The child process failed - see InnerException ro details</exception>
        /// <returns>A <see cref="Task{TResult}"/>, returning the child process output</returns>
        public async Task <TOutput> RunChildProcessAsync <TOutput>(string exePath, object input, CancellationToken cancellationToken)
        {
            this.CurrentStatus = RunChildProcessStatus.Initializing;
            this.tracer.TraceInformation($"Starting to run child process {exePath}");

            try
            {
                // The pipe from the parent to the child is used to pass a cancellation instruction
                // The pipe from the child to the parent is used to pass the child process output
                using (AnonymousPipeServerStream pipeParentToChild = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable))
                {
                    using (AnonymousPipeServerStream pipeChildToParent = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable))
                    {
                        using (Process childProcess = new Process())
                        {
                            // Write the output to the pipe
                            await this.WriteToStream(input, pipeParentToChild, cancellationToken);

                            // Get pipe handles
                            string pipeParentToChildHandle = pipeParentToChild.GetClientHandleAsString();
                            string pipeChildToParentHandle = pipeChildToParent.GetClientHandleAsString();

                            // Setup the child process
                            childProcess.StartInfo = new ProcessStartInfo(exePath)
                            {
                                Arguments             = pipeParentToChildHandle + " " + pipeChildToParentHandle + " " + this.tracer.SessionId,
                                CreateNoWindow        = true,
                                UseShellExecute       = false,
                                RedirectStandardError = true
                            };

                            // Start the child process
                            Stopwatch sw = Stopwatch.StartNew();
                            childProcess.Start();
                            this.tracer.TraceInformation($"Started to run child process '{Path.GetFileName(exePath)}', process ID {childProcess.Id}");
                            this.CurrentStatus = RunChildProcessStatus.WaitingForProcessToExit;
                            this.ChildProcessIds.Add(childProcess.Id);

                            // Dispose the local copy of the client handle
                            pipeParentToChild.DisposeLocalCopyOfClientHandle();
                            pipeChildToParent.DisposeLocalCopyOfClientHandle();

                            // Wait for the child process to finish
                            bool         wasChildTerminatedByParent = false;
                            MemoryStream outputStream = new MemoryStream();
                            using (cancellationToken.Register(() => { this.CancelChildProcess(childProcess, pipeParentToChild, ref wasChildTerminatedByParent); }))
                            {
                                // Read the child's output
                                // We do not use the cancellation token here - we want to wait for the child to gracefully cancel
                                await pipeChildToParent.CopyToAsync(outputStream, 2048, default(CancellationToken));

                                // Ensure the child existed
                                childProcess.WaitForExit();
                            }

                            this.CurrentStatus = RunChildProcessStatus.Finalizing;
                            sw.Stop();
                            this.tracer.TraceInformation($"Process {exePath} completed, duration {sw.ElapsedMilliseconds / 1000}s, exit code {childProcess.ExitCode}");

                            // If the child process was terminated by the parent, throw appropriate exception
                            if (wasChildTerminatedByParent)
                            {
                                throw new ChildProcessTerminatedByParentException();
                            }

                            // Read the process result from the stream
                            // This read ignores the cancellation token - if there was a cancellation, the process output will contain the appropriate exception
                            outputStream.Seek(0, SeekOrigin.Begin);
                            ChildProcessResult <TOutput> processResult = await this.ReadFromStream <ChildProcessResult <TOutput> >(outputStream, default(CancellationToken));

                            // Return process result
                            if (processResult == null)
                            {
                                throw new ChildProcessException("The child process returned empty results");
                            }
                            else if (processResult.Exception != null)
                            {
                                throw new ChildProcessException("The child process threw an exception: " + processResult.Exception.Message, processResult.Exception);
                            }

                            this.CurrentStatus = RunChildProcessStatus.Completed;
                            return(processResult.Output);
                        }
                    }
                }
            }
            catch (Exception)
            {
                this.CurrentStatus = cancellationToken.IsCancellationRequested ? RunChildProcessStatus.Canceled : RunChildProcessStatus.Failed;
                throw;
            }
        }
示例#28
0
        public Boolean Run(String clientExecutablePath, ICollection <FileInstruction> instructions)
        {
            lock (this.syncLock)
            {
                if (clientExecutablePath.IsNull())
                {
                    return(false);
                }
                if (instructions.IsNull())
                {
                    return(false);
                }

                var client = new Process();
                client.StartInfo.FileName        = clientExecutablePath;
                client.StartInfo.UseShellExecute = false;

                try
                {
                    using (var server = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable))
                    {
                        server.ReadMode = PipeTransmissionMode.Byte;
                        var pipeId = server.GetClientHandleAsString();

                        // Pass the client process a handle to the server.
                        client.StartInfo.Arguments = pipeId;
                        client.Start();

                        server.DisposeLocalCopyOfClientHandle();

                        try
                        {
                            // Read user input and send that to the client process.
                            using (var writer = new StreamWriter(server))
                            {
                                writer.AutoFlush = true;
                                // Send the sync message and wait for client to receive it.
                                writer.WriteLine(App.SyncMessage);
                                server.WaitForPipeDrain();

                                // Send the current process id.
                                writer.WriteLine(Process.GetCurrentProcess().Id);
                                server.WaitForPipeDrain();

                                // ~~ Information exchange. Send the current process information to the client process. ~~

                                writer.WriteLine(instructions.Count); // First: number of file instructions.
                                server.WaitForPipeDrain();
                                foreach (var item in instructions)
                                {
                                    item.WriteTo(writer);
                                }
                                server.WaitForPipeDrain();
                            }
                        }
                        // Catch the exceptions raised if the pipe is broken or disconnected.
                        catch (IOException e) { return(this.OnError(e)); }
                    }
                    return(true);
                }
                catch (Win32Exception e) { return(this.OnError(e)); }
                catch (ObjectDisposedException e) { return(this.OnError(e)); }
                catch (InvalidOperationException e) { return(this.OnError(e)); }
                catch (ArgumentOutOfRangeException e) { return(this.OnError(e)); }
                catch (ArgumentException e) { return(this.OnError(e)); }
                catch (NotSupportedException e) { return(this.OnError(e)); }
            }
        }