Skip to content
Menu
The Lonely Administrator
  • PowerShell Tips & Tricks
  • Books & Training
  • Essential PowerShell Learning Resources
  • Privacy Policy
  • About Me
The Lonely Administrator

Friday Fun: Creating PowerShell Scripts with PowerShell

Posted on September 5, 2014September 5, 2014

012914_1704_CreatingCIM1.png Sometimes PowerShell really does seem like magic. Especially when you can use it to handle complicated or tedious tasks, such as creating a PowerShell script. I know many an IT Pro who want to script but without having to actually write a script. Well, I'm not sure that is realistic, but you can get pretty close. Earlier this week I showed a set of commands built as proxy functions. I made an assumption that you find something like that useful. But perhaps it still seemed like a lot of work. So I built an accelerator tool for you I call Get-CommandMetadata.

Manage and Report Active Directory, Exchange and Microsoft 365 with
ManageEngine ADManager Plus - Download Free Trial

Exclusive offer on ADManager Plus for US and UK regions. Claim now!
#requires -version 3.0

#run this in the PowerShell ISE for best results

Function Get-CommandMetadata {

<#
.Synopsis
Create a proxy function of a PowerShell command.
.Description
This command will create a proxy version of a PowerShell cmdlet, function or alias. The intent is to simplify creating a new function from command metadata. You can give your command and opt to remove help references for the original command. 

If you run this in the PowerShell ISE, code for the new function will be inserted into a new Powershell tab.
.Parameter Command
The name of a PowerShell command to proxy. This can be a cmdlet, function or alias.
.Parameter NewName
The name you want to use for your new command.
.Parameter NoHelp
Remove references to existing command help. Using this parameter will insert a comment-based help outline.
.Example
PS C:\> Get-CommandMetadata Get-WMIObject -nohelp -newname Get-MyOS

Create a proxy function for Get-WMIObject that will be called Get-MyOS. Help references will be replaced with a comment-help block.
.Notes
Last Updated: Sept. 3, 2014
Version     : 1.1

.Link
https://jdhitsolutions.com/blog/2014/09/friday-fun-creating-powershell-scripts-with-powershell

#>
[cmdletbinding()]
Param(
[Parameter(Position=0,Mandatory,HelpMessage="Enter the name of a PowerShell command")]
[ValidateNotNullorEmpty()]
[string]$Command,
[string]$NewName,
[switch]$NoHelp
)

Try {
    Write-Verbose "Getting command metadata for $command"
    $gcm = Get-Command -Name $command -ErrorAction Stop
    #allow an alias or command name
    if ($gcm.CommandType -eq 'Alias') {
       $cmdName = $gcm.ResolvedCommandName
    }
    else {
        $cmdName = $gcm.Name
    }
    Write-Verbose "Resolved to $cmdName"
    $cmd = New-Object System.Management.Automation.CommandMetaData ($gcm)
}
Catch {
    Write-Warning "Failed to create command metadata for $command"
    Write-Warning $_.Exception.Message
}

if ($cmd) {
    #create the metadata
        
    if ($NewName) {
        $Name = $NewName
    }
    else {
        $Name = $cmd.Name
    }

    if ($noHelp) {
        #remove help link
        $cmd.HelpUri = $Null

        Write-Verbose "Defining a new comment based help block"
        #define outline for comment based help
$myHelp = @"

.Synopsis
PUT SYNTAX HERE
.Description
PUT DESCRIPTION HERE
.Notes
Created:`t$(Get-Date -format d) 

.Example
PS C:\> $Name

.Link
$cmdname

"@
    Write-Verbose "Creating proxy command with help" 
    $metadata = [System.Management.Automation.ProxyCommand]::Create($cmd,$myHelp)

    } #nohelp
    else {
        Write-Verbose "Creating proxy command" 
        $metadata = [System.Management.Automation.ProxyCommand]::Create($cmd)
    }

   Write-Verbose "Cleaning up parameter names"
   [regex]$rx="[\s+]\$\{\w+\}[,|)]"
   $metadata = $metadata.split("`n") | foreach {
     If ($rx.ismatch($_)) {
     #strip off { } around parameter names 
      $rx.Match($_).Value.Replace("{","").Replace("}","")
     # "`n"
    }
    else {
     #just write the line
     $_
     }
    } #foreach

#define the text for the new command
    $text = @"
#requires -version $($PSVersionTable.psversion)

Function $Name {

$metadata

} #end function $Name
"@
    if ($host.Name -match "PowerShell ISE") {
    #open in a new ISE tab
    $tab = $psise.CurrentPowerShellTab.Files.Add()

    Write-Verbose "Opening metadata in a new ISE tab"
    $tab.editor.InsertText($Text)

    #jump to the top
    $tab.Editor.SetCaretPosition(1,1)
    }
    else {
      $Text
    }
}
Write-Verbose "Ending $($MyInvocation.MyCommand)"

} #end function

Set-Alias -Name gcmd -Value Get-CommandMetaData

The intent is that you can use this function to quickly create a PowerShell function based on a proxy command. My function includes parameters to give your command a new name and to strip out help references. I did this under the theory that you are building a new command on top of the underlying command and want to include your own help. If you run this function in the PowerShell ISE, it will paste your code into a new ISE tab.

So I can run this:

get-commandmetadata Get-DnsClient -nohelp -NewName Get-MyDNSClient

And end up with this:

#requires -version 4.0

Function Get-MyDNSClient {

[CmdletBinding(DefaultParameterSetName='ByName', PositionalBinding=$false)]
 param(
     [Parameter(ParameterSetName='ByName', ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
     [ValidateNotNull()]
     [uint32[]]
  $InterfaceIndex, 
     [Parameter(ParameterSetName='ByName', Position=0)]
     [ValidateNotNull()]
     [string[]]
  $InterfaceAlias, 
     [Parameter(ParameterSetName='ByName')]
     [Alias('Suffix')]
     [ValidateNotNull()]
     [string[]]
  $ConnectionSpecificSuffix, 
     [Parameter(ParameterSetName='ByName')]
     [ValidateNotNull()]
     [bool[]]
  $RegisterThisConnectionsAddress, 
     [Parameter(ParameterSetName='ByName')]
     [ValidateNotNull()]
     [bool[]]
  $UseSuffixWhenRegistering, 
     [Parameter(ParameterSetName='ByName')]
     [Alias('Session')]
     [ValidateNotNullOrEmpty()]
     [Microsoft.Management.Infrastructure.CimSession[]]
  $CimSession, 
     [Parameter(ParameterSetName='ByName')]
     [int]
  $ThrottleLimit, 
     [Parameter(ParameterSetName='ByName')]
     [switch]
  $AsJob) 
 begin
 {
     try {
         $outBuffer = $null
         if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
         {
             $PSBoundParameters['OutBuffer'] = 1
         }
         $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Get-DnsClient', [System.Management.Automation.CommandTypes]::Function)
         $scriptCmd = {& $wrappedCmd @PSBoundParameters }
         $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
         $steppablePipeline.Begin($PSCmdlet)
     } catch {
         throw
     }
 }
 
 process
 {
     try {
         $steppablePipeline.Process($_)
     } catch {
         throw
     }
 }
 
 end
 {
     try {
         $steppablePipeline.End()
     } catch {
         throw
     }
 }
 <#
 
 .Syntax
 PUT SYNTAX HERE
 .Description
 PUT DESCRIPTION HERE
 .Notes
 Created:	9/3/2014 
 
 .Example
 PS C:\> Get-MyDNSClient
 
 .Link
 Get-DnsClient
 
 #>
 

} #end function Get-MyDNSClient

All I need to do now is modify this to meet my needs and flesh out the help. By the way, the #requires statement uses whatever version you have on the system where you run the function. That's about as easy as I can make it for right now but within a second I created 90 lines of PowerShell code with no typos!

As always I hope some of you will give this a try and let me know what you think. Enjoy your weekend.


Behind the PowerShell Pipeline

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to print (Opens in new window) Print
  • Click to email a link to a friend (Opens in new window) Email

Like this:

Like Loading...

Related

3 thoughts on “Friday Fun: Creating PowerShell Scripts with PowerShell”

  1. Mike Shepard says:
    September 5, 2014 at 12:25 pm

    Another awesome post. This makes proxies much easier to work with!

    1. Jeffery Hicks says:
      September 5, 2014 at 12:28 pm

      That was the idea.

  2. Arnaud Petitjean says:
    September 6, 2014 at 9:27 am

    Very cool function Jeff! Thanks

Comments are closed.

reports

Powered by Buttondown.

Join me on Mastodon

The PowerShell Practice Primer
Learn PowerShell in a Month of Lunches Fourth edition


Get More PowerShell Books

Other Online Content

github



PluralSightAuthor

Active Directory ADSI Automation Backup Books CIM CLI conferences console Friday Fun FridayFun Function functions Get-WMIObject GitHub hashtable HTML Hyper-V Iron Scripter ISE Measure-Object module modules MrRoboto new-object objects Out-Gridview Pipeline PowerShell PowerShell ISE Profile prompt Registry Regular Expressions remoting SAPIEN ScriptBlock Scripting Techmentor Training VBScript WMI WPF Write-Host xml

©2025 The Lonely Administrator | Powered by SuperbThemes!
%d