public ApplicationUpdater(ApplicationUpdaterConfig config, CancellationToken cancellationToken = default) { this.cancellationToken = cancellationToken; this.config = ApplicationUpdaterConfigFactory.Create(config); }
public static ApplicationUpdaterConfig Create(ApplicationUpdaterConfig config = null, FileVersionInfo info = null, Assembly assembly = null) { var Args = config ?? new ApplicationUpdaterConfig(); if (info == null) { var module = Process.GetCurrentProcess().MainModule; if (module == null) { throw new NotSupportedException("Can't infer application updater args as the main module for the current process can't be found"); } info = module.FileVersionInfo; } if (assembly == null) { assembly = Assembly.GetEntryAssembly(); } // Infer any arguments from the running executable Args.FullFileName ??= info.FileName; Args.FileName ??= Path.GetFileName(Args.FullFileName); Args.Name ??= Path.GetFileNameWithoutExtension(Args.FileName); Args.Version ??= info.FileVersion; Args.AssetName ??= Args.FileName; Args.CompanyName ??= info.CompanyName; Args.ProductName ??= info.ProductName; Args.Progress ??= new Progress <ProgressModel>(); if (Args.Name == null) { throw new ArgumentNullException(nameof(Args.Name), "Short filename is null"); } Args.InstallPath ??= Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Programs", Args.Name); Args.UpdateSuffix ??= ApplicationUpdaterConfig.DefaultUpdateSuffix; // Get the InstallSharp attribute, which has custom configuration that might not be inferred or passed in manual configuration var attribute = assembly?.GetCustomAttribute <InstallSharpAttribute>(); // Find the application url if not passed if (Args.UpdateUrl == null) { if (!string.IsNullOrWhiteSpace(attribute?.Url)) { // The application url is specified in the InstallSharpAttribute Args.UpdateUrl = attribute.Url; } else { // Try to automatically infer a GitHub url from the application name and company Args.UpdateUrl = "github.com/" + Args.CompanyName.Replace(" ", "") + "/" + Args.Name.Replace(" ", ""); } } // Get a GUID for the program. In order of precendance, it can be specified: // // 1. In the ApplicationUpdateConfig passed to ApplicationUpdater // 2. In the InstallSharpAttribute on the application assembly // 3. In the GuidAttribute on the application assembly // 1. In the ApplicationUpdateConfig passed to ApplicationUpdater if (Args.Guid != Guid.Empty) { return(Args); } // 2. In the InstallSharpAttribute on the application assembly if (!string.IsNullOrWhiteSpace(attribute?.Guid)) { if (!Guid.TryParse(attribute.Guid, out var guid)) { throw new FormatException($"Couldn't parse GUID from InstallSharpAttribute: '{attribute.Guid}'"); } Args.Guid = guid; return(Args); } // 3. In the GuidAttribute on the application assembly var guidAttribute = assembly.GetCustomAttribute <GuidAttribute>(); if (!string.IsNullOrWhiteSpace(guidAttribute?.Value)) { if (!Guid.TryParse(guidAttribute.Value, out var guid)) { throw new FormatException($"Couldn't parse GUID from assembly attribute: '{guidAttribute.Value}'"); } Args.Guid = guid; return(Args); } return(Args); }
public static CommandLineArguments Parse(ApplicationUpdaterConfig config) { var cmd = new CommandLineArguments(); // Default to no setup command unless we can find one cmd.Command = Command.None; var commandLine = config.CommandLine ?? Environment.CommandLine; // Split the command line up into strings we can parse // Args are positional, and exclude any flags (args that start with '/', '+' or '-') cmd.Args = commandLine.Split(" ", StringSplitOptions.RemoveEmptyEntries).Where(x => !IsFlag(x)).Select(x => x.Trim()).ToArray(); // Collect the flags, removing the leading flag characters, then trimming and making lower case for later comparison cmd.Flags = commandLine.Split(" ", StringSplitOptions.RemoveEmptyEntries).Where(IsFlag) .Select(x => x.TrimStart(flagChars).Trim().ToLowerInvariant()) .ToArray(); // If we're executing as *.update.exe, then applying a side-by-side update is inferred var isUpdateExe = config.FileName?.EndsWith(config.UpdateSuffix, StringComparison.OrdinalIgnoreCase); if (isUpdateExe == true) { cmd.Command = Command.ApplyUpdate; } else { // If there is no first argument, or it isn't "setup", then this isn't a setup commandline, so we do nothing. if (cmd.Args.Length == 0) { return(cmd); } if (!cmd.Args[0].Equals(config.CommandLineArgument ?? ApplicationUpdaterConfig.DefaultSetupArg, StringComparison.OrdinalIgnoreCase)) { return(cmd); } if (cmd.Args.Length == 1) { // If the only command was "setup" then we can infer "install" as the command cmd.Command = Command.Install; } else { // Parse the command if (!Enum.TryParse(cmd.Args[1].Trim(), true, out Command command)) { Console.WriteLine($"Unknown command: ${cmd.Args[1].Trim()}"); return(cmd); } cmd.Command = command; } } // Parse optional flag arguments that can exist on any commands foreach (var arg in cmd.Flags) { if (silentArgs.Any(x => x == arg)) { cmd.Silent = true; } else if (launchArgs.Any(x => x == arg)) { cmd.Launch = true; } else if (adminArgs.Any(x => x == arg)) { cmd.Elevate = true; } } // Parse optional positional arguments for specific commands switch (cmd.Command) { case Command.Install: case Command.Update: if (cmd.Args.Length > 2) { cmd.Target = Path.GetFullPath(cmd.Args[2]); } break; } return(cmd); }