在资源管理器中打开文件夹并选择文件

发布于 2024-07-09 12:42:45 字数 297 浏览 9 评论 0原文

我正在尝试在资源管理器中打开一个文件夹并选择一个文件。

以下代码会产生文件未找到异常:

System.Diagnostics.Process.Start(
    "explorer.exe /select," 
    + listView1.SelectedItems[0].SubItems[1].Text + "\\" 
    + listView1.SelectedItems[0].Text);

How can I get this command to run in C#?

I'm trying to open a folder in explorer with a file selected.

The following code produces a file not found exception:

System.Diagnostics.Process.Start(
    "explorer.exe /select," 
    + listView1.SelectedItems[0].SubItems[1].Text + "\\" 
    + listView1.SelectedItems[0].Text);

How can I get this command to execute in C#?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

坏尐絯℡ 2024-07-16 12:42:46

使用此方法

Process.Start(String, String)

第一个参数是一个应用程序(explorer.exe) ,第二个方法参数是您运行的应用程序的参数。

例如:

在 CMD 中:

explorer.exe -p

在 C# 中:

Process.Start("explorer.exe", "-p")

Use this method:

Process.Start(String, String)

First argument is an application (explorer.exe), second method argument are arguments of the application you run.

For example:

in CMD:

explorer.exe -p

in C#:

Process.Start("explorer.exe", "-p")
风月客 2024-07-16 12:42:46

只是我的 2 美分价值,如果您的文件名包含空格,即“c:\My File Contains Spaces.txt”,您需要用引号将文件名引起来,否则资源管理器将假定其他单词是不同的参数...

string argument = "/select, \"" + filePath +"\"";

Just my 2 cents worth, if your filename contains spaces, ie "c:\My File Contains Spaces.txt", you'll need to surround the filename with quotes otherwise explorer will assume that the othe words are different arguments...

string argument = "/select, \"" + filePath +"\"";
爱殇璃 2024-07-16 12:42:46

奇怪的是,在 explorer.exe 上使用 Process.Start 以及 /select 参数仅适用于长度小于 120 个字符的路径。

我必须使用本机 Windows 方法才能使其在所有情况下都能工作:

[DllImport("shell32.dll", SetLastError = true)]
public static extern int SHOpenFolderAndSelectItems(IntPtr pidlFolder, uint cidl, [In, MarshalAs(UnmanagedType.LPArray)] IntPtr[] apidl, uint dwFlags);

[DllImport("shell32.dll", SetLastError = true)]
public static extern void SHParseDisplayName([MarshalAs(UnmanagedType.LPWStr)] string name, IntPtr bindingContext, [Out] out IntPtr pidl, uint sfgaoIn, [Out] out uint psfgaoOut);

public static void OpenFolderAndSelectItem(string folderPath, string file)
{
    IntPtr nativeFolder;
    uint psfgaoOut;
    SHParseDisplayName(folderPath, IntPtr.Zero, out nativeFolder, 0, out psfgaoOut);

    if (nativeFolder == IntPtr.Zero)
    {
        // Log error, can't find folder
        return;
    }

    IntPtr nativeFile;
    SHParseDisplayName(Path.Combine(folderPath, file), IntPtr.Zero, out nativeFile, 0, out psfgaoOut);

    IntPtr[] fileArray;
    if (nativeFile == IntPtr.Zero)
    {
        // Open the folder without the file selected if we can't find the file
        fileArray = new IntPtr[0];
    }
    else
    {
        fileArray = new IntPtr[] { nativeFile };
    }

    SHOpenFolderAndSelectItems(nativeFolder, (uint)fileArray.Length, fileArray, 0);

    Marshal.FreeCoTaskMem(nativeFolder);
    if (nativeFile != IntPtr.Zero)
    {
        Marshal.FreeCoTaskMem(nativeFile);
    }
}

Using Process.Start on explorer.exe with the /select argument oddly only works for paths less than 120 characters long.

I had to use a native windows method to get it to work in all cases:

[DllImport("shell32.dll", SetLastError = true)]
public static extern int SHOpenFolderAndSelectItems(IntPtr pidlFolder, uint cidl, [In, MarshalAs(UnmanagedType.LPArray)] IntPtr[] apidl, uint dwFlags);

[DllImport("shell32.dll", SetLastError = true)]
public static extern void SHParseDisplayName([MarshalAs(UnmanagedType.LPWStr)] string name, IntPtr bindingContext, [Out] out IntPtr pidl, uint sfgaoIn, [Out] out uint psfgaoOut);

public static void OpenFolderAndSelectItem(string folderPath, string file)
{
    IntPtr nativeFolder;
    uint psfgaoOut;
    SHParseDisplayName(folderPath, IntPtr.Zero, out nativeFolder, 0, out psfgaoOut);

    if (nativeFolder == IntPtr.Zero)
    {
        // Log error, can't find folder
        return;
    }

    IntPtr nativeFile;
    SHParseDisplayName(Path.Combine(folderPath, file), IntPtr.Zero, out nativeFile, 0, out psfgaoOut);

    IntPtr[] fileArray;
    if (nativeFile == IntPtr.Zero)
    {
        // Open the folder without the file selected if we can't find the file
        fileArray = new IntPtr[0];
    }
    else
    {
        fileArray = new IntPtr[] { nativeFile };
    }

    SHOpenFolderAndSelectItems(nativeFolder, (uint)fileArray.Length, fileArray, 0);

    Marshal.FreeCoTaskMem(nativeFolder);
    if (nativeFile != IntPtr.Zero)
    {
        Marshal.FreeCoTaskMem(nativeFile);
    }
}
梦年海沫深 2024-07-16 12:42:46

Samuel Yang 的回答让我绊倒了,这是我的 3 美分价值。

Adrian Hum 是对的,请确保在文件名两边加上引号。 并不是因为它不能像 zourtney 指出的那样处理空格,而是因为它会将文件名中的逗号(可能还有其他字符)识别为单独的参数。
所以它应该看起来像 Adrian Hum 建议的那样。

string argument = "/select, \"" + filePath +"\"";

Samuel Yang answer tripped me up, here is my 3 cents worth.

Adrian Hum is right, make sure you put quotes around your filename. Not because it can't handle spaces as zourtney pointed out, but because it will recognize the commas (and possibly other characters) in filenames as separate arguments.
So it should look as Adrian Hum suggested.

string argument = "/select, \"" + filePath +"\"";
执手闯天涯 2024-07-16 12:42:46

使用“/select,c:\file.txt”

注意/select后面应该有一个逗号而不是空格。

Use "/select,c:\file.txt"

Notice there should be a comma after /select instead of space..

海之角 2024-07-16 12:42:46

找不到文件的最可能原因是路径中有空格。例如,它找不到“explorer /select,c:\space space\space.txt”。

只需在路径前后添加双引号即可,例如;

explorer /select,"c:\space space\space.txt"

或者在 C# 中执行相同的操作

System.Diagnostics.Process.Start("explorer.exe","/select,\"c:\space space\space.txt\"");

The most possible reason for it not to find the file is the path having spaces in. For example, it won't find "explorer /select,c:\space space\space.txt".

Just add double quotes before and after the path, like;

explorer /select,"c:\space space\space.txt"

or do the same in C# with

System.Diagnostics.Process.Start("explorer.exe","/select,\"c:\space space\space.txt\"");
街角卖回忆 2024-07-16 12:42:46

您需要将要传递的参数(“/select 等”)放在 Start 方法的第二个参数中。

You need to put the arguments to pass ("/select etc") in the second parameter of the Start method.

抚你发端 2024-07-16 12:42:46
string windir = Environment.GetEnvironmentVariable("windir");
if (string.IsNullOrEmpty(windir.Trim())) {
    windir = "C:\\Windows\\";
}
if (!windir.EndsWith("\\")) {
    windir += "\\";
}    

FileInfo fileToLocate = null;
fileToLocate = new FileInfo("C:\\Temp\\myfile.txt");

ProcessStartInfo pi = new ProcessStartInfo(windir + "explorer.exe");
pi.Arguments = "/select, \"" + fileToLocate.FullName + "\"";
pi.WindowStyle = ProcessWindowStyle.Normal;
pi.WorkingDirectory = windir;

//Start Process
Process.Start(pi)
string windir = Environment.GetEnvironmentVariable("windir");
if (string.IsNullOrEmpty(windir.Trim())) {
    windir = "C:\\Windows\\";
}
if (!windir.EndsWith("\\")) {
    windir += "\\";
}    

FileInfo fileToLocate = null;
fileToLocate = new FileInfo("C:\\Temp\\myfile.txt");

ProcessStartInfo pi = new ProcessStartInfo(windir + "explorer.exe");
pi.Arguments = "/select, \"" + fileToLocate.FullName + "\"";
pi.WindowStyle = ProcessWindowStyle.Normal;
pi.WorkingDirectory = windir;

//Start Process
Process.Start(pi)
绝不服输 2024-07-16 12:42:46

这可能有点过分了,但我喜欢方便的函数,所以采用这个:

    public static void ShowFileInExplorer(FileInfo file) {
        StartProcess("explorer.exe", null, "/select, "+file.FullName.Quote());
    }
    public static Process StartProcess(FileInfo file, params string[] args) => StartProcess(file.FullName, file.DirectoryName, args);
    public static Process StartProcess(string file, string workDir = null, params string[] args) {
        ProcessStartInfo proc = new ProcessStartInfo();
        proc.FileName = file;
        proc.Arguments = string.Join(" ", args);
        Logger.Debug(proc.FileName, proc.Arguments); // Replace with your logging function
        if (workDir != null) {
            proc.WorkingDirectory = workDir;
            Logger.Debug("WorkingDirectory:", proc.WorkingDirectory); // Replace with your logging function
        }
        return Process.Start(proc);
    }

这是我用作.Quote() 的扩展函数:

static class Extensions
{
    public static string Quote(this string text)
    {
        return SurroundWith(text, "\"");
    }
    public static string SurroundWith(this string text, string surrounds)
    {
        return surrounds + text + surrounds;
    }
}

It might be a bit of a overkill but I like convinience functions so take this one:

    public static void ShowFileInExplorer(FileInfo file) {
        StartProcess("explorer.exe", null, "/select, "+file.FullName.Quote());
    }
    public static Process StartProcess(FileInfo file, params string[] args) => StartProcess(file.FullName, file.DirectoryName, args);
    public static Process StartProcess(string file, string workDir = null, params string[] args) {
        ProcessStartInfo proc = new ProcessStartInfo();
        proc.FileName = file;
        proc.Arguments = string.Join(" ", args);
        Logger.Debug(proc.FileName, proc.Arguments); // Replace with your logging function
        if (workDir != null) {
            proc.WorkingDirectory = workDir;
            Logger.Debug("WorkingDirectory:", proc.WorkingDirectory); // Replace with your logging function
        }
        return Process.Start(proc);
    }

This is the extension function I use as <string>.Quote():

static class Extensions
{
    public static string Quote(this string text)
    {
        return SurroundWith(text, "\"");
    }
    public static string SurroundWith(this string text, string surrounds)
    {
        return surrounds + text + surrounds;
    }
}
拥抱我好吗 2024-07-16 12:42:46

基于 Jan Croonen 的简单 C# 9.0 方法答案

private static void SelectFileInExplorer(string filePath)
{
    Process.Start(new ProcessStartInfo()
    {
        FileName = "explorer.exe",
        Arguments = @$"/select, ""{filePath}"""
    });
}

Simple C# 9.0 method based on Jan Croonen's answer:

private static void SelectFileInExplorer(string filePath)
{
    Process.Start(new ProcessStartInfo()
    {
        FileName = "explorer.exe",
        Arguments = @
quot;/select, ""{filePath}"""
    });
}
白鸥掠海 2024-07-16 12:42:46

来晚会了。

我发现 RandomEngy 的解决方案很有用,但对其进行了轻微修改以允许一次选择多个文件。 希望有人觉得它有用。

    [DllImport("shell32.dll", SetLastError = true)]
    public static extern int SHOpenFolderAndSelectItems(IntPtr pidlFolder, uint cidl, [In, MarshalAs(UnmanagedType.LPArray)] IntPtr[] apidl, uint dwFlags);

    [DllImport("shell32.dll", SetLastError = true)]
    public static extern void SHParseDisplayName([MarshalAs(UnmanagedType.LPWStr)] string name, IntPtr bindingContext, [Out] out IntPtr pidl, uint sfgaoIn, [Out] out uint psfgaoOut);

    public static void OpenFolderAndSelectItem(string folderPath, List<string> files)
    {
        IntPtr nativeFolder;
        uint psfgaoOut;
        SHParseDisplayName(folderPath, IntPtr.Zero, out nativeFolder, 0, out psfgaoOut);

        if (nativeFolder == IntPtr.Zero)
        {
            // Log error, can't find folder
            return;
        }

        List<IntPtr> nativeFiles = new();
        foreach (string file in files)
        {
            IntPtr nativeFile;
            SHParseDisplayName(Path.Combine(folderPath, file), IntPtr.Zero, out nativeFile, 0, out psfgaoOut);
            if (nativeFile != IntPtr.Zero)
            {
                // Open the folder without the file selected if we can't find the file
                nativeFiles.Add(nativeFile);
            }
        }

        if (nativeFiles.Count == 0)
        {
            nativeFiles.Add(IntPtr.Zero);
        }

        IntPtr[] fileArray = nativeFiles.ToArray();

        SHOpenFolderAndSelectItems(nativeFolder, (uint)fileArray.Length, fileArray, 0);

        Marshal.FreeCoTaskMem(nativeFolder);
        nativeFiles.ForEach((x) =>
        {
            if (x != IntPtr.Zero) Marshal.FreeCoTaskMem(x);
        }); 
    }

Coming to the party late.

I found RandomEngy's solution useful, but modified it slightly to allow the selection of many files at once. Hope someone finds it useful.

    [DllImport("shell32.dll", SetLastError = true)]
    public static extern int SHOpenFolderAndSelectItems(IntPtr pidlFolder, uint cidl, [In, MarshalAs(UnmanagedType.LPArray)] IntPtr[] apidl, uint dwFlags);

    [DllImport("shell32.dll", SetLastError = true)]
    public static extern void SHParseDisplayName([MarshalAs(UnmanagedType.LPWStr)] string name, IntPtr bindingContext, [Out] out IntPtr pidl, uint sfgaoIn, [Out] out uint psfgaoOut);

    public static void OpenFolderAndSelectItem(string folderPath, List<string> files)
    {
        IntPtr nativeFolder;
        uint psfgaoOut;
        SHParseDisplayName(folderPath, IntPtr.Zero, out nativeFolder, 0, out psfgaoOut);

        if (nativeFolder == IntPtr.Zero)
        {
            // Log error, can't find folder
            return;
        }

        List<IntPtr> nativeFiles = new();
        foreach (string file in files)
        {
            IntPtr nativeFile;
            SHParseDisplayName(Path.Combine(folderPath, file), IntPtr.Zero, out nativeFile, 0, out psfgaoOut);
            if (nativeFile != IntPtr.Zero)
            {
                // Open the folder without the file selected if we can't find the file
                nativeFiles.Add(nativeFile);
            }
        }

        if (nativeFiles.Count == 0)
        {
            nativeFiles.Add(IntPtr.Zero);
        }

        IntPtr[] fileArray = nativeFiles.ToArray();

        SHOpenFolderAndSelectItems(nativeFolder, (uint)fileArray.Length, fileArray, 0);

        Marshal.FreeCoTaskMem(nativeFolder);
        nativeFiles.ForEach((x) =>
        {
            if (x != IntPtr.Zero) Marshal.FreeCoTaskMem(x);
        }); 
    }
半边脸i 2024-07-16 12:42:45
// suppose that we have a test.txt at E:\
string filePath = @"E:\test.txt";
if (!File.Exists(filePath))
{
    return;
}

// combine the arguments together
// it doesn't matter if there is a space after ','
string argument = "/select, \"" + filePath +"\"";

System.Diagnostics.Process.Start("explorer.exe", argument);
// suppose that we have a test.txt at E:\
string filePath = @"E:\test.txt";
if (!File.Exists(filePath))
{
    return;
}

// combine the arguments together
// it doesn't matter if there is a space after ','
string argument = "/select, \"" + filePath +"\"";

System.Diagnostics.Process.Start("explorer.exe", argument);
等你爱我 2024-07-16 12:42:45

如果您的路径包含逗号,则在使用 Process.Start(ProcessStartInfo) 时可以在路径周围加上引号。

但是,当使用 Process.Start(string, string) 时它将不起作用。 看起来 Process.Start(string, string) 实际上删除了参数内的引号。

这是一个对我有用的简单示例。

string p = @"C:\tmp\this path contains spaces, and,commas\target.txt";
string args = string.Format("/e, /select, \"{0}\"", p);

ProcessStartInfo info = new ProcessStartInfo();
info.FileName = "explorer";
info.Arguments = args;
Process.Start(info);

If your path contains comma's, putting quotes around the path will work when using Process.Start(ProcessStartInfo).

It will NOT work when using Process.Start(string, string) however. It seems like Process.Start(string, string) actually removes the quotes inside of your args.

Here is a simple example that works for me.

string p = @"C:\tmp\this path contains spaces, and,commas\target.txt";
string args = string.Format("/e, /select, \"{0}\"", p);

ProcessStartInfo info = new ProcessStartInfo();
info.FileName = "explorer";
info.Arguments = args;
Process.Start(info);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文