11using System ;
2+ using System . Collections . Generic ;
3+ using System . IO ;
4+ using System . Linq ;
5+ using Windows . Win32 ;
26
37namespace Flow . Launcher . Infrastructure
48{
@@ -9,10 +13,9 @@ public static class FileExplorerHelper
913 /// </summary>
1014 public static string GetActiveExplorerPath ( )
1115 {
12- var explorerPath = QuickSwitch . QuickSwitch . GetActiveExplorerPath ( ) ;
13- return ! string . IsNullOrEmpty ( explorerPath ) ?
14- GetDirectoryPath ( new Uri ( explorerPath ) . LocalPath ) :
15- null ;
16+ var explorerWindow = GetActiveExplorer ( ) ;
17+ string locationUrl = explorerWindow ? . LocationURL ;
18+ return ! string . IsNullOrEmpty ( locationUrl ) ? GetDirectoryPath ( new Uri ( locationUrl ) . LocalPath ) : null ;
1619 }
1720
1821 /// <summary>
@@ -27,5 +30,67 @@ private static string GetDirectoryPath(string path)
2730
2831 return path ;
2932 }
33+
34+ /// <summary>
35+ /// Gets the file explorer that is currently in the foreground
36+ /// </summary>
37+ private static dynamic GetActiveExplorer ( )
38+ {
39+ Type type = Type . GetTypeFromProgID ( "Shell.Application" ) ;
40+ if ( type == null ) return null ;
41+ dynamic shell = Activator . CreateInstance ( type ) ;
42+ if ( shell == null )
43+ {
44+ return null ;
45+ }
46+
47+ var explorerWindows = new List < dynamic > ( ) ;
48+ var openWindows = shell . Windows ( ) ;
49+ for ( int i = 0 ; i < openWindows . Count ; i ++ )
50+ {
51+ var window = openWindows . Item ( i ) ;
52+ if ( window == null ) continue ;
53+
54+ // find the desired window and make sure that it is indeed a file explorer
55+ // we don't want the Internet Explorer or the classic control panel
56+ // ToLower() is needed, because Windows can report the path as "C:\\Windows\\Explorer.EXE"
57+ if ( Path . GetFileName ( ( string ) window . FullName ) ? . ToLower ( ) == "explorer.exe" )
58+ {
59+ explorerWindows . Add ( window ) ;
60+ }
61+ }
62+
63+ if ( explorerWindows . Count == 0 ) return null ;
64+
65+ var zOrders = GetZOrder ( explorerWindows ) ;
66+
67+ return explorerWindows . Zip ( zOrders ) . MinBy ( x => x . Second ) . First ;
68+ }
69+
70+ /// <summary>
71+ /// 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.
72+ /// </summary>
73+ private static IEnumerable < int > GetZOrder ( List < dynamic > hWnds )
74+ {
75+ var z = new int [ hWnds . Count ] ;
76+ for ( var i = 0 ; i < hWnds . Count ; i ++ ) z [ i ] = - 1 ;
77+
78+ var index = 0 ;
79+ var numRemaining = hWnds . Count ;
80+ PInvoke . EnumWindows ( ( wnd , _ ) =>
81+ {
82+ var searchIndex = hWnds . FindIndex ( x => new IntPtr ( x . HWND ) == wnd ) ;
83+ if ( searchIndex != - 1 )
84+ {
85+ z [ searchIndex ] = index ;
86+ numRemaining -- ;
87+ if ( numRemaining == 0 ) return false ;
88+ }
89+ index ++ ;
90+ return true ;
91+ } , IntPtr . Zero ) ;
92+
93+ return z ;
94+ }
3095 }
3196}
0 commit comments