Pergunta

Posso exibir e selecionar um único arquivo no Windows Explorer assim:

explorer.exe /select, "c:\path\to\file.txt"

No entanto, não consigo descobrir como selecionar mais de um arquivo.Nenhuma das permutações de select que tentei funciona.

Observação:Olhei essas páginas em busca de documentos, mas não ajudei.

https://support.microsoft.com/kb/314853
http://www.infocellar.com/Win98/explorer-switches.htm

Foi útil?

Solução

Isso deve ser possível com a função shell SHOpenFolderAndSelectItems

EDITAR

Aqui está um exemplo de código que mostra como usar a função em C/C++, sem verificação de erros:

//Directory to open
ITEMIDLIST *dir = ILCreateFromPath(_T("C:\\"));

//Items in directory to select
ITEMIDLIST *item1 = ILCreateFromPath(_T("C:\\Program Files\\"));
ITEMIDLIST *item2 = ILCreateFromPath(_T("C:\\Windows\\"));
const ITEMIDLIST* selection[] = {item1,item2};
UINT count = sizeof(selection) / sizeof(ITEMIDLIST);

//Perform selection
SHOpenFolderAndSelectItems(dir, count, selection, 0);

//Free resources
ILFree(dir);
ILFree(item1);
ILFree(item2);

Outras dicas

A verdadeira maneira de selecionar vários arquivos no Explorer é a próxima

O código não gerenciado se parece com isto (compilado de postagens de código da China com correção de bugs)

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

    [DllImport("shell32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr ILCreateFromPath([MarshalAs(UnmanagedType.LPTStr)] string pszPath);

    [ComImport]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [Guid("000214F9-0000-0000-C000-000000000046")]
    public interface IShellLinkW
    {
        [PreserveSig]
        int GetPath(StringBuilder pszFile, int cch, [In, Out] ref WIN32_FIND_DATAW pfd, uint fFlags);

        [PreserveSig]
        int GetIDList([Out] out IntPtr ppidl);

        [PreserveSig]
        int SetIDList([In] ref IntPtr pidl);

        [PreserveSig]
        int GetDescription(StringBuilder pszName, int cch);

        [PreserveSig]
        int SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);

        [PreserveSig]
        int GetWorkingDirectory(StringBuilder pszDir, int cch);

        [PreserveSig]
        int SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);

        [PreserveSig]
        int GetArguments(StringBuilder pszArgs, int cch);

        [PreserveSig]
        int SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);

        [PreserveSig]
        int GetHotkey([Out] out ushort pwHotkey);

        [PreserveSig]
        int SetHotkey(ushort wHotkey);

        [PreserveSig]
        int GetShowCmd([Out] out int piShowCmd);

        [PreserveSig]
        int SetShowCmd(int iShowCmd);

        [PreserveSig]
        int GetIconLocation(StringBuilder pszIconPath, int cch, [Out] out int piIcon);

        [PreserveSig]
        int SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);

        [PreserveSig]
        int SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, uint dwReserved);

        [PreserveSig]
        int Resolve(IntPtr hwnd, uint fFlags);

        [PreserveSig]
        int SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
    }

    [Serializable, StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode), BestFitMapping(false)]
    public struct WIN32_FIND_DATAW
    {
        public uint dwFileAttributes;
        public FILETIME ftCreationTime;
        public FILETIME ftLastAccessTime;
        public FILETIME ftLastWriteTime;
        public uint nFileSizeHigh;
        public uint nFileSizeLow;
        public uint dwReserved0;
        public uint dwReserved1;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string cFileName;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
        public string cAlternateFileName;
    }

    public static void OpenFolderAndSelectFiles(string folder, params string[] filesToSelect)
    {
        IntPtr dir = ILCreateFromPath(folder);

        var filesToSelectIntPtrs = new IntPtr[filesToSelect.Length];
        for (int i = 0; i < filesToSelect.Length; i++)
        {
            filesToSelectIntPtrs[i] = ILCreateFromPath(filesToSelect[i]);
        }

        SHOpenFolderAndSelectItems(dir, (uint) filesToSelect.Length, filesToSelectIntPtrs, 0);
        ReleaseComObject(dir);
        ReleaseComObject(filesToSelectIntPtrs);
    }

    private static void ReleaseComObject(params object[] comObjs)
    {
        foreach (object obj in comObjs)
        {
            if (obj != null && Marshal.IsComObject(obj))
                Marshal.ReleaseComObject(obj);
        }
    }
}

isso não pode ser feito através do explorer.exe

Dependendo do que você realmente deseja realizar, você poderá fazê-lo com AutoHotKey.É uma ferramenta gratuita incrível para automatizar coisas que você normalmente não pode fazer.Deve vir com o Windows.Este script selecionará seu arquivo e destacará os próximos dois arquivos abaixo dele quando você pressionar F12.

F12:: 
 run explorer.exe /select`, "c:\path\to\file.txt"
 SendInput {Shift Down}{Down}{Down}{Shift Up}
return

Também é possível simplesmente colocar essas duas linhas do meio em um arquivo de texto e depois passá-las como um parm para autohotkey.exe.Eles também têm a opção de compilar o script, o que o tornaria um exe independente que você poderia chamar.Funciona muito bem com um ótimo arquivo de ajuda.

@Orion, é possível usar o autohotkey do C#.Você pode transformar um script autohotkey em um executável independente (cerca de 400k) que pode ser iniciado pelo seu aplicativo C# (da mesma maneira que você está iniciando o Explorer).Você também pode passar parâmetros de linha de comando.Não possui nenhum requisito de tempo de execução.

Esta é uma daquelas questões em que pode ser bom considerar o que você está tentando alcançar e se existe um método melhor.

Para adicionar mais contexto - nossa empresa desenvolve um aplicativo C# cliente, que permite aos usuários carregar arquivos e fazer coisas com eles, como o iTunes gerencia seus arquivos MP3 sem mostrar o arquivo real no disco.

É útil selecionar um arquivo no aplicativo e executar o comando 'Mostre-me este arquivo no Windows Explorer' - é isso que estou tentando alcançar, e fiz isso para arquivos únicos.

Temos um ListView que permite aos usuários selecionar vários arquivos dentro do aplicativo e movê-los/excluí-los/etc.Seria bom que o comando 'mostre-me este arquivo no Windows' funcionasse para vários arquivos selecionados - pelo menos se todos os arquivos de origem estiverem no mesmo diretório, mas se não for possível, não será um recurso importante.

Suponho que você possa usar FindWindowEx para obter o SysListView32 do Windows Explorer e use SendMessage com LVM_SETITEMSTATE para selecionar os itens.A dificuldade é saber a posição dos itens...Talvez LVM_FINDITEM pode ser usado para isso.

Grr, eu gostaria de fazer isso também.O Media Player faz isso quando você seleciona mais de 2 arquivos, clica com o botão direito e "abre o local do arquivo", mas não sabe exatamente como (nem tenho vontade de gastar tempo com o procmon para descobrir).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top