Skip to content

Commit 41c5b36

Browse files
committed
Enhance OpenDirectory method to support folder opening and file selection using SHOpenFolderAndSelectItems
1 parent 47878f3 commit 41c5b36

File tree

1 file changed

+76
-23
lines changed

1 file changed

+76
-23
lines changed

Flow.Launcher/PublicAPIInstance.cs

Lines changed: 76 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Linq;
99
using System.Net;
1010
using System.Runtime.CompilerServices;
11+
using System.Runtime.InteropServices;
1112
using System.Threading;
1213
using System.Threading.Tasks;
1314
using System.Windows;
@@ -320,47 +321,98 @@ public void SavePluginSettings()
320321
((PluginJsonStorage<T>)_pluginJsonStorages[type]).Save();
321322
}
322323

323-
public void OpenDirectory(string DirectoryPath, string FileNameOrFilePath = null)
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)
324345
{
346+
IntPtr pidlFolder = IntPtr.Zero;
347+
IntPtr pidlFile = IntPtr.Zero;
348+
uint attr;
349+
350+
string folderPath = Path.GetDirectoryName(filePath);
351+
325352
try
326353
{
327-
using var explorer = new Process();
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+
}
370+
371+
public void OpenDirectory(string directoryPath, string fileNameOrFilePath = null)
372+
{
373+
try
374+
{
375+
string targetPath = fileNameOrFilePath is null
376+
? directoryPath
377+
: Path.IsPathRooted(fileNameOrFilePath)
378+
? fileNameOrFilePath
379+
: Path.Combine(directoryPath, fileNameOrFilePath);
380+
328381
var explorerInfo = _settings.CustomExplorer;
329382
var explorerPath = explorerInfo.Path.Trim().ToLowerInvariant();
330-
var targetPath = FileNameOrFilePath is null
331-
? DirectoryPath
332-
: Path.IsPathRooted(FileNameOrFilePath)
333-
? FileNameOrFilePath
334-
: Path.Combine(DirectoryPath, FileNameOrFilePath);
335383

336384
if (Path.GetFileNameWithoutExtension(explorerPath) == "explorer")
337385
{
338-
// Windows File Manager
339-
explorer.StartInfo = new ProcessStartInfo
386+
if (fileNameOrFilePath is null)
340387
{
341-
FileName = "explorer.exe",
342-
Arguments = FileNameOrFilePath is null
343-
? DirectoryPath // only open the directory
344-
: $"/select,\"{targetPath}\"", // open the directory and select the file
345-
UseShellExecute = true
346-
};
388+
// 폴더만 열기
389+
Process.Start(new ProcessStartInfo
390+
{
391+
FileName = directoryPath,
392+
UseShellExecute = true
393+
})?.Dispose();
394+
}
395+
else
396+
{
397+
// SHOpenFolderAndSelectItems 방식
398+
OpenFolderAndSelectItem(targetPath);
399+
}
347400
}
348401
else
349402
{
350-
// Custom File Manager
351-
explorer.StartInfo = new ProcessStartInfo
403+
// 커스텀 파일 관리자
404+
var shellProcess = new ProcessStartInfo
352405
{
353-
FileName = explorerInfo.Path.Replace("%d", DirectoryPath),
406+
FileName = explorerInfo.Path.Replace("%d", directoryPath),
354407
UseShellExecute = true,
355-
Arguments = FileNameOrFilePath is null
356-
? explorerInfo.DirectoryArgument.Replace("%d", DirectoryPath)
408+
Arguments = fileNameOrFilePath is null
409+
? explorerInfo.DirectoryArgument.Replace("%d", directoryPath)
357410
: explorerInfo.FileArgument
358-
.Replace("%d", DirectoryPath)
411+
.Replace("%d", directoryPath)
359412
.Replace("%f", targetPath)
360413
};
414+
Process.Start(shellProcess)?.Dispose();
361415
}
362-
363-
explorer.Start();
364416
}
365417
catch (Win32Exception ex) when (ex.NativeErrorCode == 2)
366418
{
@@ -384,6 +436,7 @@ public void OpenDirectory(string DirectoryPath, string FileNameOrFilePath = null
384436
}
385437
}
386438

439+
387440
private void OpenUri(Uri uri, bool? inPrivate = null)
388441
{
389442
if (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps)

0 commit comments

Comments
 (0)