(view source code of printscreen.cs as plain text)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
namespace RobvanderWoude
{
class PrintScreen
{
static string progver = "1.04";
static int Main( string[] args )
{
try
{
string outputfile = String.Empty;
bool capturetext = false;
bool generatename = false;
bool overwrite = false;
bool trimoutput = false;
bool typeset = false;
bool usestandardout = false;
ImageFormat imagetype = null;
#region Command Line parsing
if ( args.Length == 0 || args.Length > 3 )
{
return ShowHelp( );
}
foreach ( string arg in args )
{
switch ( arg.ToUpper( ).Substring( 0, 2 ) )
{
case "/?":
return ShowHelp( );
case "/C":
if ( trimoutput )
{
return ShowHelp( "Duplicate command line switch /C" );
}
trimoutput = true;
break;
case "/O":
if ( overwrite )
{
return ShowHelp( "Duplicate command line switch /O" );
}
overwrite = true;
break;
case "/S":
if ( usestandardout )
{
return ShowHelp( "Duplicate command line switch /S" );
}
usestandardout = true;
break;
case "/T":
if ( typeset )
{
return ShowHelp( "Duplicate command line switch /T" );
}
switch ( arg.ToUpper( ).Substring( 3 ) )
{
case "BMP":
imagetype = ImageFormat.Bmp;
break;
case "GIF":
imagetype = ImageFormat.Gif;
break;
case "JPG":
case "JPEG":
imagetype = ImageFormat.Jpeg;
break;
case "PNG":
imagetype = ImageFormat.Png;
break;
case "TIF":
case "TIFF":
imagetype = ImageFormat.Tiff;
break;
case "TXT":
case "TEXT":
capturetext = true;
break;
default:
return ShowHelp( "Invalid file format \"{0}\"", arg.Substring( 3 ) );
}
typeset = true;
break;
case "/U":
if ( generatename )
{
return ShowHelp( "Duplicate command line switch /U" );
}
if ( !String.IsNullOrEmpty( outputfile ) )
{
return ShowHelp( "Do not specify a file name when using /U to generate one" );
}
generatename = true;
break;
default:
if ( arg[0] == '/' )
{
return ShowHelp( "Invalid command line switch \"{0}\"", arg );
}
else
{
if ( !String.IsNullOrEmpty( outputfile ) )
{
return ShowHelp( "Duplicate output file name arguments:\n\t\"{0}\"\n\t\"{1}\"", outputfile, Path.GetFullPath( arg ) );
}
if ( generatename )
{
return ShowHelp( "Do not specify a file name when using /U to generate one" );
}
try
{
outputfile = Path.GetFullPath( arg );
}
catch ( Exception )
{
return ShowHelp( "Invalid output file \"{0}\"", arg );
}
}
break;
}
}
if ( usestandardout )
{
if ( imagetype != null || overwrite || !String.IsNullOrEmpty( outputfile ) )
{
return ShowHelp( "Except /C no other command line switch can be used with /S" );
}
capturetext = true;
}
else if ( generatename )
{
// We are assuming that multiple instances, each using /U, will never "collide"
}
else
{
if ( String.IsNullOrEmpty( outputfile ) )
{
return ShowHelp( "No output file specified." );
}
// Check if directory exists
if ( !Directory.Exists( Directory.GetParent( outputfile ).FullName ) )
{
return ShowHelp( "Invalid path for output file \"{0}\"", outputfile );
}
// Check if file exists, and if so, if it can be overwritten
if ( File.Exists( outputfile ) )
{
if ( overwrite )
{
File.Delete( outputfile );
}
else
{
return ShowHelp( "Output file exists.\n\tUse /O to overwrite existing files." );
}
}
}
if ( !generatename && !usestandardout && imagetype == null && capturetext == false )
{
string ext = Path.GetExtension( outputfile ).ToUpper( );
switch ( ext )
{
case "":
return ShowHelp( "No extension for output file.\n\tUse /T to specify the output file type.", outputfile );
case ".BMP":
imagetype = ImageFormat.Bmp;
break;
case ".GIF":
imagetype = ImageFormat.Gif;
break;
case ".JPG":
case ".JPEG":
imagetype = ImageFormat.Jpeg;
break;
case ".PNG":
imagetype = ImageFormat.Png;
break;
case ".TIF":
case ".TIFF":
imagetype = ImageFormat.Tiff;
break;
case ".TXT":
capturetext = true;
break;
default:
return ShowHelp( "Unrecognized extension \"{0}\" for output file.\n\tUse /T to specify the output file type.", ext );
}
}
if ( generatename )
{
if ( capturetext )
{
outputfile = GenerateUniqueFileName( "txt" );
}
else
{
if ( imagetype == null )
{
return ShowHelp( "/U switch requires /T switch as well" );
}
outputfile = GenerateUniqueFileName( imagetype.ToString( ) );
}
}
#endregion Command Line parsing
if ( capturetext )
{
// Based on code by Simon Mourier (http://www.softfluent.com/)
// http://stackoverflow.com/questions/12355378/read-from-location-on-console-c-sharp
string readtext = string.Empty;
for ( short i = 0; i < (short) Console.BufferHeight; i++ )
{
foreach ( string line in ConsoleReader.ReadFromBuffer( 0, i, (short) Console.BufferWidth, 1 ) )
{
if ( trimoutput )
{
// Trim whitespace from the end of the line, based on a suggestion by Daniel Saul Dominguez
readtext += line.TrimEnd( "\t ".ToCharArray( ) ) + "\n";
}
else
{
readtext += line + "\n";
}
}
}
readtext = readtext.TrimEnd( " \n\r\t".ToCharArray( ) );
if ( usestandardout )
{
Console.Write( readtext );
}
else
{
StreamWriter file = new StreamWriter( outputfile );
file.Write( readtext );
file.Close( );
}
}
else
{
// Based on code by Ali Hamdar (http://alihamdar.com/)
// http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/79efecc4-fa6d-4078-afe4-bb1379bb968b
// Default values for full screen
int width = Screen.PrimaryScreen.Bounds.Width;
int height = Screen.PrimaryScreen.Bounds.Height;
int top = 0;
int left = 0;
Bitmap printscreen = new Bitmap( width, height );
Graphics graphics = Graphics.FromImage( printscreen as Image );
graphics.CopyFromScreen( top, left, 0, 0, printscreen.Size );
printscreen.Save( outputfile, imagetype );
}
return 0;
}
catch ( Exception e )
{
return ShowHelp( e.Message );
}
}
static string GenerateUniqueFileName( string type )
{
string ext = type.Substring( 0, 3 ).ToLower( );
if ( type.ToLower( ) == "jpeg" )
{
ext = "jpg";
}
return Path.Combine( Directory.GetCurrentDirectory( ), String.Format( "PrintScreen{0}.{1}", DateTime.Now.ToString( "yyyyMMddHHmmssffffff" ), ext ) );
}
#region Error Handling
public static int ShowHelp( params string[] errmsg )
{
/*
PrintScreen, Version 1.04
Save screenshot as image, or console buffer to text file or standard output
Usage: PRINTSCREEN imagefile [ /T:type ] [ /O ]
or: PRINTSCREEN textfile [ /T:TXT ] [ /O ] [ /C ]
or: PRINTSCREEN /U /T:type
or: PRINTSCREEN /S [ /C ]
Where: imagefile is the image file to save the screenshot to
textfile is the text file to save the console buffer text to
Options: /C trim lines (text only)
/O Overwrites an existing file
/S send captured text to Standard output (assuming /T:TXT;
do not specify a file name, nor type, nor overwrite)
/T:type specifies the file Type: BMP, GIF, JPG, PNG, TIF or TXT
(required only if outputfile extension is different)
/U automatically generate a Unique output file name in
PrintScreenyyyyMMddHHmmssffffff.ext format in current
directory (requires /T:type, no other arguments allowed)
Note: Return code ("errorlevel") is 1 in case of errors, or 0 otherwise.
Credits: Code to read console buffer by Simon Mourier http://www.softfluent.com
Code for graphic screenshot by Ali Hamdar http://alihamdar.com
Written by Rob van der Woude
http://www.robvanderwoude.com
*/
if ( errmsg.Length > 0 )
{
List<string> errargs = new List<string>( errmsg );
errargs.RemoveAt( 0 );
Console.Error.WriteLine( );
Console.ForegroundColor = ConsoleColor.Red;
Console.Error.Write( "ERROR:\t" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
Console.ResetColor( );
}
Console.Error.WriteLine( );
Console.Error.WriteLine( "PrintScreen, Version {0}", progver );
Console.Error.WriteLine( "Save screenshot as image, or console buffer to text file or standard output" );
Console.Error.WriteLine( );
Console.Error.Write( "Usage: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "PRINTSCREEN imagefile [ /T:type ] [ /O ]" );
Console.ResetColor( );
Console.Error.Write( " or: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "PRINTSCREEN textfile [ /T:TXT ] [ /O ] [ /C ]" );
Console.ResetColor( );
Console.Error.Write( " or: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "PRINTSCREEN /U /T:type" );
Console.ResetColor( );
Console.Error.Write( " or: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "PRINTSCREEN /S [ /C ]" );
Console.ResetColor( );
Console.Error.WriteLine( );
Console.Error.Write( "Where: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "imagefile" );
Console.ResetColor( );
Console.Error.WriteLine( " is the image file to save the screenshot to" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " textfile" );
Console.ResetColor( );
Console.Error.WriteLine( " is the text file to save the console buffer text to" );
Console.Error.WriteLine( );
Console.Error.Write( "Options: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/C" );
Console.ResetColor( );
Console.Error.WriteLine( " trim lines (text only)" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /O O" );
Console.ResetColor( );
Console.Error.WriteLine( "verwrites an existing file" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /S" );
Console.ResetColor( );
Console.Error.Write( " send captured text to " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "S" );
Console.ResetColor( );
Console.Error.Write( "tandard output (assuming " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/T:TXT" );
Console.ResetColor( );
Console.Error.WriteLine( ";" );
Console.Error.WriteLine( " do not specify a file name, nor type, nor overwrite)" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /T:type" );
Console.ResetColor( );
Console.Error.Write( " specifies the file " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "T" );
Console.ResetColor( );
Console.Error.Write( "ype: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "BMP" );
Console.ResetColor( );
Console.Error.Write( ", " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "GIF" );
Console.ResetColor( );
Console.Error.Write( ", " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "JPG" );
Console.ResetColor( );
Console.Error.Write( ", " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "PNG" );
Console.ResetColor( );
Console.Error.Write( ", " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "TIF" );
Console.ResetColor( );
Console.Error.Write( " or " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "TXT" );
Console.ResetColor( );
Console.Error.Write( " (required only if " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "outputfile" );
Console.ResetColor( );
Console.Error.WriteLine( " extension is different)" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /U" );
Console.ResetColor( );
Console.Error.Write( " automatically generate a " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "U" );
Console.ResetColor( );
Console.Error.WriteLine( "nique output file name in" );
Console.Error.Write( " PrintScreen" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "YYYYMMDDHHmmssffffff" );
Console.ResetColor( );
Console.Error.WriteLine( ".ext format in current" );
Console.Error.Write( " directory (requires " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/T:type" );
Console.ResetColor( );
Console.Error.WriteLine( ", no other arguments allowed)" );
Console.Error.WriteLine( );
Console.Error.WriteLine( "Note: Return code (\"errorlevel\") is 1 in case of errors, or 0 otherwise." );
Console.Error.WriteLine( );
Console.Error.Write( "Credits: Code to read console buffer by Simon Mourier " );
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.Error.WriteLine( "http://www.softfluent.com" );
Console.ResetColor( );
Console.Error.Write( " Code for graphic screenshot by Ali Hamdar " );
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.Error.WriteLine( "http://alihamdar.com" );
Console.ResetColor( );
Console.Error.WriteLine( );
Console.Error.WriteLine( "Written by Rob van der Woude" );
Console.Error.WriteLine( "http://www.robvanderwoude.com" );
return 1;
}
#endregion Error Handling
}
#region Read From Console Buffer
// ConsoleReader by Simon Mourier (http://www.softfluent.com/)
// http://stackoverflow.com/questions/12355378/read-from-location-on-console-c-sharp
public class ConsoleReader
{
public static IEnumerable<string> ReadFromBuffer( short x, short y, short width, short height )
{
IntPtr buffer = Marshal.AllocHGlobal( width * height * Marshal.SizeOf( typeof( CHAR_INFO ) ) );
if ( buffer == null )
{
throw new OutOfMemoryException( );
}
try
{
COORD coord = new COORD( );
SMALL_RECT rc = new SMALL_RECT( );
rc.Left = x;
rc.Top = y;
rc.Right = (short) ( x + width - 1 );
rc.Bottom = (short) ( y + height - 1 );
COORD size = new COORD( );
size.X = width;
size.Y = height;
const int STD_OUTPUT_HANDLE = -11;
if ( !ReadConsoleOutput( GetStdHandle( STD_OUTPUT_HANDLE ), buffer, size, coord, ref rc ) )
{
// Not enough storage is available to process this command
// may be raised for buffer size > 64K (see ReadConsoleOutput doc.)
throw new Win32Exception( Marshal.GetLastWin32Error( ) );
}
IntPtr ptr = buffer;
for ( int h = 0; h < height; h++ )
{
StringBuilder sb = new StringBuilder( );
for ( int w = 0; w < width; w++ )
{
CHAR_INFO ci = (CHAR_INFO) Marshal.PtrToStructure( ptr, typeof( CHAR_INFO ) );
char[] chars = Console.OutputEncoding.GetChars( ci.charData );
sb.Append( chars[0] );
ptr += Marshal.SizeOf( typeof( CHAR_INFO ) );
}
yield return sb.ToString( );
}
}
finally
{
Marshal.FreeHGlobal( buffer );
}
}
[StructLayout( LayoutKind.Sequential )]
private struct CHAR_INFO
{
[MarshalAs( UnmanagedType.ByValArray, SizeConst = 2 )]
public byte[] charData;
public short attributes;
}
[StructLayout( LayoutKind.Sequential )]
private struct COORD
{
public short X;
public short Y;
}
[StructLayout( LayoutKind.Sequential )]
private struct SMALL_RECT
{
public short Left;
public short Top;
public short Right;
public short Bottom;
}
[StructLayout( LayoutKind.Sequential )]
private struct CONSOLE_SCREEN_BUFFER_INFO
{
public COORD dwSize;
public COORD dwCursorPosition;
public short wAttributes;
public SMALL_RECT srWindow;
public COORD dwMaximumWindowSize;
}
[DllImport( "kernel32.dll", SetLastError = true )]
private static extern bool ReadConsoleOutput( IntPtr hConsoleOutput, IntPtr lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, ref SMALL_RECT lpReadRegion );
[DllImport( "kernel32.dll", SetLastError = true )]
private static extern IntPtr GetStdHandle( int nStdHandle );
}
#endregion Read From Console Buffer
}
page last modified: 2024-04-16; loaded in 0.0140 seconds