Skip to content

Commit 086aeab

Browse files
committed
Use PInvoke to improve code quality
1 parent 41c5b36 commit 086aeab

File tree

3 files changed

+50
-61
lines changed

3 files changed

+50
-61
lines changed

Flow.Launcher.Infrastructure/NativeMethods.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,7 @@ LOCALE_TRANSIENT_KEYBOARD1
5757
LOCALE_TRANSIENT_KEYBOARD2
5858
LOCALE_TRANSIENT_KEYBOARD3
5959
LOCALE_TRANSIENT_KEYBOARD4
60+
61+
SHParseDisplayName
62+
SHOpenFolderAndSelectItems
63+
CoTaskMemFree

Flow.Launcher.Infrastructure/Win32Helper.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.ComponentModel;
44
using System.Diagnostics;
55
using System.Globalization;
6+
using System.IO;
67
using System.Linq;
78
using System.Runtime.InteropServices;
89
using System.Threading;
@@ -17,6 +18,7 @@
1718
using Windows.Win32.Foundation;
1819
using Windows.Win32.Graphics.Dwm;
1920
using Windows.Win32.UI.Input.KeyboardAndMouse;
21+
using Windows.Win32.UI.Shell.Common;
2022
using Windows.Win32.UI.WindowsAndMessaging;
2123
using Point = System.Windows.Point;
2224
using SystemFonts = System.Windows.SystemFonts;
@@ -753,5 +755,34 @@ private static bool TryGetNotoFont(string langKey, out string notoFont)
753755
}
754756

755757
#endregion
758+
759+
#region Explorer
760+
761+
public static unsafe void OpenFolderAndSelectFile(string filePath)
762+
{
763+
ITEMIDLIST* pidlFolder = null;
764+
ITEMIDLIST* pidlFile = null;
765+
766+
var folderPath = Path.GetDirectoryName(filePath);
767+
768+
try
769+
{
770+
var hrFolder = PInvoke.SHParseDisplayName(folderPath, null, out pidlFolder, 0, null);
771+
if (hrFolder.Failed) throw new COMException("Failed to parse folder path", hrFolder);
772+
773+
var hrFile = PInvoke.SHParseDisplayName(filePath, null, out pidlFile, 0, null);
774+
if (hrFile.Failed) throw new COMException("Failed to parse file path", hrFile);
775+
776+
var hrSelect = PInvoke.SHOpenFolderAndSelectItems(pidlFolder, 1, &pidlFile, 0);
777+
if (hrSelect.Failed) throw new COMException("Failed to open folder and select item", hrSelect);
778+
}
779+
finally
780+
{
781+
if (pidlFile != null) PInvoke.CoTaskMemFree(pidlFile);
782+
if (pidlFolder != null) PInvoke.CoTaskMemFree(pidlFolder);
783+
}
784+
}
785+
786+
#endregion
756787
}
757788
}

Flow.Launcher/PublicAPIInstance.cs

Lines changed: 15 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,9 @@
88
using System.Linq;
99
using System.Net;
1010
using System.Runtime.CompilerServices;
11-
using System.Runtime.InteropServices;
1211
using System.Threading;
1312
using System.Threading.Tasks;
1413
using System.Windows;
15-
using System.Windows.Input;
1614
using System.Windows.Media;
1715
using CommunityToolkit.Mvvm.DependencyInjection;
1816
using Flow.Launcher.Core;
@@ -320,88 +318,44 @@ public void SavePluginSettings()
320318

321319
((PluginJsonStorage<T>)_pluginJsonStorages[type]).Save();
322320
}
323-
324-
[DllImport("shell32.dll", CharSet = CharSet.Unicode)]
325-
private static extern int SHParseDisplayName(
326-
[MarshalAs(UnmanagedType.LPWStr)] string name,
327-
IntPtr bindingContext,
328-
out IntPtr pidl,
329-
uint sfgaoIn,
330-
out uint psfgaoOut
331-
);
332-
333-
[DllImport("shell32.dll")]
334-
private static extern int SHOpenFolderAndSelectItems(
335-
IntPtr pidlFolder,
336-
uint cidl,
337-
[MarshalAs(UnmanagedType.LPArray)] IntPtr[] apidl,
338-
uint dwFlags
339-
);
340-
341-
[DllImport("ole32.dll")]
342-
private static extern void CoTaskMemFree(IntPtr pv);
343-
344-
private void OpenFolderAndSelectItem(string filePath)
345-
{
346-
IntPtr pidlFolder = IntPtr.Zero;
347-
IntPtr pidlFile = IntPtr.Zero;
348-
uint attr;
349-
350-
string folderPath = Path.GetDirectoryName(filePath);
351-
352-
try
353-
{
354-
SHParseDisplayName(folderPath, IntPtr.Zero, out pidlFolder, 0, out attr);
355-
SHParseDisplayName(filePath, IntPtr.Zero, out pidlFile, 0, out attr);
356-
357-
if (pidlFolder != IntPtr.Zero && pidlFile != IntPtr.Zero)
358-
{
359-
SHOpenFolderAndSelectItems(pidlFolder, 1, new[] { pidlFile }, 0);
360-
}
361-
}
362-
finally
363-
{
364-
if (pidlFile != IntPtr.Zero)
365-
CoTaskMemFree(pidlFile);
366-
if (pidlFolder != IntPtr.Zero)
367-
CoTaskMemFree(pidlFolder);
368-
}
369-
}
370321

371322
public void OpenDirectory(string directoryPath, string fileNameOrFilePath = null)
372323
{
373324
try
374325
{
375-
string targetPath = fileNameOrFilePath is null
326+
var explorerInfo = _settings.CustomExplorer;
327+
var explorerPath = explorerInfo.Path.Trim().ToLowerInvariant();
328+
var targetPath = fileNameOrFilePath is null
376329
? directoryPath
377330
: Path.IsPathRooted(fileNameOrFilePath)
378331
? fileNameOrFilePath
379332
: Path.Combine(directoryPath, fileNameOrFilePath);
380333

381-
var explorerInfo = _settings.CustomExplorer;
382-
var explorerPath = explorerInfo.Path.Trim().ToLowerInvariant();
383-
384334
if (Path.GetFileNameWithoutExtension(explorerPath) == "explorer")
385335
{
336+
// Windows File Manager
386337
if (fileNameOrFilePath is null)
387338
{
388-
// 폴더만 열기
389-
Process.Start(new ProcessStartInfo
339+
// Only Open the directory
340+
using var explorer = new Process();
341+
explorer.StartInfo = new ProcessStartInfo
390342
{
391343
FileName = directoryPath,
392344
UseShellExecute = true
393-
})?.Dispose();
345+
};
346+
explorer.Start();
394347
}
395348
else
396349
{
397-
// SHOpenFolderAndSelectItems 방식
398-
OpenFolderAndSelectItem(targetPath);
350+
// Open the directory and select the file
351+
Win32Helper.OpenFolderAndSelectFile(targetPath);
399352
}
400353
}
401354
else
402355
{
403-
// 커스텀 파일 관리자
404-
var shellProcess = new ProcessStartInfo
356+
// Custom File Manager
357+
using var explorer = new Process();
358+
explorer.StartInfo = new ProcessStartInfo
405359
{
406360
FileName = explorerInfo.Path.Replace("%d", directoryPath),
407361
UseShellExecute = true,
@@ -411,7 +365,7 @@ public void OpenDirectory(string directoryPath, string fileNameOrFilePath = null
411365
.Replace("%d", directoryPath)
412366
.Replace("%f", targetPath)
413367
};
414-
Process.Start(shellProcess)?.Dispose();
368+
explorer.Start();
415369
}
416370
}
417371
catch (Win32Exception ex) when (ex.NativeErrorCode == 2)

0 commit comments

Comments
 (0)