-
Notifications
You must be signed in to change notification settings - Fork 6
File explorer support #27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
6a67fd1
3cc47fe
95f0e1c
360aa1e
c6c05a6
6bd718d
1fcc0e7
858002c
3fd1fc3
c48ed99
a0f66e8
ccbbe45
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.IO; | ||
| using System.Linq; | ||
| using System.Runtime.InteropServices; | ||
|
|
||
| namespace Wox.Plugin.Runner | ||
| { | ||
| class ExplorerPathsService | ||
| { | ||
| public static List<string> GetOpenExplorerPaths() | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This uses the "Shell" to iterate over all file explorer windows and read the file paths and HWNDs from them. Finally, it combines that info to return a sorted list of open file explorer windows. This means that |
||
| { | ||
| var results = new List<string>(); | ||
| if (OperatingSystem.IsWindows()) | ||
|
||
| { | ||
| Type? type = Type.GetTypeFromProgID("Shell.Application"); | ||
| if (type == null) return results; | ||
| dynamic? shell = Activator.CreateInstance(type); | ||
| if (shell == null) return results; | ||
| try | ||
| { | ||
| var fullResults = new List<ExplorerResult>(); | ||
|
|
||
| var openWindows = shell.Windows(); | ||
| for (int i = 0; i < openWindows.Count; i++) | ||
| { | ||
| var window = openWindows.Item(i); | ||
| if (window == null) continue; | ||
| var fileName = Path.GetFileName((string)window.FullName); | ||
| if (fileName.ToLower() == "explorer.exe") | ||
| { | ||
| string locationUrl = window.LocationURL; | ||
| if (!string.IsNullOrEmpty(locationUrl)) | ||
| { | ||
| fullResults.Add(new ExplorerResult(new IntPtr(window.HWND), new Uri(locationUrl).LocalPath)); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| int zIndex = fullResults.Count; | ||
| EnumWindows((IntPtr hwnd, IntPtr param) => | ||
| { | ||
| var result = fullResults.Find(v => v.HWND == hwnd); | ||
| if(result != null) | ||
| { | ||
| result.ZIndex = zIndex; | ||
|
||
| zIndex -= 1; | ||
| } | ||
| // zIndex is also used as a counter: how many more windows do we have to find | ||
| return zIndex > 0; | ||
| }, IntPtr.Zero); | ||
|
|
||
| // sort descending | ||
| fullResults.Sort((a, b) => b.ZIndex - a.ZIndex); | ||
| results.AddRange(fullResults.Select(v => v.Path)); | ||
| } | ||
| finally | ||
| { | ||
| Marshal.FinalReleaseComObject(shell); | ||
| } | ||
| } | ||
|
|
||
| return results; | ||
| } | ||
|
|
||
| private class ExplorerResult | ||
| { | ||
| /// <summary> | ||
| /// Higher values means that the window is closer to the user | ||
| /// </summary> | ||
| public int ZIndex { get; set; } = 0; | ||
| public IntPtr HWND { get; } | ||
| public string Path { get; } | ||
|
|
||
| public ExplorerResult(IntPtr hwnd, string path) | ||
| { | ||
| HWND = hwnd; | ||
| Path = path; | ||
| } | ||
| } | ||
|
|
||
| [DllImport("user32.dll")] | ||
| [return: MarshalAs(UnmanagedType.Bool)] | ||
| private static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam); | ||
|
|
||
| // Delegate to filter which windows to include | ||
| public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); | ||
|
|
||
|
|
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,15 +1,18 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk.WindowsDesktop"> | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
| <PropertyGroup> | ||
| <TargetFramework>netcoreapp3.1</TargetFramework> | ||
| <TargetFramework>net5.0-windows</TargetFramework> | ||
| <OutputType>Library</OutputType> | ||
| <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir> | ||
| <RestorePackages>true</RestorePackages> | ||
| <GenerateAssemblyInfo>false</GenerateAssemblyInfo> | ||
| <Nullable>enable</Nullable> | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I also enabled the nullable references stuff, which makes it a lot easier to spot potential null pointer exceptions at compile time. |
||
| <UseWindowsForms>true</UseWindowsForms> | ||
| <UseWPF>true</UseWPF> | ||
| <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> | ||
| <AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath> | ||
| <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> | ||
| <PlatformTarget>AnyCPU</PlatformTarget> | ||
| <AnalysisLevel>none</AnalysisLevel> | ||
stefnotch marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| </PropertyGroup> | ||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> | ||
| <OutputPath>..\Output\Release\Wox.Plugin.Runner</OutputPath> | ||
|
|
@@ -18,7 +21,7 @@ | |
| <OutputPath>..\Output\Debug\Wox.Plugin.Runner</OutputPath> | ||
| </PropertyGroup> | ||
| <ItemGroup> | ||
| <PackageReference Include="Flow.Launcher.Plugin" Version="1.4.0" /> | ||
| <PackageReference Include="Flow.Launcher.Plugin" Version="2.1.1" /> | ||
| <PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" /> | ||
| </ItemGroup> | ||
|
|
||
|
|
@@ -36,7 +39,4 @@ | |
| <CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||
| </Content> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <PackageReference Include="CommonServiceLocator" Version="1.3" /> | ||
| </ItemGroup> | ||
| </Project> | ||
This file was deleted.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Working directory can be set to
{explorer}, which will trigger the new behavior where it tries to get the path of the topmost file explorer window.