Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,6 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

<ItemGroup>
<Reference Include="AppxPackagingTlb">
<HintPath>.\AppxPackagingTlb.dll</HintPath>
<EmbedInteropTypes>True</EmbedInteropTypes>
</Reference>
</ItemGroup>

<ItemGroup>
<Content Include="Languages\*.xaml">
Expand Down
82 changes: 82 additions & 0 deletions Plugins/Flow.Launcher.Plugin.Program/Programs/AppxPackageHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using Windows.Storage;

namespace Flow.Launcher.Plugin.Program.Programs
{
public class AppxPackageHelper
{
// This function returns a list of attributes of applications
public 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())
{
string appListEntry;
var manifestApp = manifestApps.GetCurrent();
manifestApp.GetStringValue("AppListEntry", out appListEntry);
if (appListEntry != "none")
{
apps.Add(manifestApp);
}
manifestApps.MoveNext();
}
return apps;
}

// 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
{
void _VtblGap0_2(); // skip 2 methods
IAppxManifestReader CreateManifestReader(IStream inputStream);
}

[Guid("4E1BD148-55A0-4480-A3D1-15544710637C"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IAppxManifestReader
{
void _VtblGap0_1(); // skip 1 method
IAppxManifestProperties GetProperties();
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]
int GetStringValue([MarshalAs(UnmanagedType.LPWStr)] string name, [MarshalAs(UnmanagedType.LPWStr)] out string value);

[PreserveSig]
int GetAppUserModelId([MarshalAs(UnmanagedType.LPWStr)] out string value);
}

[Guid("03FAF64D-F26F-4B2C-AAF7-8FE7789B8BCA"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IAppxManifestProperties
{
[PreserveSig]
int GetBoolValue([MarshalAs(UnmanagedType.LPWStr)]string name, out bool value);
[PreserveSig]
int GetStringValue([MarshalAs(UnmanagedType.LPWStr)] string name, [MarshalAs(UnmanagedType.LPWStr)] out string value);
}
}
}
56 changes: 30 additions & 26 deletions Plugins/Flow.Launcher.Plugin.Program/Programs/UWP.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
Expand All @@ -12,10 +13,8 @@
using System.Xml.Linq;
using Windows.ApplicationModel;
using Windows.Management.Deployment;
using AppxPackaing;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Plugin.Program.Logger;
using IStream = AppxPackaing.IStream;
using Rect = System.Windows.Rect;
using Flow.Launcher.Plugin.SharedModels;

Expand Down Expand Up @@ -51,33 +50,27 @@ public UWP(Package package)

private void InitializeAppInfo()
{
AppxPackageHelper _helper = new AppxPackageHelper();
var path = Path.Combine(Location, "AppxManifest.xml");

var namespaces = XmlNamespaces(path);
InitPackageVersion(namespaces);

var appxFactory = new AppxFactory();
IStream stream;
const uint noAttribute = 0x80;
const Stgm exclusiveRead = Stgm.Read | Stgm.ShareExclusive;
var hResult = SHCreateStreamOnFileEx(path, exclusiveRead, noAttribute, false, null, out stream);
var hResult = SHCreateStreamOnFileEx(path, exclusiveRead, noAttribute, false, null, out IStream stream);

if (hResult == Hresult.Ok)
{
var reader = appxFactory.CreateManifestReader(stream);
var manifestApps = reader.GetApplications();
var apps = new List<Application>();
while (manifestApps.GetHasCurrent() != 0)

List<AppxPackageHelper.IAppxManifestApplication> _apps = _helper.getAppsFromManifest(stream);
foreach(var _app in _apps)
{
var manifestApp = manifestApps.GetCurrent();
var appListEntry = manifestApp.GetStringValue("AppListEntry");
if (appListEntry != "none")
{
var app = new Application(manifestApp, this);
apps.Add(app);
}
manifestApps.MoveNext();
var app = new Application(_app, this);
apps.Add(app);
}

Apps = apps.Where(a => a.AppListEntry != "none").ToArray();
}
else
Expand Down Expand Up @@ -253,6 +246,7 @@ public class Application : IProgram
public string UserModelId { get; set; }
public string BackgroundColor { get; set; }

public string EntryPoint { get; set; }
public string Name => DisplayName;
public string Location => Package.Location;

Expand Down Expand Up @@ -350,14 +344,13 @@ public List<Result> ContextMenus(IPublicAPI api)
private async void Launch(IPublicAPI api)
{
var appManager = new ApplicationActivationHelper.ApplicationActivationManager();
uint unusedPid;
const string noArgs = "";
const ApplicationActivationHelper.ActivateOptions noFlags = ApplicationActivationHelper.ActivateOptions.None;
await Task.Run(() =>
{
try
{
appManager.ActivateApplication(UserModelId, noArgs, noFlags, out unusedPid);
appManager.ActivateApplication(UserModelId, noArgs, noFlags, out _);
}
catch (Exception)
{
Expand All @@ -368,13 +361,24 @@ await Task.Run(() =>
});
}

public Application(IAppxManifestApplication manifestApp, UWP package)
public Application(AppxPackageHelper.IAppxManifestApplication manifestApp, UWP package)
{
UserModelId = manifestApp.GetAppUserModelId();
UniqueIdentifier = manifestApp.GetAppUserModelId();
DisplayName = manifestApp.GetStringValue("DisplayName");
Description = manifestApp.GetStringValue("Description");
BackgroundColor = manifestApp.GetStringValue("BackgroundColor");
// This is done because we cannot use the keyword 'out' along with a property

manifestApp.GetAppUserModelId(out string tmpUserModelId);
manifestApp.GetAppUserModelId(out string tmpUniqueIdentifier);
manifestApp.GetStringValue("DisplayName", out string tmpDisplayName);
manifestApp.GetStringValue("Description", out string tmpDescription);
manifestApp.GetStringValue("BackgroundColor", out string tmpBackgroundColor);
manifestApp.GetStringValue("EntryPoint", out string tmpEntryPoint);

UserModelId = tmpUserModelId;
UniqueIdentifier = tmpUniqueIdentifier;
DisplayName = tmpDisplayName;
Description = tmpDescription;
BackgroundColor = tmpBackgroundColor;
EntryPoint = tmpEntryPoint;

Package = package;

DisplayName = ResourceFromPri(package.FullName, package.Name, DisplayName);
Expand Down Expand Up @@ -442,7 +446,7 @@ public string FormattedPriReferenceValue(string packageName, string rawPriRefere
return $"{prefix}//{packageName}{key}";
}

internal string LogoUriFromManifest(IAppxManifestApplication app)
internal string LogoUriFromManifest(AppxPackageHelper.IAppxManifestApplication app)
{
var logoKeyFromVersion = new Dictionary<PackageVersion, string>
{
Expand All @@ -453,7 +457,7 @@ internal string LogoUriFromManifest(IAppxManifestApplication app)
if (logoKeyFromVersion.ContainsKey(Package.Version))
{
var key = logoKeyFromVersion[Package.Version];
var logoUri = app.GetStringValue(key);
app.GetStringValue(key, out string logoUri);
return logoUri;
}
else
Expand Down
2 changes: 1 addition & 1 deletion Plugins/Flow.Launcher.Plugin.Program/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"Name": "Program",
"Description": "Search programs in Flow.Launcher",
"Author": "qianlifeng",
"Version": "1.4.1",
"Version": "1.4.2",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.Program.dll",
Expand Down