Apertura di una cartella in Explorer e selezione di un file


150

Sto cercando di aprire una cartella in Explorer con un file selezionato.

Il codice seguente produce un'eccezione file non trovato:

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

Come posso ottenere questo comando da eseguire in C #?

Risposte:


51

Usa questo metodo :

Process.Start(String, String)

Il primo argomento è un'applicazione (explorer.exe), il secondo argomento del metodo sono argomenti dell'applicazione eseguita.

Per esempio:

in CMD:

explorer.exe -p

in C #:

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

32
questo non seleziona il file come la risposta di Samuel Yangs
henon il

-p non è sufficiente per selezionare il file
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
è stato significativo per me :) non solo ha aperto la directory ma anche selezionato il file particolare :) grazie
InfantPro'Aravind '28

2
Funziona come un fascino ma qualsiasi idea come possiamo farlo per più file?
Pankaj,

7
Piccola nota, l'argomento / select con il percorso del file non sembra funzionare per me se il mio percorso del file utilizza barre. Quindi devo fare filePath = filePath.Replace ('/', '\\');
Victor Chelaru,

6
Come menzionato altrove, il percorso deve essere racchiuso tra virgolette: questo evita problemi con nomi di directory o file che contengono virgole.
Kaganar,

4
Stavo combattendo sul problema a volte l'approccio sopra non funzionava perché il file contiene una virgola. Se avessi letto il commento di Kaganar, mi avrebbe risparmiato un'ora di lavoro. Esorto Samuel Yang a modificare il codice sopra in: string argomento = @ "/ seleziona" + "\" "+ filePath +" \ ""
Wayne Lo

34

Se il percorso contiene virgole, l'inserimento di virgolette attorno al percorso funzionerà quando si utilizza Process.Start (ProcessStartInfo).

Tuttavia, NON funzionerà quando si utilizza Process.Start (stringa, stringa). Sembra che Process.Start (stringa, stringa) rimuova effettivamente le virgolette all'interno dei tuoi argomenti.

Ecco un semplice esempio che funziona per 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);

Questa dovrebbe essere la risposta accettata. Manca solo una corretta gestione delle eccezioni per vari possibili guasti (problema dei diritti, percorso errato, ecc.)
AFract

Questa è la risposta giusta, la risposta accettata non funziona, anche la risposta di Yang non funziona.
VK,

31

Vale solo i miei 2 centesimi, se il tuo nome file contiene spazi, ad esempio "c: \ Il mio file contiene Spaces.txt", dovrai racchiudere il nome del file tra virgolette, altrimenti Explorer supporrà che le altre parole siano argomenti diversi ...

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

4
In realtà no. L'esempio di @Samuel Yang funziona con percorsi con spazi (testato Win7)
Courtney Christensen,

8
Leggi la risposta di Phil Hustwick in basso sul perché dovresti mettere comunque delle virgolette
Akku,

18

La risposta di Samuel Yang mi ha fatto inciampare, ecco i miei 3 centesimi.

Adrian Hum ha ragione, assicurati di mettere le virgolette attorno al tuo nome file. Non perché non sia in grado di gestire gli spazi come sottolineato da Zourtney, ma perché riconoscerà le virgole (e possibilmente altri caratteri) nei nomi dei file come argomenti separati. Quindi dovrebbe sembrare come suggerito Adrian Hum.

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

1
E assicurati di assicurarti che filePathnon contenga "in esso. Questo personaggio è apparentemente illegale sui sistemi Windows, ma è consentito su tutti gli altri (ad esempio, i sistemi POSIXish), quindi è necessario ancora più codice se si desidera la portabilità.
binki,

14

Utilizzando Process.Startil explorer.execon il/select argomento funziona stranamente solo per percorsi lunghi meno di 120 caratteri.

Ho dovuto usare un metodo Windows nativo per farlo funzionare in tutti i casi:

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

Questo mi ha aiutato a riutilizzare una cartella. Process.Start ("explorer.exe", "/ select xxx") apre ogni volta una nuova cartella!
Mitkins,

ecco come dovrebbe essere fatto, vorrei anche creare una bandiera per sfgao, e passare quell'enum invece di uint
L.Trabacchin

Funziona anche se con un piccolo problema; la prima volta che la cartella è aperta non è evidenziata. Lo chiamo all'interno di un metodo di clic sul pulsante e, una volta aperta la cartella, se faccio nuovamente clic sul pulsante, evidenzia il file / la cartella selezionati. Quale potrebbe essere il problema?
Sach

13

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

Si noti che dovrebbe essere presente una virgola dopo / seleziona anziché spazio.


6

Devi inserire gli argomenti da passare ("/ select etc") nel secondo parametro del metodo 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

Il motivo più possibile per cui non trova il file è il percorso con spazi. Ad esempio, non troverà "explorer / select, c: \ space space \ space.txt".

Basta aggiungere doppie virgolette prima e dopo il percorso, come;

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

o fare lo stesso in C # con

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

1

Potrebbe essere un po 'eccessivo, ma mi piacciono le funzioni di comodità quindi prendi questa:

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

Questa è la funzione di estensione che uso come <stringa> .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;
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.