Как я могу определить, что каталог является корзиной в C #?

StackOverflow https://stackoverflow.com/questions/1585295

  •  22-09-2019
  •  | 
  •  

Вопрос

Учитывая папку, как я могу определить, что это корзина?Я нашел ответ для C ++, но не для C #.

Моей первой идеей было проверить наличие атрибутов FileAttributes.System (что было бы приемлемым приближением в моем случае), но на самом деле этот флаг снят в папке recycle .

О грубых решениях, использующих жестко заданные имена папок, не может быть и речи (в конце концов, мы находимся в 2009 году).

Это было полезно?

Решение

Здесь есть небольшая проблема.Корзина Windows - это виртуальная папка, которая на самом деле не существует.Файлы, которые вы видите, на самом деле не находятся в этой папке, они представляют собой существующие файлы на диске, которые были переименованы в специальное имя, которое "удаляет" их из видимой файловой системы, но не из физической.

Вы можете "доказать" это сами, запросив местоположение папки с помощью win32 API.Это вернется E_FAIL для корзины, но не для других папок (см. SHGetKnownFolderPath на pinvoke.net (и на MSDN) для всех констант, которые вы можете использовать, и объявлений, необходимых для запуска этого кода):

IntPtr ptrRecycleBinPath;
// try it with KnownFolder.QuickLaunch to see it working:
HRESULT hr = (HRESULT) SHGetKnownFolderPath(
     KnownFolder.RecycleBinFolder, 
     0, 
     IntPtr.Zero, 
     out ptrRecycleBinPath);

if (hr == HRESULT.E_FAIL)
{
    Console.WriteLine("No folder avaialable, virtual folder");
}
else if (hr == HRESULT.S_OK)
{
    string RecycleBinPath = Marshal.PtrToStringUni(ptrRecycleBinPath);
    Marshal.FreeCoTaskMem(ptrRecycleBinPath);
    Console.WriteLine("path: " + RecycleBinPath);
}

// for convenience, you can use the code above
// directly if you paste the follow declarations in your class:

// get a "known path"
[DllImport("shell32.dll")]
static extern long SHGetKnownFolderPath(
    [MarshalAs(UnmanagedType.LPStruct)] Guid rfid, 
    uint dwFlags, 
    IntPtr hToken, 
    out IntPtr pszPath);

// known folder GUID declarations
public static class KnownFolder
{
    // many more entries exist, left out for clarity here

    public static readonly Guid RecycleBinFolder = 
         new Guid("B7534046-3ECB-4C18-BE4E-64CD4CB7D6AC");

    public static readonly Guid QuickLaunch = 
         new Guid("52a4f021-7b75-48a9-9f6b-4b87a210bc8f");

    //....
}

// results of COM invocations:
enum HRESULT : uint
{
    S_FALSE = 0x0001,
    S_OK = 0x0000,
    E_FAIL = 0x80004005,
    E_INVALIDARG = 0x80070057,
    E_OUTOFMEMORY = 0x8007000E
}

Поддельное имя папки "$Recycle.bin" (Корзинадля мусора) повторяется для каждого диска.Скрытое имя не хранится в реестре и недоступно API как таковому.Ранее предложенный KnownFolderHelper также не будет извлекать эту информацию (в той же библиотеке есть именованный метод для получения корзины, он также имеет GetPath, он окажется пустым).

Но еще не все потеряно.Это поддельное несуществующее "имя файла" или "имя папки" содержит скрытый файл, который выглядит примерно так "С-1-5-21-2703390745-3900912742-210389625-1000" (ваш будет другим).Это один из двух "надежных" способов узнать, действительно ли определенное имя файла является виртуальным каталогом корзины (другой способ заключается:удалить файл с помощью SHFileOperation, объяснено здесь, и проверьте, отображается ли он в папке, которая у вас есть):

string [] entries = Directory.GetFileSystemEntries(@"c:\$Recycle.bin", "?-?-?-??*");
if(entries.Length > 0)
   // we have a winner
else 
   // no, not the recycle bin

Примечание:Я не знаю, какие скрытые папки есть в других версиях win32, вам придется немного поэкспериментировать.Все они имеют установленный флаг system и hidden и выглядят как искаженный GUID.

Документы API не очень понятны по этому поводу, но если вам нужно подтверждение, на этой странице объясняется что на самом деле нет пути, который можно было бы извлечь (the более старая страница, связанная с CSIDL гораздо менее ясно об этом).

Обновить: альтернативные подходы с SHGetSpecialFolderPath, SHGetSpecialFolderLocation, ShellAPI.SHGetFolderLocation и SHGetPathFromIDList все терпят неудачу с одним и тем же:либо пустой результат, либо ошибка.Я протестировал все функции как для корзины, так и для AppData (чтобы убедиться, что я использовал правильные параметры).

Только документация по ShGetPathFromIDListEx сказал это прямо, цитирую: "За исключением имен принтеров UNC, если расположение, указанное параметром pidl, не является частью файловой системы, эта функция завершается с ошибкой"..

Другие советы

Корпорация Майкрософт Пакет кода Windows API содержит эту функциональность.

Чтобы получить папку корзины, используйте

Microsoft.WindowsAPICodePack.Shell.KnownFolderHelper.FromPath("::{645FF040-5081-101B-9F08-00AA002F954E}");

Я понятия не имею, что означает эта строка, но она была включена в документы как ссылка на корзину.

Надеюсь, это поможет :)

Большинство методов, связанных с корзиной, были написаны на C ++, как вы упомянули.Вы могли бы создать класс-оболочку в своем приложении, используя управляемые расширения для C ++, тогда вам придется использовать DllImport следующим образом:

using System;
using System.Runtime.InteropServices;

class MainApp
{
[DllImport("user32.dll", EntryPoint="MessageBox")]
public static extern int MessageBox(int hWnd, String strMessage, String
strCaption, uint uiType);

public static void Main()
{
MessageBox( 0, "Hello, this is PInvoke in operation!", ".NET", 0 );
}
}

Есть также статьи, которые делают это каким-то другим способом с C #, большинство из них используют PInvoke или полагаются на папку, в названии которой есть $ Recycle.Ниже приведены несколько ссылок, которые я нашел по этой теме

http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/05f1476f-a101-4766-847b-0bdf4f6ad397

http://www.codeproject.com/KB/shell/recyclebin.aspx

http://www.pinvoke.net/default.aspx/shell32.SHFileOperation

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top