I got some great comments and suggestion on my original version of Out-Notepad, which should work just find on PowerShell v1.0 or 2.0. However, because v2.0 has such terrific features I decided to rework my function into a PowerShell v2.0 only version that also incorporates a few new features.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
The function now includes help, which I always like, and is much more like a cmdlet now.
Even though I expect most people will be happy with Notepad.exe, a few will want to specify an alternate text editor. I added a –editor parameter so you can specify a program. You can use an alias or filename, but it must be something that Get-Command can find because if it can’t verify the editor, then the function defaults back to Notepad.exe. I could have added the validation code to the parameter, but it’s a little ugly and not very friendly if validation fails. My approach is a little more gentle and doesn’t slow you down. You can see it in the revised code for the function.
Function Out-Notepad {
#requires -version 2.0
<#
.Synopsis
Pipe PowerShell output to a temp file and open the file in Notepad or an editor of your choice
.Description
This function creates a temporary file from pipelined input and opens in in a text editor of
your choice. The default is Notepad.exe but you can use -editor to specify the filename and path
for any text editor. The temp file will be deleted after closing the text editor. If you want to
save the output you'll need to give it a new name.
.Parameter InputObject
Any pipelined input
.Parameter Editor
The file name and path, if necessary, to any text editor of your choice. You can also use any
command aliases that you have defined.
.Example
PS C:\> ps | out-notepad
Take the output from Get-Process and send it to Notepad.
.Example
PS C:\> get-wmiobject win32_logicaldisk | Select * | out-notepad -editor nplus
Output from the Get-WMIObject expression is sent to the temp file and opened with Notepad++
which has been defined with an alias of nplus
.Inputs
Accepts pipelined input
.Outputs
None
.Link
Out-File
Out-Printer
OUt-GridView
.Notes
NAME: Out-Notepad
VERSION: 2.0
AUTHOR: Jeffery Hicks https://jdhitsolutions.com/blog
LASTEDIT: 10/7/2009
****************************************************************
* DO NOT USE IN A PRODUCTION ENVIRONMENT UNTIL YOU HAVE TESTED *
* THOROUGHLY IN A LAB ENVIRONMENT. USE AT YOUR OWN RISK. IF *
* YOU DO NOT UNDERSTAND WHAT THIS SCRIPT DOES OR HOW IT WORKS, *
* DO NOT USE IT OUTSIDE OF A SECURE, TEST ENVIRONMENT. *
****************************************************************
#>
[CmdletBinding()]
Param (
[Parameter(ValueFromPipeline=$True,Position=0,Mandatory=$True,HelpMessage="Pipelined input.")]
[object[]]$InputObject,
[Parameter(
ValueFromPipeline=$False, Mandatory=$False,HelpMessage="The filename and path to your text editor of choice.")]
[string]$Editor="Notepad.exe"
)
Begin {
Write-Debug "Beginning"
Write-Verbose "Beginning"
#get a temporary filename
Write-Debug "Getting the temp filename"
Write-Verbose "Getting the temp filename"
$tempfile=[System.IO.Path]::GetTempFileName()
Write-Debug "Temp filename is $tempfile"
Write-Verbose "Temp filename is $tempfile"
#initialize a placeholder array
$data=@()
#validate -editor value if other than the default
if ($Editor -ne "Notepad.exe") {
Write-Verbose "Validating -editor value $editor"
Write-Debug "Validating -editor value $editor"
#Get-Command might return more than one entry
Get-Command $Editor -ea SilentlyContinue | foreach {
Write-Debug $_.definition
$editorpath=$_.Definition
}
if ($editorpath -AND (Test-Path $editorPath) ) {
Write-Debug "Command definition for $editor is $editorPath"
Write-Verbose "Command definition for $editor is $editorPath"
}
else {
Write-Warning "Can't find a command path for $editor. Defaulting to Notepad.exe"
$Editor="Notepad.exe"
}
}
} #end Begin scriptblock
Process {
#save incoming objects to a variable
if ($InputObject) {
$data+=$InputObject
}
else {
$data+=$_
}
} #end Process scriptblock
End {
Write-Debug "Writing data to $tempfile"
Write-Verbose "Writing data to $tempfile"
#write data to the temp file
$data | Out-File $tempfile
#open the tempfile with the specified editor and monitor the process
Write-Debug "Opening $tempfile with $editor"
Write-Verbose "Opening $tempfile with $editor"
#wait for the editor to close because it may have a lock on the file
#once closed the temp file can then be deleted.
Start-Process $Editor $tempfile -wait
#sleep for 3 seconds before continuing on with the script. Some editors like
#Write.exe will actually launch another process, wordpad.exe, in which case
#command will return to the script almost immediately, deleting the temp file
#before the editor has had a chance to open it.
Write-Verbose "Sleeping for 3 seconds"
sleep 3
#Delete the temp file. It should still exist but we'll use an IF statement just to be neat about it.
if (Test-Path $tempfile) {
Write-Debug "Deleting $tempfile"
Write-Verbose "Deleting $tempfile"
del $tempfile
}
Write-Debug "Exiting"
Write-Verbose "Exiting"
} #end End scriptblock
} #end Function
The function uses cmdlet binding so you can use –Debug or –Verbose since I’ve coded for those parameters.
Thanks to a comment from Alex, I revised the code for getting the temp file name. I knew there was a way with the .NET framework but I couldn’t remember and didn’t have the energy at the time to dig it up.
Using $tempfile=[System.IO.Path]::GetTempFileName() creates a complete filename in the %TEMP% folder.
The other major change is that I use Start-Process to launch the editor using the –wait parameter to tell PowerShell to wait until the process finishes. Once you close Notepad, or whatever, the script sleeps for 3 seconds (I’ll explain why in a moment) and then the temp file is deleted.
The reason for the sleep is that during development I was testing (on Windows 7) using Wordpad which is started by using Write.exe. However, PowerShell wasn’t waiting as I expected and was deleting the file before Wordpad had a chance to open it. Thanks to Lee Holmes for digging into this for me, Write.exe launches Wordpad.exe and then exits so Start-Process is in fact waiting for Write.exe to finish. It has no idea that the process launched another process. My solution was to add the 3 second sleep. The downside, small though it is, is that even using the default, PowerShell will sleep for 3 seconds after you close Notepad before exiting. I can live it and I trust you can too.