mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-02-23 19:49:43 +01:00
Program plugin fully on stylecop (#5964)
This commit is contained in:
@@ -41,7 +41,7 @@ namespace Microsoft.Plugin.Program.UnitTests.Programs
|
||||
public void AllShouldReturnPackagesWithDevelopmentModeWhenCalled()
|
||||
{
|
||||
// Arrange
|
||||
Main._settings = new ProgramPluginSettings();
|
||||
Main.Settings = new ProgramPluginSettings();
|
||||
List<IPackage> packages = new List<IPackage>() { DevelopmentModeApp, PackagedApp };
|
||||
var mock = new Mock<IPackageManager>();
|
||||
mock.Setup(x => x.FindPackagesForCurrentUser()).Returns(packages);
|
||||
@@ -60,7 +60,7 @@ namespace Microsoft.Plugin.Program.UnitTests.Programs
|
||||
public void AllShouldNotReturnPackageFrameworksWhenCalled()
|
||||
{
|
||||
// Arrange
|
||||
Main._settings = new ProgramPluginSettings();
|
||||
Main.Settings = new ProgramPluginSettings();
|
||||
List<IPackage> packages = new List<IPackage>() { FrameworkApp, PackagedApp };
|
||||
var mock = new Mock<IPackageManager>();
|
||||
mock.Setup(x => x.FindPackagesForCurrentUser()).Returns(packages);
|
||||
@@ -79,7 +79,7 @@ namespace Microsoft.Plugin.Program.UnitTests.Programs
|
||||
{
|
||||
// Arrange
|
||||
PackageWrapper invalidPackagedApp = new PackageWrapper();
|
||||
Main._settings = new ProgramPluginSettings();
|
||||
Main.Settings = new ProgramPluginSettings();
|
||||
List<IPackage> packages = new List<IPackage>() { invalidPackagedApp };
|
||||
var mock = new Mock<IPackageManager>();
|
||||
mock.Setup(x => x.FindPackagesForCurrentUser()).Returns(packages);
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Microsoft.Plugin.Program
|
||||
{
|
||||
public class DisabledProgramSource : ProgramSource
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -90,7 +90,8 @@ namespace Microsoft.Plugin.Program.Logger
|
||||
|
||||
innerExceptionNumber++;
|
||||
e = e.InnerException;
|
||||
} while (e != null);
|
||||
}
|
||||
while (e != null);
|
||||
|
||||
logger.Error("------------- END Microsoft.Plugin.Program exception -------------");
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Plugin.Program.Programs;
|
||||
using Microsoft.Plugin.Program.Storage;
|
||||
using Microsoft.PowerToys.Settings.UI.Lib;
|
||||
using Wox.Infrastructure.Logger;
|
||||
using Wox.Infrastructure.Storage;
|
||||
using Wox.Plugin;
|
||||
@@ -19,9 +18,9 @@ namespace Microsoft.Plugin.Program
|
||||
{
|
||||
public class Main : IPlugin, IPluginI18n, IContextMenu, ISavable, IReloadable, IDisposable
|
||||
{
|
||||
internal static ProgramPluginSettings _settings { get; set; }
|
||||
internal static ProgramPluginSettings Settings { get; set; }
|
||||
|
||||
private static bool IsStartupIndexProgramsRequired => _settings.LastIndexTime.AddDays(3) < DateTime.Today;
|
||||
private static bool IsStartupIndexProgramsRequired => Settings.LastIndexTime.AddDays(3) < DateTime.Today;
|
||||
|
||||
private static PluginInitContext _context;
|
||||
|
||||
@@ -34,13 +33,13 @@ namespace Microsoft.Plugin.Program
|
||||
public Main()
|
||||
{
|
||||
_settingsStorage = new PluginJsonStorage<ProgramPluginSettings>();
|
||||
_settings = _settingsStorage.Load();
|
||||
Settings = _settingsStorage.Load();
|
||||
|
||||
// This helper class initializes the file system watchers based on the locations to watch
|
||||
_win32ProgramRepositoryHelper = new Win32ProgramFileSystemWatchers();
|
||||
|
||||
// Initialize the Win32ProgramRepository with the settings object
|
||||
_win32ProgramRepository = new Win32ProgramRepository(_win32ProgramRepositoryHelper._fileSystemWatchers.Cast<IFileSystemWatcherWrapper>().ToList(), new BinaryStorage<IList<Programs.Win32Program>>("Win32"), _settings, _win32ProgramRepositoryHelper._pathsToWatch);
|
||||
_win32ProgramRepository = new Win32ProgramRepository(_win32ProgramRepositoryHelper.FileSystemWatchers.Cast<IFileSystemWatcherWrapper>().ToList(), new BinaryStorage<IList<Programs.Win32Program>>("Win32"), Settings, _win32ProgramRepositoryHelper.PathsToWatch);
|
||||
|
||||
Stopwatch.Normal("|Microsoft.Plugin.Program.Main|Preload programs cost", () =>
|
||||
{
|
||||
@@ -67,7 +66,7 @@ namespace Microsoft.Plugin.Program
|
||||
|
||||
Task.WaitAll(a, b);
|
||||
|
||||
_settings.LastIndexTime = DateTime.Today;
|
||||
Settings.LastIndexTime = DateTime.Today;
|
||||
}
|
||||
|
||||
public void Save()
|
||||
@@ -89,7 +88,7 @@ namespace Microsoft.Plugin.Program
|
||||
|
||||
var result = results1.Concat(results2).Where(r => r != null && r.Score > 0);
|
||||
var maxScore = result.Max(x => x.Score);
|
||||
result = result.Where(x => x.Score > _settings.MinScoreThreshold * maxScore);
|
||||
result = result.Where(x => x.Score > Settings.MinScoreThreshold * maxScore);
|
||||
|
||||
return result.ToList();
|
||||
}
|
||||
@@ -98,12 +97,13 @@ namespace Microsoft.Plugin.Program
|
||||
{
|
||||
_context = context ?? throw new ArgumentNullException(nameof(context));
|
||||
_context.API.ThemeChanged += OnThemeChanged;
|
||||
|
||||
UpdateUWPIconPath(_context.API.GetCurrentTheme());
|
||||
}
|
||||
|
||||
public void OnThemeChanged(Theme _, Theme currentTheme)
|
||||
public void OnThemeChanged(Theme currentTheme, Theme newTheme)
|
||||
{
|
||||
UpdateUWPIconPath(currentTheme);
|
||||
UpdateUWPIconPath(newTheme);
|
||||
}
|
||||
|
||||
public void UpdateUWPIconPath(Theme theme)
|
||||
@@ -121,7 +121,7 @@ namespace Microsoft.Plugin.Program
|
||||
|
||||
Task.WaitAll(t1, t2);
|
||||
|
||||
_settings.LastIndexTime = DateTime.Today;
|
||||
Settings.LastIndexTime = DateTime.Today;
|
||||
}
|
||||
|
||||
public string GetTranslatedPluginTitle()
|
||||
@@ -142,8 +142,7 @@ namespace Microsoft.Plugin.Program
|
||||
}
|
||||
|
||||
var menuOptions = new List<ContextMenuResult>();
|
||||
var program = selectedResult.ContextData as Programs.IProgram;
|
||||
if (program != null)
|
||||
if (selectedResult.ContextData is Programs.IProgram program)
|
||||
{
|
||||
menuOptions = program.ContextMenus(_context.API);
|
||||
}
|
||||
@@ -180,10 +179,6 @@ namespace Microsoft.Plugin.Program
|
||||
{
|
||||
IndexPrograms();
|
||||
}
|
||||
|
||||
public static void UpdateSettings(PowerLauncherSettings _)
|
||||
{
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
@@ -140,7 +140,7 @@
|
||||
</AssemblyAttribute>
|
||||
</ItemGroup>
|
||||
|
||||
<!--<ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\..\..\codeAnalysis\GlobalSuppressions.cs">
|
||||
<Link>GlobalSuppressions.cs</Link>
|
||||
</Compile>
|
||||
@@ -154,5 +154,5 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>-->
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Microsoft.Plugin.Program
|
||||
{
|
||||
@@ -30,29 +29,4 @@ namespace Microsoft.Plugin.Program
|
||||
|
||||
internal const char SuffixSeparator = ';';
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains user added folder location contents as well as all user disabled applications
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Win32 class applications set UniqueIdentifier using their full file path</para>
|
||||
/// <para>UWP class applications set UniqueIdentifier using their Application User Model ID</para>
|
||||
/// <para>Custom user added program sources set UniqueIdentifier using their location</para>
|
||||
/// </remarks>
|
||||
public class ProgramSource
|
||||
{
|
||||
private string name;
|
||||
|
||||
public string Location { get; set; }
|
||||
|
||||
public string Name { get => name ?? new DirectoryInfo(Location).Name; set => name = value; }
|
||||
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
public string UniqueIdentifier { get; set; }
|
||||
}
|
||||
|
||||
public class DisabledProgramSource : ProgramSource
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.IO;
|
||||
|
||||
namespace Microsoft.Plugin.Program
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains user added folder location contents as well as all user disabled applications
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Win32 class applications set UniqueIdentifier using their full file path</para>
|
||||
/// <para>UWP class applications set UniqueIdentifier using their Application User Model ID</para>
|
||||
/// <para>Custom user added program sources set UniqueIdentifier using their location</para>
|
||||
/// </remarks>
|
||||
public class ProgramSource
|
||||
{
|
||||
private string name;
|
||||
|
||||
public string Location { get; set; }
|
||||
|
||||
public string Name { get => name ?? new DirectoryInfo(Location).Name; set => name = value; }
|
||||
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
public string UniqueIdentifier { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,38 +1,15 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.Plugin.Program.Programs.ApplicationActivationHelper
|
||||
{
|
||||
// Reference : https://github.com/MicrosoftEdge/edge-launcher/blob/108e63df0b4cb5cd9d5e45aa7a264690851ec51d/MIcrosoftEdgeLauncherCsharp/Program.cs
|
||||
[Flags]
|
||||
public enum ActivateOptions
|
||||
{
|
||||
None = 0x00000000,
|
||||
DesignMode = 0x00000001,
|
||||
NoErrorUI = 0x00000002,
|
||||
NoSplashScreen = 0x00000004,
|
||||
}
|
||||
|
||||
// ApplicationActivationManager
|
||||
[ComImport]
|
||||
[Guid("2e941141-7f97-4756-ba1d-9decde894a3d")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IApplicationActivationManager
|
||||
{
|
||||
IntPtr ActivateApplication([In] string appUserModelId, [In] string arguments, [In] ActivateOptions options, [Out] out uint processId);
|
||||
|
||||
IntPtr ActivateForFile([In] string appUserModelId, [In] IntPtr /*IShellItemArray* */ itemArray, [In] string verb, [Out] out uint processId);
|
||||
|
||||
IntPtr ActivateForProtocol([In] string appUserModelId, [In] IntPtr /* IShellItemArray* */itemArray, [Out] out uint processId);
|
||||
}
|
||||
|
||||
{
|
||||
// Application Activation Manager Class
|
||||
[ComImport]
|
||||
[ComImport]
|
||||
[Guid("45BA127D-10A8-46EA-8AB7-56EA9078943C")]
|
||||
public class ApplicationActivationManager : IApplicationActivationManager
|
||||
{
|
||||
@@ -0,0 +1,16 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.Plugin.Program.Programs
|
||||
{
|
||||
// Reference : https://stackoverflow.com/questions/32122679/getting-icon-of-modern-windows-app-from-a-desktop-application
|
||||
[Guid("5842a140-ff9f-4166-8f5c-62f5b7b0c781")]
|
||||
[ComImport]
|
||||
public class AppxFactory
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -2,37 +2,37 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using static Microsoft.Plugin.Program.Programs.UWP;
|
||||
|
||||
namespace Microsoft.Plugin.Program.Programs
|
||||
{
|
||||
public static class AppxPackageHelper
|
||||
{
|
||||
// This function returns a list of attributes of applications
|
||||
public static List<IAppxManifestApplication> getAppsFromManifest(IStream stream)
|
||||
{
|
||||
List<IAppxManifestApplication> apps = new List<IAppxManifestApplication>();
|
||||
var appxFactory = new AppxFactory();
|
||||
var reader = ((IAppxFactory)appxFactory).CreateManifestReader(stream);
|
||||
var manifestApps = reader.GetApplications();
|
||||
while (manifestApps.GetHasCurrent())
|
||||
{
|
||||
var manifestApp = manifestApps.GetCurrent();
|
||||
var hr = manifestApp.GetStringValue("AppListEntry", out var appListEntry);
|
||||
_ = CheckHRAndReturnOrThrow(hr, appListEntry);
|
||||
if (appListEntry != "none")
|
||||
{
|
||||
apps.Add(manifestApp);
|
||||
}
|
||||
namespace Microsoft.Plugin.Program.Programs
|
||||
{
|
||||
public static class AppxPackageHelper
|
||||
{
|
||||
// This function returns a list of attributes of applications
|
||||
public static List<IAppxManifestApplication> GetAppsFromManifest(IStream stream)
|
||||
{
|
||||
List<IAppxManifestApplication> apps = new List<IAppxManifestApplication>();
|
||||
var appxFactory = new AppxFactory();
|
||||
var reader = ((IAppxFactory)appxFactory).CreateManifestReader(stream);
|
||||
var manifestApps = reader.GetApplications();
|
||||
|
||||
manifestApps.MoveNext();
|
||||
}
|
||||
while (manifestApps.GetHasCurrent())
|
||||
{
|
||||
var manifestApp = manifestApps.GetCurrent();
|
||||
var hr = manifestApp.GetStringValue("AppListEntry", out var appListEntry);
|
||||
_ = CheckHRAndReturnOrThrow(hr, appListEntry);
|
||||
if (appListEntry != "none")
|
||||
{
|
||||
apps.Add(manifestApp);
|
||||
}
|
||||
|
||||
return apps;
|
||||
manifestApps.MoveNext();
|
||||
}
|
||||
|
||||
return apps;
|
||||
}
|
||||
|
||||
public static T CheckHRAndReturnOrThrow<T>(Hresult hr, T result)
|
||||
@@ -43,71 +43,6 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reference : https://stackoverflow.com/questions/32122679/getting-icon-of-modern-windows-app-from-a-desktop-application
|
||||
[Guid("5842a140-ff9f-4166-8f5c-62f5b7b0c781")]
|
||||
[ComImport]
|
||||
public class AppxFactory
|
||||
{
|
||||
}
|
||||
|
||||
[Guid("BEB94909-E451-438B-B5A7-D79E767B75D8")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IAppxFactory
|
||||
{
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Implements COM Interface")]
|
||||
void _VtblGap0_2(); // skip 2 methods
|
||||
|
||||
IAppxManifestReader CreateManifestReader(IStream inputStream);
|
||||
}
|
||||
|
||||
[Guid("4E1BD148-55A0-4480-A3D1-15544710637C")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IAppxManifestReader
|
||||
{
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Implements COM Interface")]
|
||||
void _VtblGap0_1(); // skip 1 method
|
||||
|
||||
IAppxManifestProperties GetProperties();
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Implements COM Interface")]
|
||||
void _VtblGap1_5(); // skip 5 methods
|
||||
|
||||
IAppxManifestApplicationsEnumerator GetApplications();
|
||||
}
|
||||
|
||||
[Guid("9EB8A55A-F04B-4D0D-808D-686185D4847A")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IAppxManifestApplicationsEnumerator
|
||||
{
|
||||
IAppxManifestApplication GetCurrent();
|
||||
|
||||
bool GetHasCurrent();
|
||||
|
||||
bool MoveNext();
|
||||
}
|
||||
|
||||
[Guid("5DA89BF4-3773-46BE-B650-7E744863B7E8")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IAppxManifestApplication
|
||||
{
|
||||
[PreserveSig]
|
||||
Hresult GetStringValue([MarshalAs(UnmanagedType.LPWStr)] string name, [MarshalAs(UnmanagedType.LPWStr)] out string value);
|
||||
|
||||
[PreserveSig]
|
||||
Hresult GetAppUserModelId([MarshalAs(UnmanagedType.LPWStr)] out string value);
|
||||
}
|
||||
|
||||
[Guid("03FAF64D-F26F-4B2C-AAF7-8FE7789B8BCA")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IAppxManifestProperties
|
||||
{
|
||||
[PreserveSig]
|
||||
Hresult GetBoolValue([MarshalAs(UnmanagedType.LPWStr)] string name, out bool value);
|
||||
|
||||
[PreserveSig]
|
||||
Hresult GetStringValue([MarshalAs(UnmanagedType.LPWStr)] string name, [MarshalAs(UnmanagedType.LPWStr)] out string value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.Plugin.Program.Programs.ApplicationActivationHelper
|
||||
{
|
||||
// Reference : https://github.com/MicrosoftEdge/edge-launcher/blob/108e63df0b4cb5cd9d5e45aa7a264690851ec51d/MIcrosoftEdgeLauncherCsharp/Program.cs
|
||||
[Flags]
|
||||
public enum ActivateOptions
|
||||
{
|
||||
None = 0x00000000,
|
||||
DesignMode = 0x00000001,
|
||||
NoErrorUI = 0x00000002,
|
||||
NoSplashScreen = 0x00000004,
|
||||
}
|
||||
|
||||
// ApplicationActivationManager
|
||||
[ComImport]
|
||||
[Guid("2e941141-7f97-4756-ba1d-9decde894a3d")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IApplicationActivationManager
|
||||
{
|
||||
IntPtr ActivateApplication([In] string appUserModelId, [In] string arguments, [In] ActivateOptions options, [Out] out uint processId);
|
||||
|
||||
IntPtr ActivateForFile([In] string appUserModelId, [In] IntPtr /*IShellItemArray* */ itemArray, [In] string verb, [Out] out uint processId);
|
||||
|
||||
IntPtr ActivateForProtocol([In] string appUserModelId, [In] IntPtr /* IShellItemArray* */itemArray, [Out] out uint processId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
|
||||
namespace Microsoft.Plugin.Program.Programs
|
||||
{
|
||||
[Guid("BEB94909-E451-438B-B5A7-D79E767B75D8")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IAppxFactory
|
||||
{
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Implements COM Interface")]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "Implements COM Interface")]
|
||||
void _VtblGap0_2(); // skip 2 methods
|
||||
|
||||
IAppxManifestReader CreateManifestReader(IStream inputStream);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using static Microsoft.Plugin.Program.Programs.UWP;
|
||||
|
||||
namespace Microsoft.Plugin.Program.Programs
|
||||
{
|
||||
[Guid("5DA89BF4-3773-46BE-B650-7E744863B7E8")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IAppxManifestApplication
|
||||
{
|
||||
[PreserveSig]
|
||||
Hresult GetStringValue([MarshalAs(UnmanagedType.LPWStr)] string name, [MarshalAs(UnmanagedType.LPWStr)] out string value);
|
||||
|
||||
[PreserveSig]
|
||||
Hresult GetAppUserModelId([MarshalAs(UnmanagedType.LPWStr)] out string value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.Plugin.Program.Programs
|
||||
{
|
||||
[Guid("9EB8A55A-F04B-4D0D-808D-686185D4847A")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IAppxManifestApplicationsEnumerator
|
||||
{
|
||||
IAppxManifestApplication GetCurrent();
|
||||
|
||||
bool GetHasCurrent();
|
||||
|
||||
bool MoveNext();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using static Microsoft.Plugin.Program.Programs.UWP;
|
||||
|
||||
namespace Microsoft.Plugin.Program.Programs
|
||||
{
|
||||
[Guid("03FAF64D-F26F-4B2C-AAF7-8FE7789B8BCA")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IAppxManifestProperties
|
||||
{
|
||||
[PreserveSig]
|
||||
Hresult GetBoolValue([MarshalAs(UnmanagedType.LPWStr)] string name, out bool value);
|
||||
|
||||
[PreserveSig]
|
||||
Hresult GetStringValue([MarshalAs(UnmanagedType.LPWStr)] string name, [MarshalAs(UnmanagedType.LPWStr)] out string value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.Plugin.Program.Programs
|
||||
{
|
||||
[Guid("4E1BD148-55A0-4480-A3D1-15544710637C")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IAppxManifestReader
|
||||
{
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Implements COM Interface")]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "Implements COM Interface")]
|
||||
void _VtblGap0_1(); // skip 1 method
|
||||
|
||||
IAppxManifestProperties GetProperties();
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Implements COM Interface")]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "Implements COM Interface")]
|
||||
void _VtblGap1_5(); // skip 5 methods
|
||||
|
||||
IAppxManifestApplicationsEnumerator GetApplications();
|
||||
}
|
||||
}
|
||||
@@ -8,10 +8,10 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
{
|
||||
string RetrieveTargetPath(string path);
|
||||
|
||||
string description { get; set; }
|
||||
string Description { get; set; }
|
||||
|
||||
string Arguments { get; set; }
|
||||
|
||||
bool hasArguments { get; set; }
|
||||
bool HasArguments { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
/// </summary>
|
||||
internal class PackageCatalogWrapper : IPackageCatalog
|
||||
{
|
||||
PackageCatalog _packageCatalog;
|
||||
private PackageCatalog _packageCatalog;
|
||||
|
||||
public PackageCatalogWrapper()
|
||||
{
|
||||
|
||||
@@ -27,14 +27,14 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
{
|
||||
}
|
||||
|
||||
public PackageWrapper(string Name, string FullName, string FamilyName, bool IsFramework, bool IsDevelopmentMode, string InstalledLocation)
|
||||
public PackageWrapper(string name, string fullName, string familyName, bool isFramework, bool isDevelopmentMode, string installedLocation)
|
||||
{
|
||||
this.Name = Name;
|
||||
this.FullName = FullName;
|
||||
this.FamilyName = FamilyName;
|
||||
this.IsFramework = IsFramework;
|
||||
this.IsDevelopmentMode = IsDevelopmentMode;
|
||||
this.InstalledLocation = InstalledLocation;
|
||||
Name = name;
|
||||
FullName = fullName;
|
||||
FamilyName = familyName;
|
||||
IsFramework = isFramework;
|
||||
IsDevelopmentMode = isDevelopmentMode;
|
||||
InstalledLocation = installedLocation;
|
||||
}
|
||||
|
||||
public static PackageWrapper GetWrapperFromPackage(Package package)
|
||||
|
||||
@@ -11,11 +11,11 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
{
|
||||
public class PackageManagerWrapper : IPackageManager
|
||||
{
|
||||
readonly PackageManager packageManager;
|
||||
private readonly PackageManager _packageManager;
|
||||
|
||||
public PackageManagerWrapper()
|
||||
{
|
||||
packageManager = new PackageManager();
|
||||
_packageManager = new PackageManager();
|
||||
}
|
||||
|
||||
public IEnumerable<IPackage> FindPackagesForCurrentUser()
|
||||
@@ -26,7 +26,7 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
if (user != null)
|
||||
{
|
||||
var id = user.Value;
|
||||
var m = this.packageManager.FindPackagesForUser(id);
|
||||
var m = _packageManager.FindPackagesForUser(id);
|
||||
foreach (Package p in m)
|
||||
{
|
||||
packages.Add(PackageWrapper.GetWrapperFromPackage(p));
|
||||
|
||||
@@ -22,8 +22,9 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Matching COM")]
|
||||
private struct WIN32_FIND_DATAW
|
||||
{
|
||||
{
|
||||
public uint dwFileAttributes;
|
||||
public long ftCreationTime;
|
||||
public long ftLastAccessTime;
|
||||
@@ -58,7 +59,7 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
[ComImport]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[Guid("000214F9-0000-0000-C000-000000000046")]
|
||||
interface IShellLinkW
|
||||
private interface IShellLinkW
|
||||
{
|
||||
/// <summary>Retrieves the path and file name of a Shell link object</summary>
|
||||
void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, ref WIN32_FIND_DATAW pfd, SLGP_FLAGS fFlags);
|
||||
@@ -122,12 +123,12 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
}
|
||||
|
||||
// Contains the description of the app
|
||||
public string description { get; set; } = string.Empty;
|
||||
public string Description { get; set; } = string.Empty;
|
||||
|
||||
// Contains the arguments to the app
|
||||
public string Arguments { get; set; } = string.Empty;
|
||||
|
||||
public bool hasArguments { get; set; } = false;
|
||||
public bool HasArguments { get; set; } = false;
|
||||
|
||||
// Retrieve the target path using Shell Link
|
||||
public string RetrieveTargetPath(string path)
|
||||
@@ -160,7 +161,7 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
{
|
||||
buffer = new StringBuilder(MAX_PATH);
|
||||
((IShellLinkW)link).GetDescription(buffer, MAX_PATH);
|
||||
description = buffer.ToString();
|
||||
Description = buffer.ToString();
|
||||
|
||||
StringBuilder argumentBuffer = new StringBuilder(MAX_PATH);
|
||||
((IShellLinkW)link).GetArguments(argumentBuffer, argumentBuffer.Capacity);
|
||||
@@ -169,7 +170,7 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
// Set variable to true if the program takes in any arguments
|
||||
if (argumentBuffer.Length != 0)
|
||||
{
|
||||
hasArguments = true;
|
||||
HasArguments = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,10 +60,10 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
{
|
||||
var apps = new List<UWPApplication>();
|
||||
|
||||
List<IAppxManifestApplication> _apps = AppxPackageHelper.getAppsFromManifest(stream);
|
||||
foreach (var _app in _apps)
|
||||
List<IAppxManifestApplication> appsViaManifests = AppxPackageHelper.GetAppsFromManifest(stream);
|
||||
foreach (var appInManifest in appsViaManifests)
|
||||
{
|
||||
var app = new UWPApplication(_app, this);
|
||||
var app = new UWPApplication(appInManifest, this);
|
||||
apps.Add(app);
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
}).ToArray();
|
||||
|
||||
var updatedListWithoutDisabledApps = applications
|
||||
.Where(t1 => !Main._settings.DisabledProgramSources
|
||||
.Where(t1 => !Main.Settings.DisabledProgramSources
|
||||
.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier))
|
||||
.Select(x => x);
|
||||
|
||||
|
||||
@@ -237,7 +237,7 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
|
||||
DisplayName = ResourceFromPri(package.FullName, DisplayName);
|
||||
Description = ResourceFromPri(package.FullName, Description);
|
||||
this.logoUri = LogoUriFromManifest(manifestApp);
|
||||
logoUri = LogoUriFromManifest(manifestApp);
|
||||
|
||||
Enabled = true;
|
||||
CanRunElevated = IfApplicationcanRunElevated();
|
||||
@@ -354,11 +354,11 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
{
|
||||
if (theme == Theme.Light || theme == Theme.HighContrastWhite)
|
||||
{
|
||||
LogoPath = LogoPathFromUri(this.logoUri, "contrast-white");
|
||||
LogoPath = LogoPathFromUri(logoUri, "contrast-white");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogoPath = LogoPathFromUri(this.logoUri, "contrast-black");
|
||||
LogoPath = LogoPathFromUri(logoUri, "contrast-black");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
public bool hasArguments { get; set; } = false;
|
||||
public bool HasArguments { get; set; } = false;
|
||||
|
||||
public string Arguments { get; set; } = string.Empty;
|
||||
|
||||
@@ -66,8 +66,8 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
private const string ExeExtension = "exe";
|
||||
private const string InternetShortcutExtension = "url";
|
||||
|
||||
private const string proxyWebApp = "_proxy.exe";
|
||||
private const string appIdArgument = "--app-id";
|
||||
private const string ProxyWebApp = "_proxy.exe";
|
||||
private const string AppIdArgument = "--app-id";
|
||||
|
||||
private enum ApplicationTypes
|
||||
{
|
||||
@@ -92,7 +92,7 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
// To Filter PWAs when the user searches for the main application
|
||||
// All Chromium based applications contain the --app-id argument
|
||||
// Reference : https://codereview.chromium.org/399045/show
|
||||
bool isWebApplication = FullPath.Contains(proxyWebApp, StringComparison.OrdinalIgnoreCase) && Arguments.Contains(appIdArgument, StringComparison.OrdinalIgnoreCase);
|
||||
bool isWebApplication = FullPath.Contains(ProxyWebApp, StringComparison.OrdinalIgnoreCase) && Arguments.Contains(AppIdArgument, StringComparison.OrdinalIgnoreCase);
|
||||
return isWebApplication;
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!hasArguments)
|
||||
if (!HasArguments)
|
||||
{
|
||||
var noArgumentScoreModifier = 5;
|
||||
score += noArgumentScoreModifier;
|
||||
@@ -348,13 +348,11 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
private static Win32Program InternetShortcutProgram(string path)
|
||||
{
|
||||
string[] lines = FileWrapper.ReadAllLines(path);
|
||||
string appName = string.Empty;
|
||||
string iconPath = string.Empty;
|
||||
string urlPath = string.Empty;
|
||||
string scheme = string.Empty;
|
||||
bool validApp = false;
|
||||
|
||||
Regex InternetShortcutURLPrefixes = new Regex(@"^steam:\/\/(rungameid|run)\/|^com\.epicgames\.launcher:\/\/apps\/");
|
||||
Regex internetShortcutURLPrefixes = new Regex(@"^steam:\/\/(rungameid|run)\/|^com\.epicgames\.launcher:\/\/apps\/");
|
||||
|
||||
const string urlPrefix = "URL=";
|
||||
const string iconFilePrefix = "IconFile=";
|
||||
@@ -367,7 +365,7 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
Uri uri = new Uri(urlPath);
|
||||
|
||||
// To filter out only those steam shortcuts which have 'run' or 'rungameid' as the hostname
|
||||
if (InternetShortcutURLPrefixes.Match(urlPath).Success)
|
||||
if (internetShortcutURLPrefixes.Match(urlPath).Success)
|
||||
{
|
||||
validApp = true;
|
||||
}
|
||||
@@ -429,10 +427,10 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
program.LnkResolvedPath = program.FullPath;
|
||||
program.FullPath = Path.GetFullPath(target).ToLower(CultureInfo.CurrentCulture);
|
||||
program.ExecutableName = Path.GetFileName(target);
|
||||
program.hasArguments = Helper.hasArguments;
|
||||
program.HasArguments = Helper.HasArguments;
|
||||
program.Arguments = Helper.Arguments;
|
||||
|
||||
var description = Helper.description;
|
||||
var description = Helper.Description;
|
||||
if (!string.IsNullOrEmpty(description))
|
||||
{
|
||||
program.Description = description;
|
||||
@@ -588,7 +586,8 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
$"|Win32|ProgramPaths|{currentDirectory}" +
|
||||
$"|Permission denied when trying to load programs from {currentDirectory}", e);
|
||||
}
|
||||
} while (folderQueue.Any());
|
||||
}
|
||||
while (folderQueue.Any());
|
||||
|
||||
return files;
|
||||
}
|
||||
@@ -613,7 +612,7 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
sources.Where(s => Directory.Exists(s.Location) && s.Enabled)
|
||||
.SelectMany(s => ProgramPaths(s.Location, suffixes))
|
||||
.ToList()
|
||||
.Where(t1 => !Main._settings.DisabledProgramSources.Any(x => t1 == x.UniqueIdentifier))
|
||||
.Where(t1 => !Main.Settings.DisabledProgramSources.Any(x => t1 == x.UniqueIdentifier))
|
||||
.ToList()
|
||||
.ForEach(x => listToAdd.Add(x));
|
||||
|
||||
@@ -660,20 +659,24 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
var allPrograms = programs1.Concat(programs2).Where(p => p.Valid)
|
||||
.Concat(programs3).Where(p => p.Valid)
|
||||
.Concat(programs4).Where(p => p.Valid)
|
||||
.Select(p => { p.AppType = (uint)ApplicationTypes.RUN_COMMAND; return p; });
|
||||
.Select(p =>
|
||||
{
|
||||
p.AppType = (uint)ApplicationTypes.RUN_COMMAND;
|
||||
return p;
|
||||
});
|
||||
|
||||
return allPrograms;
|
||||
}
|
||||
|
||||
private static ParallelQuery<Win32Program> IndexPath(IList<string> suffixes, List<string> IndexLocation)
|
||||
private static ParallelQuery<Win32Program> IndexPath(IList<string> suffixes, List<string> indexLocation)
|
||||
{
|
||||
var disabledProgramsList = Main._settings.DisabledProgramSources;
|
||||
var disabledProgramsList = Main.Settings.DisabledProgramSources;
|
||||
|
||||
IEnumerable<string> toFilter = new List<string>();
|
||||
foreach (string location in IndexLocation)
|
||||
foreach (string location in indexLocation)
|
||||
{
|
||||
var _paths = ProgramPaths(location, suffixes);
|
||||
toFilter = toFilter.Concat(_paths);
|
||||
var programPaths = ProgramPaths(location, suffixes);
|
||||
toFilter = toFilter.Concat(programPaths);
|
||||
}
|
||||
|
||||
var paths = toFilter
|
||||
@@ -696,17 +699,17 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
{
|
||||
var directory1 = Environment.GetFolderPath(Environment.SpecialFolder.Programs);
|
||||
var directory2 = Environment.GetFolderPath(Environment.SpecialFolder.CommonPrograms);
|
||||
List<string> IndexLocation = new List<string>() { directory1, directory2 };
|
||||
List<string> indexLocation = new List<string>() { directory1, directory2 };
|
||||
|
||||
return IndexPath(suffixes, IndexLocation);
|
||||
return IndexPath(suffixes, indexLocation);
|
||||
}
|
||||
|
||||
private static ParallelQuery<Win32Program> DesktopPrograms(IList<string> suffixes)
|
||||
{
|
||||
var directory1 = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
|
||||
List<string> IndexLocation = new List<string>() { directory1 };
|
||||
List<string> indexLocation = new List<string>() { directory1 };
|
||||
|
||||
return IndexPath(suffixes, IndexLocation);
|
||||
return IndexPath(suffixes, indexLocation);
|
||||
}
|
||||
|
||||
private static ParallelQuery<Win32Program> AppPathsPrograms(IList<string> suffixes)
|
||||
@@ -730,7 +733,7 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
}
|
||||
}
|
||||
|
||||
var disabledProgramsList = Main._settings.DisabledProgramSources;
|
||||
var disabledProgramsList = Main.Settings.DisabledProgramSources;
|
||||
var toFilter = programs.AsParallel().Where(p => suffixes.Contains(Extension(p.ExecutableName)));
|
||||
|
||||
var filtered = toFilter.Where(t1 => !disabledProgramsList.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier)).Select(t1 => t1);
|
||||
@@ -804,17 +807,15 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
// Overriding the object.GetHashCode() function to aid in removing duplicates while adding and removing apps from the concurrent dictionary storage
|
||||
public override int GetHashCode()
|
||||
{
|
||||
removeDuplicatesComparer _removeDuplicatesHelper = new removeDuplicatesComparer();
|
||||
return _removeDuplicatesHelper.GetHashCode(this);
|
||||
return new RemoveDuplicatesComparer().GetHashCode(this);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
removeDuplicatesComparer _removeDuplicatesHelper = new removeDuplicatesComparer();
|
||||
return obj is Win32Program win && _removeDuplicatesHelper.Equals(this, win);
|
||||
return obj is Win32Program win && new RemoveDuplicatesComparer().Equals(this, win);
|
||||
}
|
||||
|
||||
private class removeDuplicatesComparer : IEqualityComparer<Win32Program>
|
||||
private class RemoveDuplicatesComparer : IEqualityComparer<Win32Program>
|
||||
{
|
||||
public bool Equals(Win32Program app1, Win32Program app2)
|
||||
{
|
||||
@@ -838,9 +839,9 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
int fullPathPrime = 31;
|
||||
|
||||
int result = 1;
|
||||
result = result * namePrime + obj.Name.ToUpperInvariant().GetHashCode(StringComparison.Ordinal);
|
||||
result = result * executablePrime + obj.ExecutableName.ToUpperInvariant().GetHashCode(StringComparison.Ordinal);
|
||||
result = result * fullPathPrime + obj.FullPath.ToUpperInvariant().GetHashCode(StringComparison.Ordinal);
|
||||
result = (result * namePrime) + obj.Name.ToUpperInvariant().GetHashCode(StringComparison.Ordinal);
|
||||
result = (result * executablePrime) + obj.ExecutableName.ToUpperInvariant().GetHashCode(StringComparison.Ordinal);
|
||||
result = (result * fullPathPrime) + obj.FullPath.ToUpperInvariant().GetHashCode(StringComparison.Ordinal);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -850,7 +851,7 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
public static Win32Program[] DeduplicatePrograms(ParallelQuery<Win32Program> programs)
|
||||
{
|
||||
var uniqueExePrograms = programs.Where(x => !(string.IsNullOrEmpty(x.LnkResolvedPath) && (Extension(x.FullPath) == ExeExtension) && !(x.AppType == (uint)ApplicationTypes.RUN_COMMAND)));
|
||||
var uniquePrograms = uniqueExePrograms.Distinct(new removeDuplicatesComparer());
|
||||
var uniquePrograms = uniqueExePrograms.Distinct(new RemoveDuplicatesComparer());
|
||||
return uniquePrograms.ToArray();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,14 +10,16 @@ namespace Microsoft.Plugin.Program.Storage
|
||||
{
|
||||
internal class Win32ProgramFileSystemWatchers : IDisposable
|
||||
{
|
||||
public readonly string[] _pathsToWatch;
|
||||
public List<FileSystemWatcherWrapper> _fileSystemWatchers;
|
||||
public string[] PathsToWatch { get; set; }
|
||||
|
||||
public List<FileSystemWatcherWrapper> FileSystemWatchers { get; set; }
|
||||
|
||||
private bool _disposed = false;
|
||||
|
||||
// This class contains the list of directories to watch and initializes the File System Watchers
|
||||
public Win32ProgramFileSystemWatchers()
|
||||
{
|
||||
_pathsToWatch = GetPathsToWatch();
|
||||
PathsToWatch = GetPathsToWatch();
|
||||
SetFileSystemWatchers();
|
||||
}
|
||||
|
||||
@@ -36,10 +38,10 @@ namespace Microsoft.Plugin.Program.Storage
|
||||
// Initializes the FileSystemWatchers
|
||||
private void SetFileSystemWatchers()
|
||||
{
|
||||
_fileSystemWatchers = new List<FileSystemWatcherWrapper>();
|
||||
for (int index = 0; index < _pathsToWatch.Length; index++)
|
||||
FileSystemWatchers = new List<FileSystemWatcherWrapper>();
|
||||
for (int index = 0; index < PathsToWatch.Length; index++)
|
||||
{
|
||||
_fileSystemWatchers.Add(new FileSystemWatcherWrapper());
|
||||
FileSystemWatchers.Add(new FileSystemWatcherWrapper());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,9 +57,9 @@ namespace Microsoft.Plugin.Program.Storage
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
for (int index = 0; index < _pathsToWatch.Length; index++)
|
||||
for (int index = 0; index < PathsToWatch.Length; index++)
|
||||
{
|
||||
_fileSystemWatchers[index].Dispose();
|
||||
FileSystemWatchers[index].Dispose();
|
||||
}
|
||||
|
||||
_disposed = true;
|
||||
|
||||
@@ -15,22 +15,23 @@ namespace Microsoft.Plugin.Program.Storage
|
||||
{
|
||||
internal class Win32ProgramRepository : ListRepository<Programs.Win32Program>, IProgramRepository
|
||||
{
|
||||
private const string LnkExtension = ".lnk";
|
||||
private const string UrlExtension = ".url";
|
||||
|
||||
private IStorage<IList<Programs.Win32Program>> _storage;
|
||||
private ProgramPluginSettings _settings;
|
||||
private IList<IFileSystemWatcherWrapper> _fileSystemWatcherHelpers;
|
||||
private string[] _pathsToWatch;
|
||||
private int _numberOfPathsToWatch;
|
||||
private Collection<string> extensionsToWatch = new Collection<string> { "*.exe", "*.lnk", "*.appref-ms", "*.url" };
|
||||
private readonly string lnkExtension = ".lnk";
|
||||
private readonly string urlExtension = ".url";
|
||||
private Collection<string> extensionsToWatch = new Collection<string> { "*.exe", $"*{LnkExtension}", "*.appref-ms", $"*{UrlExtension}" };
|
||||
|
||||
public Win32ProgramRepository(IList<IFileSystemWatcherWrapper> fileSystemWatcherHelpers, IStorage<IList<Win32Program>> storage, ProgramPluginSettings settings, string[] pathsToWatch)
|
||||
{
|
||||
this._fileSystemWatcherHelpers = fileSystemWatcherHelpers;
|
||||
this._storage = storage ?? throw new ArgumentNullException(nameof(storage), "Win32ProgramRepository requires an initialized storage interface");
|
||||
this._settings = settings ?? throw new ArgumentNullException(nameof(settings), "Win32ProgramRepository requires an initialized settings object");
|
||||
this._pathsToWatch = pathsToWatch;
|
||||
this._numberOfPathsToWatch = pathsToWatch.Length;
|
||||
_fileSystemWatcherHelpers = fileSystemWatcherHelpers;
|
||||
_storage = storage ?? throw new ArgumentNullException(nameof(storage), "Win32ProgramRepository requires an initialized storage interface");
|
||||
_settings = settings ?? throw new ArgumentNullException(nameof(settings), "Win32ProgramRepository requires an initialized settings object");
|
||||
_pathsToWatch = pathsToWatch;
|
||||
_numberOfPathsToWatch = pathsToWatch.Length;
|
||||
InitializeFileSystemWatchers();
|
||||
}
|
||||
|
||||
@@ -77,11 +78,11 @@ namespace Microsoft.Plugin.Program.Storage
|
||||
// This situation is not encountered for other application types because the fullPath is the path itself, instead of being computed by using the path to the app.
|
||||
try
|
||||
{
|
||||
if (extension.Equals(lnkExtension, StringComparison.OrdinalIgnoreCase))
|
||||
if (extension.Equals(LnkExtension, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
oldApp = new Win32Program() { Name = Path.GetFileNameWithoutExtension(e.OldName), ExecutableName = newApp.ExecutableName, FullPath = newApp.FullPath };
|
||||
}
|
||||
else if (extension.Equals(urlExtension, StringComparison.OrdinalIgnoreCase))
|
||||
else if (extension.Equals(UrlExtension, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
oldApp = new Win32Program() { Name = Path.GetFileNameWithoutExtension(e.OldName), ExecutableName = Path.GetFileName(e.OldName), FullPath = newApp.FullPath };
|
||||
}
|
||||
@@ -117,11 +118,11 @@ namespace Microsoft.Plugin.Program.Storage
|
||||
try
|
||||
{
|
||||
// To mitigate the issue of not having a FullPath for a shortcut app, we iterate through the items and find the app with the same hashcode.
|
||||
if (extension.Equals(lnkExtension, StringComparison.OrdinalIgnoreCase))
|
||||
if (extension.Equals(LnkExtension, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
app = GetAppWithSameLnkResolvedPath(path);
|
||||
}
|
||||
else if (extension.Equals(urlExtension, StringComparison.OrdinalIgnoreCase))
|
||||
else if (extension.Equals(UrlExtension, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
app = GetAppWithSameNameAndExecutable(Path.GetFileNameWithoutExtension(path), Path.GetFileName(path));
|
||||
}
|
||||
@@ -173,7 +174,7 @@ namespace Microsoft.Plugin.Program.Storage
|
||||
private void OnAppCreated(object sender, FileSystemEventArgs e)
|
||||
{
|
||||
string path = e.FullPath;
|
||||
if (!Path.GetExtension(path).Equals(urlExtension, StringComparison.CurrentCultureIgnoreCase))
|
||||
if (!Path.GetExtension(path).Equals(UrlExtension, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
Programs.Win32Program app = Programs.Win32Program.GetAppFromPath(path);
|
||||
if (app != null)
|
||||
@@ -186,7 +187,7 @@ namespace Microsoft.Plugin.Program.Storage
|
||||
private void OnAppChanged(object sender, FileSystemEventArgs e)
|
||||
{
|
||||
string path = e.FullPath;
|
||||
if (Path.GetExtension(path).Equals(urlExtension, StringComparison.CurrentCultureIgnoreCase))
|
||||
if (Path.GetExtension(path).Equals(UrlExtension, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
Programs.Win32Program app = Programs.Win32Program.GetAppFromPath(path);
|
||||
if (app != null)
|
||||
|
||||
@@ -9,12 +9,11 @@ using System.Windows.Markup;
|
||||
|
||||
namespace Microsoft.Plugin.Program
|
||||
{
|
||||
public class SuffixesConvert : MarkupExtension, IValueConverter
|
||||
public class SuffixesConverter : MarkupExtension, IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
var text = value as string[];
|
||||
if (text != null)
|
||||
if (value is string[] text)
|
||||
{
|
||||
return string.Join(";", text);
|
||||
}
|
||||
|
||||
@@ -24,9 +24,9 @@ namespace Microsoft.Plugin.Program.Views.Commands
|
||||
}));
|
||||
|
||||
// Even though these are disabled, we still want to display them so users can enable later on
|
||||
Main._settings
|
||||
Main.Settings
|
||||
.DisabledProgramSources
|
||||
.Where(t1 => !Main._settings
|
||||
.Where(t1 => !Main.Settings
|
||||
.ProgramSources // program sources added above already, so exclude
|
||||
.Any(x => t1.UniqueIdentifier == x.UniqueIdentifier))
|
||||
.Select(x => x)
|
||||
@@ -76,16 +76,16 @@ namespace Microsoft.Plugin.Program.Views.Commands
|
||||
|
||||
internal static void StoreDisabledInSettings(this List<ProgramSource> list)
|
||||
{
|
||||
Main._settings.ProgramSources
|
||||
Main.Settings.ProgramSources
|
||||
.Where(t1 => ProgramSetting.ProgramSettingDisplayList.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier && !x.Enabled))
|
||||
.ToList()
|
||||
.ForEach(t1 => t1.Enabled = false);
|
||||
|
||||
ProgramSetting.ProgramSettingDisplayList
|
||||
.Where(t1 => !t1.Enabled
|
||||
&& !Main._settings.DisabledProgramSources.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier))
|
||||
&& !Main.Settings.DisabledProgramSources.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier))
|
||||
.ToList()
|
||||
.ForEach(x => Main._settings.DisabledProgramSources
|
||||
.ForEach(x => Main.Settings.DisabledProgramSources
|
||||
.Add(
|
||||
new DisabledProgramSource
|
||||
{
|
||||
@@ -98,15 +98,15 @@ namespace Microsoft.Plugin.Program.Views.Commands
|
||||
|
||||
internal static void RemoveDisabledFromSettings(this List<ProgramSource> list)
|
||||
{
|
||||
Main._settings.ProgramSources
|
||||
Main.Settings.ProgramSources
|
||||
.Where(t1 => ProgramSetting.ProgramSettingDisplayList.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier && x.Enabled))
|
||||
.ToList()
|
||||
.ForEach(t1 => t1.Enabled = true);
|
||||
|
||||
Main._settings.DisabledProgramSources
|
||||
Main.Settings.DisabledProgramSources
|
||||
.Where(t1 => ProgramSetting.ProgramSettingDisplayList.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier && x.Enabled))
|
||||
.ToList()
|
||||
.ForEach(x => Main._settings.DisabledProgramSources.Remove(x));
|
||||
.ForEach(x => Main.Settings.DisabledProgramSources.Remove(x));
|
||||
}
|
||||
|
||||
internal static bool IsReindexRequired(this List<ProgramSource> selectedItems)
|
||||
@@ -119,7 +119,7 @@ namespace Microsoft.Plugin.Program.Views.Commands
|
||||
// ProgramSources holds list of user added directories,
|
||||
// so when we enable/disable we need to reindex to show/not show the programs
|
||||
// that are found in those directories.
|
||||
if (selectedItems.Where(t1 => Main._settings.ProgramSources.Any(x => t1.UniqueIdentifier == x.UniqueIdentifier)).Any())
|
||||
if (selectedItems.Where(t1 => Main.Settings.ProgramSources.Any(x => t1.UniqueIdentifier == x.UniqueIdentifier)).Any())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -18,15 +18,15 @@
|
||||
<CheckBox Name="RegistryEnabled" Click="RegistryEnabled_Click" Margin="5" Content="{DynamicResource wox_plugin_program_index_registry}" />
|
||||
</StackPanel>
|
||||
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
|
||||
<Button Height="30" HorizontalAlignment="Right" Margin="10" Width="100" x:Name="btnLoadAllProgramSource" Click="btnLoadAllProgramSource_OnClick" Content="{DynamicResource wox_plugin_program_all_programs}" />
|
||||
<Button Height="30" HorizontalAlignment="Right" Margin="10" Width="100" x:Name="btnLoadAllProgramSource" Click="BtnLoadAllProgramSource_OnClick" Content="{DynamicResource wox_plugin_program_all_programs}" />
|
||||
<Button Height="30" HorizontalAlignment="Right" Margin="10" Width="100" x:Name="btnProgramSuffixes" Click="BtnProgramSuffixes_OnClick" Content="{DynamicResource wox_plugin_program_suffixes}" />
|
||||
<Button Height="30" HorizontalAlignment="Right" Margin="10" Width="100" x:Name="btnReindex" Click="btnReindex_Click" Content="{DynamicResource wox_plugin_program_reindex}" />
|
||||
<Button Height="30" HorizontalAlignment="Right" Margin="10" Width="100" x:Name="btnReindex" Click="BtnReindex_Click" Content="{DynamicResource wox_plugin_program_reindex}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
<ListView x:Name="programSourceView" Grid.Row="1" AllowDrop="True" SelectionMode="Extended" GridViewColumnHeader.Click="GridViewColumnHeaderClickedHandler"
|
||||
PreviewMouseRightButtonUp="ProgramSourceView_PreviewMouseRightButtonUp"
|
||||
DragEnter="programSourceView_DragEnter"
|
||||
Drop="programSourceView_Drop" >
|
||||
DragEnter="ProgramSourceView_DragEnter"
|
||||
Drop="ProgramSourceView_Drop" >
|
||||
<ListView.ItemContainerStyle>
|
||||
<Style TargetType="ListViewItem">
|
||||
<EventSetter Event="PreviewMouseUp" Handler="Row_OnClick"/>
|
||||
@@ -64,9 +64,9 @@
|
||||
<TextBlock Margin="10 0 0 0" Height="20" HorizontalAlignment="Center" Text="{DynamicResource wox_plugin_program_indexing}" />
|
||||
</StackPanel>
|
||||
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
|
||||
<Button x:Name="btnProgramSourceStatus" Click="btnProgramSourceStatus_OnClick" Width="100" Margin="10" Content="{DynamicResource wox_plugin_program_disable}" />
|
||||
<Button x:Name="btnAddProgramSource" Click="btnAddProgramSource_OnClick" Width="100" Margin="10" Content="{DynamicResource wox_plugin_program_add}"/>
|
||||
<Button x:Name="btnEditProgramSource" Click="btnEditProgramSource_OnClick" Width="100" Margin="10" Content="{DynamicResource wox_plugin_program_edit}"/>
|
||||
<Button x:Name="btnProgramSourceStatus" Click="BtnProgramSourceStatus_OnClick" Width="100" Margin="10" Content="{DynamicResource wox_plugin_program_disable}" />
|
||||
<Button x:Name="btnAddProgramSource" Click="BtnAddProgramSource_OnClick" Width="100" Margin="10" Content="{DynamicResource wox_plugin_program_add}"/>
|
||||
<Button x:Name="btnEditProgramSource" Click="BtnEditProgramSource_OnClick" Width="100" Margin="10" Content="{DynamicResource wox_plugin_program_edit}"/>
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace Microsoft.Plugin.Program.Views
|
||||
});
|
||||
}
|
||||
|
||||
private void btnAddProgramSource_OnClick(object sender, RoutedEventArgs e)
|
||||
private void BtnAddProgramSource_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var add = new AddProgramSource(context, _settings);
|
||||
if (add.ShowDialog() ?? false)
|
||||
@@ -80,7 +80,7 @@ namespace Microsoft.Plugin.Program.Views
|
||||
ReIndexing();
|
||||
}
|
||||
|
||||
private void btnEditProgramSource_OnClick(object sender, RoutedEventArgs e)
|
||||
private void BtnEditProgramSource_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var selectedProgramSource = programSourceView.SelectedItem as ProgramSource;
|
||||
if (selectedProgramSource != null)
|
||||
@@ -98,7 +98,7 @@ namespace Microsoft.Plugin.Program.Views
|
||||
}
|
||||
}
|
||||
|
||||
private void btnReindex_Click(object sender, RoutedEventArgs e)
|
||||
private void BtnReindex_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ReIndexing();
|
||||
}
|
||||
@@ -112,7 +112,7 @@ namespace Microsoft.Plugin.Program.Views
|
||||
}
|
||||
}
|
||||
|
||||
private void programSourceView_DragEnter(object sender, DragEventArgs e)
|
||||
private void ProgramSourceView_DragEnter(object sender, DragEventArgs e)
|
||||
{
|
||||
if (e.Data.GetDataPresent(DataFormats.FileDrop))
|
||||
{
|
||||
@@ -124,7 +124,7 @@ namespace Microsoft.Plugin.Program.Views
|
||||
}
|
||||
}
|
||||
|
||||
private void programSourceView_Drop(object sender, DragEventArgs e)
|
||||
private void ProgramSourceView_Drop(object sender, DragEventArgs e)
|
||||
{
|
||||
var directories = (string[])e.Data.GetData(DataFormats.FileDrop);
|
||||
|
||||
@@ -169,14 +169,14 @@ namespace Microsoft.Plugin.Program.Views
|
||||
ReIndexing();
|
||||
}
|
||||
|
||||
private void btnLoadAllProgramSource_OnClick(object sender, RoutedEventArgs e)
|
||||
private void BtnLoadAllProgramSource_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ProgramSettingDisplayList.LoadAllApplications();
|
||||
|
||||
programSourceView.Items.Refresh();
|
||||
}
|
||||
|
||||
private void btnProgramSourceStatus_OnClick(object sender, RoutedEventArgs e)
|
||||
private void BtnProgramSourceStatus_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var selectedItems = programSourceView
|
||||
.SelectedItems.Cast<ProgramSource>()
|
||||
|
||||
@@ -10,7 +10,7 @@ using static Microsoft.Plugin.Program.Programs.UWP;
|
||||
|
||||
namespace Microsoft.Plugin.Program.Win32
|
||||
{
|
||||
class NativeMethods
|
||||
internal class NativeMethods
|
||||
{
|
||||
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
|
||||
internal static extern Hresult SHCreateStreamOnFileEx(string fileName, Stgm grfMode, uint attributes, bool create, IStream reserved, out IStream stream);
|
||||
|
||||
Reference in New Issue
Block a user