::::::::: PowerShell :::::::::
Tuesday, January 31, 2006
  [MSH] Clipboard Snapin...
Thanks to both /\/\o\/\/ and Keith Hill, I was able to somewhat improve the Clipboard snapin by adding "Get-Clipboard" cmdlet.

I was able to fix "Out-Clipboard" cmdlet to receive an input from pipe by setting type of "inputData" to that of "string" from "object"(thanks /\/\o\/\/).

Well, I just couldn't improve much from Keith's orignal Clipboard Cmdlet other than the fact that this is now a Snapin and fixed one small bug(refer to OutClipboardCommand.SetObject)...

Anyways, here is how this Clipboard Snapin can be used

Here is a simple one.

MSH> "Hello, World!" | Out-Clipboard
MSH> Get-Clipboard
Hello, World!
MSH>


Now let's try to send the output of "get-process" to the clipboard

MSH> get-process | Out-Clipboard
MSH> Get-Clipboard
System.Diagnostics.Process (ahnsd)
System.Diagnostics.Process (ahnsdsv)
...
System.Diagnostics.Process (winlogon)
System.Diagnostics.Process (wmiprvse)
MSH>


Now, what is going on here? Well, I don't want to go too deep with that because it was explained in Keith's blog on MSH: Get-Clipboard and Set-Clipboard Cmdlets already.

Anyways, the problem is that, "out-clipboard" is receiving unformatted input string so MSH user have to explicitly have to convert piped data to string (through "out-string") before sending the data to Out-Clipboard(well, that is why the cmdlet only supports data of type string, for now)

So, i was searching and reading documents on MSDN and was looking for ways to put that "out-string" behavior inside "out-clipboard". Well, I haven't found the answer yet... It seems like there is not "a recommanded way invoking a cmdlet that is a subclass of MshCmdlet from another cmdlet" according to Kevin Loo who also suggested me to create a new function defined like the following
function set-clipboard {$input | out-string | out-clipboard}


Using "set-clipboard", try to run "get-process | set-clipboard", "get-childitem | set-clipboard", etc... But the problem with "set-clipboard" approach is that, you can't explicitly pass the object to "set-clipboard"... while something like "out-clipboard $(dir)" would work(although not how you might expect it to work).
I guess a workaround for that problem might be my next topic...



For instructions on how to compile and install the snapin, please refer to Appendix D in "Getting Started" document for MSH.

Here is how to load Clipboard Snapin
MSH> set-alias installutil $env:windir\Microsoft.NET\Framework\v2.0.50727\installutil
MSH> cd [go to Snapin assembly directory]
MSH> installutil Snapins.dll
MSH> get-mshsnapin -r
Name : ClipboardSnapin
MshVersion : 1.0
Description : Provides retrieving/sending data from/to Clipboard
MSH> add-mshsnapin ClipboardSnapin
Now, ClipboardSnapin is loaded and you are good to go.

Well, the source's below... but I was deliberately trying to make each line shortern than 80 columns... so it looks longer than it should be...


using System;
using System.Text;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;
using System.Management.Automation;

namespace D2D.Snapins
{
/// <summary>
/// Define basic information of this snap in
/// </summary>
[RunInstaller(true)]
public class ClipboardSnapin : MshSnapIn
{
public ClipboardSnapin() : base()
{
}

public override string Name
{
get { return "ClipboardSnapin"; }
}

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

public override string Description
{
get { return "Provides retrieving/sending data from/to Clipboard"; }
}
}

/// <summary>
/// Cmdlet to return clipboard text to pipe
/// </summary>
/// <remarks>
/// Original Author: Keith Hill (http://spaces.msn.com/keithhill)
/// Original Source URL: http://home.comcast.net/~rkeithhill/MSH/Clipboard.cs
/// Modified by: DBMwS
/// Date: 01/31/2006 @ 12:59AM
///
/// Removed, "timeout" feature
/// </remarks>
[Cmdlet("Get", "Clipboard")]
public class GetClipboardCommand : Cmdlet
{
private Exception ex;
private string dataObject = "";

protected override void BeginProcessing()
{
Thread t = new Thread(new ThreadStart(GetObject));

try
{
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
}
catch (Exception ex)
{
ErrorRecord err = new ErrorRecord(ex, "GetClipboardError",
ErrorCategory.NotSpecified, t);
WriteError(err);
}

if (this.ex != null)
{
WriteError(new ErrorRecord(this.ex,
"GetClipboard::GetObjectError",
ErrorCategory.NotSpecified, null));
}

WriteVerbose(string.Format("Sending '{0}' to pipe",
this.dataObject.ToString()));
WriteObject(this.dataObject,
(this.dataObject.GetType().IsArray));
}

private void GetObject()
{
try
{
this.dataObject = Clipboard.GetText();
}
catch (Exception ex)
{
this.ex = ex;
}
}
}

/// <summary>
/// send output string to clipboard
/// </summary>
[Cmdlet("Out", "Clipboard")]
public class OutClipboardCommand : Cmdlet
{
/// <summary>
/// Unhandled exception
/// </summary>
private Exception ex;
/// <summary>
/// Actuall worker thread
/// </summary>
private Thread t;
/// <summary>
/// Holds all the necessary input data to send to Clipboard
/// </summary>
private StringBuilder sb = new StringBuilder();

/// <summary>
/// Input data received either from pipe or as an argument
/// </summary>
private string []inputData;
/// <summary>
/// Input data to send to clipboard
/// </summary>
[Parameter(Mandatory = true, Position = 0, ValueFromPipeline = true)]
public string []InputData
{
get { return inputData; }
set { inputData = value; }
}

/// <summary>
/// Create a STA thread to start later on.
/// </summary>
protected override void BeginProcessing()
{
WriteVerbose("Begin Processing(Creating a new STA thread)...");

t = new Thread(new ThreadStart(SetObject));
t.SetApartmentState(ApartmentState.STA);
}

/// <summary>
/// Append all input lines into one
/// (with a newline appended for each input data)
/// </summary>
protected override void ProcessRecord()
{
WriteVerbose("Processing Record...");

try
{
if (this.InputData != null)
{
WriteVerbose(
string.Format("\tAppending {0}", this.InputData));
foreach (string line in this.InputData)
{
this.sb.AppendLine(line);
}
}
}
catch (Exception ex)
{
// Well I don't know what happened,
// so send the error to the host...
ErrorRecord err = new ErrorRecord(ex, "OutClipboardError",
ErrorCategory.NotSpecified, t);
WriteError(err);
}
}

/// <summary>
/// Start a thread to send input data to Clipboard
/// </summary>
protected override void EndProcessing()
{
try
{
t.Start();
t.Join();
}
catch (Exception ex)
{
ErrorRecord err = new ErrorRecord(ex, "OutClipboardError",
ErrorCategory.NotSpecified, t);
WriteError(err);
}

// Handle error occurred while sending text to clipboard
// Well, try out something as stupid as "clear-host | out-clipboard"...
if (this.ex != null)
{
WriteError(new ErrorRecord(this.ex,
"OutClipboard::SetObjectError",
ErrorCategory.NotSpecified, null));
}
WriteVerbose("End Processing...");
}

/// <summary>
/// Send input data to clipboard
/// </summary>
private void SetObject()
{
try
{
// Before sending the inputData to clipboard,
// we need to drop the last newline character
string text = this.sb.ToString();
text = text.Substring(0,
(text.Length - System.Environment.NewLine.Length));

Clipboard.SetText(text);
}
catch (Exception ex)
{
this.ex = ex;
}
}

}
}




Tags :
 
Comments:
Who knows where to download XRumer 5.0 Palladium?
Help, please. All recommend this program to effectively advertise on the Internet, this is the best program!
 
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