tgstation-server 6.1.2
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 Microsoft.Extensions.Logging;
10
28
30{
33 {
37 const string DreamDaemonLogsPath = "DreamDaemonLogs";
38
43
48
53
58
63
68
73
78
83
88
93
98
103
108
112 readonly ILoggerFactory loggerFactory;
113
117 readonly ILogger<SessionControllerFactory> logger;
118
123
128
136 async ValueTask PortBindTest(ushort port, EngineType engineType, CancellationToken cancellationToken)
137 {
138 logger.LogTrace("Bind test: {port}", port);
139 try
140 {
141 // GIVE ME THE FUCKING PORT BACK WINDOWS!!!!
142 const int MaxAttempts = 5;
143 for (var i = 0; i < MaxAttempts; ++i)
144 try
145 {
146 SocketExtensions.BindTest(platformIdentifier, port, false, engineType == EngineType.OpenDream);
147 if (i > 0)
148 logger.LogDebug("Clearing the socket took {iterations} attempts :/", i + 1);
149
150 break;
151 }
152 catch (SocketException ex) when (platformIdentifier.IsWindows && ex.SocketErrorCode == SocketError.AddressAlreadyInUse && i < (MaxAttempts - 1))
153 {
154 await asyncDelayer.Delay(TimeSpan.FromSeconds(1), cancellationToken);
155 }
156 }
157 catch (SocketException ex) when (ex.SocketErrorCode == SocketError.AddressAlreadyInUse)
158 {
159 throw new JobException(ErrorCode.GameServerPortInUse, ex);
160 }
161 }
162
199 ILoggerFactory loggerFactory,
200 ILogger<SessionControllerFactory> logger,
202 Api.Models.Instance instance)
203 {
204 this.processExecutor = processExecutor ?? throw new ArgumentNullException(nameof(processExecutor));
205 this.engineManager = engineManager ?? throw new ArgumentNullException(nameof(engineManager));
206 this.topicClientFactory = topicClientFactory ?? throw new ArgumentNullException(nameof(topicClientFactory));
207 this.cryptographySuite = cryptographySuite ?? throw new ArgumentNullException(nameof(cryptographySuite));
208 this.assemblyInformationProvider = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider));
209 this.gameIOManager = gameIOManager ?? throw new ArgumentNullException(nameof(gameIOManager));
210 this.diagnosticsIOManager = diagnosticsIOManager ?? throw new ArgumentNullException(nameof(diagnosticsIOManager));
211 this.chat = chat ?? throw new ArgumentNullException(nameof(chat));
212 this.networkPromptReaper = networkPromptReaper ?? throw new ArgumentNullException(nameof(networkPromptReaper));
213 this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier));
214 this.bridgeRegistrar = bridgeRegistrar ?? throw new ArgumentNullException(nameof(bridgeRegistrar));
215 this.serverPortProvider = serverPortProvider ?? throw new ArgumentNullException(nameof(serverPortProvider));
216 this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
217 this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
218 this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
219 this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
220 this.sessionConfiguration = sessionConfiguration ?? throw new ArgumentNullException(nameof(sessionConfiguration));
221 this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
222 }
223
225 #pragma warning disable CA1506 // TODO: Decomplexify
226 public async ValueTask<ISessionController> LaunchNew(
227 IDmbProvider dmbProvider,
228 IEngineExecutableLock? currentByondLock,
229 DreamDaemonLaunchParameters launchParameters,
230 bool apiValidate,
231 CancellationToken cancellationToken)
232 {
233 logger.LogTrace("Begin session launch...");
234 if (!launchParameters.Port.HasValue)
235 throw new InvalidOperationException("Given port is null!");
236
237 switch (dmbProvider.CompileJob.MinimumSecurityLevel)
238 {
239 case DreamDaemonSecurity.Ultrasafe:
240 break;
241 case DreamDaemonSecurity.Safe:
242 if (launchParameters.SecurityLevel == DreamDaemonSecurity.Ultrasafe)
243 {
244 logger.LogTrace("Boosting security level to minimum of Safe");
245 launchParameters.SecurityLevel = DreamDaemonSecurity.Safe;
246 }
247
248 break;
249 case DreamDaemonSecurity.Trusted:
250 if (launchParameters.SecurityLevel != DreamDaemonSecurity.Trusted)
251 logger.LogTrace("Boosting security level to minimum of Trusted");
252
253 launchParameters.SecurityLevel = DreamDaemonSecurity.Trusted;
254 break;
255 default:
256 throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Invalid DreamDaemonSecurity value: {0}", dmbProvider.CompileJob.MinimumSecurityLevel));
257 }
258
259 // get the byond lock
260 var engineLock = currentByondLock ?? await engineManager.UseExecutables(
261 dmbProvider.EngineVersion,
262 gameIOManager.ConcatPath(dmbProvider.Directory, dmbProvider.DmbName),
263 cancellationToken);
264 try
265 {
266 logger.LogDebug(
267 "Launching session with CompileJob {compileJobId}...",
268 dmbProvider.CompileJob.Id);
269
270 // mad this isn't abstracted but whatever
271 var engineType = dmbProvider.EngineVersion.Engine!.Value;
272 if (engineType == EngineType.Byond)
274
275 await PortBindTest(launchParameters.Port.Value, engineType, cancellationToken);
276
277 string? outputFilePath = null;
278 var preserveLogFile = true;
279
280 var hasStandardOutput = engineLock.HasStandardOutput;
281 if (launchParameters.LogOutput!.Value)
282 {
283 var now = DateTimeOffset.UtcNow;
284 var dateDirectory = diagnosticsIOManager.ConcatPath(DreamDaemonLogsPath, now.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture));
285 await diagnosticsIOManager.CreateDirectory(dateDirectory, cancellationToken);
286 outputFilePath = diagnosticsIOManager.ResolvePath(
288 dateDirectory,
289 $"server-utc-{now.ToString("yyyy-MM-dd-HH-mm-ss", CultureInfo.InvariantCulture)}{(apiValidate ? "-dmapi" : String.Empty)}.log"));
290
291 logger.LogInformation("Logging server output to {path}...", outputFilePath);
292 }
293 else if (!hasStandardOutput)
294 {
295 outputFilePath = gameIOManager.ConcatPath(dmbProvider.Directory, $"{Guid.NewGuid()}.server.log");
296 preserveLogFile = false;
297 }
298
299 var accessIdentifier = cryptographySuite.GetSecureString();
300
301 if (!apiValidate && dmbProvider.CompileJob.DMApiVersion == null)
302 logger.LogDebug("Session will have no DMAPI support!");
303
304 // launch dd
305 var process = await CreateGameServerProcess(
306 dmbProvider,
307 engineLock,
308 launchParameters,
309 accessIdentifier,
310 outputFilePath,
311 apiValidate,
312 cancellationToken);
313
314 try
315 {
316 var chatTrackingContext = chat.CreateTrackingContext();
317
318 try
319 {
320 var runtimeInformation = CreateRuntimeInformation(
321 dmbProvider,
322 chatTrackingContext,
323 launchParameters.SecurityLevel!.Value,
324 launchParameters.Visibility!.Value,
325 apiValidate);
326
327 var reattachInformation = new ReattachInformation(
328 dmbProvider,
329 process,
330 runtimeInformation,
331 accessIdentifier,
332 launchParameters.Port.Value);
333
334 var byondTopicSender = topicClientFactory.CreateTopicClient(
335 TimeSpan.FromMilliseconds(
336 launchParameters.TopicRequestTimeout!.Value));
337
338 var sessionController = new SessionController(
339 reattachInformation,
340 instance,
341 process,
342 engineLock,
343 byondTopicSender,
344 chatTrackingContext,
346 chat,
349 loggerFactory.CreateLogger<SessionController>(),
350 () => LogDDOutput(
351 process,
352 outputFilePath,
353 hasStandardOutput,
354 preserveLogFile,
355 CancellationToken.None), // DCT: None available
356 launchParameters.StartupTimeout,
357 false,
358 apiValidate);
359
360 return sessionController;
361 }
362 catch
363 {
364 chatTrackingContext.Dispose();
365 throw;
366 }
367 }
368 catch
369 {
370 await using (process)
371 {
372 process.Terminate();
373 await process.Lifetime;
374 throw;
375 }
376 }
377 }
378 catch
379 {
380 if (currentByondLock == null)
381 engineLock.Dispose();
382 throw;
383 }
384 }
385#pragma warning restore CA1506
386
388 public async ValueTask<ISessionController?> Reattach(
389 ReattachInformation reattachInformation,
390 CancellationToken cancellationToken)
391 {
392 ArgumentNullException.ThrowIfNull(reattachInformation);
393
394 logger.LogTrace("Begin session reattach...");
395 var byondTopicSender = topicClientFactory.CreateTopicClient(reattachInformation.TopicRequestTimeout);
396 var engineLock = await engineManager.UseExecutables(
397 reattachInformation.Dmb.EngineVersion,
398 null, // Doesn't matter if it's trusted or not on reattach
399 cancellationToken);
400
401 try
402 {
403 logger.LogDebug(
404 "Attaching to session PID: {pid}, CompileJob: {compileJobId}...",
405 reattachInformation.ProcessId,
406 reattachInformation.Dmb.CompileJob.Id);
407
408 var process = processExecutor.GetProcess(reattachInformation.ProcessId);
409 if (process == null)
410 return null;
411
412 try
413 {
414 if (engineLock.PromptsForNetworkAccess)
416
417 var chatTrackingContext = chat.CreateTrackingContext();
418 try
419 {
420 var runtimeInformation = CreateRuntimeInformation(
421 reattachInformation.Dmb,
422 chatTrackingContext,
423 reattachInformation.LaunchSecurityLevel,
424 reattachInformation.LaunchVisibility,
425 false);
426 reattachInformation.SetRuntimeInformation(runtimeInformation);
427
428 var controller = new SessionController(
429 reattachInformation,
430 instance,
431 process,
432 engineLock,
433 byondTopicSender,
434 chatTrackingContext,
436 chat,
439 loggerFactory.CreateLogger<SessionController>(),
440 () => ValueTask.CompletedTask,
441 null,
442 true,
443 false);
444
445 process = null;
446 engineLock = null;
447 chatTrackingContext = null;
448
449 return controller;
450 }
451 catch
452 {
453 chatTrackingContext?.Dispose();
454 throw;
455 }
456 }
457 catch
458 {
459 if (process != null)
460 await process.DisposeAsync();
461
462 throw;
463 }
464 }
465 catch
466 {
467 engineLock?.Dispose();
468 throw;
469 }
470 }
471
483 async ValueTask<IProcess> CreateGameServerProcess(
484 IDmbProvider dmbProvider,
485 IEngineExecutableLock engineLock,
486 DreamDaemonLaunchParameters launchParameters,
487 string accessIdentifier,
488 string? logFilePath,
489 bool apiValidate,
490 CancellationToken cancellationToken)
491 {
492 // important to run on all ports to allow port changing
493 var arguments = engineLock.FormatServerArguments(
494 dmbProvider,
495 new Dictionary<string, string>
496 {
498 { DMApiConstants.ParamServerPort, serverPortProvider.HttpApiPort.ToString(CultureInfo.InvariantCulture) },
499 { DMApiConstants.ParamAccessIdentifier, accessIdentifier },
500 },
501 launchParameters,
502 !engineLock.HasStandardOutput || engineLock.PreferFileLogging
503 ? logFilePath
504 : null);
505
506 var process = processExecutor.LaunchProcess(
507 engineLock.ServerExePath,
508 dmbProvider.Directory,
509 arguments,
510 logFilePath,
511 engineLock.HasStandardOutput,
512 true);
513
514 try
515 {
516 if (!apiValidate)
517 {
519 process.AdjustPriority(true);
520 }
522 process.AdjustPriority(false);
523
524 if (!engineLock.HasStandardOutput)
526
527 // If this isnt a staging DD (From a Deployment), fire off an event
528 if (!apiValidate)
530 EventType.DreamDaemonLaunch,
531 new List<string>
532 {
533 process.Id.ToString(CultureInfo.InvariantCulture),
534 },
535 false,
536 cancellationToken);
537
538 return process;
539 }
540 catch
541 {
542 await using (process)
543 {
544 process.Terminate();
545 await process.Lifetime;
546 throw;
547 }
548 }
549 }
550
560 async ValueTask LogDDOutput(IProcess process, string? outputFilePath, bool cliSupported, bool preserveFile, CancellationToken cancellationToken)
561 {
562 try
563 {
564 string? ddOutput = null;
565 if (cliSupported)
566 ddOutput = (await process.GetCombinedOutput(cancellationToken))!;
567
568 if (ddOutput == null)
569 try
570 {
571 var dreamDaemonLogBytes = await gameIOManager.ReadAllBytes(
572 outputFilePath!,
573 cancellationToken);
574
575 ddOutput = Encoding.UTF8.GetString(dreamDaemonLogBytes);
576 }
577 finally
578 {
579 if (!preserveFile)
580 try
581 {
582 logger.LogTrace("Deleting temporary log file {path}...", outputFilePath);
583 await gameIOManager.DeleteFile(outputFilePath!, cancellationToken);
584 }
585 catch (Exception ex)
586 {
587 // this is expected on OD at time of the support changes.
588 // I've open a change to fix it: https://github.com/space-wizards/RobustToolbox/pull/4501
589 logger.LogWarning(ex, "Failed to delete server log file {outputFilePath}!", outputFilePath);
590 }
591 }
592
593 logger.LogTrace(
594 "Server Output:{newLine}{output}",
595 Environment.NewLine,
596 ddOutput);
597 }
598 catch (Exception ex)
599 {
600 logger.LogWarning(ex, "Error reading server output!");
601 }
602 }
603
614 IDmbProvider dmbProvider,
615 IChatTrackingContext chatTrackingContext,
616 DreamDaemonSecurity securityLevel,
617 DreamDaemonVisibility visibility,
618 bool apiValidateOnly)
619 => new(
620 chatTrackingContext,
621 dmbProvider,
623 instance.Name!,
624 securityLevel,
625 visibility,
627 apiValidateOnly);
628
633 async ValueTask CheckPagerIsNotRunning()
634 {
636 return;
637
638 await using var otherProcess = processExecutor.GetProcessByName("byond");
639 if (otherProcess == null)
640 return;
641
642 var otherUsername = otherProcess.GetExecutingUsername();
643
644 await using var ourProcess = processExecutor.GetCurrentProcess();
645 var ourUsername = ourProcess.GetExecutingUsername();
646
647 if (otherUsername.Equals(ourUsername, StringComparison.Ordinal))
648 throw new JobException(ErrorCode.DreamDaemonPagerRunning);
649 }
650 }
651}
EngineType? Engine
The EngineType.
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. No-op for EngineType.OpenDream.
bool? LogOutput
If process output/error text should be logged.
uint? TopicRequestTimeout
The timeout for sending and receiving BYOND topics in milliseconds.
uint? StartupTimeout
The DreamDaemon startup timeout in seconds.
DreamDaemonSecurity? SecurityLevel
The DreamDaemonSecurity level of DreamDaemon. No-op for EngineType.OpenDream.
Representation of the initial data passed as part of a BridgeCommandType.Startup request.
Constants used for communication with the DMAPI.
const string ParamServerPort
Identifies the Core.IServerPortProvider.HttpApiPort of the server.
const string ParamAccessIdentifier
Identifies the DMApiParameters.AccessIdentifier for the session.
const string ParamApiVersion
Identifies a DMAPI execution with the version as the value.
static readonly Version InteropVersion
The DMAPI InteropVersion being used.
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.
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.
async ValueTask CheckPagerIsNotRunning()
Make sure the BYOND pager is not running.
readonly IPlatformIdentifier platformIdentifier
The IPlatformIdentifier for the SessionControllerFactory.
async ValueTask LogDDOutput(IProcess process, string? outputFilePath, bool cliSupported, bool preserveFile, CancellationToken cancellationToken)
Attempts to log DreamDaemon output.
RuntimeInformation CreateRuntimeInformation(IDmbProvider dmbProvider, IChatTrackingContext chatTrackingContext, DreamDaemonSecurity securityLevel, DreamDaemonVisibility visibility, bool apiValidateOnly)
Create RuntimeInformation.
readonly ICryptographySuite cryptographySuite
The ICryptographySuite for the SessionControllerFactory.
async ValueTask< IProcess > CreateGameServerProcess(IDmbProvider dmbProvider, IEngineExecutableLock engineLock, DreamDaemonLaunchParameters launchParameters, string accessIdentifier, string? logFilePath, bool apiValidate, CancellationToken cancellationToken)
Creates the game server IProcess.
readonly IBridgeRegistrar bridgeRegistrar
The IBridgeRegistrar for the SessionControllerFactory.
async ValueTask PortBindTest(ushort port, EngineType engineType, CancellationToken cancellationToken)
Check if a given port can be bound to.
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.
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 ValueTask< ISessionController > LaunchNew(IDmbProvider dmbProvider, IEngineExecutableLock? currentByondLock, DreamDaemonLaunchParameters launchParameters, bool apiValidate, CancellationToken cancellationToken)
Create a ISessionController from a freshly launch DreamDaemon instance. A ValueTask<TResult> resultin...
SessionControllerFactory(IProcessExecutor processExecutor, IEngineManager engineManager, 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.
readonly IEngineManager engineManager
The IEngineManager for the SessionControllerFactory.
async ValueTask< ISessionController?> Reattach(ReattachInformation reattachInformation, CancellationToken cancellationToken)
Create a ISessionController from an existing DreamDaemon instance. A ValueTask<TResult> resulting in ...
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer 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(IPlatformIdentifier platformIdentifier, ushort port, bool includeIPv6, bool udp)
Attempt to exclusively bind to a given port .
Operation exceptions thrown from the context of a Models.Job.
Definition: JobException.cs:11
DreamDaemonSecurity LaunchSecurityLevel
The DreamDaemonSecurity level DreamDaemon was launched with.
DreamDaemonVisibility LaunchVisibility
The DreamDaemonVisibility DreamDaemon was launched with.
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
EngineVersion EngineVersion
The Api.Models.EngineVersion used to build the .dmb.
Definition: IDmbProvider.cs:30
string Directory
The primary game directory with a trailing directory separator.
Definition: IDmbProvider.cs:20
Models.CompileJob CompileJob
The CompileJob of the .dmb.
Definition: IDmbProvider.cs:25
Represents usage of the two primary BYOND server executables.
string ServerExePath
The full path to the game server executable.
string FormatServerArguments(IDmbProvider dmbProvider, IReadOnlyDictionary< string, string > parameters, DreamDaemonLaunchParameters launchParameters, string? logFilePath)
Return the command line arguments for launching with given launchParameters .
bool HasStandardOutput
If ServerExePath supports being run as a command-line application and outputs log information to be c...
For managing the engine installations.
ValueTask< IEngineExecutableLock > UseExecutables(EngineVersion? requiredVersion, string? trustDmbFullPath, CancellationToken cancellationToken)
Lock the current installation's location and return a IEngineExecutableLock.
Consumes EventTypes and takes the appropriate actions.
ValueTask 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.
ValueTask< byte[]> ReadAllBytes(string path, CancellationToken cancellationToken)
Returns all the contents of a file at path as a byte array.
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 .
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.
void AdjustPriority(bool higher)
Set's the owned global::System.Diagnostics.Process.PriorityClass to a non-normal value.
IProcess GetCurrentProcess()
Get a IProcess representing the running executable.
IProcess? GetProcess(int id)
Get a IProcess by id .
IProcess LaunchProcess(string fileName, string workingDirectory, string arguments, string? fileRedirect=null, bool readStandardHandles=false, bool noShellExecute=false)
Launch a IProcess.
IProcess? GetProcessByName(string name)
Get a IProcess with a given name .
Abstraction over a global::System.Diagnostics.Process.
Definition: IProcess.cs:11
string GetExecutingUsername()
Get the name of the account executing the IProcess.
Task< string?> GetCombinedOutput(CancellationToken cancellationToken)
Get the stderr and stdout output of the IProcess.
Task Delay(TimeSpan timeSpan, CancellationToken cancellationToken)
Create a Task that completes after a given timeSpan .
ErrorCode
Types of Response.ErrorMessageResponses that the API may return.
Definition: ErrorCode.cs:13
DreamDaemonVisibility
The visibility setting for DreamDaemon.
DreamDaemonSecurity
DreamDaemon's security level.
EngineType
The type of engine the codebase is using.
Definition: EngineType.cs:7
EventType
Types of events. Mirror in tgs.dm. Prefer last listed name for script.
Definition: EventType.cs:7