Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for printscreen.cs

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Drawing;
  5. using System.Drawing.Imaging;
  6. using System.IO;
  7. using System.Runtime.InteropServices;
  8. using System.Text;
  9. using System.Windows.Forms;
  10.  
  11.  
  12. namespace RobvanderWoude
  13. {
  14. 	class PrintScreen
  15. 	{
  16. 		static string progver = "1.04";
  17.  
  18.  
  19. 		static int Main( string[] args )
  20. 		{
  21. 			try
  22. 			{
  23. 				string outputfile = String.Empty;
  24. 				bool capturetext = false;
  25. 				bool generatename = false;
  26. 				bool overwrite = false;
  27. 				bool trimoutput = false;
  28. 				bool typeset = false;
  29. 				bool usestandardout = false;
  30. 				ImageFormat imagetype = null;
  31.  
  32. 				#region Command Line parsing
  33.  
  34. 				if ( args.Length == 0 || args.Length > 3 )
  35. 				{
  36. 					return ShowHelp( );
  37. 				}
  38.  
  39. 				foreach ( string arg in args )
  40. 				{
  41. 					switch ( arg.ToUpper( ).Substring( 0, 2 ) )
  42. 					{
  43. 						case "/?":
  44. 							return ShowHelp( );
  45. 						case "/C":
  46. 							if ( trimoutput )
  47. 							{
  48. 								return ShowHelp( "Duplicate command line switch /C" );
  49. 							}
  50. 							trimoutput = true;
  51. 							break;
  52. 						case "/O":
  53. 							if ( overwrite )
  54. 							{
  55. 								return ShowHelp( "Duplicate command line switch /O" );
  56. 							}
  57. 							overwrite = true;
  58. 							break;
  59. 						case "/S":
  60. 							if ( usestandardout )
  61. 							{
  62. 								return ShowHelp( "Duplicate command line switch /S" );
  63. 							}
  64. 							usestandardout = true;
  65. 							break;
  66. 						case "/T":
  67. 							if ( typeset )
  68. 							{
  69. 								return ShowHelp( "Duplicate command line switch /T" );
  70. 							}
  71. 							switch ( arg.ToUpper( ).Substring( 3 ) )
  72. 							{
  73. 								case "BMP":
  74. 									imagetype = ImageFormat.Bmp;
  75. 									break;
  76. 								case "GIF":
  77. 									imagetype = ImageFormat.Gif;
  78. 									break;
  79. 								case "JPG":
  80. 								case "JPEG":
  81. 									imagetype = ImageFormat.Jpeg;
  82. 									break;
  83. 								case "PNG":
  84. 									imagetype = ImageFormat.Png;
  85. 									break;
  86. 								case "TIF":
  87. 								case "TIFF":
  88. 									imagetype = ImageFormat.Tiff;
  89. 									break;
  90. 								case "TXT":
  91. 								case "TEXT":
  92. 									capturetext = true;
  93. 									break;
  94. 								default:
  95. 									return ShowHelp( "Invalid file format \"{0}\"", arg.Substring( 3 ) );
  96. 							}
  97. 							typeset = true;
  98. 							break;
  99. 						case "/U":
  100. 							if ( generatename )
  101. 							{
  102. 								return ShowHelp( "Duplicate command line switch /U" );
  103. 							}
  104. 							if ( !String.IsNullOrEmpty( outputfile ) )
  105. 							{
  106. 								return ShowHelp( "Do not specify a file name when using /U to generate one" );
  107. 							}
  108. 							generatename = true;
  109. 							break;
  110. 						default:
  111. 							if ( arg[0] == '/' )
  112. 							{
  113. 								return ShowHelp( "Invalid command line switch \"{0}\"", arg );
  114. 							}
  115. 							else
  116. 							{
  117. 								if ( !String.IsNullOrEmpty( outputfile ) )
  118. 								{
  119. 									return ShowHelp( "Duplicate output file name arguments:\n\t\"{0}\"\n\t\"{1}\"", outputfile, Path.GetFullPath( arg ) );
  120. 								}
  121. 								if ( generatename )
  122. 								{
  123. 									return ShowHelp( "Do not specify a file name when using /U to generate one" );
  124. 								}
  125. 								try
  126. 								{
  127. 									outputfile = Path.GetFullPath( arg );
  128. 								}
  129. 								catch ( Exception )
  130. 								{
  131. 									return ShowHelp( "Invalid output file \"{0}\"", arg );
  132. 								}
  133. 							}
  134. 							break;
  135. 					}
  136. 				}
  137.  
  138. 				if ( usestandardout )
  139. 				{
  140. 					if ( imagetype != null || overwrite || !String.IsNullOrEmpty( outputfile ) )
  141. 					{
  142. 						return ShowHelp( "Except /C no other command line switch can be used with /S" );
  143. 					}
  144. 					capturetext = true;
  145. 				}
  146. 				else if ( generatename )
  147. 				{
  148. 					// We are assuming that multiple instances, each using /U, will never "collide"
  149. 				}
  150. 				else
  151. 				{
  152. 					if ( String.IsNullOrEmpty( outputfile ) )
  153. 					{
  154. 						return ShowHelp( "No output file specified." );
  155. 					}
  156.  
  157. 					// Check if directory exists
  158. 					if ( !Directory.Exists( Directory.GetParent( outputfile ).FullName ) )
  159. 					{
  160. 						return ShowHelp( "Invalid path for output file \"{0}\"", outputfile );
  161. 					}
  162.  
  163. 					// Check if file exists, and if so, if it can be overwritten
  164. 					if ( File.Exists( outputfile ) )
  165. 					{
  166. 						if ( overwrite )
  167. 						{
  168. 							File.Delete( outputfile );
  169. 						}
  170. 						else
  171. 						{
  172. 							return ShowHelp( "Output file exists.\n\tUse /O to overwrite existing files." );
  173. 						}
  174. 					}
  175. 				}
  176.  
  177. 				if ( !generatename && !usestandardout && imagetype == null && capturetext == false )
  178. 				{
  179. 					string ext = Path.GetExtension( outputfile ).ToUpper( );
  180. 					switch ( ext )
  181. 					{
  182. 						case "":
  183. 							return ShowHelp( "No extension for output file.\n\tUse /T to specify the output file type.", outputfile );
  184. 						case ".BMP":
  185. 							imagetype = ImageFormat.Bmp;
  186. 							break;
  187. 						case ".GIF":
  188. 							imagetype = ImageFormat.Gif;
  189. 							break;
  190. 						case ".JPG":
  191. 						case ".JPEG":
  192. 							imagetype = ImageFormat.Jpeg;
  193. 							break;
  194. 						case ".PNG":
  195. 							imagetype = ImageFormat.Png;
  196. 							break;
  197. 						case ".TIF":
  198. 						case ".TIFF":
  199. 							imagetype = ImageFormat.Tiff;
  200. 							break;
  201. 						case ".TXT":
  202. 							capturetext = true;
  203. 							break;
  204. 						default:
  205. 							return ShowHelp( "Unrecognized extension \"{0}\" for output file.\n\tUse /T to specify the output file type.", ext );
  206. 					}
  207. 				}
  208.  
  209. 				if ( generatename )
  210. 				{
  211. 					if ( capturetext )
  212. 					{
  213. 						outputfile = GenerateUniqueFileName( "txt" );
  214. 					}
  215. 					else
  216. 					{
  217. 						if ( imagetype == null )
  218. 						{
  219. 							return ShowHelp( "/U switch requires /T switch as well" );
  220. 						}
  221. 						outputfile = GenerateUniqueFileName( imagetype.ToString( ) );
  222. 					}
  223. 				}
  224.  
  225. 				#endregion Command Line parsing
  226.  
  227. 				if ( capturetext )
  228. 				{
  229. 					// Based on code by Simon Mourier (http://www.softfluent.com/)
  230. 					// http://stackoverflow.com/questions/12355378/read-from-location-on-console-c-sharp
  231. 					string readtext = string.Empty;
  232. 					for ( short i = 0; i < (short) Console.BufferHeight; i++ )
  233. 					{
  234. 						foreach ( string line in ConsoleReader.ReadFromBuffer( 0, i, (short) Console.BufferWidth, 1 ) )
  235. 						{
  236. 							if ( trimoutput )
  237. 							{
  238. 								// Trim whitespace from the end of the line, based on a suggestion by Daniel Saul Dominguez
  239. 								readtext += line.TrimEnd( "\t ".ToCharArray( ) ) + "\n";
  240. 							}
  241. 							else
  242. 							{
  243. 								readtext += line + "\n";
  244. 							}
  245. 						}
  246. 					}
  247. 					readtext = readtext.TrimEnd( " \n\r\t".ToCharArray( ) );
  248. 					if ( usestandardout )
  249. 					{
  250. 						Console.Write( readtext );
  251. 					}
  252. 					else
  253. 					{
  254. 						StreamWriter file = new StreamWriter( outputfile );
  255. 						file.Write( readtext );
  256. 						file.Close( );
  257. 					}
  258. 				}
  259. 				else
  260. 				{
  261. 					// Based on code by Ali Hamdar (http://alihamdar.com/)
  262. 					// http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/79efecc4-fa6d-4078-afe4-bb1379bb968b
  263. 					// Default values for full screen
  264. 					int width = Screen.PrimaryScreen.Bounds.Width;
  265. 					int height = Screen.PrimaryScreen.Bounds.Height;
  266. 					int top = 0;
  267. 					int left = 0;
  268. 					Bitmap printscreen = new Bitmap( width, height );
  269. 					Graphics graphics = Graphics.FromImage( printscreen as Image );
  270. 					graphics.CopyFromScreen( top, left, 0, 0, printscreen.Size );
  271. 					printscreen.Save( outputfile, imagetype );
  272. 				}
  273. 				return 0;
  274. 			}
  275. 			catch ( Exception e )
  276. 			{
  277. 				return ShowHelp( e.Message );
  278. 			}
  279. 		}
  280.  
  281.  
  282. 		static string GenerateUniqueFileName( string type )
  283. 		{
  284. 			string ext = type.Substring( 0, 3 ).ToLower( );
  285. 			if ( type.ToLower( ) == "jpeg" )
  286. 			{
  287. 				ext = "jpg";
  288. 			}
  289. 			return Path.Combine( Directory.GetCurrentDirectory( ), String.Format( "PrintScreen{0}.{1}", DateTime.Now.ToString( "yyyyMMddHHmmssffffff" ), ext ) );
  290. 		}
  291.  
  292. 		#region Error Handling
  293.  
  294. 		public static int ShowHelp( params string[] errmsg )
  295. 		{
  296. 			/*
  297. 			PrintScreen,  Version 1.04
  298. 			Save screenshot as image, or console buffer to text file or standard output
  299.  
  300. 			Usage:   PRINTSCREEN  imagefile  [ /T:type ]  [ /O ]
  301. 			   or:   PRINTSCREEN  textfile   [ /T:TXT  ]  [ /O ]  [ /C ]
  302. 			   or:   PRINTSCREEN  /U  /T:type
  303. 			   or:   PRINTSCREEN  /S  [ /C ]
  304.  
  305. 			Where:   imagefile    is the image file to save the screenshot to
  306. 			         textfile     is the text file to save the console buffer text to
  307. 			Options: /C           trim lines (text only)
  308. 			         /O           Overwrites an existing file
  309. 			         /S           send captured text to Standard output (assuming /T:TXT;
  310. 			                      do not specify a file name, nor type, nor overwrite)
  311. 			         /T:type      specifies the file Type: BMP, GIF, JPG, PNG, TIF or TXT
  312. 			                      (required only if outputfile extension is different)
  313. 			         /U           automatically generate a Unique output file name in
  314. 			                      PrintScreenyyyyMMddHHmmssffffff.ext format in current
  315. 			                      directory (requires /T:type, no other arguments allowed)
  316.  
  317. 			Note:    Return code ("errorlevel") is 1 in case of errors, or 0 otherwise.
  318.  
  319. 			Credits: Code to read console buffer by Simon Mourier http://www.softfluent.com
  320. 			         Code for graphic screenshot by Ali Hamdar    http://alihamdar.com
  321.  
  322. 			Written by Rob van der Woude
  323. 			http://www.robvanderwoude.com
  324. 			*/
  325.  
  326. 			if ( errmsg.Length > 0 )
  327. 			{
  328. 				List<string> errargs = new List<string>( errmsg );
  329. 				errargs.RemoveAt( 0 );
  330. 				Console.Error.WriteLine( );
  331. 				Console.ForegroundColor = ConsoleColor.Red;
  332. 				Console.Error.Write( "ERROR:\t" );
  333. 				Console.ForegroundColor = ConsoleColor.White;
  334. 				Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
  335. 				Console.ResetColor( );
  336. 			}
  337.  
  338. 			Console.Error.WriteLine( );
  339.  
  340. 			Console.Error.WriteLine( "PrintScreen,  Version {0}", progver );
  341.  
  342. 			Console.Error.WriteLine( "Save screenshot as image, or console buffer to text file or standard output" );
  343.  
  344. 			Console.Error.WriteLine( );
  345.  
  346. 			Console.Error.Write( "Usage:   " );
  347. 			Console.ForegroundColor = ConsoleColor.White;
  348. 			Console.Error.WriteLine( "PRINTSCREEN  imagefile  [ /T:type ]  [ /O ]" );
  349. 			Console.ResetColor( );
  350.  
  351. 			Console.Error.Write( "   or:   " );
  352. 			Console.ForegroundColor = ConsoleColor.White;
  353. 			Console.Error.WriteLine( "PRINTSCREEN  textfile   [ /T:TXT  ]  [ /O ]  [ /C ]" );
  354. 			Console.ResetColor( );
  355.  
  356. 			Console.Error.Write( "   or:   " );
  357. 			Console.ForegroundColor = ConsoleColor.White;
  358. 			Console.Error.WriteLine( "PRINTSCREEN  /U  /T:type" );
  359. 			Console.ResetColor( );
  360.  
  361. 			Console.Error.Write( "   or:   " );
  362. 			Console.ForegroundColor = ConsoleColor.White;
  363. 			Console.Error.WriteLine( "PRINTSCREEN  /S  [ /C ]" );
  364. 			Console.ResetColor( );
  365.  
  366. 			Console.Error.WriteLine( );
  367.  
  368. 			Console.Error.Write( "Where:   " );
  369. 			Console.ForegroundColor = ConsoleColor.White;
  370. 			Console.Error.Write( "imagefile" );
  371. 			Console.ResetColor( );
  372. 			Console.Error.WriteLine( "    is the image file to save the screenshot to" );
  373.  
  374. 			Console.ForegroundColor = ConsoleColor.White;
  375. 			Console.Error.Write( "         textfile" );
  376. 			Console.ResetColor( );
  377. 			Console.Error.WriteLine( "     is the text file to save the console buffer text to" );
  378.  
  379. 			Console.Error.WriteLine( );
  380.  
  381. 			Console.Error.Write( "Options: " );
  382. 			Console.ForegroundColor = ConsoleColor.White;
  383. 			Console.Error.Write( "/C" );
  384. 			Console.ResetColor( );
  385. 			Console.Error.WriteLine( "           trim lines (text only)" );
  386.  
  387. 			Console.ForegroundColor = ConsoleColor.White;
  388. 			Console.Error.Write( "         /O           O" );
  389. 			Console.ResetColor( );
  390. 			Console.Error.WriteLine( "verwrites an existing file" );
  391.  
  392. 			Console.ForegroundColor = ConsoleColor.White;
  393. 			Console.Error.Write( "         /S" );
  394. 			Console.ResetColor( );
  395. 			Console.Error.Write( "           send captured text to " );
  396. 			Console.ForegroundColor = ConsoleColor.White;
  397. 			Console.Error.Write( "S" );
  398. 			Console.ResetColor( );
  399. 			Console.Error.Write( "tandard output (assuming " );
  400. 			Console.ForegroundColor = ConsoleColor.White;
  401. 			Console.Error.Write( "/T:TXT" );
  402. 			Console.ResetColor( );
  403. 			Console.Error.WriteLine( ";" );
  404.  
  405. 			Console.Error.WriteLine( "                      do not specify a file name, nor type, nor overwrite)" );
  406.  
  407. 			Console.ForegroundColor = ConsoleColor.White;
  408. 			Console.Error.Write( "         /T:type" );
  409. 			Console.ResetColor( );
  410. 			Console.Error.Write( "      specifies the file " );
  411. 			Console.ForegroundColor = ConsoleColor.White;
  412. 			Console.Error.Write( "T" );
  413. 			Console.ResetColor( );
  414. 			Console.Error.Write( "ype: " );
  415. 			Console.ForegroundColor = ConsoleColor.White;
  416. 			Console.Error.Write( "BMP" );
  417. 			Console.ResetColor( );
  418. 			Console.Error.Write( ", " );
  419. 			Console.ForegroundColor = ConsoleColor.White;
  420. 			Console.Error.Write( "GIF" );
  421. 			Console.ResetColor( );
  422. 			Console.Error.Write( ", " );
  423. 			Console.ForegroundColor = ConsoleColor.White;
  424. 			Console.Error.Write( "JPG" );
  425. 			Console.ResetColor( );
  426. 			Console.Error.Write( ", " );
  427. 			Console.ForegroundColor = ConsoleColor.White;
  428. 			Console.Error.Write( "PNG" );
  429. 			Console.ResetColor( );
  430. 			Console.Error.Write( ", " );
  431. 			Console.ForegroundColor = ConsoleColor.White;
  432. 			Console.Error.Write( "TIF" );
  433. 			Console.ResetColor( );
  434. 			Console.Error.Write( " or " );
  435. 			Console.ForegroundColor = ConsoleColor.White;
  436. 			Console.Error.WriteLine( "TXT" );
  437. 			Console.ResetColor( );
  438.  
  439. 			Console.Error.Write( "                      (required only if " );
  440. 			Console.ForegroundColor = ConsoleColor.White;
  441. 			Console.Error.Write( "outputfile" );
  442. 			Console.ResetColor( );
  443. 			Console.Error.WriteLine( " extension is different)" );
  444.  
  445. 			Console.ForegroundColor = ConsoleColor.White;
  446. 			Console.Error.Write( "         /U" );
  447. 			Console.ResetColor( );
  448. 			Console.Error.Write( "           automatically generate a " );
  449. 			Console.ForegroundColor = ConsoleColor.White;
  450. 			Console.Error.Write( "U" );
  451. 			Console.ResetColor( );
  452. 			Console.Error.WriteLine( "nique output file name in" );
  453.  
  454. 			Console.Error.Write( "                      PrintScreen" );
  455. 			Console.ForegroundColor = ConsoleColor.White;
  456. 			Console.Error.Write( "YYYYMMDDHHmmssffffff" );
  457. 			Console.ResetColor( );
  458. 			Console.Error.WriteLine( ".ext format in current" );
  459.  
  460. 			Console.Error.Write( "                      directory (requires " );
  461. 			Console.ForegroundColor = ConsoleColor.White;
  462. 			Console.Error.Write( "/T:type" );
  463. 			Console.ResetColor( );
  464. 			Console.Error.WriteLine( ", no other arguments allowed)" );
  465.  
  466. 			Console.Error.WriteLine( );
  467.  
  468. 			Console.Error.WriteLine( "Note:    Return code (\"errorlevel\") is 1 in case of errors, or 0 otherwise." );
  469.  
  470. 			Console.Error.WriteLine( );
  471.  
  472. 			Console.Error.Write( "Credits: Code to read console buffer by Simon Mourier " );
  473. 			Console.ForegroundColor = ConsoleColor.DarkGray;
  474. 			Console.Error.WriteLine( "http://www.softfluent.com" );
  475. 			Console.ResetColor( );
  476.  
  477. 			Console.Error.Write( "         Code for graphic screenshot by Ali Hamdar    " );
  478. 			Console.ForegroundColor = ConsoleColor.DarkGray;
  479. 			Console.Error.WriteLine( "http://alihamdar.com" );
  480. 			Console.ResetColor( );
  481.  
  482. 			Console.Error.WriteLine( );
  483.  
  484. 			Console.Error.WriteLine( "Written by Rob van der Woude" );
  485.  
  486. 			Console.Error.WriteLine( "http://www.robvanderwoude.com" );
  487.  
  488. 			return 1;
  489. 		}
  490.  
  491. 		#endregion Error Handling
  492. 	}
  493.  
  494. 	#region Read From Console Buffer
  495.  
  496. 	// ConsoleReader by Simon Mourier (http://www.softfluent.com/)
  497. 	// http://stackoverflow.com/questions/12355378/read-from-location-on-console-c-sharp
  498. 	public class ConsoleReader
  499. 	{
  500. 		public static IEnumerable<string> ReadFromBuffer( short x, short y, short width, short height )
  501. 		{
  502. 			IntPtr buffer = Marshal.AllocHGlobal( width * height * Marshal.SizeOf( typeof( CHAR_INFO ) ) );
  503. 			if ( buffer == null )
  504. 			{
  505. 				throw new OutOfMemoryException( );
  506. 			}
  507. 			try
  508. 			{
  509. 				COORD coord = new COORD( );
  510. 				SMALL_RECT rc = new SMALL_RECT( );
  511. 				rc.Left = x;
  512. 				rc.Top = y;
  513. 				rc.Right = (short) ( x + width - 1 );
  514. 				rc.Bottom = (short) ( y + height - 1 );
  515.  
  516. 				COORD size = new COORD( );
  517. 				size.X = width;
  518. 				size.Y = height;
  519.  
  520. 				const int STD_OUTPUT_HANDLE = -11;
  521. 				if ( !ReadConsoleOutput( GetStdHandle( STD_OUTPUT_HANDLE ), buffer, size, coord, ref rc ) )
  522. 				{
  523. 					// Not enough storage is available to process this command
  524. 					// may be raised for buffer size > 64K (see ReadConsoleOutput doc.)
  525. 					throw new Win32Exception( Marshal.GetLastWin32Error( ) );
  526. 				}
  527.  
  528. 				IntPtr ptr = buffer;
  529. 				for ( int h = 0; h < height; h++ )
  530. 				{
  531. 					StringBuilder sb = new StringBuilder( );
  532. 					for ( int w = 0; w < width; w++ )
  533. 					{
  534. 						CHAR_INFO ci = (CHAR_INFO) Marshal.PtrToStructure( ptr, typeof( CHAR_INFO ) );
  535. 						char[] chars = Console.OutputEncoding.GetChars( ci.charData );
  536. 						sb.Append( chars[0] );
  537. 						ptr += Marshal.SizeOf( typeof( CHAR_INFO ) );
  538. 					}
  539. 					yield return sb.ToString( );
  540. 				}
  541. 			}
  542. 			finally
  543. 			{
  544. 				Marshal.FreeHGlobal( buffer );
  545. 			}
  546. 		}
  547.  
  548. 		[StructLayout( LayoutKind.Sequential )]
  549. 		private struct CHAR_INFO
  550. 		{
  551. 			[MarshalAs( UnmanagedType.ByValArray, SizeConst = 2 )]
  552. 			public byte[] charData;
  553. 			public short attributes;
  554. 		}
  555.  
  556. 		[StructLayout( LayoutKind.Sequential )]
  557. 		private struct COORD
  558. 		{
  559. 			public short X;
  560. 			public short Y;
  561. 		}
  562.  
  563. 		[StructLayout( LayoutKind.Sequential )]
  564. 		private struct SMALL_RECT
  565. 		{
  566. 			public short Left;
  567. 			public short Top;
  568. 			public short Right;
  569. 			public short Bottom;
  570. 		}
  571.  
  572. 		[StructLayout( LayoutKind.Sequential )]
  573. 		private struct CONSOLE_SCREEN_BUFFER_INFO
  574. 		{
  575. 			public COORD dwSize;
  576. 			public COORD dwCursorPosition;
  577. 			public short wAttributes;
  578. 			public SMALL_RECT srWindow;
  579. 			public COORD dwMaximumWindowSize;
  580. 		}
  581.  
  582. 		[DllImport( "kernel32.dll", SetLastError = true )]
  583. 		private static extern bool ReadConsoleOutput( IntPtr hConsoleOutput, IntPtr lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, ref SMALL_RECT lpReadRegion );
  584.  
  585. 		[DllImport( "kernel32.dll", SetLastError = true )]
  586. 		private static extern IntPtr GetStdHandle( int nStdHandle );
  587.  
  588. 	}
  589.  
  590. 	#endregion Read From Console Buffer
  591. }

page last uploaded: 2018-12-04, 10:47