Opening a folder in explorer and selecting a file
Asked Answered
U

13

185

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#?

Ursuline answered 2/12, 2008 at 16:42 Comment(0)
E
44

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")
Eskew answered 2/12, 2008 at 16:46 Comment(2)
this does not select the file like Samuel Yangs answerFelizio
-p is not enough to select the fileLungan
B
405
// 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);
Bypass answered 30/3, 2009 at 6:9 Comment(10)
it was significant for me :) it not only opened the directory but selected the particular file as well :) thanks regardsPiscine
It works like a charm but any Idea how can we do that for multiple files ?Caliginous
Small note, the /select argument with file path doesn't seem to work for me if my file path uses forward slashes. Therefore I have to do filePath = filePath.Replace('/', '\\');Symbolize
As mentioned elsewhere, your path should be contained in quotes -- this prevents problems with directory or file names that contain commas.Deandeana
I was battling on the issue sometimes the above approach did not work because the file contains a comma. If I had read Kaganar's comment, it would have saved me a hour of work. I urge Samuel Yang to modify above code to: string argument=@"/select"+"\"" + filePath+"\""Frunze
This is the most accurate response, and should be marked as the answer for this question.Macadam
even though this works, it sometimes does not select the files (first time mostly, as reported here: https://mcmap.net/q/130865/-open-a-folder-in-windows-explorer-and-select-a-file-works-second-time-only). I ended up using code from the following answer which manages the Shell API and supports multiple file selection: stackoverflow.com/a/3578581Bitters
Maybe it was just me, BUT the comma after the /select is required so "/select," otherwise it doesn't work as expected. If it is just me, does that mean I was the only one who didn't copy paste?Ship
This works well thank you. I do have one issue. If I have a long list of files in the folder, and my file is toward the bottom, the windows opens, the file is selected, but the user has to scroll down to the file. Is there a way to get the windows to scroll to the selected file?Numbersnumbfish
Will this work on Linux? I'm making app for Windows only but I'm just curious.Ruel
M
52

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);
Mammillary answered 28/3, 2012 at 9:38 Comment(3)
This should be the accepted answer. It just lacks a proper exception handling for various possible failures (rights issue, wrong path, etc)False
This is the right answer, the accepted answer does not work, Yang's answer also does not work.Janel
Please note that if the file is already selected in an explorer window, running this code will not open a new explorer window. It will use the existing window and selected the file.Morello
E
44

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")
Eskew answered 2/12, 2008 at 16:46 Comment(2)
this does not select the file like Samuel Yangs answerFelizio
-p is not enough to select the fileLungan
P
33

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 +"\"";
Pound answered 3/10, 2010 at 23:5 Comment(2)
Actually, no, you don't. @Samuel Yang's example works with paths with spaces (tested Win7)Digestant
Read answer by Phil Hustwick below on why you should put quotes around neverthelessMiltonmilty
A
28

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);
    }
}
Allude answered 10/9, 2016 at 15:8 Comment(5)
This helped me re-use one folder. Process.Start("explorer.exe", "/select xxx") opens a new folder every time!Jampan
this is how it should be done, i would also create an flag for sfgao, and pass that enum instead of uintCartography
This works although with a small problem; the first time the folder is open it's not highlighted. I call this inside a button click method, and once the folder is open if I click the button again, then it highlights the selected file/folder. What could be the problem?Buhl
This is the only solution that is consistent with professional software's "show in Explorer" functionality. (1) Re-use the same explorer process. (2) Re-use the same window whereas possible.Intelsat
I just checked it on Windows 11 by putting code inside button click. Worked perfectly with file as selected.Ephemera
R
18

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 +"\"";
Rowney answered 30/1, 2012 at 5:41 Comment(1)
And be sure to ensure that filePath doesn’t contain " in it. This character is apparently illegal on Windows systems but allowed on all others (e.g., POSIXish systems), so you need even more code if you want portability.Glaucoma
H
14

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

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

Hays answered 13/2, 2009 at 6:28 Comment(0)
S
9

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\"");
Scarlet answered 8/11, 2017 at 14:55 Comment(0)
E
6

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

Ethiop answered 2/12, 2008 at 16:46 Comment(0)
C
5
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)
Clintonclintonia answered 5/3, 2012 at 17:21 Comment(0)
F
3

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;
    }
}
Formalin answered 23/4, 2019 at 17:45 Comment(0)
H
3

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 = @$"/select, ""{filePath}"""
    });
}
Hemipterous answered 18/8, 2022 at 16:58 Comment(0)
Q
0

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);
        }); 
    }
Quassia answered 25/3 at 16:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.