string BuildDesktopShortcut([NotNull] SnapOsShortcutDescription shortcutDescription, string description) { if (shortcutDescription == null) { throw new ArgumentNullException(nameof(shortcutDescription)); } var workingDirectory = Filesystem.PathGetDirectoryName(shortcutDescription.ExeAbsolutePath); switch (DistroType) { case SnapOsDistroType.Ubuntu: return($@"[Desktop Entry] Encoding=UTF-8 Version={shortcutDescription.SnapApp.Version} Type=Application Terminal=false Exec=bash -c 'cd ""{workingDirectory}"" && LD_LIBRARY_PATH=. {shortcutDescription.ExeAbsolutePath}' Icon={shortcutDescription.IconAbsolutePath} Name={shortcutDescription.SnapApp.Id} Comment={description}"); default: return(null); } }
public Task CreateShortcutsForExecutableAsync(SnapOsShortcutDescription shortcutDescription, ILog logger = null, CancellationToken cancellationToken = default) { return(OsImpl.CreateShortcutsForExecutableAsync(shortcutDescription, logger, cancellationToken)); }
public async Task CreateShortcutsForExecutableAsync(SnapOsShortcutDescription shortcutDescription, ILog logger = null, CancellationToken cancellationToken = default) { if (shortcutDescription == null) { throw new ArgumentNullException(nameof(shortcutDescription)); } var exeName = Filesystem.PathGetFileName(shortcutDescription.ExeAbsolutePath); if (Username == null) { _logger?.Error($"Unable to create shortcut because username is null. Executable: {exeName}"); return; } logger?.Info($"Creating shortcuts for executable: {shortcutDescription.ExeAbsolutePath}"); var autoStartEnabled = shortcutDescription.ShortcutLocations.HasFlag(SnapShortcutLocation.Startup); var desktopEnabled = shortcutDescription.ShortcutLocations.HasFlag(SnapShortcutLocation.Desktop); var startMenuEnabled = shortcutDescription.ShortcutLocations.HasFlag(SnapShortcutLocation.StartMenu); var desktopShortcutUtf8Content = BuildDesktopShortcut(shortcutDescription, shortcutDescription.NuspecReader.GetDescription()); if (desktopShortcutUtf8Content == null) { _logger?.Warn( $"Unknown error while building desktop shortcut for exe: {exeName}. Distro: {DistroType}. Maybe unsupported distro?"); return; } var applicationsDirectoryAbsolutePath = Filesystem.PathCombine($"/home/{Username}", ".local/share/applications"); var autoStartDirectoryAbsolutePath = Filesystem.PathCombine($"/home/{Username}", ".config/autostart"); var autoStartShortcutAbsolutePath = Filesystem.PathCombine(autoStartDirectoryAbsolutePath, $"{exeName}.desktop"); var desktopShortcutAbsolutePath = Filesystem.PathCombine(applicationsDirectoryAbsolutePath, $"{exeName}.desktop"); if (startMenuEnabled) { _logger?.Warn("Creating start menu shortcuts is not supported on this OS."); } if (autoStartEnabled) { if (Filesystem.DirectoryCreateIfNotExists(autoStartDirectoryAbsolutePath)) { _logger?.Info($"Created autostart directory: {autoStartDirectoryAbsolutePath}"); } if (Filesystem.FileDeleteIfExists(autoStartShortcutAbsolutePath)) { _logger?.Info($"Deleted existing auto start shortcut: {autoStartShortcutAbsolutePath}"); } _logger?.Info($"Creating autostart shortcut: {autoStartShortcutAbsolutePath}. " + $"Absolute path: {shortcutDescription.ExeAbsolutePath}."); await Filesystem.FileWriteUtf8StringAsync(desktopShortcutUtf8Content, autoStartShortcutAbsolutePath, cancellationToken); _logger?.Info($"Attempting to mark shortcut as trusted: {autoStartShortcutAbsolutePath}."); var trustedSuccess = await OsProcessManager.ChmodExecuteAsync(autoStartShortcutAbsolutePath, cancellationToken); _logger?.Info($"Shortcut marked as trusted: {(trustedSuccess ? "yes" : "no")}"); } if (desktopEnabled) { if (!Filesystem.DirectoryExists(applicationsDirectoryAbsolutePath)) { _logger?.Error($"Applications directory does not exist. Desktop shortcut will not be created. Path: {applicationsDirectoryAbsolutePath}"); goto next; } if (Filesystem.FileDeleteIfExists(desktopShortcutAbsolutePath)) { _logger?.Info($"Deleted existing shortcut: {desktopShortcutAbsolutePath}"); } _logger?.Info($"Creating desktop shortcut: {desktopShortcutAbsolutePath}. " + $"Auto startup: {autoStartEnabled}. " + $"Absolute path: {shortcutDescription.ExeAbsolutePath}."); await Filesystem.FileWriteUtf8StringAsync(desktopShortcutUtf8Content, desktopShortcutAbsolutePath, cancellationToken); _logger?.Info($"Attempting to mark shortcut as trusted: {desktopShortcutAbsolutePath}."); var trustedSuccess = await OsProcessManager.ChmodExecuteAsync(desktopShortcutAbsolutePath, cancellationToken); _logger?.Info($"Shortcut marked as trusted: {(trustedSuccess ? "yes" : "no")}"); } next :; }
async Task InvokePostInstall(SnapApp snapApp, NuspecReader nuspecReader, string baseDirectory, string appDirectory, SemanticVersion currentVersion, bool isInitialInstall, ILog logger = null, CancellationToken cancellationToken = default) { var chmod = !RuntimeInformation.IsOSPlatform(OSPlatform.Windows); var coreRunExeAbsolutePath = _snapOs.Filesystem .PathCombine(baseDirectory, _snapEmbeddedResources.GetCoreRunExeFilenameForSnapApp(snapApp)); var mainExeAbsolutePath = _snapOs.Filesystem .PathCombine(appDirectory, _snapEmbeddedResources.GetCoreRunExeFilenameForSnapApp(snapApp)); var iconAbsolutePath = !RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && snapApp.Target.Icon != null? _snapOs.Filesystem.PathCombine(appDirectory, snapApp.Target.Icon) : null; var snapChannel = snapApp.GetCurrentChannelOrThrow(); logger?.Debug($"{nameof(coreRunExeAbsolutePath)}: {coreRunExeAbsolutePath}"); logger?.Debug($"{nameof(mainExeAbsolutePath)}: {mainExeAbsolutePath}"); logger?.Debug($"{nameof(iconAbsolutePath)}: {iconAbsolutePath}"); async Task ChmodAsync(string exePath) { if (exePath == null) { throw new ArgumentNullException(nameof(exePath)); } logger?.Info($"Attempting to change file permission for executable: {exePath}."); var chmodSuccess = await _snapOs.ProcessManager.ChmodExecuteAsync(exePath, cancellationToken); logger?.Info($"Permissions changed successfully: {(chmodSuccess ? "true" : "false")}."); } if (chmod) { await ChmodAsync(coreRunExeAbsolutePath); await ChmodAsync(mainExeAbsolutePath); } var coreRunExeFilename = _snapOs.Filesystem.PathGetFileName(coreRunExeAbsolutePath); if (!snapApp.Target.Shortcuts.Any()) { logger?.Warn("This application does not specify any shortcut locations."); } else { var shortcutLocations = snapApp.Target.Shortcuts.First(); snapApp.Target.Shortcuts.Skip(1).ForEach(x => shortcutLocations |= x); logger?.Info($"Shortcuts will be created in the following locations: {string.Join(", ", shortcutLocations)}"); try { var shortcutDescription = new SnapOsShortcutDescription { SnapApp = snapApp, UpdateOnly = isInitialInstall == false, NuspecReader = nuspecReader, ShortcutLocations = shortcutLocations, ExeAbsolutePath = coreRunExeAbsolutePath, IconAbsolutePath = iconAbsolutePath }; await _snapOs.CreateShortcutsForExecutableAsync(shortcutDescription, logger, cancellationToken); } catch (Exception e) { logger?.ErrorException($"Exception thrown while creating shortcut for exe: {coreRunExeFilename}", e); } } var snapAppDllAbsolutePath = _snapOs.Filesystem.PathCombine(appDirectory, SnapConstants.SnapAppDllFilename); try { logger?.Info($"Updating {snapAppDllAbsolutePath}. Current channel is: {snapChannel.Name}."); using var snapAppDllAssemblyDefinition = _snapAppWriter.BuildSnapAppAssembly(snapApp); using var snapAPpDllDestinationStream = _snapOs.Filesystem.FileWrite(snapAppDllAbsolutePath); snapAppDllAssemblyDefinition.Write(snapAPpDllDestinationStream); } catch (Exception e) { logger?.ErrorException($"Unknown error updating {snapAppDllAbsolutePath}", e); } var allSnapAwareApps = new List <string> { mainExeAbsolutePath }.Select(x => { var installOrUpdateTxt = isInitialInstall ? "--snapx-installed" : "--snapx-updated"; return(new ProcessStartInfoBuilder(x) .Add(installOrUpdateTxt) .Add(currentVersion.ToNormalizedString())); }) .ToList(); await InvokeSnapApps(allSnapAwareApps, TimeSpan.FromSeconds(15), isInitialInstall, currentVersion, logger, cancellationToken); }