::::::::: PowerShell :::::::::
Saturday, February 18, 2006
  [MSH] print-image *Snapin* version
During my spare time, i spent sometime converting "print-image" cmdlet into a Snapin version.

I have extended its functionality just by a tiny bit by adding "Landscape" mode printing. Well, I still haven't tried adding a "help" file yet so I will try to add one when I have more time(so for now, something like "print-image -?" will complain that cmdlet cannot find a help xml file).

Anyways, here is the usage for "print-image" for this this version.

This command also supports only one ubiquitous parameter: -Verbose(-vb)

print-image [-FileName|-fn] System.String [[-Printer|-p|-pn] System.String] [[-Landscape|-l|-ls] System.Boolean]
Where,
  1. FileName: Fully Qualified File Name

  2. Printer: Name of print to send image to

  3. Landscape: Print images in Landscape mode


Well, if you would like to change "margins", there are two options. First one is you go to your printer setting and change the margin size there, or modify the msh script to be able to receive margin data.

To retrieve available printer names on your current machine, you can load "System.Drawing" assembly and then retrieve "System.Drawing.Printing.PrinterSettings.InstalledPrinters" property like the following

MSH>[reflection.assembly]::loadwithpartialname("system.drawing")

GAC Version Location
--- ------- --------
True v2.0.50727 C:\WINDOWS\assembly\GAC_MSIL\System.Drawing\2.0.0.0__b03f5f7f11d50a3a\Syst...

MSH>[Drawing.Printing.PrinterSettings]::InstalledPrinters
Microsoft Office Document Image Writer
HP LaserJet 8150 PCL 5e
HP LaserJet 5000 Series PCL 5e
HP Color LaserJet 5500 PCL6(Color)
Adobe PDF
MSH>

and then use the printer names listed above


Here is how you can use the "print-image"
Image hosting by Photobucket

Uhm, I don't have any storage areas where I can just put my source or compiled binaries on... So, i am just pasting the source here...
using System;
using System.IO;
using System.Drawing;
using System.Drawing.Printing;

using System.ComponentModel;
using System.Management.Automation;
using System.Collections.Generic;
using System.Text;

namespace D2D.Snapins
{
/// <summary>
/// Prints image files
/// </summary>
/// <remarks>
/// @TODO: Display Preview form
/// </remarks>
[RunInstaller(true)]
public class PrintImageSnapin : MshSnapIn
{
public override string Description
{
get { return "Prints an image file"; }
}

public override string Name
{
get { return "D2D_print-image"; }
}

public override string Vendor
{
get { return "DontBotherMeWithSpam"; }
}
}

[Cmdlet("print", "image")]
public class PrintImageCommand : MshCmdlet
{
#region Private Member Variables
/// <summary>
/// Fully qualified image file name to print
/// </summary>
private string fileName;
/// <summary>
/// Name of printer to use
/// </summary>
private string printer;
/// <summary>
/// Should we use landscape mode or not
/// </summary>
private bool landscape;


/// <summary>
/// Responsible for printing image document
/// </summary>
private PrintDocument doc;

/// <summary>
/// Image to constructed from input file name
/// </summary>
private Bitmap img;

/// <summary>
/// Holds exception thrown in functions other than
/// "BeginProcessing", "EndProcessing", "ProcessRecord"
/// </summary>
private Exception ex;
#endregion

#region MSH Parameters
/// <summary>
/// Fully qualified image file name to print
/// </summary>
[Alias("fn")]
[Parameter(Mandatory = true, Position = 0, ValueFromPipeline = true,
HelpMessage = "Fully qualified image file name to print")]
public string FileName
{
get { return this.fileName; }
set { this.fileName = value; }
}

/// <summary>
/// Name of printer to use
/// </summary>
[Alias("p", "pn")]
[Parameter(Mandatory = false, Position = 1, ValueFromPipeline = true,
HelpMessage = "Name of printer to print image")]
public string Printer
{
get { return this.printer; }
set { this.printer = value; }
}

[Alias("l", "ls")]
[Parameter(Mandatory = false, Position = 2, ValueFromPipeline = false,
HelpMessage = "Toggle Landscape mode")]
[DefaultValue(false)]
public bool Landscape
{
get { return this.landscape; }
set { this.landscape = value; }
}
#endregion

protected override void EndProcessing()
{
this.doc = new PrintDocument();

this.doc.BeginPrint += new PrintEventHandler(doc_BeginPrint);
this.doc.PrintPage += new PrintPageEventHandler(doc_PrintPage);
this.doc.EndPrint += new PrintEventHandler(doc_EndPrint);

this.doc.Print();

}

#region PrintDocument Event Handlers
/// <summary>
/// Construct image to print
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void doc_BeginPrint(object sender, PrintEventArgs e)
{
// Construct image to print
try
{
this.img = new Bitmap(this.FileName);
this.doc.DocumentName = Path.GetFileName(this.FileName);
this.doc.DefaultPageSettings.Landscape = this.Landscape;
if (this.Printer != "")
{
this.doc.PrinterSettings.PrinterName = this.Printer;
}
}
catch (Exception ex)
{
// We have failed create an image from the given file name
// No need to process any further, actually...
/// How do i abort the script at this point?
ErrorRecord err = new ErrorRecord(ex, "doc_BeginPrintError",
ErrorCategory.InvalidData, this.fileName);
WriteError(err);

e.Cancel = true; // abort printing job
}

//e.PrintAction = this.PrintAction;
e.Cancel = false;

WriteVerbose(string.Format(
"==================== {0} ====================",
this.doc.DocumentName));
}

/// <summary>
/// Print constructed image according to PrintAction
/// </summary>
private void doc_PrintPage(object sender, PrintPageEventArgs e)
{
WriteVerbose(string.Format("Printing {0}",
this.doc.DocumentName));

Graphics g = e.Graphics;
Rectangle paperBounds = e.MarginBounds;
SizeF adjSize = AdjustImageSize(this.img.Size, paperBounds);

if (this.ex == null)
{

// Calculate source and destination sizes
RectangleF destRec = new RectangleF(paperBounds.Location, adjSize);
RectangleF srcRec = new RectangleF(0, 0, img.Width, img.Height);

// Print to according to "PrintAction"
g.DrawImage(this.img, destRec, srcRec, GraphicsUnit.Pixel);
}
else
{
ErrorRecord err = new ErrorRecord(this.ex, "AdjustImageSizeError",
ErrorCategory.NotSpecified, null);
WriteError(err);
}

// Nothing else to print...
e.HasMorePages = false;
}

/// <summary>
/// Clean up used resources
/// </summary>
private void doc_EndPrint(object sender, PrintEventArgs e)
{
// Free Bitmap resource
if (this.img != null)
{
this.img.Dispose();
this.img = null;
}

WriteVerbose(string.Format(
"xxxxxxxxxxxxxxxxxxxx {0} xxxxxxxxxxxxxxxxxxxx",
this.doc.DocumentName));
}
#endregion

/// <summary>
/// Adjust image size to fit to the paper size
/// </summary>
/// <param name="imgSize">Size of image to adjust to fit to paper size</param>
/// <param name="paperBound">Bounding area of paper</param>
/// <returns>Adjusted size of image that fits on the paper</returns>
/// <remarks>If image's width is bigger than its height, try to fit width, else fit height</remarks>
private SizeF AdjustImageSize(Size imgSize, RectangleF paperBound)
{
bool fitWidth = (imgSize.Width > imgSize.Height); // Fit width or the height?
double ratio = 1;
SizeF adjSize = new SizeF(imgSize.Width, imgSize.Height); // adjusted size to return

try
{
// Image size is smaller than actual paper size to print on,
// so we use the original image's size
if ((imgSize.Width > paperBound.Width) &&
(imgSize.Height > paperBound.Height))
{
// If width is longer than the height of its image,
// we get the ratio of the width, else get the ratio of the height
if ((fitWidth == true))
{
ratio = (double)(paperBound.Width / imgSize.Height);
}
else
{
ratio = (double)(paperBound.Height / imgSize.Height);
}

adjSize = new SizeF(
// Flip the width of the image in Landscape mode
(this.Landscape ? paperBound.Height : paperBound.Width),
(float)(imgSize.Height * ratio));
}
}
catch (Exception ex)
{
this.ex = ex;
}

return adjSize;
}
}
}




Tags :
 
Comments:
I noticed that your -Landscape is supposed to be a boolean parameter. Is there a way to not have to specify the boolean vaule? That is if -landscape is present, it is true, if -landscape is not present, it is false.


print-image [-FileName|-fn] System.String [[-Printer|-p|-pn] System.String] [[-Landscape|-l|-ls] System.Boolean]
 
Hello there ~

I would actually have to use "System.Management.Automation.SwitchParameter" structure instead of System.Boolean for such a switch but at the time of writing that cmdlet, PowerShell did not have "System.Management.Automation.SwitchParameter" structure which is to be used for a switch parameter as the name suggests.

I have not actually tried to use the SwitchParameter in a cmdlet yet, but according to MSDN documentation on SwitchParameter memebers,(http://windowssdk.msdn.microsoft.com/en-us/library/system.management.automation.switchparameter_members.aspx), there are two public properties that can be used to achieve what you are trying to do.

> if -landscape is present, it is true, if -landscape is not present, it is false.
I can probably update the cmdlet to check for "IsPresent" property of SwitchParameter, and if "-Landscape".IsPresent, then else if the switch parameter is not present then false.

Hope that helps ;)
 
Post a Comment



<< Home
Let's get lazy with PowerShell!

Name:
Location: Flushing, NY, United States

Experimenting with a different format of blogs...

Links
ARCHIVES
10/01/2005 - 11/01/2005 / 11/01/2005 - 12/01/2005 / 12/01/2005 - 01/01/2006 / 01/01/2006 - 02/01/2006 / 02/01/2006 - 03/01/2006 / 03/01/2006 - 04/01/2006 / 04/01/2006 - 05/01/2006 / 05/01/2006 - 06/01/2006 / 06/01/2006 - 07/01/2006 / 07/01/2006 - 08/01/2006 / 08/01/2006 - 09/01/2006 / 10/01/2006 - 11/01/2006 / 11/01/2006 - 12/01/2006 /


Powered by Blogger