private void CheckHeartbeat(Object source, ElapsedEventArgs e) { if (!HeartbeatReceived) { ClientMsgReceivedHandler?.Invoke(this, "\t\theartbeat timeout"); } else { WriteToClient("echo **HEARTBEAT"); HeartbeatReceived = false; } }
/// <summary> /// Handles messages received from the client. /// </summary> protected virtual void OnClientMsgReceived(string e) { string trimString = e.TrimEnd('\0'); if (trimString.StartsWith("**HEARTBEAT")) { HeartbeatReceived = true; } else { ClientMsgReceivedHandler?.Invoke(this, trimString); } }
/// <summary> /// Launches the paexec.exe service. Calling this method will prompt for elevated credentials because the program runs in two different user contexts. /// </summary> /// <param name="paexec_EXE">The full path to the "paexec.exe" binary.</param> /// <param name="testComputer">The name of the test computer to launch paexec.exe on."</param> /// <param name="elevatedUsername"> /// The username of the elevated account that will be used to launch paexec. Should include the account domain. /// <para/>E.g. <paramref name="elevatedUsername"/> = @"domain\\administrator.account" /// </param> /// <param name="elevatedContext_EXE">The full path to the ElevatedProcess.exe binary.</param> public bool StartService(string paexec_EXE, string testComputer, string elevatedUsername, string elevatedContext_EXE) { string pipeName = Guid.NewGuid().ToString(); try { // configure pipe security PipeSecurity pipeSecurity = new PipeSecurity(); pipeSecurity.AddAccessRule(new PipeAccessRule(elevatedUsername, PipeAccessRights.FullControl, AccessControlType.Allow)); pipeSecurity.AddAccessRule(new PipeAccessRule(pipeUser, PipeAccessRights.FullControl, AccessControlType.Allow)); // launch server first server = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 2, PipeTransmissionMode.Message, PipeOptions.Asynchronous, MaxLen, MaxLen, pipeSecurity) { ReadMode = PipeTransmissionMode.Message }; // this is the admin/elevated process that runs paexec.exe and acts as a pipe client clientProcess = new Process { StartInfo = new ProcessStartInfo(elevatedContext_EXE) { Verb = "RunAs", Arguments = string.Join("", "\"", paexec_EXE, "\" ", pipeName, " \"\\\\", testComputer.Trim(), " -h cmd\"") } }; ClientMsgReceivedHandler?.Invoke(this, "Prompting for elevated credentials needed to launch paexec.exe wrapper.\r\n"); clientProcess.Start(); // will prompt for credentials, due to "RunAs" verb Thread.Sleep(500); // Async await for connection. if shut down flag is set, it will stop ShouldRun = true; serverconnect: while (ShouldRun) { try { IAsyncResult asyncResult = server.BeginWaitForConnection(HandleConnection, server); int waitResult = WaitHandle.WaitAny(new[] { asyncResult.AsyncWaitHandle }); if (waitResult == 0) { server.EndWaitForConnection(asyncResult); IsRunning = true; break; } } catch (Exception) { ClientMsgReceivedHandler?.Invoke(this, "Server connection error. Retrying... \r\n\r\n"); IsRunning = false; server.Close(); continue; } } // after connection is made, await messages over the pipe. try { new Task(ReadFromClientTask).Start(); new Task(WriteToClientTask).Start(); StartHeartbeatTimer(60); ClientMsgReceivedHandler?.Invoke(this, "Connected to paexec.exe wrapper. Redirecting output...\r\n\r\n"); return(true); } catch (Exception) { server.Close(); IsRunning = false; ClientMsgReceivedHandler?.Invoke(this, "Pipe exception. Resetting server... \r\n"); Thread.Sleep(1500); goto serverconnect; } } catch (Exception e) { System.Windows.Forms.MessageBox.Show("Error launching the paexec.exe pipe service. \r\n\r\n" + e.ToString()); if (server.IsConnected) { server.Close(); } return(false); } }