c#回收站相关函数

本文介绍了如何在C#中使用SHEmptyRecycleBin和SHQueryRecycleBin函数来清空和查询回收站内容。由于SHEmptyRecycleBin函数必须在STA线程中调用,因此提供了RecycleBinInfo类,该类在内部创建一个STA线程以确保函数的正确执行。同时,给出了这两个函数的C#封装和示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

清空回收站,可调用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

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Threading;
using System.Runtime.InteropServices;

namespace Feng {
    namespace WinShellApi {
             [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);

            uint rv=    LibWarp.SHQueryRecycleBinW(null,ref 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);

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值