Skip to content

Commit

Permalink
Feature: Added "run" settings to properties window for shortcut files (
Browse files Browse the repository at this point in the history
  • Loading branch information
marcofranzen99 authored Jan 12, 2025
1 parent e9199bd commit 8dcb100
Show file tree
Hide file tree
Showing 15 changed files with 112 additions and 22 deletions.
9 changes: 5 additions & 4 deletions src/Files.App/Data/Items/ListedItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using System.IO;
using System.Text;
using Windows.Storage;
using Windows.Win32.UI.WindowsAndMessaging;

#pragma warning disable CS0618 // Type or member is obsolete

Expand Down Expand Up @@ -526,6 +527,7 @@ public override string Name
public string Arguments { get; set; }
public string WorkingDirectory { get; set; }
public bool RunAsAdmin { get; set; }
public SHOW_WINDOW_CMD ShowWindowCommand { get; set; }
public bool IsUrl { get; set; }
public bool IsSymLink { get; set; }
public override bool IsExecutable => FileExtensionHelpers.IsExecutableFile(TargetPath, true);
Expand Down Expand Up @@ -678,7 +680,7 @@ public string? GitLastCommitFullSha
set => SetProperty(ref _GitLastCommitFullSha, value);
}
}
public sealed class GitShortcutItem : GitItem,IShortcutItem
public sealed class GitShortcutItem : GitItem, IShortcutItem
{
private volatile int statusPropertiesInitialized = 0;
public bool StatusPropertiesInitialized
Expand Down Expand Up @@ -762,6 +764,7 @@ public override string Name
public string Arguments { get; set; }
public string WorkingDirectory { get; set; }
public bool RunAsAdmin { get; set; }
public SHOW_WINDOW_CMD ShowWindowCommand { get; set; }
public bool IsUrl { get; set; }
public bool IsSymLink { get; set; }
public override bool IsExecutable => FileExtensionHelpers.IsExecutableFile(TargetPath, true);
Expand Down Expand Up @@ -800,11 +803,9 @@ public interface IShortcutItem
public string Arguments { get; set; }
public string WorkingDirectory { get; set; }
public bool RunAsAdmin { get; set; }
public SHOW_WINDOW_CMD ShowWindowCommand { get; set; }
public bool IsUrl { get; set; }
public bool IsSymLink { get; set; }

public bool IsExecutable { get; }


}
}
4 changes: 4 additions & 0 deletions src/Files.App/Data/Items/ShellLinkItem.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Files Community
// Licensed under the MIT License.

using Windows.Win32.UI.WindowsAndMessaging;

namespace Files.App.Data.Items
{
public sealed class ShellLinkItem : ShellFileItem
Expand All @@ -15,6 +17,8 @@ public sealed class ShellLinkItem : ShellFileItem

public bool InvalidTarget { get; set; }

public SHOW_WINDOW_CMD ShowWindowCommand { get; set; }

public ShellLinkItem()
{
}
Expand Down
52 changes: 51 additions & 1 deletion src/Files.App/Data/Models/SelectedItemsPropertiesViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Files.Shared.Helpers;
using System.Windows.Input;
using TagLib;
using Windows.Win32.UI.WindowsAndMessaging;

namespace Files.App.Data.Models
{
Expand Down Expand Up @@ -526,7 +527,6 @@ public bool IsItemSelected

public SelectedItemsPropertiesViewModel()
{

}

private bool isSelectedItemImage = false;
Expand Down Expand Up @@ -782,6 +782,56 @@ public bool RunAsAdminEnabled
set => SetProperty(ref runAsAdminEnabled, value);
}

private static readonly IReadOnlyDictionary<SHOW_WINDOW_CMD, string> showWindowCommandTypes = new Dictionary<SHOW_WINDOW_CMD, string>
{
{ SHOW_WINDOW_CMD.SW_NORMAL, Strings.NormalWindow.GetLocalizedResource() },
{ SHOW_WINDOW_CMD.SW_SHOWMINNOACTIVE, Strings.Minimized.GetLocalizedResource() },
{ SHOW_WINDOW_CMD.SW_MAXIMIZE, Strings.Maximized.GetLocalizedResource() }
}.AsReadOnly();

/// <summary>
/// The available show window command types.
/// </summary>
public IReadOnlyDictionary<SHOW_WINDOW_CMD, string> ShowWindowCommandTypes { get => showWindowCommandTypes; }

/// <summary>
/// The localized string of the currently selected ShowWindowCommand.
/// This value can be used for display in the UI.
/// </summary>
public string SelectedShowWindowCommand
{
get => ShowWindowCommandTypes.GetValueOrDefault(ShowWindowCommandEditedValue)!;
set => ShowWindowCommandEditedValue = ShowWindowCommandTypes.First(e => e.Value == value).Key;
}

private SHOW_WINDOW_CMD showWindowCommand;
/// <summary>
/// The current <see cref="SHOW_WINDOW_CMD"/> property of the item.
/// </summary>
public SHOW_WINDOW_CMD ShowWindowCommand
{
get => showWindowCommand;
set
{
if (SetProperty(ref showWindowCommand, value))
ShowWindowCommandEditedValue = value;
}
}

private SHOW_WINDOW_CMD showWindowCommandEditedValue;
/// <summary>
/// The edited <see cref="SHOW_WINDOW_CMD"/> property of the item.
/// </summary>
public SHOW_WINDOW_CMD ShowWindowCommandEditedValue
{
get => showWindowCommandEditedValue;
set
{
if (SetProperty(ref showWindowCommandEditedValue, value))
OnPropertyChanged(nameof(SelectedShowWindowCommand));
}
}

private bool isPropertiesLoaded;
public bool IsPropertiesLoaded
{
Expand Down
9 changes: 3 additions & 6 deletions src/Files.App/Helpers/UI/UIFilesystemHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Text;
using Windows.ApplicationModel.DataTransfer;
using Windows.Storage;
using Windows.Win32.UI.WindowsAndMessaging;

namespace Files.App.Helpers
{
Expand Down Expand Up @@ -245,17 +246,13 @@ public static async Task<bool> HandleShortcutCannotBeCreated(string shortcutName
/// <summary>
/// Updates ListedItem properties for a shortcut
/// </summary>
/// <param name="item"></param>
/// <param name="targetPath"></param>
/// <param name="arguments"></param>
/// <param name="workingDir"></param>
/// <param name="runAsAdmin"></param>
public static void UpdateShortcutItemProperties(IShortcutItem item, string targetPath, string arguments, string workingDir, bool runAsAdmin)
public static void UpdateShortcutItemProperties(IShortcutItem item, string targetPath, string arguments, string workingDir, bool runAsAdmin, SHOW_WINDOW_CMD showWindowCommand)
{
item.TargetPath = Environment.ExpandEnvironmentVariables(targetPath);
item.Arguments = arguments;
item.WorkingDirectory = workingDir;
item.RunAsAdmin = runAsAdmin;
item.ShowWindowCommand = showWindowCommand;
}

public async static Task<StorageCredential> RequestPassword(IPasswordProtectedItem sender)
Expand Down
12 changes: 12 additions & 0 deletions src/Files.App/Strings/en-US/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -1838,6 +1838,18 @@
<data name="CompatibilityRegisterThisProgramForRestart" xml:space="preserve">
<value>Register this program for restart</value>
</data>
<data name="StartWindow" xml:space="preserve">
<value>Start window</value>
</data>
<data name="NormalWindow" xml:space="preserve">
<value>Normal window</value>
</data>
<data name="Minimized" xml:space="preserve">
<value>Minimized</value>
</data>
<data name="Maximized" xml:space="preserve">
<value>Maximized</value>
</data>
<data name="RunAsAdministrator" xml:space="preserve">
<value>Run as administrator</value>
</data>
Expand Down
1 change: 1 addition & 0 deletions src/Files.App/Utils/Shell/ShellFolderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ public static ShellLinkItem GetShellLinkItem(ShellLink linkItem)
{
IsFolder = !string.IsNullOrEmpty(linkItem.TargetPath) && linkItem.Target.IsFolder,
RunAsAdmin = linkItem.RunAsAdministrator,
ShowWindowCommand = (Windows.Win32.UI.WindowsAndMessaging.SHOW_WINDOW_CMD)linkItem.ShowState,
Arguments = linkItem.Arguments,
WorkingDirectory = Environment.ExpandEnvironmentVariables(linkItem.WorkingDirectory),
TargetPath = Environment.ExpandEnvironmentVariables(linkItem.TargetPath)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@ public static async Task<ListedItem> AddFolderAsync(
TargetPath = linkFolder.TargetPath,
Arguments = linkFolder.Arguments,
WorkingDirectory = linkFolder.WorkingDirectory,
RunAsAdmin = linkFolder.RunAsAdmin
RunAsAdmin = linkFolder.RunAsAdmin,
ShowWindowCommand = linkFolder.ShowWindowCommand
};
}
else if (folder is BinStorageFolder binFolder)
Expand Down Expand Up @@ -293,6 +294,7 @@ public static async Task<ListedItem> AddFileAsync(
Arguments = linkFile.Arguments,
WorkingDirectory = linkFile.WorkingDirectory,
RunAsAdmin = linkFile.RunAsAdmin,
ShowWindowCommand = linkFile.ShowWindowCommand,
IsUrl = isUrl,
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,6 @@ CancellationToken cancellationToken
IsSymLink = true
};
}

}
else if (FileExtensionHelpers.IsShortcutOrUrlFile(findData.cFileName))
{
Expand Down Expand Up @@ -351,6 +350,7 @@ CancellationToken cancellationToken
Arguments = shInfo.Arguments,
WorkingDirectory = shInfo.WorkingDirectory,
RunAsAdmin = shInfo.RunAsAdmin,
ShowWindowCommand = shInfo.ShowWindowCommand,
IsUrl = isUrl,
};
}
Expand All @@ -376,6 +376,7 @@ CancellationToken cancellationToken
Arguments = shInfo.Arguments,
WorkingDirectory = shInfo.WorkingDirectory,
RunAsAdmin = shInfo.RunAsAdmin,
ShowWindowCommand = shInfo.ShowWindowCommand,
IsUrl = isUrl,
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Vanara.PInvoke;
using Vanara.Windows.Shell;
using Windows.ApplicationModel.DataTransfer;
using Windows.Win32.UI.WindowsAndMessaging;

namespace Files.App.Utils.Storage
{
Expand Down Expand Up @@ -733,7 +734,7 @@ public static void TryCancelOperation(string operationId)
}
}

public static Task<bool> CreateOrUpdateLinkAsync(string linkSavePath, string targetPath, string arguments = "", string workingDirectory = "", bool runAsAdmin = false)
public static Task<bool> CreateOrUpdateLinkAsync(string linkSavePath, string targetPath, string arguments = "", string workingDirectory = "", bool runAsAdmin = false, SHOW_WINDOW_CMD showWindowCommand = SHOW_WINDOW_CMD.SW_NORMAL)
{
try
{
Expand All @@ -746,6 +747,10 @@ public static Task<bool> CreateOrUpdateLinkAsync(string linkSavePath, string tar
newLink.RunAsAdministrator = runAsAdmin;

newLink.SaveAs(linkSavePath); // Overwrite if exists

// ShowState has to be set after SaveAs has been called, otherwise an UnauthorizedAccessException gets thrown in some cases
newLink.ShowState = (ShowWindowCommand)showWindowCommand;

return Task.FromResult(true);
}
else if (FileExtensionHelpers.IsWebLinkFile(linkSavePath))
Expand Down
4 changes: 4 additions & 0 deletions src/Files.App/Utils/Storage/StorageItems/ShellStorageFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
// Licensed under the MIT License.

using System.Runtime.InteropServices.WindowsRuntime;
using Vanara.PInvoke;
using Windows.Foundation;
using Windows.Storage;
using Windows.Storage.FileProperties;
using Windows.Storage.Streams;
using Windows.Win32.UI.WindowsAndMessaging;
using IO = System.IO;

namespace Files.App.Utils.Storage
Expand All @@ -16,13 +18,15 @@ public sealed class ShortcutStorageFile : ShellStorageFile, IShortcutStorageItem
public string Arguments { get; }
public string WorkingDirectory { get; }
public bool RunAsAdmin { get; }
public SHOW_WINDOW_CMD ShowWindowCommand { get; set; }

public ShortcutStorageFile(ShellLinkItem item) : base(item)
{
TargetPath = item.TargetPath;
Arguments = item.Arguments;
WorkingDirectory = item.WorkingDirectory;
RunAsAdmin = item.RunAsAdmin;
ShowWindowCommand = item.ShowWindowCommand;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Windows.Storage;
using Windows.Storage.FileProperties;
using Windows.Storage.Search;
using Windows.Win32.UI.WindowsAndMessaging;

namespace Files.App.Utils.Storage
{
Expand All @@ -15,13 +16,15 @@ public sealed class ShortcutStorageFolder : ShellStorageFolder, IShortcutStorage
public string Arguments { get; }
public string WorkingDirectory { get; }
public bool RunAsAdmin { get; }
public SHOW_WINDOW_CMD ShowWindowCommand { get; set; }

public ShortcutStorageFolder(ShellLinkItem item) : base(item)
{
TargetPath = item.TargetPath;
Arguments = item.Arguments;
WorkingDirectory = item.WorkingDirectory;
RunAsAdmin = item.RunAsAdmin;
ShowWindowCommand = item.ShowWindowCommand;
}
}

Expand Down
4 changes: 3 additions & 1 deletion src/Files.App/ViewModels/Properties/Items/FileProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public override void GetBaseProperties()
ViewModel.ShortcutItemWorkingDir = shortcutItem.WorkingDirectory;
ViewModel.ShortcutItemWorkingDirVisibility = Item.IsLinkItem || shortcutItem.IsSymLink ? false : true;
ViewModel.ShortcutItemArguments = shortcutItem.Arguments;
ViewModel.ShowWindowCommand = shortcutItem.ShowWindowCommand;
ViewModel.ShortcutItemArgumentsVisibility = Item.IsLinkItem || shortcutItem.IsSymLink ? false : true;

if (isApplication)
Expand Down Expand Up @@ -293,11 +294,12 @@ private async void ViewModel_PropertyChanged(object sender, System.ComponentMode
case nameof(ViewModel.RunAsAdmin):
case nameof(ViewModel.ShortcutItemPath):
case nameof(ViewModel.ShortcutItemWorkingDir):
case nameof(ViewModel.ShowWindowCommand):
case nameof(ViewModel.ShortcutItemArguments):
if (string.IsNullOrWhiteSpace(ViewModel.ShortcutItemPath))
return;

await FileOperationsHelpers.CreateOrUpdateLinkAsync(Item.ItemPath, ViewModel.ShortcutItemPath, ViewModel.ShortcutItemArguments, ViewModel.ShortcutItemWorkingDir, ViewModel.RunAsAdmin);
await FileOperationsHelpers.CreateOrUpdateLinkAsync(Item.ItemPath, ViewModel.ShortcutItemPath, ViewModel.ShortcutItemArguments, ViewModel.ShortcutItemWorkingDir, ViewModel.RunAsAdmin, ViewModel.ShowWindowCommand);

break;
}
Expand Down
14 changes: 8 additions & 6 deletions src/Files.App/ViewModels/Properties/Items/FolderProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public override void GetBaseProperties()
ViewModel.ShortcutItemPath = shortcutItem.TargetPath;
ViewModel.IsShortcutItemPathReadOnly = false;
ViewModel.ShortcutItemWorkingDir = shortcutItem.WorkingDirectory;
ViewModel.ShowWindowCommand = shortcutItem.ShowWindowCommand;
ViewModel.ShortcutItemWorkingDirVisibility = false;
ViewModel.ShortcutItemArguments = shortcutItem.Arguments;
ViewModel.ShortcutItemArgumentsVisibility = false;
Expand Down Expand Up @@ -202,7 +203,7 @@ private async void ViewModel_PropertyChanged(object sender, System.ComponentMode
{
switch (e.PropertyName)
{
case "IsHidden":
case nameof(ViewModel.IsHidden):
if (ViewModel.IsHidden is not null)
{
if ((bool)ViewModel.IsHidden)
Expand All @@ -212,19 +213,20 @@ private async void ViewModel_PropertyChanged(object sender, System.ComponentMode
}
break;

case "IsContentCompressed":
case nameof(ViewModel.IsContentCompressed):
Win32Helper.SetCompressionAttributeIoctl(Item.ItemPath, ViewModel.IsContentCompressed ?? false);
break;

case "ShortcutItemPath":
case "ShortcutItemWorkingDir":
case "ShortcutItemArguments":
case nameof(ViewModel.ShortcutItemPath):
case nameof(ViewModel.ShortcutItemWorkingDir):
case nameof(ViewModel.ShowWindowCommand):
case nameof(ViewModel.ShortcutItemArguments):
var tmpItem = (ShortcutItem)Item;

if (string.IsNullOrWhiteSpace(ViewModel.ShortcutItemPath))
return;

await FileOperationsHelpers.CreateOrUpdateLinkAsync(Item.ItemPath, ViewModel.ShortcutItemPath, ViewModel.ShortcutItemArguments, ViewModel.ShortcutItemWorkingDir, tmpItem.RunAsAdmin);
await FileOperationsHelpers.CreateOrUpdateLinkAsync(Item.ItemPath, ViewModel.ShortcutItemPath, ViewModel.ShortcutItemArguments, ViewModel.ShortcutItemWorkingDir, tmpItem.RunAsAdmin, ViewModel.ShowWindowCommand);
break;
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/Files.App/Views/Properties/ShortcutPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@
Text="{x:Bind ViewModel.ShortcutItemWorkingDirEditedValue, Mode=TwoWay}" />
</Grid>

<settingsuc:SettingsBlockControl Title="{helpers:ResourceString Name=StartWindow}" HorizontalAlignment="Stretch">
<ComboBox ItemsSource="{x:Bind ViewModel.ShowWindowCommandTypes.Values, Mode=OneWay}" SelectedItem="{x:Bind ViewModel.SelectedShowWindowCommand, Mode=TwoWay}" />
</settingsuc:SettingsBlockControl>

<settingsuc:SettingsBlockControl
x:Name="RunAsAdminCheckbox"
Title="{helpers:ResourceString Name=RunAsAdministrator}"
Expand Down
Loading

0 comments on commit 8dcb100

Please sign in to comment.