-
-
Notifications
You must be signed in to change notification settings - Fork 344
/
Copy pathFileExplorerHelper.cs
96 lines (84 loc) · 3.21 KB
/
FileExplorerHelper.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Win32;
namespace Flow.Launcher.Infrastructure
{
public static class FileExplorerHelper
{
/// <summary>
/// Gets the path of the file explorer that is currently in the foreground
/// </summary>
public static string GetActiveExplorerPath()
{
var explorerWindow = GetActiveExplorer();
string locationUrl = explorerWindow?.LocationURL;
return !string.IsNullOrEmpty(locationUrl) ? GetDirectoryPath(new Uri(locationUrl).LocalPath) : null;
}
/// <summary>
/// Get directory path from a file path
/// </summary>
private static string GetDirectoryPath(string path)
{
if (!path.EndsWith("\\"))
{
return path + "\\";
}
return path;
}
/// <summary>
/// Gets the file explorer that is currently in the foreground
/// </summary>
private static dynamic GetActiveExplorer()
{
Type type = Type.GetTypeFromProgID("Shell.Application");
if (type == null) return null;
dynamic shell = Activator.CreateInstance(type);
if (shell == null)
{
return null;
}
var explorerWindows = new List<dynamic>();
var openWindows = shell.Windows();
for (int i = 0; i < openWindows.Count; i++)
{
var window = openWindows.Item(i);
if (window == null) continue;
// find the desired window and make sure that it is indeed a file explorer
// we don't want the Internet Explorer or the classic control panel
// ToLower() is needed, because Windows can report the path as "C:\\Windows\\Explorer.EXE"
if (Path.GetFileName((string)window.FullName)?.ToLower() == "explorer.exe")
{
explorerWindows.Add(window);
}
}
if (explorerWindows.Count == 0) return null;
var zOrders = GetZOrder(explorerWindows);
return explorerWindows.Zip(zOrders).MinBy(x => x.Second).First;
}
/// <summary>
/// Gets the z-order for one or more windows atomically with respect to each other. In Windows, smaller z-order is higher. If the window is not top level, the z order is returned as -1.
/// </summary>
private static IEnumerable<int> GetZOrder(List<dynamic> hWnds)
{
var z = new int[hWnds.Count];
for (var i = 0; i < hWnds.Count; i++) z[i] = -1;
var index = 0;
var numRemaining = hWnds.Count;
PInvoke.EnumWindows((wnd, _) =>
{
var searchIndex = hWnds.FindIndex(x => new IntPtr(x.HWND) == wnd);
if (searchIndex != -1)
{
z[searchIndex] = index;
numRemaining--;
if (numRemaining == 0) return false;
}
index++;
return true;
}, IntPtr.Zero);
return z;
}
}
}