potisanのプログラミングメモ

趣味のプログラマーがプログラミング関係で気になったことや調べたことをいつでも忘れられるようにメモするブログです。はてなブログ無料版なので記事の上の方はたぶん広告です。記事中にも広告挿入されるみたいです。

C# 9 &Win32 API ごみ箱のファイル数とサイズを取得するクラス

実行するとドライブ毎のゴミ箱に存在するファイルの数とサイズを列挙します。

using System;
using System.IO;
using System.Runtime.InteropServices;

foreach (var driveInfo in DriveInfo.GetDrives())
{
    Console.WriteLine(driveInfo.Name);
    if (RecycleBinInfo.TryGetInfo(driveInfo.Name, out var info))
    {
        Console.WriteLine($"Size: {info.Size}");
        Console.WriteLine($"Number of items: {info.NumberOfItems}");
    }
    Console.WriteLine();
}

/// <summary>
/// 各ボリュームのゴミ箱の情報を取得します。
/// </summary>
public static class RecycleBinInfo
{
    private static class NativeMethod
    {
        [DllImport("shell32.dll")]
        public static extern int SHEmptyRecycleBin(
            IntPtr hwnd,
            [In] string pszRootPath,
            uint dwFlags);

        [DllImport("shell32.dll")]
        public static extern int SHQueryRecycleBin(
            [In] string pszRootPath,
            ref SHQUERYRBINFO pSHQueryRBInfo);
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct SHQUERYRBINFO
    {
        public uint cbSize;
        public long i64Size;
        public long i64NumItems;
    }

    [Flags]
    public enum EmptyRecycleBinFlags : uint
    {
        NoConfirmation = 0x1,
        NoPregressUI = 0x2,
        NoSound = 0x4
    }

    public static bool Empty(
        string rootPath,
        EmptyRecycleBinFlags flags,
        IntPtr windowHandle = default)
    {
        return NativeMethod.SHEmptyRecycleBin(windowHandle, rootPath, (uint)flags) == 0;
    }

    public static bool TryGetInfo(
        string rootPath,
        out (long Size, long NumberOfItems) result)
    {
        var rbi = new SHQUERYRBINFO()
        {
            cbSize = checked((uint)Marshal.SizeOf<SHQUERYRBINFO>())
        };

        if (NativeMethod.SHQueryRecycleBin(rootPath, ref rbi) == 0)
        {
            result = (rbi.i64Size, rbi.i64NumItems);
            return true;
        }
        else
        {
            result = default;
            return false;
        }
    }
}

2021/3/10:この記事は別のブログで投稿した記事を移動したものです。