Abrindo uma pasta no explorer e selecionando um arquivo


150

Estou tentando abrir uma pasta no explorer com um arquivo selecionado.

O código a seguir produz uma exceção de arquivo não encontrado:

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

Como posso obter esse comando para executar em c #?

Respostas:


51

Use este método :

Process.Start(String, String)

O primeiro argumento é um aplicativo (explorer.exe), o segundo argumento do método são argumentos do aplicativo que você executa.

Por exemplo:

em CMD:

explorer.exe -p

em c #:

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

32
isso não selecione o arquivo como Samuel Yangs resposta
Henon

-p não é suficiente para selecionar o arquivo
07/07

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
foi significativo para mim :) ele não apenas abriu o diretório, mas também selecionou o arquivo específico :) obrigado, obrigado.
InfantPro'Aravind '

2
Funciona como um encanto, mas qualquer idéia, como podemos fazer isso para vários arquivos?
Pankaj

7
Nota pequena, o argumento / select com o caminho do arquivo parece não funcionar para mim se o caminho do arquivo usar barras. Portanto, eu tenho que fazer filePath = filePath.Replace ('/', '\\');
Victor Chelaru

6
Como mencionado em outro lugar, seu caminho deve estar entre aspas - isso evita problemas com nomes de diretórios ou arquivos que contêm vírgulas.
Kaganar

4
Eu estava lutando contra o problema algumas vezes a abordagem acima não funcionou porque o arquivo contém uma vírgula. Se eu tivesse lido o comentário de Kaganar, teria me poupado uma hora de trabalho. Peço a Samuel Yang que modifique o código acima para: string argument = @ "/ select" + "\" "+ filePath +" \ "" #
405 Wayne Wayne Lo

34

Se o seu caminho contiver vírgula, colocar aspas no caminho funcionará ao usar Process.Start (ProcessStartInfo).

No entanto, ele NÃO funcionará ao usar Process.Start (string, string). Parece que Process.Start (string, string) na verdade remove as aspas dentro de seus argumentos.

Aqui está um exemplo simples que funciona para mim.

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

Essa deve ser a resposta aceita. Ele só não tem uma exceção adequada manipulação para várias falhas possíveis (emissão de direitos, caminho errado, etc)
AFract

Esta é a resposta certa, a resposta aceita não funciona, a resposta de Yang também não funciona.
VK

31

Apenas meus 2 centavos valem, se o seu nome de arquivo contiver espaços, por exemplo "c: \ Meu arquivo contém espaços.txt", será necessário cercar o nome do arquivo com aspas, caso contrário, o Explorer assumirá que as outras palavras são argumentos diferentes ...

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

4
Na verdade, não, você não. O exemplo de @Samuel Yang trabalha com caminhos com espaços (testado Win7)
Courtney Christensen

8
Leia resposta por Phil Hustwick abaixo sobre por que você deve colocar aspas em torno no entanto
Akku

18

A resposta de Samuel Yang me fez tropeçar, aqui estão meus 3 centavos.

Adrian Hum está certo, certifique-se de colocar aspas em torno de seu nome de arquivo. Não porque ele não pode manipular espaços como zourtney apontou, mas porque reconhece as vírgulas (e possivelmente outros caracteres) nos nomes de arquivos como argumentos separados. Então deve parecer como Adrian Hum sugeriu.

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

1
E certifique-se de garantir que filePathnão contenha "nele. Esse caractere é aparentemente ilegal nos sistemas Windows, mas permitido em todos os outros (por exemplo, sistemas POSIXish); portanto, você precisa de mais código se quiser portabilidade.
binki

14

Usando Process.Starton explorer.execom o /selectargumento estranhamente só funciona para caminhos menos de 120 caracteres.

Eu tive que usar um método nativo do Windows para fazê-lo funcionar em todos os casos:

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

Isso me ajudou a reutilizar uma pasta. Process.Start ("explorer.exe", "/ selecione xxx") abre uma nova pasta sempre!
Mitkins

é assim que deve ser feito, eu também iria criar uma bandeira para sfgao, e passar essa enumeração em vez de uint
L.Trabacchin

Isso funciona, embora com um pequeno problema; a primeira vez que a pasta é aberta, não é destacada. Eu chamo isso dentro de um método de clique no botão e, quando a pasta é aberta, se eu clicar no botão novamente, ele destaca o arquivo / pasta selecionado. Qual poderia ser o problema?
Sach

13

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

Observe que deve haver uma vírgula após / selecionar em vez de espaço.


6

Você precisa colocar os argumentos para passar ("/ select etc") no segundo parâmetro do método 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

O motivo mais possível para não encontrar o arquivo é o caminho com espaços. Por exemplo, ele não encontrará "explorer / select, c: \ space space \ space.txt".

Basta adicionar aspas duplas antes e depois do caminho, como;

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

ou faça o mesmo em C # com

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

1

Pode ser um pouco exagerado, mas eu gosto de funções de conveniência, então faça isso:

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

Esta é a função de extensão que eu uso como <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;
    }
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.