gpt4 book ai didi

c# - 发送文件到回收站,大文件永久删除

转载 作者:可可西里 更新时间:2023-11-01 07:46:55 25 4
gpt4 key购买 nike

好的,在 .net 中有两种方法可以将文件发送到回收站,使用 Microsoft.VisualBasic.FileIO.FileSystem.DeleteFile 或使用 SHFileOperation。两者都很好,但如果文件无法放入回收站,它们将永久删除文件。如果文件太大或者只是不删除它,它是否有可能抛出异常或返回 bool 值? (不要默认确认对话框)

我得到的一种方法是获取该卷允许的最大回收站大小,然后减去已用大小并检查文件是否将发送到 RB 或永久删除,但如果删除许多文件并再次检查可能会变坏又一次。

还有什么我可以尝试的吗?

最佳答案

这道题并没有我一开始想的那么简单。但是,我发现它仍然可以解决。

首先,您需要了解回收站的使用量。 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 上)用户可以确定他们为(几乎)每个驱动器上的回收站保留多少大小。因此,您需要知道我们可以获得的每个驱动器的回收站的最大容量。此信息可在注册表中找到。但我们还需要检索所有驱动器的 guid:

/// <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's recycle bin's 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));
}

我们要做的最后一件事是将 guid 映射到驱动器号。我们仍然需要使用注册表:

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

只要传递guid就可以得到盘号:

string code = MapDriveLetter("{f4b90148-66f6-11e3-9ac5-806e6f6e6963}");

将所有信息结合在一起,您应该能够知道在哪个驱动器上,系统可能会永久删除一个或多个文件的大小。

关于c# - 发送文件到回收站,大文件永久删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21406508/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com