Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for deltrash.cs

(view source code of deltrash.cs as plain text)

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Runtime.InteropServices;
  5.  
  6.  
  7. namespace RobvanderWoude
  8. {
  9. 	class DelTrash
  10. 	{
  11. 		static readonly string progver = "1.05";
  12.  
  13.  
  14. 		static int Main( string[] args )
  15. 		{
  16. 			#region Initialize Variables
  17.  
  18. 			int rc = 0;
  19. 			long totalsize = 0;
  20. 			int deleteditems = 0;
  21. 			int accessdenieddirs = 0;
  22. 			bool accessdenied = false;
  23. 			bool confirm = false;
  24. 			bool listonly = false;
  25. 			bool progress = false;
  26. 			bool quiet = false;
  27. 			bool verbose = false;
  28. 			RecycleFlags flags = RecycleFlags.RecycleNoSound;
  29. 			string drive = null; // default: All drives
  30. 			string windrive = Path.GetPathRoot( Environment.SystemDirectory );
  31.  
  32. 			#endregion Initialize Variables
  33.  
  34.  
  35. 			#region Parse Command Line
  36.  
  37. 			if ( args.Length > 3 )
  38. 			{
  39. 				return ShowHelp( );
  40. 			}
  41.  
  42. 			foreach ( string arg in args )
  43. 			{
  44. 				switch ( arg.ToUpper( ) )
  45. 				{
  46. 					case "/?":
  47. 						return ShowHelp( );
  48. 					case "/C":
  49. 						if ( confirm )
  50. 						{
  51. 							return ShowHelp( "Duplicate command line switch /C" );
  52. 						}
  53. 						confirm = true;
  54. 						break;
  55. 					case "/L":
  56. 						if ( listonly )
  57. 						{
  58. 							return ShowHelp( "Duplicate command line switch /L" );
  59. 						}
  60. 						listonly = true;
  61. 						break;
  62. 					case "/P":
  63. 						if ( progress )
  64. 						{
  65. 							return ShowHelp( "Duplicate command line switch /P" );
  66. 						}
  67. 						progress = true;
  68. 						break;
  69. 					case "/Q":
  70. 						if ( quiet )
  71. 						{
  72. 							return ShowHelp( "Duplicate command line switch /Q" );
  73. 						}
  74. 						if ( verbose )
  75. 						{
  76. 							return ShowHelp( "Switches /V and /Q are mutually exclusive" );
  77. 						}
  78. 						verbose = true;
  79. 						break;
  80. 					case "/V":
  81. 						if ( verbose )
  82. 						{
  83. 							return ShowHelp( "Duplicate command line switch /V" );
  84. 						}
  85. 						if ( quiet )
  86. 						{
  87. 							return ShowHelp( "Switches /V and /Q are mutually exclusive" );
  88. 						}
  89. 						verbose = true;
  90. 						break;
  91. 					case "/W":
  92. 						if ( drive != null )
  93. 						{
  94. 							if ( drive == windrive )
  95. 							{
  96. 								return ShowHelp( "Either specify a drive letter or use the /W switch, not both" );
  97. 							}
  98. 							else
  99. 							{
  100. 								return ShowHelp( "Duplicate drive specification {0} and {1}", drive, arg.ToUpper( ) );
  101. 							}
  102. 						}
  103. 						drive = windrive;
  104. 						break;
  105. 					default:
  106. 						bool validdrive = false;
  107. 						DriveInfo[] alldrives = DriveInfo.GetDrives( );
  108. 						foreach ( DriveInfo drvinf in alldrives )
  109. 						{
  110. 							if ( drvinf.Name.Equals( arg + "\\", StringComparison.OrdinalIgnoreCase ) )
  111. 							{
  112. 								if ( drvinf.DriveType == DriveType.Fixed ) // Local harddisks only
  113. 								{
  114. 									validdrive = true;
  115. 									drive = arg.ToUpper( );
  116. 								}
  117. 								else
  118. 								{
  119. 									return ShowHelp( "Drive \"{0}\" is not a local harddisk", arg );
  120. 								}
  121. 							}
  122. 						}
  123. 						if ( !validdrive )
  124. 						{
  125. 							return ShowHelp( "Invalid command line argument \"{0}\"", arg );
  126. 						}
  127. 						break;
  128. 				}
  129. 			}
  130.  
  131. 			verbose = verbose || listonly;
  132.  
  133. 			if ( !confirm )
  134. 			{
  135. 				flags |= RecycleFlags.RecycleNoConfirmation;
  136. 			}
  137. 			if ( !progress )
  138. 			{
  139. 				flags |= RecycleFlags.RecycleNoProgressUI;
  140. 			}
  141.  
  142. 			#endregion Parse Command Line
  143.  
  144.  
  145. 			#region Verbose Output
  146.  
  147. 			if ( verbose )
  148. 			{
  149. 				foreach ( DriveInfo diskdrive in DriveInfo.GetDrives( ) )
  150. 				{
  151. 					if ( diskdrive.Name.StartsWith( drive, StringComparison.OrdinalIgnoreCase ) )
  152. 					{
  153. 						if ( diskdrive.DriveType == DriveType.Fixed ) // local harddisks only
  154. 						{
  155. 							string recyclebin = Path.Combine( diskdrive.Name, "$RECYCLE.BIN" );
  156. 							if ( Directory.Exists( recyclebin ) )
  157. 							{
  158. 								long size = 0;
  159. 								int items = 0;
  160. 								string[] files = new string[0];
  161. 								string[] folders = Directory.GetDirectories( recyclebin );
  162. 								foreach ( string folder in folders )
  163. 								{
  164. 									try
  165. 									{
  166. 										// assuming any access denied will occur on the first directory level
  167. 										files = Directory.GetFiles( folder, "*.*", SearchOption.AllDirectories );
  168. 										foreach ( string file in files )
  169. 										{
  170. 											size += new FileInfo( file ).Length;
  171. 											items++;
  172. 										}
  173. 									}
  174. 									catch ( UnauthorizedAccessException )
  175. 									{
  176. 										accessdenied = true;
  177. 										accessdenieddirs++;
  178. 									}
  179. 								}
  180. 								if ( size > 129 )
  181. 								{
  182. 									if ( items == 1 )
  183. 									{
  184. 										Console.WriteLine( "Marking 1 file ({1}) from drive {2} for deletion", items, FormatBytes( size ), diskdrive.Name.Remove( 2 ) );
  185. 										totalsize += size;
  186. 										deleteditems += items;
  187. 									}
  188. 									else if ( items > 1 )
  189. 									{
  190. 										Console.WriteLine( "Marking {0} files ({1}) from drive {2} for deletion", items, FormatBytes( size ), diskdrive.Name.Remove( 2 ) );
  191. 										totalsize += size;
  192. 										deleteditems += items;
  193. 									}
  194. 								}
  195. 							}
  196. 						}
  197. 					}
  198. 				}
  199. 			}
  200.  
  201. 			#endregion Verbose Output
  202.  
  203.  
  204. 			#region Actual Deletion
  205.  
  206. 			if ( listonly )
  207. 			{
  208. 				Console.WriteLine( "\n{0} items with a total size of {1} would have been deleted.", deleteditems, FormatBytes( totalsize ) );
  209. 			}
  210. 			else
  211. 			{
  212. 				uint result = SHEmptyRecycleBin( IntPtr.Zero, drive, flags );
  213. 				if ( result == 0 )
  214. 				{
  215. 					if ( !quiet )
  216. 					{
  217. 						Console.WriteLine( "\n{0} items with a total size of {1} have been permanently deleted.", deleteditems, FormatBytes( totalsize ) );
  218. 						if ( accessdenied )
  219. 						{
  220. 							if ( accessdenieddirs == 1 )
  221. 							{
  222. 								Console.WriteLine( "Not all items could be removed permanently because access was denied to 1 directory." );
  223. 							}
  224. 							else
  225. 							{
  226. 								Console.WriteLine( "Not all items could be removed permanently because access was denied to {0} directories.", accessdenieddirs );
  227. 							}
  228. 						}
  229. 					}
  230. 					rc = 0;
  231. 				}
  232. 				else
  233. 				{
  234. 					if ( !quiet )
  235. 					{
  236. 						Console.WriteLine( "\nNot all items could be removed permanently." );
  237. 					}
  238. 					rc = 1;
  239. 				}
  240. 			}
  241.  
  242. 			#endregion Actual Deletion
  243.  
  244.  
  245. 			return rc;
  246. 		}
  247.  
  248.  
  249. 		static string FormatBytes( long bytes )
  250. 		{
  251. 			int KB = 1024;
  252. 			int MB = 1024 * KB;
  253. 			int GB = 1024 * MB;
  254. 			if ( bytes < KB )
  255. 			{
  256. 				return bytes.ToString( ) + " B";
  257. 			}
  258. 			else if ( bytes < MB )
  259. 			{
  260. 				return ( bytes / KB ).ToString( ) + " KB";
  261. 			}
  262. 			else if ( bytes < GB )
  263. 			{
  264. 				return ( bytes / MB ).ToString( ) + " MB";
  265. 			}
  266. 			else
  267. 			{
  268. 				return ( bytes / GB ).ToString( ) + " GB";
  269. 			}
  270. 		}
  271.  
  272.  
  273. 		static int ShowHelp( params string[] errmsg )
  274. 		{
  275. 			#region Error Message
  276.  
  277. 			if ( errmsg.Length > 0 )
  278. 			{
  279. 				List<string> errargs = new List<string>( errmsg );
  280. 				errargs.RemoveAt( 0 );
  281. 				Console.Error.WriteLine( );
  282. 				Console.ForegroundColor = ConsoleColor.Red;
  283. 				Console.Error.Write( "ERROR:\t" );
  284. 				Console.ForegroundColor = ConsoleColor.White;
  285. 				Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
  286. 				Console.ResetColor( );
  287. 			}
  288.  
  289. 			#endregion Error Message
  290.  
  291.  
  292. 			#region Help Text
  293.  
  294. 			/*
  295. 			DelTrash.exe,  Version 1.04
  296. 			Empty the Recycle Bin
  297.  
  298. 			Usage:   DelTrash.exe  [ drive: | /W ]  [ /C ]  [ /P ]  [ /L | /Q | /V ]
  299.  
  300. 			Where:   drive:  empty recycle bin on this drive only
  301. 			                 (default: all local harddisks)
  302. 			         /W      empty recycle bin on Windows' drive only
  303. 			                 (default: all local harddisks)
  304. 			         /C      prompt for Confirmation
  305. 			         /L      List only, do not delete
  306. 			         /P      show Progress bar
  307. 			         /Q      Quiet mode, no screen output
  308. 			         /V      Verbose mode, show number of files and total size per disk drive
  309.  
  310. 			Notes:   Switches /L and /Q and /V are mutually exclusive.
  311. 			         Return code is 0 if the Recycle Bin was emptied successfully, or 1
  312. 			         if there was nothing to delete or in case of (command line) errors.
  313.  
  314. 			Credits: Based on code by Vinoth Kumar
  315. 			         www.codeproject.com/Articles/20172/Empty-the-Recycle-Bin-using-C
  316. 			         Number of items and size calculation based on 
  317.  
  318. 			Written by Rob van der Woude
  319. 			https://www.robvanderwoude.com
  320. 			*/
  321.  
  322. 			#endregion Help Text
  323.  
  324.  
  325. 			#region Display Help Text
  326.  
  327. 			Console.Error.WriteLine( );
  328.  
  329. 			Console.Error.WriteLine( "DelTrash.exe,  Version {0}", progver );
  330.  
  331. 			Console.Error.WriteLine( "Empty the Recycle Bin" );
  332.  
  333. 			Console.Error.WriteLine( );
  334.  
  335. 			Console.Error.Write( "Usage:   " );
  336. 			Console.ForegroundColor = ConsoleColor.White;
  337. 			Console.Error.WriteLine( "DelTrash.exe  [ drive: | /W ]  [ /C ]  [ /P ]  [ /L | /Q | /V ]" );
  338. 			Console.ResetColor( );
  339.  
  340. 			Console.Error.WriteLine( );
  341.  
  342. 			Console.Error.Write( "Where:   " );
  343. 			Console.ForegroundColor = ConsoleColor.White;
  344. 			Console.Error.Write( "drive:" );
  345. 			Console.ResetColor( );
  346. 			Console.Error.WriteLine( "  empty recycle bin on this drive only" );
  347.  
  348. 			Console.Error.WriteLine( "                 (default: all local harddisks)" );
  349.  
  350. 			Console.ForegroundColor = ConsoleColor.White;
  351. 			Console.Error.Write( "         /W" );
  352. 			Console.ResetColor( );
  353. 			Console.Error.Write( "      empty recycle bin on " );
  354. 			Console.ForegroundColor = ConsoleColor.White;
  355. 			Console.Error.Write( "W" );
  356. 			Console.ResetColor( );
  357. 			Console.Error.WriteLine( "indows' drive only" );
  358.  
  359. 			Console.Error.WriteLine( "                 (default: all local harddisks)" );
  360.  
  361. 			Console.ForegroundColor = ConsoleColor.White;
  362. 			Console.Error.Write( "         /C" );
  363. 			Console.ResetColor( );
  364. 			Console.Error.Write( "      prompt for " );
  365. 			Console.ForegroundColor = ConsoleColor.White;
  366. 			Console.Error.Write( "C" );
  367. 			Console.ResetColor( );
  368. 			Console.Error.WriteLine( "onfirmation" );
  369.  
  370. 			Console.ForegroundColor = ConsoleColor.White;
  371. 			Console.Error.Write( "         /L      L" );
  372. 			Console.ResetColor( );
  373. 			Console.Error.WriteLine( "ist only, do not delete" );
  374.  
  375. 			Console.ForegroundColor = ConsoleColor.White;
  376. 			Console.Error.Write( "         /P" );
  377. 			Console.ResetColor( );
  378. 			Console.Error.Write( "      show " );
  379. 			Console.ForegroundColor = ConsoleColor.White;
  380. 			Console.Error.Write( "P" );
  381. 			Console.ResetColor( );
  382. 			Console.Error.WriteLine( "rogress bar" );
  383.  
  384. 			Console.ForegroundColor = ConsoleColor.White;
  385. 			Console.Error.Write( "         /Q      Q" );
  386. 			Console.ResetColor( );
  387. 			Console.Error.WriteLine( "uiet mode, no screen output" );
  388.  
  389. 			Console.ForegroundColor = ConsoleColor.White;
  390. 			Console.Error.Write( "         /V      V" );
  391. 			Console.ResetColor( );
  392. 			Console.Error.WriteLine( "erbose mode, show number of files and total size per disk drive" );
  393.  
  394. 			Console.Error.WriteLine( );
  395.  
  396. 			Console.Error.Write( "Notes:   Switches " );
  397. 			Console.ForegroundColor = ConsoleColor.White;
  398. 			Console.Error.Write( "/L" );
  399. 			Console.ResetColor( );
  400. 			Console.Error.Write( " and " );
  401. 			Console.ForegroundColor = ConsoleColor.White;
  402. 			Console.Error.Write( "/Q" );
  403. 			Console.ResetColor( );
  404. 			Console.Error.Write( " and " );
  405. 			Console.ForegroundColor = ConsoleColor.White;
  406. 			Console.Error.Write( "/V" );
  407. 			Console.ResetColor( );
  408. 			Console.Error.WriteLine( " are mutually exclusive." );
  409.  
  410. 			Console.Error.WriteLine( "         Return code is 0 if the Recycle Bin was emptied successfully, or 1" );
  411.  
  412. 			Console.Error.WriteLine( "         if there was nothing to delete or in case of (command line) errors." );
  413.  
  414. 			Console.Error.WriteLine( );
  415.  
  416. 			Console.Error.WriteLine( "Credits: Based on code by Vinoth Kumar" );
  417.  
  418. 			Console.ForegroundColor = ConsoleColor.DarkGray;
  419. 			Console.Error.WriteLine( "         www.codeproject.com/Articles/20172/Empty-the-Recycle-Bin-using-C" );
  420. 			Console.ResetColor( );
  421.  
  422. 			Console.Error.WriteLine( );
  423.  
  424. 			Console.Error.WriteLine( "Written by Rob van der Woude" );
  425.  
  426. 			Console.Error.WriteLine( "https://www.robvanderwoude.com" );
  427.  
  428. 			#endregion Display Help Text
  429.  
  430.  
  431. 			return 1;
  432. 		}
  433.  
  434.  
  435. 		public enum RecycleFlags : uint
  436. 		{
  437. 			RecycleNoConfirmation = 0x00000001,
  438. 			RecycleNoProgressUI = 0x00000002,
  439. 			RecycleNoSound = 0x00000004
  440. 		}
  441.  
  442.  
  443. 		[DllImport( "Shell32.dll", CharSet = CharSet.Unicode )]
  444. 		static extern uint SHEmptyRecycleBin( IntPtr hwnd, string pszRootPath, RecycleFlags dwFlags );
  445. 	}
  446. }

page last modified: 2024-04-16; loaded in 0.0124 seconds