Отправить файл в RecyleBin, большой файл получить постоянное удаление
Хорошо, есть два способа отправить файл в Recyle Bin в .net, либо используйте Microsoft.VisualBasic.FileIO.FileSystem.DeleteFile
, либо используйте SHFileOperation
. Оба работают хорошо, но они постоянно удаляют файл, если он не может помещаться внутри корзины.
Как-то возможно, что он может выбрасывать исключение или возвращать логическое значение, если файл слишком велик или просто не удаляет его? (Не требуется диалог подтверждения по умолчанию)
Один из способов получить максимальный размер корзины разрешен для тома, а затем вычесть использованный размер и проверить, будет ли файл отправляться в RB или удаленно навсегда, но он может стать плохим, если удалить много файлов и снова проверить и снова.
Что-нибудь еще я могу попробовать?
Ответы
Ответ 1
Что я могу собрать из вашего сообщения, так это то, что вы хотите удалить файлы, но не хотите их удалять, если они слишком велики для отправки в корзину. Ваши цели немного неясны, но кажется, что вы опасаетесь проверять корзину на каждый файл при удалении в целом.
Считайте это, если вы удаляете массовое количество, а некоторые из файлов могут переходить в корзину, а некоторые из них не подходят, но вы хотите, чтобы ваш пользователь мог восстановить эти файлы, а затем какие файлы в наборе получают в корзину, а какие нет?
Вы можете собрать размер всех файлов, а затем проверить это на корзине. Если он слишком велик, не удаляйте ни одного из них (или дайте постоянное удаление).
Если вы не пытаетесь переделать "Проводник", я бы предложил вместо этого использовать в вашем приложении папку с корзиной, которая даст вам больше контроля.
Ответ 2
Этот вопрос не так прост, как я думал в начале. Однако, я нашел, что все еще можно решить.
Прежде всего, вам нужно знать, сколько использовались корзины. Win32 SHQueryRecycleBin может сделать это за вас:
/// <summary>
/// Retrieves the size of the Recycle Bin and the number of items in it, of a specific drive
/// </summary>
/// <param name="pszRootPath">The path of the root drive on which the Recycle Bin is located</param>
/// <param name="pSHQueryRBInfo">A SHQUERYRBINFO structure that receives the Recycle Bin information</param>
/// <returns></returns>
[DllImport("shell32.dll")]
static extern int SHQueryRecycleBin(string pszRootPath, ref SHQUERYRBINFO pSHQueryRBInfo);
/// <summary>
/// Contains the size and item count information retrieved by the SHQueryRecycleBin function
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct SHQUERYRBINFO
{
/// <summary>
/// The size of the structure, in bytes
/// </summary>
public int cbSize;
/// <summary>
/// The total size of all the objects in the specified Recycle Bin, in bytes
/// </summary>
public long i64Size;
/// <summary>
/// The total number of items in the specified Recycle Bin
/// </summary>
public long i64NumItems;
}
Для получения этой информации используйте следующий демо-код:
const int S_OK = 0;
//string drivePath = @"C:\$RECYCLE.BIN\";
string drivePath = @"D:\$RECYCLE.BIN\";
SHQUERYRBINFO pSHQueryRBInfo = new SHQUERYRBINFO();
pSHQueryRBInfo.cbSize = Marshal.SizeOf(typeof(SHQUERYRBINFO));
int hresult = SHQueryRecycleBin(drivePath, ref pSHQueryRBInfo);
Console.WriteLine("{0} Drive {1} contains {2} item(s) in {3:#,##0} bytes",
hresult == S_OK ? "Success!" : "Fail!",
drivePath, pSHQueryRBInfo.i64NumItems, pSHQueryRBInfo.i64Size);
Во-вторых, (по крайней мере, на Win7) пользователи могут определить, сколько размеров они резервируют для корзины на (почти) каждом диске. Поэтому вам нужно знать максимальную емкость корзины для каждого диска, который мы можем получить. Эту информацию можно найти в реестре. Но нам также нужно получить подсказки для всех дисков:
/// <summary>
/// Get from the registry all the drive guids
/// </summary>
static string[] GetDriveIds()
{
const string registryPath = @"Software\Microsoft\Windows\CurrentVersion\Explorer\BitBucket\Volume\";
RegistryKey reg = Registry.CurrentUser.OpenSubKey(registryPath);
string[] readIn = reg.GetSubKeyNames();
string[] driveIds = new string[readIn.Length - 1];
Array.Copy(readIn, 1, driveIds, 0, readIn.Length - 1); // The first item must be removed
return driveIds;
}
/// <summary>
/// Get and return the drive recycle bin MaxCapacity
/// </summary>
/// <param name="driveId">The guid of the specified drive</param>
/// <returns>The size in mega bytes</returns>
static int FindDriveCapacity(string driveId)
{
const string registryPath = @"Software\Microsoft\Windows\CurrentVersion\Explorer\BitBucket\Volume\{0}\";
RegistryKey reg = Registry.CurrentUser.OpenSubKey(
string.Format(registryPath, driveId));
return (int)reg.GetValue("MaxCapacity", 0);
}
В следующем коде вы можете получить максимальную емкость для каждого диска:
string[] driveIds = GetDriveIds();
int driveNo = 0;
foreach (string driveId in driveIds)
{
Console.WriteLine("{0}. MaxCapacity of drive {1} is {2:#,##0} bytes",
++driveNo, driveId, FindDriveCapacity(driveId));
}
Последнее, что нам нужно сделать, - это сопоставить букву с буквой диска. Нам все еще нужно использовать реестр:
/// <summary>
/// Map the drive letter mapped by the drive ID
/// </summary>
/// <param name="driveId">The guid of the drive</param>
static string MapDriveLetter(string driveId)
{
const string registryPath = @"SYSTEM\MountedDevices";
RegistryKey reg = Registry.LocalMachine.OpenSubKey(registryPath);
string[] readIn = reg.GetValueNames();
byte[] keyCode = {};
Regex regGuid = new Regex(@"\{[^\}]+\}");
Regex regDriveLetter = new Regex(@"[A-Z]:$");
foreach (string keyRead in readIn) {
if (regGuid.IsMatch(keyRead) && regGuid.Match(keyRead).Value == driveId )
keyCode = (byte[])reg.GetValue(keyRead, null);
}
foreach (string keyRead in readIn)
{
byte[] codeRead = (byte[])reg.GetValue(keyRead, null);
if (!regGuid.IsMatch(keyRead) && keyCode.SequenceEqual(codeRead))
{
if (regDriveLetter.IsMatch(keyRead)) // Get the drive letter in the form "E:"
return regDriveLetter.Match(keyRead).Value;
}
}
return string.Empty;
}
Просто пропустите указатель, и вы можете получить номер диска:
string code = MapDriveLetter("{f4b90148-66f6-11e3-9ac5-806e6f6e6963}");
Со всей информацией, объединенной вместе, вы должны быть в состоянии сказать, на каком диске зависит размер файла или файлов, которые могут быть окончательно удалены системой.
Ответ 3
Вместо удаления файла переименуйте файл с другим путем, то есть в папку app_history. Метод переименования имеет два основных момента.
Вы можете переименовать часть пути файла, и если путь на том же самом диске, то переименование диска выполняется быстро, потому что изменяется только указатель на файл на диске. Если путь к другому диску, файл будет перемещен. Все это происходит автоматически в окнах os.
Программа физически не может удалять файлы, поэтому она никогда не может быть плохим нажатием на удаление неисправимого файла.
Здесь некоторые документы по методу переименования помните, что переименование в Windows может изменить путь к файлу.