Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for printany.cs

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.IO;
  5. using System.Management;
  6. using Microsoft.Win32;
  7.  
  8.  
  9. namespace RobvanderWoude
  10. {
  11. 	class PrintAny
  12. 	{
  13. 		public static string progver = "3.04";
  14.  
  15. 		// Remember last file type, this may save lots of time searching for the associated Print(To) commands or verbs
  16. 		public static string lasttype = string.Empty;
  17. 		public static string lastprintcommand = string.Empty;
  18. 		public static bool skipprintercheck = false;
  19. 		public static bool skipverbs = false;
  20.  
  21.  
  22. 		static int Main( string[] args )
  23. 		{
  24. 			try
  25. 			{
  26. 				#region Command Line Parsing
  27.  
  28. 				string filespec = string.Empty;
  29. 				string printer = string.Empty;
  30. 				string option = string.Empty;
  31.  
  32. 				if ( args.Length == 0 )
  33. 				{
  34. 					return ShowHelp( );
  35. 				}
  36. 				if ( args.Length > 4 )
  37. 				{
  38. 					return ShowHelp( "Too many command line arguments" );
  39. 				}
  40.  
  41. 				foreach ( string arg in args )
  42. 				{
  43. 					if ( arg[0] == '/' )
  44. 					{
  45. 						if ( arg == "/?" )
  46. 						{
  47. 							return ShowHelp( );
  48. 						}
  49. 						else if ( arg.ToUpper( ) == "/NP" )
  50. 						{
  51. 							if ( skipprintercheck )
  52. 							{
  53. 								return ShowHelp( "Duplicate command line switch /NP" );
  54. 							}
  55. 							skipprintercheck = true;
  56. 						}
  57. 						else if ( arg.ToUpper( ) == "/NV" )
  58. 						{
  59. 							if ( skipverbs )
  60. 							{
  61. 								return ShowHelp( "Duplicate command line switch /NV" );
  62. 							}
  63. 							skipverbs = true;
  64. 						}
  65. 						else
  66. 						{
  67. 							return ShowHelp( "Invalid command line switch {0}", arg );
  68. 						}
  69. 					}
  70. 					else if ( string.IsNullOrEmpty( filespec ) )
  71. 					{
  72. 						filespec = arg;
  73. 					}
  74. 					else if ( string.IsNullOrEmpty( printer ) )
  75. 					{
  76. 						printer = arg;
  77. 					}
  78. 					else
  79. 					{
  80. 						return ShowHelp( "Invalid command line argument \"{0}\"", arg );
  81. 					}
  82. 				}
  83.  
  84. 				if ( !string.IsNullOrWhiteSpace( printer ) && !PrinterExists( printer ) )
  85. 				{
  86. 					return ShowHelp( "Printer not found: \"{0}\"", printer );
  87. 				}
  88.  
  89. 				#endregion
  90.  
  91.  
  92. 				// Use the current directory if no directory was specified
  93. 				if ( filespec.IndexOf( '\\' ) == -1 )
  94. 				{
  95. 					filespec = Path.Combine( Directory.GetCurrentDirectory( ), filespec );
  96. 				}
  97.  
  98. 				// Get a list of all files in the specified directory
  99. 				string[] files = Directory.GetFiles( Path.GetDirectoryName( filespec ), Path.GetFileName( filespec ) );
  100.  
  101. 				// Iterate through the list of all files . . .*/
  102. 				foreach ( string file in files )
  103. 				{
  104. 					PrintFile( file, printer );
  105. 				}
  106.  
  107. 				return 0;
  108. 			}
  109. 			catch ( Exception e )
  110. 			{
  111. 				return ShowHelp( e.Message );
  112. 			}
  113. 		}
  114.  
  115.  
  116. 		public static int ExecutePrintCommand( string printcommand )
  117. 		{
  118. 			try
  119. 			{
  120. 				string command = string.Empty;
  121. 				string arguments = string.Empty;
  122.  
  123. 				if ( printcommand.StartsWith( "\"" ) )
  124. 				{
  125. 					// Strip leading doublequote from command
  126. 					command = printcommand.Substring( 1 );
  127. 					// Arguments are everything following trailing doublequote of command
  128. 					arguments = command.Substring( command.IndexOf( '"' ) + 1 );
  129. 					// Strip trailing doublequote from command
  130. 					command = command.Substring( 0, command.IndexOf( '"' ) );
  131. 				}
  132. 				else
  133. 				{
  134. 					// Command is first "word" of string
  135. 					command = printcommand.Substring( 0, printcommand.IndexOf( ' ' ) );
  136. 					// Arguments is the rest of the string
  137. 					arguments = printcommand.Substring( printcommand.IndexOf( ' ' ) + 1 );
  138. 				}
  139.  
  140. 				ProcessStartInfo prog = new ProcessStartInfo( command );
  141. 				prog.Arguments = arguments;
  142. 				prog.CreateNoWindow = true;
  143. 				prog.UseShellExecute = true;
  144.  
  145. 				Process proc = new Process( );
  146. 				proc.StartInfo = prog;
  147. 				proc.Start( );
  148. 				proc.CloseMainWindow( );
  149. 				proc.Close( );
  150.  
  151. 				Console.WriteLine( printcommand );
  152. 				return 0;
  153. 			}
  154. 			catch ( Exception e )
  155. 			{
  156. 				return ShowHelp( e.Message );
  157. 			}
  158. 		}
  159.  
  160.  
  161. 		// Search the registry for the required Print(To) command
  162. 		public static string GetRegPrintCommand( string file, string printer )
  163. 		{
  164. 			string ext = Path.GetExtension( file );
  165. 			RegistryKey hkcrext = Registry.ClassesRoot.OpenSubKey( ext );
  166. 			string ftype = hkcrext.GetValue( "" ).ToString( );
  167.  
  168. 			RegistryKey curver = Registry.ClassesRoot.OpenSubKey( ftype + "\\CurVer" );
  169. 			if ( curver != null )
  170. 			{
  171. 				ftype = curver.GetValue( "" ).ToString( );
  172. 			}
  173.  
  174. 			string printcmd = string.Empty;
  175. 			RegistryKey hkcrprint = Registry.ClassesRoot.OpenSubKey( ftype + "\\shell\\Print\\command" );
  176. 			if ( hkcrprint != null )
  177. 			{
  178. 				printcmd = hkcrprint.GetValue( "" ).ToString( );
  179. 			}
  180.  
  181. 			string printtocmd = string.Empty;
  182. 			RegistryKey hkcrprintto = Registry.ClassesRoot.OpenSubKey( ftype + "\\shell\\Printto\\command" );
  183. 			if ( hkcrprintto != null )
  184. 			{
  185. 				printtocmd = hkcrprintto.GetValue( "" ).ToString( );
  186. 			}
  187.  
  188. 			try
  189. 			{
  190. 				hkcrext.Close( );
  191. 				curver.Close( );
  192. 				hkcrprint.Close( );
  193. 				hkcrprintto.Close( );
  194. 			}
  195. 			catch { } // If a key cannot be closed, we'll just ignore it
  196.  
  197. 			if ( string.IsNullOrWhiteSpace( printer ) )
  198. 			{
  199. 				return printcmd;
  200. 			}
  201. 			else
  202. 			{
  203. 				return printtocmd;
  204. 			}
  205. 		}
  206.  
  207.  
  208. 		public static bool PrinterExists( string printer )
  209. 		{
  210. 			if ( skipprintercheck )
  211. 			{
  212. 				return true;
  213. 			}
  214. 			string query = String.Format( "SELECT * FROM Win32_Printer WHERE Name='{0}'", printer.Replace( @"\", @"\\" ) );
  215. 			ManagementObjectSearcher searcher = new ManagementObjectSearcher( "root\\CIMV2", query );
  216. 			int found = searcher.Get( ).Count;
  217. 			if ( found == 1 )
  218. 			{
  219. 				return true;
  220. 			}
  221. 			else
  222. 			{
  223. 				return false;
  224. 			}
  225. 		}
  226.  
  227.  
  228. 		// Print a single specified file to the specified (or default) printer
  229. 		public static int PrintFile( string file, string printer )
  230. 		{
  231. 			if ( !skipverbs )
  232. 			{
  233. 				// First we'll try to use the Print or PrintTo Verbs, if available
  234. 				bool printverb = false;
  235. 				bool printtoverb = false;
  236. 				ProcessStartInfo fileinfo = new ProcessStartInfo( file );
  237. 				fileinfo.UseShellExecute = true;
  238. 				if ( fileinfo.Verbs.Length > 0 )
  239. 				{
  240. 					foreach ( string verb in fileinfo.Verbs )
  241. 					{
  242. 						if ( verb.ToLower( ) == "print" )
  243. 						{
  244. 							printverb = true;
  245. 						}
  246. 						if ( verb.ToLower( ) == "printto" )
  247. 						{
  248. 							printtoverb = true;
  249. 						}
  250. 					}
  251. 				}
  252.  
  253. 				if ( string.IsNullOrWhiteSpace( printer ) )
  254. 				{
  255. 					if ( printverb )
  256. 					{
  257. 						fileinfo.Verb = "Print";
  258. 						Process proc = new Process( );
  259. 						proc.StartInfo = fileinfo;
  260. 						proc.Start( );
  261. 						Console.WriteLine( "Print \"{0}\"", file );
  262. 						return 0;
  263. 					}
  264. 				}
  265. 				else
  266. 				{
  267. 					if ( printtoverb )
  268. 					{
  269. 						fileinfo.Verb = "PrintTo";
  270. 						fileinfo.Arguments = printer;
  271. 						Process proc = new Process( );
  272. 						proc.StartInfo = fileinfo;
  273. 						proc.Start( );
  274. 						Console.WriteLine( "PrintTo \"{0}\", \"{1}\"", file, printer );
  275. 						return 0;
  276. 					}
  277. 				}
  278. 			}
  279.  
  280. 			// If the required Verb is not available, we'll try it the old-fashioned
  281. 			// way by reading the Print or PrintTo command from the registry
  282. 			string printcmd = GetRegPrintCommand( file, printer );
  283.  
  284. 			// Now we have to substitute "%1" and "%2" in the Print(To) command withe the properly escaped and trimmed parameters 
  285. 			if ( printcmd.IndexOf( "%1" ) == -1 )
  286. 			{
  287. 				return ShowHelp( "Command line printing not available for file type " + Path.GetExtension( file ) );
  288. 			}
  289. 			printcmd = printcmd.Replace( "%1", "\"" + file + "\"" );
  290. 			printcmd = printcmd.Replace( @"""""", @"""" );
  291. 			if ( printcmd.IndexOf( "%2" ) == -1 )
  292. 			{
  293. 				if ( !string.IsNullOrWhiteSpace( printer ) )
  294. 				{
  295. 					return ShowHelp( "Printer cannot be specified for file type " + Path.GetExtension( file ) );
  296. 				}
  297. 			}
  298. 			else
  299. 			{
  300. 				printcmd = printcmd.Replace( "%2", "\"" + printer + "\"" );
  301. 				printcmd = printcmd.Replace( @"""""", @"""" );
  302. 			}
  303. 			printcmd = printcmd.Replace( "\"%3\"", "" );
  304. 			printcmd = printcmd.Replace( "%3", "" );
  305. 			printcmd = printcmd.Replace( "\"%4\"", "" );
  306. 			printcmd = printcmd.Replace( "%4", "" );
  307. 			return ExecutePrintCommand( printcmd );
  308. 		}
  309.  
  310.  
  311. 		public static int ShowHelp( params string[] errmsg )
  312. 		{
  313. 			/*
  314. 			PrintAny.exe,  Version 3.04
  315. 			Print files using the registered Print(To) command or verb for the file types
  316.  
  317. 			Usage:    PrintAny.exe  filespec  [ printer ]  [ options ]
  318.  
  319. 			Where:    filespec  the file(s) to be printed (wildcards allowed)
  320. 			          printer   the printer to be used
  321.  
  322. 			Options:  /NP       No Printer check: skip check for printer in WMI
  323. 			                    (may be necessary for network printers)
  324. 			          /NV       No Verb: force the program to find the Print(To) command
  325. 			                    in the registry (may be necessary for some combinations
  326. 			                    of file type and printer, e.g. PDFs on network printers)
  327.  
  328. 			Examples: PrintAny.exe "d:\some folder\some file.pdf"
  329. 			          PrintAny.exe "d:\some folder\some file.pdf" "Color Printer Sales Dept"
  330. 			          PrintAny.exe "d:\some folder\*.pdf" "\\server\printer" /NP /NV
  331.  
  332. 			Notes:    Use doublequotes if the file and/or printer names contain spaces.
  333. 			          The Print(To) verb or command is displayed for each matching file.
  334. 			          Not all file types have registered Print(To) commands or verbs.
  335.  
  336. 			Written by Rob van der Woude
  337. 			http://www.robvanderwoude.com
  338. 			*/
  339.  
  340. 			if ( errmsg.Length > 0 )
  341. 			{
  342. 				List<string> errargs = new List<string>( errmsg );
  343. 				errargs.RemoveAt( 0 );
  344. 				Console.Error.WriteLine( );
  345. 				Console.ForegroundColor = ConsoleColor.Red;
  346. 				Console.Error.Write( "ERROR:\t" );
  347. 				Console.ForegroundColor = ConsoleColor.White;
  348. 				Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
  349. 				Console.ResetColor( );
  350. 			}
  351.  
  352. 			Console.Error.WriteLine( );
  353.  
  354. 			Console.Error.WriteLine( "PrintAny.exe,  Version {0}", progver );
  355.  
  356. 			Console.Error.WriteLine( "Print files using the registered Print(To) command or verb for the file types" );
  357.  
  358. 			Console.Error.WriteLine( );
  359.  
  360. 			Console.Error.Write( "Usage:    " );
  361. 			Console.ForegroundColor = ConsoleColor.White;
  362. 			Console.Error.WriteLine( "PrintAny.exe  filespec  [ printer ]  [ options ]" );
  363. 			Console.ResetColor( );
  364.  
  365. 			Console.Error.WriteLine( );
  366.  
  367. 			Console.Error.Write( "Where:    " );
  368. 			Console.ForegroundColor = ConsoleColor.White;
  369. 			Console.Error.Write( "filespec" );
  370. 			Console.ResetColor( );
  371. 			Console.Error.WriteLine( "  the file(s) to be printed (wildcards allowed)" );
  372.  
  373. 			Console.ForegroundColor = ConsoleColor.White;
  374. 			Console.Error.Write( "          printer" );
  375. 			Console.ResetColor( );
  376. 			Console.Error.WriteLine( "   the printer to be used" );
  377.  
  378. 			Console.Error.WriteLine( );
  379.  
  380. 			Console.Error.Write( "Options:  " );
  381. 			Console.ForegroundColor = ConsoleColor.White;
  382. 			Console.Error.Write( "/NP       N" );
  383. 			Console.ResetColor( );
  384. 			Console.Error.Write( "o " );
  385. 			Console.ForegroundColor = ConsoleColor.White;
  386. 			Console.Error.Write( "P" );
  387. 			Console.ResetColor( );
  388. 			Console.Error.WriteLine( "rinter check: skip check for printer in WMI" );
  389.  
  390. 			Console.Error.WriteLine( "                    (may be necessary for network printers)" );
  391.  
  392. 			Console.ForegroundColor = ConsoleColor.White;
  393. 			Console.Error.Write( "          /NV       N" );
  394. 			Console.ResetColor( );
  395. 			Console.Error.Write( "o " );
  396. 			Console.ForegroundColor = ConsoleColor.White;
  397. 			Console.Error.Write( "V" );
  398. 			Console.ResetColor( );
  399. 			Console.Error.WriteLine( "erb: force the program to find the Print(To) command" );
  400.  
  401. 			Console.Error.WriteLine( "                    in the registry (may be necessary for some combinations" );
  402.  
  403. 			Console.Error.WriteLine( "                    of file type and printer, e.g. PDFs on network printers)" );
  404.  
  405. 			Console.Error.WriteLine( );
  406.  
  407. 			Console.Error.WriteLine( "Examples: PrintAny.exe \"d:\\some folder\\some file.doc\"" );
  408.  
  409. 			Console.Error.WriteLine( "          PrintAny.exe \"d:\\some folder\\some file.pdf\" \"Color Printer Sales\"" );
  410.  
  411. 			Console.Error.WriteLine( "          PrintAny.exe \"d:\\some folder\\*.pdf\" \"\\\\server\\printer\" /NP /NV" );
  412.  
  413. 			Console.Error.WriteLine( );
  414.  
  415. 			Console.Error.WriteLine( "Notes:    Use doublequotes if the file and/or printer names contain spaces." );
  416.  
  417. 			Console.Error.WriteLine( "          The Print(To) verb or command is displayed for each matching file." );
  418.  
  419. 			Console.Error.WriteLine( "          Not all file types have registered Print(To) commands or verbs." );
  420.  
  421. 			Console.Error.WriteLine( );
  422.  
  423. 			Console.Error.WriteLine( "Written by Rob van der Woude" );
  424.  
  425. 			Console.Error.WriteLine( "http://www.robvanderwoude.com" );
  426.  
  427. 			return 1;
  428. 		}
  429. 	}
  430. }
  431.  

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