Программный выбор нескольких файлов в проводнике Windows
-
08-06-2019 - |
Вопрос
Я могу отобразить и выбрать один файл в проводнике Windows следующим образом:
explorer.exe /select, "c:\path\to\file.txt"
Однако я не могу понять, как выбрать более одного файла.Ни одна из перестановок select, которые я пробовал, не работает.
Примечание:Я просмотрел документы на этих страницах, но ни то, ни другое не помогло.
https://support.microsoft.com/kb/314853
http://www.infocellar.com/Win98/explorer-switches.htm
Решение
Это должно быть возможно с помощью функции оболочки SHOpenFolderAndSelectItems
Редактировать
Вот несколько примеров кода, показывающих, как использовать функцию в C / C ++, без проверки ошибок:
//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);
Другие советы
Истинный способ выбора нескольких файлов в Проводнике следующий
Неуправляемый код выглядит следующим образом (скомпилирован из сообщений China code с исправлением ошибок)
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);
}
}
}
это не может быть сделано с помощью explorer.exe
В зависимости от того, чего вы на самом деле хотите достичь, вы можете сделать это с помощью Автоотключение.Это удивительный бесплатный инструмент для автоматизации того, что вы обычно не можете сделать.Он должен поставляться вместе с Windows.Этот скрипт выберет ваш файл и выделит следующие два файла под ним, когда вы нажмете клавишу F12.
F12::
run explorer.exe /select`, "c:\path\to\file.txt"
SendInput {Shift Down}{Down}{Down}{Shift Up}
return
Также можно просто поместить эти две средние строки в текстовый файл, а затем передать это parm в autohotkey.exe.У них также есть возможность скомпилировать скрипт, что сделало бы его автономным exe-файлом, который вы могли бы вызвать.Отлично работает с отличным файлом справки.
@Orion, можно использовать autohotkey из C #.Вы можете превратить скрипт autohotkey в автономный исполняемый файл (около 400 КБ), который может быть запущен вашим приложением на C # (точно так же, как вы запускаете explorer).Вы также можете передать ему параметры командной строки.У него нет никаких требований к времени выполнения.
Это один из тех вопросов, когда, возможно, было бы полезно рассмотреть, чего вы пытаетесь достичь, и есть ли лучший метод.
Чтобы добавить еще немного контекста - Наша компания разрабатывает клиентское приложение на C #, которое позволяет пользователям загружать файлы и что-то с ними делать, вроде того, как iTunes управляет вашими MP3-файлами, не показывая вам сам файл на диске.
Полезно выбрать файл в приложении и выполнить команду "Показать мне этот файл в проводнике Windows" - это то, чего я пытаюсь достичь, и сделал это для отдельных файлов.
У нас есть ListView, который позволяет пользователям выбирать несколько файлов в приложении и перемещать / удалять / etc их.Было бы неплохо, если бы эта команда "показать мне этот файл в Windows" работала для нескольких выбранных файлов - по крайней мере, если все исходные файлы находятся в одном каталоге, но если это невозможно, то это не является важной функцией.
Я полагаю, вы можете использовать FindWindowEx
чтобы получить SysListView32 проводника Windows, затем используйте SendMessage
с LVM_SETITEMSTATE
чтобы выбрать нужные элементы.Трудность заключается в том, чтобы знать расположение предметов...Возможно LVM_FINDITEM
может быть использован для этого.
Grr, я бы тоже хотел это сделать.Медиаплеер делает это, когда вы выбираете 2 + файла и щелкаете правой кнопкой мыши и делаете "открыть расположение файла", но не совсем уверен, как это сделать (и мне действительно не хочется тратить время на procmon, чтобы разобраться в этом).