/// <summary> /// Runs the specified service using the command console as a user interface. /// </summary> /// <param name="service">The service.</param> /// <param name="runMode">The run mode.</param> /// <param name="defaultLogFormat">The default log format.</param> /// <param name="defaultLoggingLevels">The default logging levels.</param> /// <param name="token">The token.</param> /// <returns> /// An awaitable task. /// </returns> // ReSharper disable once CodeAnnotationAnalyzer public static async Task RunAsync( [NotNull] BaseService service, RunMode runMode = RunMode.Default, [CanBeNull] FormatBuilder defaultLogFormat = null, LoggingLevels defaultLoggingLevels = LoggingLevels.All, CancellationToken token = default(CancellationToken)) { if (service == null) { throw new ArgumentNullException("service"); } if (!ConsoleHelper.IsConsole) { return; } Console.Clear(); Log.SetTrace(validLevels: LoggingLevels.None); Log.SetConsole(defaultLogFormat ?? Log.ShortFormat, defaultLoggingLevels); await Log.Flush(token).ConfigureAwait(false); Impersonator impersonator = null; try { if (runMode.HasFlag(RunMode.Prompt)) { Debug.Assert(service.ServiceName != null); // Whether we start will depend on the selected option in prompt. runMode = runMode.Clear(RunMode.Start, true); Console.Title = ServiceResources.ConsoleConnection_RunAsync_ConfigureTitle + service.ServiceName; bool done = false; do { if (token.IsCancellationRequested) { return; } Dictionary <string, string> options = new Dictionary <string, string> { { "I", ServiceResources.ConsoleConnection_RunAsync_OptionInstall }, { "U", ServiceResources.ConsoleConnection_RunAsync_OptionUninstall }, { "S", ServiceResources.ConsoleConnection_RunAsync_OptionStart }, { "R", ServiceResources.ConsoleConnection_RunAsync_OptionRestart }, { "T", ServiceResources.ConsoleConnection_RunAsync_OptionStop }, { "P", ServiceResources.ConsoleConnection_RunAsync_OptionPause }, { "C", ServiceResources.ConsoleConnection_RunAsync_OptionContinue }, { "Y", ServiceResources.ConsoleConnection_RunAsync_OptionRunCmd }, { "V", ServiceResources.ConsoleConnection_RunAsync_OptionStartCmd }, { "W", ServiceResources.ConsoleConnection_RunAsync_OptionRunCmdNewCredentials }, { "Z", ServiceResources.ConsoleConnection_RunAsync_OptionRunNoInteraction }, { "X", ServiceResources.ConsoleConnection_RunAsync_OptionExit } }; if (!runMode.HasFlag(RunMode.Interactive)) { options.Remove("V"); options.Remove("Y"); options.Remove("W"); } bool isAdmin; string currentUser; try { WindowsIdentity identity = WindowsIdentity.GetCurrent(); currentUser = identity.Name; Debug.Assert(identity != null); WindowsPrincipal principal = new WindowsPrincipal(identity); isAdmin = principal.IsInRole(WindowsBuiltInRole.Administrator); } catch { isAdmin = false; currentUser = null; } if (!string.IsNullOrEmpty(currentUser)) { FormatBuilder fb = new FormatBuilder() .AppendForegroundColor(ConsoleColor.Cyan) .Append("Current User: "******" [Admin]"); } fb.AppendLine().WriteToConsole(); } if (!isAdmin) { options.Remove("I"); options.Remove("U"); } if (Controller.ServiceIsInstalled(service.ServiceName)) { ServiceControllerStatus state = Controller.GetServiceStatus(service.ServiceName); new FormatBuilder() .AppendForegroundColor(ConsoleColor.White) .AppendFormatLine( ServiceResources.ConsoleConnection_RunAsync_ServiceInstalledState, service.ServiceName, state) .AppendResetForegroundColor() .WriteToConsole(); options.Remove("I"); switch (state) { case ServiceControllerStatus.StopPending: case ServiceControllerStatus.Stopped: // Service is stopped or stopping. options.Remove("C"); options.Remove("R"); options.Remove("T"); break; case ServiceControllerStatus.StartPending: case ServiceControllerStatus.ContinuePending: case ServiceControllerStatus.Running: // Service is starting or running. options.Remove("S"); options.Remove("C"); break; case ServiceControllerStatus.PausePending: case ServiceControllerStatus.Paused: // Service is paused or pausing. options.Remove("S"); options.Remove("R"); options.Remove("T"); options.Remove("P"); break; default: // Service is not installed - shouldn't happen. options.Remove("U"); options.Remove("S"); options.Remove("R"); options.Remove("T"); options.Remove("C"); options.Remove("P"); break; } options.Remove("V"); options.Remove("Y"); options.Remove("Z"); } else { // No service installed. options.Remove("U"); options.Remove("S"); options.Remove("R"); options.Remove("T"); options.Remove("P"); options.Remove("C"); } _promptInstall.WriteToConsole( null, // ReSharper disable once PossibleNullReferenceException (_, c) => !string.Equals(c.Tag, "options", StringComparison.CurrentCultureIgnoreCase) ? Resolution.Unknown : options); string key; do { key = Char.ToUpperInvariant(Console.ReadKey(true).KeyChar) .ToString(CultureInfo.InvariantCulture); } while (!options.ContainsKey(key)); try { string userName; string password; switch (key) { case "I": GetUserNamePassword(out userName, out password); service.Install(ConsoleTextWriter.Default, userName, password); Console.Write(ServiceResources.ConsoleConnection_RunAsync_WaitInstall); while (!Controller.ServiceIsInstalled(service.ServiceName)) { await Task.Delay(250, token).ConfigureAwait(false); Console.Write('.'); } Console.WriteLine(ServiceResources.Done); Console.WriteLine(); break; case "U": await service.Uninstall(ConsoleTextWriter.Default, token).ConfigureAwait(false); Console.Write(ServiceResources.ConsoleConnection_RunAsync_WaitUninstall); while (Controller.ServiceIsInstalled(service.ServiceName)) { await Task.Delay(250, token).ConfigureAwait(false); Console.Write('.'); } Console.WriteLine(ServiceResources.Done); Console.WriteLine(); break; case "R": Console.Write(ServiceResources.ConsoleConnection_RunAsync_AttemptingStop); await Controller.StopService(service.ServiceName, token).ConfigureAwait(false); Console.WriteLine(ServiceResources.Done); Console.WriteLine(); Console.Write(ServiceResources.ConsoleConnection_RunAsync_AttemptingStart); await Controller.StartService(service.ServiceName, null, token).ConfigureAwait(false); Console.WriteLine(ServiceResources.Done); Console.WriteLine(); break; case "S": Console.Write(ServiceResources.ConsoleConnection_RunAsync_AttemptingStart); await Controller.StartService(service.ServiceName, null, token).ConfigureAwait(false); Console.WriteLine(ServiceResources.Done); Console.WriteLine(); break; case "T": Console.Write(ServiceResources.ConsoleConnection_RunAsync_AttemptingStop); await Controller.StopService(service.ServiceName, token).ConfigureAwait(false); Console.WriteLine(ServiceResources.Done); Console.WriteLine(); break; case "P": Console.Write(ServiceResources.ConsoleConnection_RunAsync_AttemptingPause); await Controller.PauseService(service.ServiceName, token).ConfigureAwait(false); Console.WriteLine(ServiceResources.Done); break; case "C": Console.Write(ServiceResources.ConsoleConnection_RunAsync_AttemptingContinue); await Controller.ContinueService(service.ServiceName, token).ConfigureAwait(false); Console.WriteLine(ServiceResources.Done); Console.WriteLine(); break; case "V": runMode = runMode.Set(RunMode.Start, true).Set(RunMode.Interactive, true); done = true; break; case "Y": runMode = runMode.Set(RunMode.Interactive, true); done = true; break; case "W": GetUserNamePassword(out userName, out password); if (userName == null) { break; } Debug.Assert(password != null); Impersonator ei = impersonator; impersonator = null; if (ei != null) { ei.Dispose(); } // Run in new security context. impersonator = new Impersonator(userName, password); break; case "Z": runMode = runMode.Set(RunMode.Start, true).Clear(RunMode.Interactive, true); done = true; Console.WriteLine(ServiceResources.ConsoleConnection_RunAsync_RunningNonInteractive); Console.WriteLine( ServiceResources.ConsoleConnection_RunAsync_RunningNonInteractive2); Console.WriteLine(); break; default: return; } } catch (TaskCanceledException) { return; } catch (Exception e) { if (!token.IsCancellationRequested) { Log.Add(e); } } } while (!done); } else if (!runMode.HasFlag(RunMode.Interactive)) { // If we don't show prompt and we're not interactive we should always start the service. runMode = runMode.Set(RunMode.Start, true); } // Create connection Console.Title = ServiceResources.ConsoleConnection_RunAsync_RunningTitle + service.ServiceName; ConsoleConnection connection = new ConsoleConnection(defaultLogFormat, defaultLoggingLevels, token); Guid id = service.Connect(connection); // Combined cancellation tokens. ITokenSource tSource = token.CreateLinked(connection._cancellationTokenSource.Token); try { CancellationToken t = tSource.Token; if (t.IsCancellationRequested) { return; } if (runMode.HasFlag(RunMode.Start)) { // Start the service await service.StartService(ConsoleTextWriter.Default, null, t).ConfigureAwait(false); if (t.IsCancellationRequested) { return; } } if (!runMode.HasFlag(RunMode.Interactive)) { // Wait to be cancelled as nothing to do. await t.WaitHandle; return; } do { // Flush logs await Log.Flush(t).ConfigureAwait(false); if (t.IsCancellationRequested) { break; } WritePrompt(service); try { string commandLine = await Console.In.ReadLineAsync().ConfigureAwait(false); if (!string.IsNullOrWhiteSpace(commandLine)) { bool completed = false; ICancelableTokenSource commandCancellationSource = t.ToCancelable(); CancellationToken commandToken = commandCancellationSource.Token; #pragma warning disable 4014 service.ExecuteAsync(id, commandLine, ConsoleTextWriter.Default, commandToken) .ContinueWith( task => { Debug.Assert(task != null); completed = true; if (task.IsCompleted || task.IsCanceled) { return; } if (task.IsFaulted) { Debug.Assert(task.Exception != null); _errorFormat.WriteToConsoleInstance(null, task.Exception); } }, TaskContinuationOptions.ExecuteSynchronously); #pragma warning restore 4014 while (!completed) { if (!commandCancellationSource.IsCancellationRequested && Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.Escape) { // Cancel command Console.Write(ServiceResources.ConsoleConnection_RunAsync_Cancelling); commandCancellationSource.Cancel(); break; } await Task.Delay(100, token).ConfigureAwait(false); } } } catch (TaskCanceledException) { throw; } catch (Exception e) { if (!t.IsCancellationRequested) { _errorFormat.WriteToConsoleInstance(null, e); } } // Let any async stuff done by the command have a bit of time, also throttle commands. await Task.Delay(500, t).ConfigureAwait(false); } while (!t.IsCancellationRequested); } catch (TaskCanceledException) { } finally { tSource.Dispose(); // ReSharper disable MethodSupportsCancellation Log.Flush().Wait(); // ReSharper restore MethodSupportsCancellation service.Disconnect(id); Console.WriteLine(ServiceResources.ConsoleConnection_RunAsync_PressKeyToExit); Console.ReadKey(true); } } finally { if (impersonator != null) { impersonator.Dispose(); } } }
// Dont link this list public static void Create(Bot.Bot bot) { var imp = new Impersonator(); try { if (bot.UseWindowsUser) { imp.Impersonate(bot.WindowsUserName, "localhost", bot.WindowsUserPassword); } bot.Status = "Create Diablo Clone"; var basepath = Path.GetDirectoryName(bot.Diablo.Location); var clonepath = Path.Combine(bot.DiabloCloneLocation, "Diablo III"); // if diablo base path does not exist stop here! if (basepath != null && !Directory.Exists(basepath)) { bot.Stop(); throw new Exception("Diablo base directory does not exist!"); } // Check if given language is installed on basepath var testpath = Path.Combine(basepath, @"Data_D3\PC\MPQs", General.GetLocale(bot.Diablo.Language)); if (!Directory.Exists(testpath)) { bot.Stop(); throw new Exception($"ERROR: {bot.Diablo.Language} language is not installed (path: {testpath})"); } // if diablo clone does not exist create it if (!Directory.Exists(Path.Combine(clonepath, @"Data_D3\PC\MPQs\Cache"))) { Logger.Instance.Write(bot, "Creating new Diablo Clone"); Directory.CreateDirectory(Path.Combine(clonepath, @"Data_D3\PC\MPQs\Cache")); } // Create Search caches var baseFileCache = new FileListCache(basepath); var cloneFileCache = new FileListCache(clonepath); // Check if all links are made for our clone foreach (var p in baseFileCache.FileList) { try { if (p.Directory && !Directory.Exists(Path.Combine(clonepath.ToLower(), p.Path.ToLower()))) { if (!s_noLinks.Any(n => General.WildcardMatch(n.Source, p.Path))) { Logger.Instance.Write(bot, "NewLink: {0} -> {1}", Path.Combine(clonepath, p.Path), Path.Combine(basepath, p.Path)); //if (!CreateSymbolicLink( Path.Combine(clonepath,p.Path), Path.Combine(basepath,p.Path), 1)) // throw new Exception("Failed to create link!"); Directory.CreateDirectory(Path.Combine(clonepath, p.Path)); } continue; } if (!p.Directory && !File.Exists(Path.Combine(clonepath.ToLower(), p.Path.ToLower()))) { if (!s_noLinks.Any(n => General.WildcardMatch(n.Source, p.Path))) { Logger.Instance.Write(bot, "NewLink: {0} -> {1}", Path.Combine(clonepath, p.Path), Path.Combine(basepath, p.Path)); if (Path.GetExtension(Path.Combine(clonepath, p.Path)).ToLower().Equals(".exe")) { if ( !CreateHardLink(Path.Combine(clonepath, p.Path), Path.Combine(basepath, p.Path), IntPtr.Zero)) { throw new Exception("Failed to create link!"); } } else { if ( !CreateSymbolicLink(Path.Combine(clonepath, p.Path), Path.Combine(basepath, p.Path), 0)) { throw new Exception("Failed to create link!"); } } } } } catch (Exception ex) { Console.WriteLine(ex); } } // Remove links that have no target /* * foreach (var p in cloneFileCache.FileList) * { * try * { * if (p.directory && !Directory.Exists(Path.Combine(basepath, p.Path))) * { * if (!_noLinks.Any(n => General.WildcardMatch(n.Source.ToLower(), p.Path.ToLower()))) * Console.WriteLine("Delete: {0}", p.Path); * continue; * } * * if (!p.directory && !File.Exists(Path.Combine(basepath.ToLower(), p.Path.ToLower()))) * { * if (!_noLinks.Any(n => General.WildcardMatch(n.Source, p.Path))) * Console.WriteLine("Delete: {0}", p.Path); * } * } * catch (Exception ex) * { * Logger.Instance.Write(bot, ex.ToString()); * } * } */ } catch (Exception ex) { bot.Stop(); DebugHelper.Write(bot, "Failed to create clone!"); DebugHelper.Exception(ex); } imp.Dispose(); }