管理

c#回收站相关函数

Posted on 2022-10-21 10:55  lzhdim  阅读(102)  评论(0编辑  收藏  举报

清空回收站,可调用SHEmptyRecycleBin 函数,在shell32.dll,dwFlags参数指定清空回收站时,是否显示提示操作的对话框?显示删除过程的进度条? 静音操作?

注意:SHEmptyRecycleBin 函数必须在标识为STA的线程里才能成功调用


调用SHQueryRecycleBin 函数查询 指定目录(或者整个回收站,当pszRootPath参数为null时),有多少个被删除到回收站的项,以及它们占用多大的空间


在客户端的代码实现处不能确定调用SHEmptyRecycleBin 函数的线程是否是一个STA线程,或许它就是一个MTA线程,并且线程一旦在运行,就不能改变它的单位状态,也就是:不能调用Thread.SetApartmentState来设置已经在运行的线程的单位状态。.net默认的线程为MTA单位.因此想要成功调用SHEmptyRecycleBin 必须在STA的线程里;或者开启一个新的STA线程来操作:只有这样才能在不影响其他代码在实现的限制。

RecycleBinInfo类是对SHEmptyRecycleBin 函数和SHQueryRecycleBin 这两个函数的封装,如果用户调用RecycleBinInfo.SHEmptyRecycleBin 的任何一个重载都会在内部开启一个STA单位的线程,这样,在不影响外部线程单位状态的前提下实现清空回收站。

这里是代码实现,可导出为DLL

namespace RecycleBinMgr
{
    /*
     * 
     *  注意:使用此类必须将项目的目标平台改成x86,编译那边也选择x86
     *  
    */
    namespace RecycleBinHelper
    {
        using System;
        using System.Threading;
        using System.Runtime.InteropServices;


        [Flags]
        public enum SHERB : uint
        {
            /* #define SHERB_NOCONFIRMATION 0x00000001
            #define SHERB_NOPROGRESSUI 0x00000002
            #define SHERB_NOSOUND 0x00000004*/

            /// <summary>
            /// 不选择其他的三个项,不可与其他选项同时使用
            /// </summary>
            SHERB_GENNERAL = 0x00000000,

            /// <summary>
            /// 不显示确认删除的对话框
            /// </summary>
            SHERB_NOCONFIRMATION = 0x00000001,
            /// <summary>
            /// 不显示删除过程的进度条
            /// </summary>
            SHERB_NOPROGRESSUI = 0x00000002,
            /// <summary>
            /// 当删除完成时,不播放声音
            /// </summary>
            SHERB_NOSOUND = 0x00000004

        };


        [StructLayout(LayoutKind.Explicit, Pack = 2)]
        public struct SHQUERYRBINFO
        {
            //这个结构必须是用户显示编写偏移量才能准确获取数值
            [FieldOffset(0)]
            public int cbsize;
            [FieldOffset(4)]
            public long i64Size;
            [FieldOffset(12)]
            public long i64NumItems;
        };

        public static class LibWarp
        {
            /// <summary>
            /// 清空指定磁盘或目录的回收站的内容
            /// </summary>
            /// <param name="hwnd">对话框的句柄,通常应当设为NULL</param>
            /// <param name="RootPath">磁盘路径,如果要清空所有磁盘,设置为null值或空值</param>
            /// <param name="flags">SHERB枚举的值,一个或多个的组合</param>
            /// <returns>成功返回0,S_OK值,失败为其他的OLE定义值</returns>

            [DllImport("shell32.dll", CharSet = CharSet.Unicode, CallingConvention =
            CallingConvention.StdCall)]
            // [PreserveSig()]
            public static extern uint
            SHEmptyRecycleBinW(
            IntPtr hwnd,
            [In()]
            [MarshalAs(UnmanagedType.LPWStr,SizeConst=260)]
            string rootpath,
            SHERB flags);


            /// <summary>
            ///API的SHQueryRecycleBinW
            /// </summary>
            [DllImport("shell32.dll", CharSet = CharSet.Unicode)]
            public static extern uint SHQueryRecycleBinW(
            [In()]
            [MarshalAs(UnmanagedType.LPWStr,SizeConst=260)]
            string RootPath
            , ref SHQUERYRBINFO queyRBInfo);
        };

        internal class _rbState
        {
            private IntPtr _hwnd;
            private string _rootpath;
            private SHERB _sherb;
            private uint _rv;
            internal _rbState(IntPtr hwnd, string rootpath, SHERB sherb)
            {
                this._hwnd = hwnd;
                this._rootpath = rootpath;
                this._sherb = sherb;
                _rv = 0;
            }
            internal _rbState()
            {
                this._hwnd = IntPtr.Zero;
                this._rootpath = null;
                this._sherb = SHERB.SHERB_GENNERAL;
            }
            internal IntPtr Hwnd
            {
                get
                {
                    return this._hwnd;
                }
                set
                {
                    this._hwnd = value;
                }
            }
            internal string Rootpath
            {
                get
                {
                    return this._rootpath;
                }
                set
                {
                    this._rootpath = value;
                }
            }
            internal SHERB Sherb
            {
                get
                {
                    return this._sherb;
                }
                set
                {
                    this._sherb = value;
                }
            }
            internal uint Revalue
            {
                set
                {
                    this._rv = value;
                }
                get
                {
                    return this._rv;
                }
            }
            internal void
            ReSetState(IntPtr hwnd, string rootpath, SHERB sherb)
            {
                this._hwnd = hwnd;
                this._rootpath = rootpath;
                this._sherb = sherb;
            }
        };

        //回收站相关
        //解决不能删除的原因:调用线程必须是STA线程

        /// <summary>
        /// 查询回收站的大小和个数,以及从回收站清空文件
        /// 这个类是对SHQueryRecycleBinW函数和SHEmptyRecycleBinW函数的封装
        /// 调用EmptyRecycleBin方法,删除回收站的内容;调用QuerySizeRecycleBin,查询
        /// 回收站的大小和文件的个数
        /// </summary>
        public class RecycleBinInfo
        {
            /*
            * 注意:多个对象实例(不同引用的),如果调用EmptyRecycleBin方法的任何重载,
            * 它们的调用是顺序的,(就好象在单个线程里的调用是一样的)*/
            //--------------

            /*这个类的实现是,在内部创建一个线程调用wrokThread,这样做的原因是将对象完全封装起来,
            * 因为并不能确定用户调用SHEmptyRecycleBin函数的线程模式是否为STA模式,
            * SHEmptyRecycleBin函数必须在STA模式下才能正确调用,这个类采用一个折衷的方法来实现。
            * 当调用EmptyRecycleBin方法之一的重载,都在内部创建一个线程,将线程模式设置为STAThread
            *
            */

            private void wrokThread(object state)
            {
                //state对象转换_rbState
                lock (state)
                { /*同步*/
                    _rbState temp = (_rbState)state;

                    temp.Revalue = LibWarp.SHEmptyRecycleBinW(
                    temp.Hwnd,
                    temp.Rootpath,
                    temp.Sherb);
                    ((_rbState)state).Revalue = temp.Revalue;

                }
                this.ewh.Set();
            }
            /// <summary>
            /// 实例化一个RecycleBinInfo对象
            /// </summary>
            public RecycleBinInfo()
            {
                /*初始化对象*/
                this.ewh = new EventWaitHandle(
                false, EventResetMode.AutoReset,
                Guid.NewGuid().ToString());
            }
            /// <summary>
            /// 清空回收站,这个方法同SHEmptyRecycleBin函数一样调用
            /// </summary>
            /// <param name="hwnd">在调用SHEmptyRecycleBin期间,指向用来显示的对话框的父窗体的句柄
            /// 可为NULL值
            /// </param>
            /// <param name="rootpath">最大长度为260个字符的字符串,指定磁盘根目录或文件夹目录,可为null,则清空整个回收站的内容</param>
            /// <param name="dwFlags">SHERB枚举,可组合使用</param>
            /// <returns>成功返回0,否则为OLE定义的错误值</returns>
            public uint EmptyRecycleBin(IntPtr hwnd, string rootpath, SHERB dwFlags)
            {

                _rbState rvs = new _rbState(hwnd, rootpath, dwFlags);
                rvs.Revalue = 0x8000FFFF;


                long size, items;

                this.QuerySizeRecycleBin(out size, out items);
                if (size == 0)
                    return rvs.Revalue;

                lock (rvs)
                {
                    Thread t = new Thread(
                    new ParameterizedThreadStart(this.wrokThread));
                    t.SetApartmentState(ApartmentState.STA);
                    t.Start(rvs);
                }
                /* Console.WriteLine("aaa");测试了,同一个对象实例,依次调用EmptyRecycleBin
                的任何一个重载,其顺序总是:先被调用的,总是先运行,后面的--排队等待
                * 这样的原因是ewh是AUTO的,set之后,同样命名的对象就不会wait了
                */
                this.ewh.WaitOne();
                this.ewh.Reset();
                return rvs.Revalue;
            }

            /// <summary>
            /// 清空整个回收站的内容
            /// </summary>
            /// <returns>成功返回0,否则为OLE定义的错误值</returns>
            public uint EmptyRecycleBin()
            {
                _rbState rvs = new _rbState();
                rvs.Revalue = 0x8000FFFF;

                long size, items;

                this.QuerySizeRecycleBin(out size, out items);
                if (size == 0)
                    return rvs.Revalue;

                lock (rvs)
                {
                    Thread t = new Thread(
                    new ParameterizedThreadStart(this.wrokThread));
                    t.SetApartmentState(ApartmentState.STA);//将线程设置为STA
                    t.Start(rvs);

                }
                this.ewh.WaitOne();
                this.ewh.Reset();
                return rvs.Revalue;
            }
            /// <summary>
            /// 查询回收站的大小和文件个数。
            /// </summary>
            /// <param name="RBsize">总大小(以字节为单位)。</param>
            /// <param name="RBNumItems">删除的项目数量。</param>
            /// <returns>如果函数成功,返回0;否则返回OLE定义的错误值。</returns>
            public uint QuerySizeRecycleBin(out long RBsize, out long RBNumItems)
            {
                // 将初始值设置为-1,以便在查询失败时表示错误。
                RBsize = -1;
                RBNumItems = -1;

                SHQUERYRBINFO rbinfo = new SHQUERYRBINFO();
                rbinfo.cbsize = Marshal.SizeOf(rbinfo);

                // 使用null作为根路径调用SHQueryRecycleBinW函数,以获取回收站的信息。
                uint rv = LibWarp.SHQueryRecycleBinW(null, ref rbinfo);

                // 检查函数调用是否成功。
                if (rv == 0)
                {
                    // 函数调用成功,从rbinfo结构中获取大小和文件数量。
                    RBsize = rbinfo.i64Size;
                    RBNumItems = rbinfo.i64NumItems;
                }

                return rv;
            }
            /// <summary>
            /// 查询指定目录或磁盘下被删除到回收站的文件的总大小和个数。
            /// 如果设置为null,效果跟 QuerySizeRecycleBin(out long RBsize,out long RBNumItems )一样
            /// </summary>
            /// <param name="rootpath">指定的磁盘和目录</param>
            /// <param name="RBsize">总大小,按字节计算</param>
            /// <param name="RBNumItems">文件的个数</param>
            /// <returns>如果函数成功返回0,错误为其他OLE定义的错误值</returns>
            public uint QuerySizeRecycleBin(string rootpath, out long RBsize, out long RBNumItems)
            {

                RBsize = -1;
                RBNumItems = -1;
                SHQUERYRBINFO rbinfo = new SHQUERYRBINFO();
                rbinfo.cbsize = Marshal.SizeOf(rbinfo);

                uint rv = LibWarp.SHQueryRecycleBinW(rootpath, ref rbinfo);
                RBsize = rbinfo.i64Size;
                RBNumItems = rbinfo.i64NumItems;
                return rv;
            }
            #region 字段

            private EventWaitHandle ewh;
            /// <summary>
            /// HRSULT的E_UNEXCEPTED值
            /// </summary>
            public static readonly uint E_UNEXCEPTED = 0x8000FFFF;
            #endregion 字段
        };
    }
}

//main 调用

Feng.WinShellApi.RecycleBinInfo rb=new Feng.WinShellApi.RecycleBinInfo();
;
long size,items;
rb.QuerySizeRecycleBin(out size,out items);
Console.WriteLine(size);//单位为字节
Console.WriteLine(items);//个数
rb.EmptyRecycleBin(
IntPtr.Zero,
@"C:/Users/Feng/Desktop",
Feng.WinShellApi.SHERB.SHERB_GENNERAL);//只清空C:/Users/Feng/Desktop目录下的项
// rb.EmptyRecycleBin();//清空所有
Console.ReadKey(true);

 

Copyright © 2000-2022 Lzhdim Technology Software All Rights Reserved