Otwarcie folderu w eksploratorze i wybranie pliku


150

Próbuję otworzyć folder w eksploratorze z wybranym plikiem.

Poniższy kod tworzy wyjątek „nie znaleziono pliku”:

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

Jak mogę uzyskać to polecenie do wykonania w C #?

Odpowiedzi:


51

Użyj tej metody :

Process.Start(String, String)

Pierwszy argument to aplikacja (explorer.exe), drugi argument metody to argumenty uruchomionej aplikacji.

Na przykład:

w CMD:

explorer.exe -p

w C #:

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

32
nie powoduje to wybrania pliku takiego jak odpowiedź Samuela
Yangsa

-p nie wystarczy, aby wybrać plik
Jek

327
// 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);

1
to było dla mnie znaczące :) nie tylko otworzyło katalog, ale także wybrało konkretny plik :) dzięki pozdrawiam
InfantPro'Aravind '

2
To działa jak urok, ale jakikolwiek pomysł, jak możemy to zrobić dla wielu plików?
Pankaj

7
Mała uwaga, argument / select ze ścieżką pliku wydaje się nie działać, jeśli moja ścieżka pliku używa ukośników. Dlatego muszę zrobić filePath = filePath.Replace ('/', '\\');
Victor Chelaru,

6
Jak wspomniano w innym miejscu, ścieżka powinna być ujęta w cudzysłowy - zapobiega to problemom z nazwami katalogów lub plików, które zawierają przecinki.
Kaganar

4
Walczyłem z tym problemem, czasami powyższe podejście nie działało, ponieważ plik zawiera przecinek. Gdybym przeczytał komentarz Kaganara, zaoszczędziłoby mi to godzinę pracy. Namawiam Samuela Yang do zmodyfikowania powyższego kodu na: string argument = @ "/ select" + "\" "+ filePath +" \ ""
Wayne Lo,

34

Jeśli ścieżka zawiera przecinki, umieszczanie cudzysłowów wokół ścieżki będzie działać, gdy używasz Process.Start (ProcessStartInfo).

NIE zadziała jednak przy używaniu Process.Start (string, string). Wygląda na to, że Process.Start (string, string) faktycznie usuwa cudzysłowy z twoich argumentów.

Oto prosty przykład, który mi pasuje.

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);

To powinna być akceptowana odpowiedź. Po prostu brakuje odpowiedniej obsługi wyjątków dla różnych możliwych awarii (problem z prawami, zła ścieżka itp.)
AFract

To jest właściwa odpowiedź, zaakceptowana odpowiedź nie działa, odpowiedź Yanga również nie działa.
VK

31

Tylko moje 2 centy warte, jeśli nazwa twojego pliku zawiera spacje, np. „C: \ Mój plik zawiera spacje.txt”, musisz ująć nazwę pliku w cudzysłów, w przeciwnym razie eksplorator założy, że te słowa są różnymi argumentami ...

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

4
Właściwie nie, nie masz. Przykład @Samuel Yang działa ze ścieżkami ze spacjami (testowane Win7)
Courtney Christensen

8
Przeczytaj odpowiedź Phila Hustwicka poniżej, aby mimo to umieścić cytaty
Akku,

18

Odpowiedź Samuela Yang zaskoczyła mnie, oto moje 3 centy warte.

Adrian Hum ma rację, upewnij się, że nazwa pliku jest umieszczona w cudzysłowie. Nie dlatego, że nie obsługuje spacji, jak wskazał zourtney, ale dlatego, że rozpozna przecinki (i prawdopodobnie inne znaki) w nazwach plików jako oddzielne argumenty. Powinno więc wyglądać tak, jak zasugerował Adrian Hum.

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

1
I upewnij się, że filePathto nie zawiera ". Ten znak jest najwyraźniej nielegalny w systemach Windows, ale dozwolony we wszystkich innych (np. Systemach POSIXish), więc potrzebujesz jeszcze więcej kodu, jeśli chcesz przenośności.
binki

14

Używanie Process.Starton explorer.exez /selectargumentem dziwnie działa tylko dla ścieżek krótszych niż 120 znaków.

Musiałem użyć natywnej metody Windows, aby działała we wszystkich przypadkach:

[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);
    }
}

Pomogło mi to ponownie użyć jednego folderu. Process.Start („explorer.exe”, „/ select xxx”) otwiera nowy folder za każdym razem!
Mitkins

to w jaki sposób należy to zrobić, chciałbym też stworzyć flagę sfgao i przekazać tę enum zamiast uint
L.Trabacchin

To działa, chociaż z małym problemem; gdy folder jest otwierany po raz pierwszy, nie jest podświetlony. Nazywam to metodą klikania przycisku, a gdy folder jest otwarty, jeśli ponownie kliknę przycisk, podświetla wybrany plik / folder. Jaki może być problem?
Sach

13

Użyj „/select,c:\file.txt”

Zauważ, że po / select zamiast spacji powinien znajdować się przecinek.


6

Musisz umieścić argumenty do przekazania („/ select etc”) w drugim parametrze metody Start.


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)

5

Najbardziej prawdopodobnym powodem, dla którego nie może znaleźć pliku, jest ścieżka zawierająca spacje. Na przykład nie znajdzie „explorer / select, c: \ space space \ space.txt”.

Po prostu dodaj cudzysłowy przed i po ścieżce, na przykład;

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

lub zrób to samo w C # z

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

1

Może to być trochę przesada, ale lubię funkcje zapewniające wygodę, więc weź tę:

    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);
    }

To jest funkcja rozszerzenia, której używam jako <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;
    }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.