tgstation-server 5.12.7
The /tg/station 13 server suite
Loading...
Searching...
No Matches
SessionControllerFactory.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
3using System.Globalization;
4using System.Net.Sockets;
5using System.Text;
6using System.Threading;
7using System.Threading.Tasks;
8
9using Byond.TopicSender;
10
11using Microsoft.Extensions.Logging;
12
30
32{
35 {
39 const string DreamDaemonLogsPath = "DreamDaemonLogs";
40
45
50
55
60
65
70
75
80
85
90
95
100
105
110
114 readonly ILoggerFactory loggerFactory;
115
119 readonly ILogger<SessionControllerFactory> logger;
120
125
130
136 static string SecurityWord(DreamDaemonSecurity securityLevel)
137 {
138 return securityLevel switch
139 {
140 DreamDaemonSecurity.Safe => "safe",
141 DreamDaemonSecurity.Trusted => "trusted",
142 DreamDaemonSecurity.Ultrasafe => "ultrasafe",
143 _ => throw new ArgumentOutOfRangeException(nameof(securityLevel), securityLevel, String.Format(CultureInfo.InvariantCulture, "Bad DreamDaemon security level: {0}", securityLevel)),
144 };
145 }
146
152 static string VisibilityWord(DreamDaemonVisibility visibility)
153 {
154 return visibility switch
155 {
156 DreamDaemonVisibility.Public => "public",
157 DreamDaemonVisibility.Private => "private",
158 DreamDaemonVisibility.Invisible => "invisible",
159 _ => throw new ArgumentOutOfRangeException(nameof(visibility), visibility, String.Format(CultureInfo.InvariantCulture, "Bad DreamDaemon visibility level: {0}", visibility)),
160 };
161 }
162
167 void PortBindTest(ushort port)
168 {
169 try
170 {
171 logger.LogTrace("Bind test: {port}", port);
172 SocketExtensions.BindTest(port, false);
173 }
174 catch (SocketException ex) when (ex.SocketErrorCode == SocketError.AddressAlreadyInUse)
175 {
176 throw new JobException(ErrorCode.DreamDaemonPortInUse, ex);
177 }
178 }
179
216 ILoggerFactory loggerFactory,
217 ILogger<SessionControllerFactory> logger,
219 Api.Models.Instance instance)
220 {
221 this.processExecutor = processExecutor ?? throw new ArgumentNullException(nameof(processExecutor));
222 this.byond = byond ?? throw new ArgumentNullException(nameof(byond));
223 this.topicClientFactory = topicClientFactory ?? throw new ArgumentNullException(nameof(topicClientFactory));
224 this.cryptographySuite = cryptographySuite ?? throw new ArgumentNullException(nameof(cryptographySuite));
225 this.assemblyInformationProvider = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider));
226 this.gameIOManager = gameIOManager ?? throw new ArgumentNullException(nameof(gameIOManager));
227 this.diagnosticsIOManager = diagnosticsIOManager ?? throw new ArgumentNullException(nameof(diagnosticsIOManager));
228 this.chat = chat ?? throw new ArgumentNullException(nameof(chat));
229 this.networkPromptReaper = networkPromptReaper ?? throw new ArgumentNullException(nameof(networkPromptReaper));
230 this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier));
231 this.bridgeRegistrar = bridgeRegistrar ?? throw new ArgumentNullException(nameof(bridgeRegistrar));
232 this.serverPortProvider = serverPortProvider ?? throw new ArgumentNullException(nameof(serverPortProvider));
233 this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
234 this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
235 this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
236 this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
237 this.sessionConfiguration = sessionConfiguration ?? throw new ArgumentNullException(nameof(sessionConfiguration));
238 this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
239 }
240
242 public async Task<ISessionController> LaunchNew(
243 IDmbProvider dmbProvider,
244 IByondExecutableLock currentByondLock,
245 DreamDaemonLaunchParameters launchParameters,
246 bool apiValidate,
247 CancellationToken cancellationToken)
248 {
249 logger.LogTrace("Begin session launch...");
250 if (!launchParameters.Port.HasValue)
251 throw new InvalidOperationException("Given port is null!");
252 switch (dmbProvider.CompileJob.MinimumSecurityLevel)
253 {
254 case DreamDaemonSecurity.Ultrasafe:
255 break;
256 case DreamDaemonSecurity.Safe:
257 if (launchParameters.SecurityLevel == DreamDaemonSecurity.Ultrasafe)
258 {
259 logger.LogTrace("Boosting security level to minimum of Safe");
260 launchParameters.SecurityLevel = DreamDaemonSecurity.Safe;
261 }
262
263 break;
264 case DreamDaemonSecurity.Trusted:
265 if (launchParameters.SecurityLevel != DreamDaemonSecurity.Trusted)
266 logger.LogTrace("Boosting security level to minimum of Trusted");
267
268 launchParameters.SecurityLevel = DreamDaemonSecurity.Trusted;
269 break;
270 default:
271 throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Invalid DreamDaemonSecurity value: {0}", dmbProvider.CompileJob.MinimumSecurityLevel));
272 }
273
274 // get the byond lock
275 var byondLock = currentByondLock ?? await byond.UseExecutables(
276 Version.Parse(dmbProvider.CompileJob.ByondVersion),
277 gameIOManager.ConcatPath(dmbProvider.Directory, dmbProvider.DmbName),
278 cancellationToken);
279 try
280 {
281 logger.LogDebug(
282 "Launching session with CompileJob {compileJobId}...",
283 dmbProvider.CompileJob.Id);
284
285 PortBindTest(launchParameters.Port.Value);
286 await CheckPagerIsNotRunning(cancellationToken);
287
288 string outputFilePath = null;
289 var preserveLogFile = true;
290 if (launchParameters.LogOutput.Value)
291 {
292 var now = DateTimeOffset.UtcNow;
293 var dateDirectory = diagnosticsIOManager.ConcatPath(DreamDaemonLogsPath, now.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture));
294 await diagnosticsIOManager.CreateDirectory(dateDirectory, cancellationToken);
295 outputFilePath = diagnosticsIOManager.ResolvePath(
297 dateDirectory,
298 $"dd-utc-{now.ToString("yyyy-MM-dd-HH-mm-ss", CultureInfo.InvariantCulture)}{(apiValidate ? "-dmapi" : String.Empty)}.log"));
299
300 logger.LogInformation("Logging DreamDaemon output to {path}...", outputFilePath);
301 }
302 else if (!byondLock.SupportsCli)
303 {
304 outputFilePath = gameIOManager.ConcatPath(dmbProvider.Directory, $"{Guid.NewGuid()}.dd.log");
305 preserveLogFile = false;
306 }
307
308 var accessIdentifier = cryptographySuite.GetSecureString();
309
310 var byondTopicSender = topicClientFactory.CreateTopicClient(
311 TimeSpan.FromMilliseconds(
312 launchParameters.TopicRequestTimeout.Value));
313
314 if (!apiValidate && dmbProvider.CompileJob.DMApiVersion == null)
315 logger.LogDebug("Session will have no DMAPI support!");
316
317 // launch dd
318 var process = await CreateDreamDaemonProcess(
319 dmbProvider,
320 byondTopicSender,
321 byondLock,
322 launchParameters,
323 accessIdentifier,
324 outputFilePath,
325 apiValidate,
326 cancellationToken);
327
328 try
329 {
330 var chatTrackingContext = chat.CreateTrackingContext();
331
332 try
333 {
334 var runtimeInformation = CreateRuntimeInformation(
335 dmbProvider,
336 chatTrackingContext,
337 launchParameters,
338 apiValidate);
339
340 var reattachInformation = new ReattachInformation(
341 dmbProvider,
342 process,
343 runtimeInformation,
344 accessIdentifier,
345 launchParameters.Port.Value);
346
347 var sessionController = new SessionController(
348 reattachInformation,
349 instance,
350 process,
351 byondLock,
352 byondTopicSender,
353 chatTrackingContext,
355 chat,
358 loggerFactory.CreateLogger<SessionController>(),
359 () => LogDDOutput(
360 process,
361 outputFilePath,
362 byondLock.SupportsCli,
363 preserveLogFile,
364 CancellationToken.None), // DCT: None available
365 launchParameters.StartupTimeout,
366 false,
367 apiValidate);
368
369 return sessionController;
370 }
371 catch
372 {
373 chatTrackingContext.Dispose();
374 throw;
375 }
376 }
377 catch
378 {
379 await using (process)
380 {
381 process.Terminate();
382 await process.Lifetime;
383 throw;
384 }
385 }
386 }
387 catch
388 {
389 if (currentByondLock == null)
390 byondLock.Dispose();
391 throw;
392 }
393 }
394
396 public async Task<ISessionController> Reattach(
397 ReattachInformation reattachInformation,
398 CancellationToken cancellationToken)
399 {
400 ArgumentNullException.ThrowIfNull(reattachInformation);
401
402 logger.LogTrace("Begin session reattach...");
403 var byondTopicSender = topicClientFactory.CreateTopicClient(reattachInformation.TopicRequestTimeout);
404 var byondLock = await byond.UseExecutables(
405 Version.Parse(reattachInformation.Dmb.CompileJob.ByondVersion),
406 null, // Doesn't matter if it's trusted or not on reattach
407 cancellationToken);
408
409 try
410 {
411 logger.LogDebug(
412 "Attaching to session PID: {pid}, CompileJob: {compileJobId}...",
413 reattachInformation.ProcessId,
414 reattachInformation.Dmb.CompileJob.Id);
415
416 var process = processExecutor.GetProcess(reattachInformation.ProcessId);
417 if (process == null)
418 return null;
419
420 try
421 {
422 if (!byondLock.SupportsCli)
424
425 var chatTrackingContext = chat.CreateTrackingContext();
426 try
427 {
428 var runtimeInformation = CreateRuntimeInformation(
429 reattachInformation.Dmb,
430 chatTrackingContext,
431 null,
432 false);
433 reattachInformation.SetRuntimeInformation(runtimeInformation);
434
435 var controller = new SessionController(
436 reattachInformation,
437 instance,
438 process,
439 byondLock,
440 byondTopicSender,
441 chatTrackingContext,
443 chat,
446 loggerFactory.CreateLogger<SessionController>(),
447 () => Task.CompletedTask,
448 null,
449 true,
450 false);
451
452 process = null;
453 byondLock = null;
454 chatTrackingContext = null;
455
456 return controller;
457 }
458 catch
459 {
460 chatTrackingContext.Dispose();
461 throw;
462 }
463 }
464 catch
465 {
466 await process.DisposeAsync();
467 throw;
468 }
469 }
470 catch
471 {
472 byondLock.Dispose();
473 throw;
474 }
475 }
476
489 async Task<IProcess> CreateDreamDaemonProcess(
490 IDmbProvider dmbProvider,
491 ITopicClient byondTopicSender,
492 IByondExecutableLock byondLock,
493 DreamDaemonLaunchParameters launchParameters,
494 string accessIdentifier,
495 string logFilePath,
496 bool apiValidate,
497 CancellationToken cancellationToken)
498 {
499 // set command line options
500 // more sanitization here cause it uses the same scheme
501 var parameters = $"{DMApiConstants.ParamApiVersion}={byondTopicSender.SanitizeString(DMApiConstants.InteropVersion.Semver().ToString())}&{byondTopicSender.SanitizeString(DMApiConstants.ParamServerPort)}={serverPortProvider.HttpApiPort}&{byondTopicSender.SanitizeString(DMApiConstants.ParamAccessIdentifier)}={byondTopicSender.SanitizeString(accessIdentifier)}";
502
503 if (!String.IsNullOrEmpty(launchParameters.AdditionalParameters))
504 parameters = $"{parameters}&{launchParameters.AdditionalParameters}";
505
506 // important to run on all ports to allow port changing
507 var arguments = String.Format(
508 CultureInfo.InvariantCulture,
509 "{0} -port {1} -ports 1-65535 {2}-close -verbose -{3} -{4}{5}{6} -params \"{7}\"",
510 dmbProvider.DmbName,
511 launchParameters.Port.Value,
512 launchParameters.AllowWebClient.Value ? "-webclient " : String.Empty,
513 SecurityWord(launchParameters.SecurityLevel.Value),
514 VisibilityWord(launchParameters.Visibility.Value),
515 !byondLock.SupportsCli
516 ? $" -logself -log {logFilePath}"
517 : String.Empty, // DD doesn't output anything if -logself is set???
518 launchParameters.StartProfiler.Value
519 ? " -profile"
520 : String.Empty,
521 parameters);
522
523 var process = await processExecutor.LaunchProcess(
524 byondLock.DreamDaemonPath,
525 dmbProvider.Directory,
526 arguments,
527 logFilePath,
528 byondLock.SupportsCli,
529 true);
530
531 try
532 {
533 if (!apiValidate)
534 {
536 process.AdjustPriority(true);
537 }
539 process.AdjustPriority(false);
540
541 if (!byondLock.SupportsCli)
543
544 // If this isnt a staging DD (From a Deployment), fire off an event
545 if (!apiValidate)
547 EventType.DreamDaemonLaunch,
548 new List<string>
549 {
550 process.Id.ToString(CultureInfo.InvariantCulture),
551 },
552 false,
553 cancellationToken);
554
555 return process;
556 }
557 catch
558 {
559 await using (process)
560 {
561 process.Terminate();
562 await process.Lifetime;
563 throw;
564 }
565 }
566 }
567
577 async Task LogDDOutput(IProcess process, string outputFilePath, bool cliSupported, bool preserveFile, CancellationToken cancellationToken)
578 {
579 try
580 {
581 string ddOutput = null;
582 if (cliSupported)
583 ddOutput = await process.GetCombinedOutput(cancellationToken);
584
585 if (ddOutput == null)
586 try
587 {
588 var dreamDaemonLogBytes = await gameIOManager.ReadAllBytes(
589 outputFilePath,
590 cancellationToken);
591
592 ddOutput = Encoding.UTF8.GetString(dreamDaemonLogBytes);
593 }
594 finally
595 {
596 if (!preserveFile)
597 try
598 {
599 logger.LogTrace("Deleting temporary log file {path}...", outputFilePath);
600 await gameIOManager.DeleteFile(outputFilePath, cancellationToken);
601 }
602 catch (Exception ex)
603 {
604 logger.LogWarning(ex, "Failed to delete DreamDaemon log file {outputFilePath}!", outputFilePath);
605 }
606 }
607
608 logger.LogTrace(
609 "DreamDaemon Output:{newLine}{output}",
610 Environment.NewLine,
611 ddOutput);
612 }
613 catch (Exception ex)
614 {
615 logger.LogWarning(ex, "Error reading DreamDaemon output!");
616 }
617 }
618
628 IDmbProvider dmbProvider,
629 IChatTrackingContext chatTrackingContext,
630 DreamDaemonLaunchParameters launchParameters,
631 bool apiValidateOnly)
632 => new (
633 chatTrackingContext,
634 dmbProvider,
636 instance.Name,
637 launchParameters?.SecurityLevel,
638 launchParameters?.Visibility,
640 apiValidateOnly);
641
647 async Task CheckPagerIsNotRunning(CancellationToken cancellationToken)
648 {
650 return;
651
652 await using var otherProcess = processExecutor.GetProcessByName("byond");
653 if (otherProcess == null)
654 return;
655
656 var otherUsernameTask = otherProcess.GetExecutingUsername(cancellationToken);
657 await using var ourProcess = processExecutor.GetCurrentProcess();
658 var ourUserName = await ourProcess.GetExecutingUsername(cancellationToken);
659 var otherUserName = await otherUsernameTask;
660
661 if (otherUserName.Equals(ourUserName, StringComparison.Ordinal))
662 throw new JobException(ErrorCode.DeploymentPagerRunning);
663 }
664 }
665}
virtual ? long Id
The ID of the entity.
Definition: EntityId.cs:13
Metadata about a server instance.
Definition: Instance.cs:9
virtual ? Version DMApiVersion
The DMAPI Version.
Definition: CompileJob.cs:41
DreamDaemonSecurity? MinimumSecurityLevel
The minimum DreamDaemonSecurity required to run the CompileJob's output.
Definition: CompileJob.cs:34
ushort? Port
The port DreamDaemon uses. This should be publically accessible.
DreamDaemonVisibility? Visibility
The DreamDaemonVisibility level of DreamDaemon.
bool? LogOutput
If process output/error text should be logged.
uint? TopicRequestTimeout
The timeout for sending and receiving BYOND topics in milliseconds.
bool? AllowWebClient
If the BYOND web client can be used to connect to the game server.
uint? StartupTimeout
The DreamDaemon startup timeout in seconds.
bool? StartProfiler
If -profile is passed in on the DreamDaemon command line.
DreamDaemonSecurity? SecurityLevel
The DreamDaemonSecurity level of DreamDaemon.
Representation of the initial data passed as part of a BridgeCommandType.Startup request.
Parameters necessary for duplicating a ISessionController session.
TimeSpan TopicRequestTimeout
The TimeSpan which indicates when topic requests should timeout.
void SetRuntimeInformation(RuntimeInformation runtimeInformation)
Set the RuntimeInformation post construction.
IDmbProvider Dmb
The IDmbProvider used by DreamDaemon.
readonly IEventConsumer eventConsumer
The IEventConsumer for the SessionControllerFactory.
readonly ITopicClientFactory topicClientFactory
The ITopicClientFactory for the SessionControllerFactory.
readonly SessionConfiguration sessionConfiguration
The SessionConfiguration for the SessionControllerFactory.
async Task< ISessionController > LaunchNew(IDmbProvider dmbProvider, IByondExecutableLock currentByondLock, DreamDaemonLaunchParameters launchParameters, bool apiValidate, CancellationToken cancellationToken)
Create a ISessionController from a freshly launch DreamDaemon instance. A Task<TResult> resulting in ...
readonly IServerPortProvider serverPortProvider
The IServerPortProvider for the SessionControllerFactory.
readonly ILoggerFactory loggerFactory
The ILoggerFactory for the SessionControllerFactory.
readonly IProcessExecutor processExecutor
The IProcessExecutor for the SessionControllerFactory.
readonly IIOManager gameIOManager
The IIOManager for the Game directory.
RuntimeInformation CreateRuntimeInformation(IDmbProvider dmbProvider, IChatTrackingContext chatTrackingContext, DreamDaemonLaunchParameters launchParameters, bool apiValidateOnly)
Create RuntimeInformation.
SessionControllerFactory(IProcessExecutor processExecutor, IByondManager byond, ITopicClientFactory topicClientFactory, ICryptographySuite cryptographySuite, IAssemblyInformationProvider assemblyInformationProvider, IIOManager gameIOManager, IIOManager diagnosticsIOManager, IChatManager chat, INetworkPromptReaper networkPromptReaper, IPlatformIdentifier platformIdentifier, IBridgeRegistrar bridgeRegistrar, IServerPortProvider serverPortProvider, IEventConsumer eventConsumer, IAsyncDelayer asyncDelayer, ILoggerFactory loggerFactory, ILogger< SessionControllerFactory > logger, SessionConfiguration sessionConfiguration, Api.Models.Instance instance)
Initializes a new instance of the SessionControllerFactory class.
static string SecurityWord(DreamDaemonSecurity securityLevel)
Change a given securityLevel into the appropriate DreamDaemon command line word.
async Task CheckPagerIsNotRunning(CancellationToken cancellationToken)
Make sure the BYOND pager is not running.
readonly IPlatformIdentifier platformIdentifier
The IPlatformIdentifier for the SessionControllerFactory.
async Task LogDDOutput(IProcess process, string outputFilePath, bool cliSupported, bool preserveFile, CancellationToken cancellationToken)
Attempts to log DreamDaemon output.
readonly ICryptographySuite cryptographySuite
The ICryptographySuite for the SessionControllerFactory.
readonly IBridgeRegistrar bridgeRegistrar
The IBridgeRegistrar for the SessionControllerFactory.
async Task< IProcess > CreateDreamDaemonProcess(IDmbProvider dmbProvider, ITopicClient byondTopicSender, IByondExecutableLock byondLock, DreamDaemonLaunchParameters launchParameters, string accessIdentifier, string logFilePath, bool apiValidate, CancellationToken cancellationToken)
Creates the DreamDaemon IProcess.
const string DreamDaemonLogsPath
Path in Diagnostics folder to DreamDaemon logs.
readonly Api.Models.Instance instance
The Api.Models.Instance for the SessionControllerFactory.
readonly INetworkPromptReaper networkPromptReaper
The INetworkPromptReaper for the SessionControllerFactory.
static string VisibilityWord(DreamDaemonVisibility visibility)
Change a given visibility into the appropriate DreamDaemon command line word.
readonly ILogger< SessionControllerFactory > logger
The ILogger for the SessionControllerFactory.
readonly IChatManager chat
The IChatManager for the SessionControllerFactory.
readonly IAssemblyInformationProvider assemblyInformationProvider
The IAssemblyInformationProvider for the SessionControllerFactory.
async Task< ISessionController > Reattach(ReattachInformation reattachInformation, CancellationToken cancellationToken)
Create a ISessionController from an existing DreamDaemon instance. A Task<TResult> resulting in a new...
void PortBindTest(ushort port)
Check if a given port can be bound to.
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the SessionControllerFactory.
readonly IByondManager byond
The IByondManager for the SessionControllerFactory.
readonly IIOManager diagnosticsIOManager
The IIOManager for the Diagnostics directory.
Configuration options for the game sessions.
bool HighPriorityLiveDreamDaemon
If the public DreamDaemon instances are set to be above normal priority processes.
bool LowPriorityDeploymentProcesses
If the deployment DreamMaker and DreamDaemon instances are set to be below normal priority processes.
Extension methods for the Socket class.
static void BindTest(ushort port, bool includeIPv6)
Attempt to exclusively bind to a given port .
Operation exceptions thrown from the context of a Models.Job.
Definition: JobException.cs:11
Represents usage of the two primary BYOND server executables.
bool SupportsCli
If DreamDaemonPath supports being run as a command-line application.
string DreamDaemonPath
The full path to the DreamDaemon executable.
For managing the BYOND installation.
Task< IByondExecutableLock > UseExecutables(Version requiredVersion, string trustDmbFullPath, CancellationToken cancellationToken)
Lock the current installation's location and return a IByondExecutableLock.
For managing connected chat services.
Definition: IChatManager.cs:15
IChatTrackingContext CreateTrackingContext()
Start tracking Commands.CustomCommands and ChannelRepresentations.
Represents a tracking of dynamic chat json files.
Provides absolute paths to the latest compiled .dmbs.
Definition: IDmbProvider.cs:11
string Directory
The primary game directory with a trailing directory separator.
Definition: IDmbProvider.cs:20
CompileJob CompileJob
The CompileJob of the .dmb.
Definition: IDmbProvider.cs:25
Consumes EventTypes and takes the appropriate actions.
Task HandleEvent(EventType eventType, IEnumerable< string > parameters, bool deploymentPipeline, CancellationToken cancellationToken)
Handle a given eventType .
ITopicClient CreateTopicClient(TimeSpan timeout)
Create a ITopicClient.
Provides access to the server's HttpApiPort.
ushort HttpApiPort
The port the server listens on.
Interface for using filesystems.
Definition: IIOManager.cs:13
string ResolvePath()
Retrieve the full path of the current working directory.
string ConcatPath(params string[] paths)
Combines an array of strings into a path.
Task CreateDirectory(string path, CancellationToken cancellationToken)
Create a directory at path .
Task DeleteFile(string path, CancellationToken cancellationToken)
Deletes a file at path .
Task< byte[]> ReadAllBytes(string path, CancellationToken cancellationToken)
Returns all the contents of a file at path as a byte array.
Contains various cryptographic functions.
string GetSecureString()
Generates a 40-length secure ascii string.
On Windows, DreamDaemon will show an unskippable prompt when using /world/proc/OpenPort()....
void RegisterProcess(IProcess process)
Register a given process for network prompt reaping.
For identifying the current platform.
bool IsWindows
If the current platform is a Windows platform.
Task< IProcess > LaunchProcess(string fileName, string workingDirectory, string arguments=null, string fileRedirect=null, bool readStandardHandles=false, bool noShellExecute=false)
Launch a IProcess.
IProcess GetProcessByName(string name)
Get a IProcess with a given name .
IProcess GetProcess(int id)
Get a IProcess by id .
IProcess GetCurrentProcess()
Get a IProcess representing the running executable.
Abstraction over a global::System.Diagnostics.Process.
Definition: IProcess.cs:11
Task< string > GetCombinedOutput(CancellationToken cancellationToken)
Get the stderr and stdout output of the IProcess.
Task< string > GetExecutingUsername(CancellationToken cancellationToken)
Get the name of the account executing the IProcess.
ErrorCode
Types of Response.ErrorMessageResponses that the API may return.
Definition: ErrorCode.cs:11
DreamDaemonVisibility
The visibility setting for DreamDaemon.
DreamDaemonSecurity
DreamDaemon's security level.
EventType
Types of events. Mirror in tgs.dm.
Definition: EventType.cs:7