{"id":4005,"date":"2014-09-10T11:09:07","date_gmt":"2014-09-10T15:09:07","guid":{"rendered":"http:\/\/jdhitsolutions.com\/blog\/?p=4005"},"modified":"2014-09-10T11:36:08","modified_gmt":"2014-09-10T15:36:08","slug":"creating-your-own-powershell-command","status":"publish","type":"post","link":"https:\/\/jdhitsolutions.com\/blog\/powershell\/4005\/creating-your-own-powershell-command\/","title":{"rendered":"Creating Your Own PowerShell Command"},"content":{"rendered":"<p><a href=\"http:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2013\/02\/atomicps.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-thumbnail wp-image-2826\" src=\"http:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2013\/02\/atomicps-150x150.jpg\" alt=\"atomic powershell\" width=\"150\" height=\"150\" \/><\/a>Last week, <a title=\"Friday Fun: Creating PowerShell Scripts with PowerShell\" href=\"http:\/\/jdhitsolutions.com\/blog\/2014\/09\/friday-fun-creating-powershell-scripts-with-powershell\/\" target=\"_blank\">I posted a PowerShell function<\/a> that you could use as an accelerator to create your own PowerShell tools. My tool takes command metadata from an existing PowerShell cmdlet and gives you the structure to create your own tool wrapped around what is in essence a proxy function.<\/p>\n<p>The advantage, besides saving a lot of typing, is that by using a proxy function you can take advantage of the wrapped cmdlet's features and parameters. But perhaps it would help to see an example. With the Get-CommandMetadata function loaded into the PowerShell ISE, I run this command:<\/p>\n<pre class=\"lang:ps decode:true \">get-commandmetadata get-ciminstance -NoHelp -NewName Get-CimOS<\/pre>\n<p>Instead of using CDXML, or writing my own function to call Get-Cimstance, I'm going to create a proxy to Get-Ciminstance that designed to retrieve operating system information. Here's what I start with.<\/p>\n<pre class=\"lang:ps decode:true \">#requires -version 4.0\r\n\r\nFunction Get-CimOS {\r\n\r\n[CmdletBinding(DefaultParameterSetName='ClassNameComputerSet')]\r\n param(\r\n     [Parameter(ParameterSetName='QuerySessionSet', Mandatory=$true, ValueFromPipeline=$true)]\r\n     [Parameter(ParameterSetName='CimInstanceSessionSet', Mandatory=$true, ValueFromPipeline=$true)]\r\n     [Parameter(ParameterSetName='ClassNameSessionSet', Mandatory=$true, ValueFromPipeline=$true)]\r\n     [Parameter(ParameterSetName='ResourceUriSessionSet', Mandatory=$true, ValueFromPipeline=$true)]\r\n     [Microsoft.Management.Infrastructure.CimSession[]]\r\n  $CimSession, \r\n     [Parameter(ParameterSetName='ClassNameSessionSet', Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]\r\n     [Parameter(ParameterSetName='ClassNameComputerSet', Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]\r\n     [string]\r\n  $ClassName, \r\n     [Parameter(ParameterSetName='CimInstanceSessionSet')]\r\n     [Parameter(ParameterSetName='CimInstanceComputerSet')]\r\n     [Parameter(ParameterSetName='QuerySessionSet', ValueFromPipelineByPropertyName=$true)]\r\n     [Parameter(ParameterSetName='QueryComputerSet', ValueFromPipelineByPropertyName=$true)]\r\n     [Parameter(ParameterSetName='ResourceUriSessionSet', Mandatory=$true, ValueFromPipelineByPropertyName=$true)]\r\n     [Parameter(ParameterSetName='ResourceUriComputerSet', Mandatory=$true, ValueFromPipelineByPropertyName=$true)]\r\n     [uri]\r\n  $ResourceUri, \r\n     [Parameter(ParameterSetName='QueryComputerSet', ValueFromPipelineByPropertyName=$true)]\r\n     [Parameter(ParameterSetName='ResourceUriComputerSet', ValueFromPipelineByPropertyName=$true)]\r\n     [Parameter(ParameterSetName='CimInstanceComputerSet')]\r\n     [Parameter(ParameterSetName='ClassNameComputerSet', ValueFromPipelineByPropertyName=$true)]\r\n     [Alias('CN','ServerName')]\r\n     [string[]]\r\n  $ComputerName, \r\n     [Parameter(ParameterSetName='ResourceUriSessionSet')]\r\n     [Parameter(ParameterSetName='ClassNameSessionSet')]\r\n     [Parameter(ParameterSetName='ResourceUriComputerSet')]\r\n     [Parameter(ParameterSetName='ClassNameComputerSet')]\r\n     [switch]\r\n  $KeyOnly, \r\n     [Parameter(ParameterSetName='ClassNameSessionSet', ValueFromPipelineByPropertyName=$true)]\r\n     [Parameter(ParameterSetName='ResourceUriComputerSet', ValueFromPipelineByPropertyName=$true)]\r\n     [Parameter(ParameterSetName='QuerySessionSet', ValueFromPipelineByPropertyName=$true)]\r\n     [Parameter(ParameterSetName='ClassNameComputerSet', ValueFromPipelineByPropertyName=$true)]\r\n     [Parameter(ParameterSetName='QueryComputerSet', ValueFromPipelineByPropertyName=$true)]\r\n     [Parameter(ParameterSetName='ResourceUriSessionSet', ValueFromPipelineByPropertyName=$true)]\r\n     [string]\r\n  $Namespace, \r\n     [Alias('OT')]\r\n     [uint32]\r\n  $OperationTimeoutSec, \r\n     [Parameter(ParameterSetName='CimInstanceComputerSet', Mandatory=$true, Position=0, ValueFromPipeline=$true)]\r\n     [Parameter(ParameterSetName='CimInstanceSessionSet', Mandatory=$true, Position=0, ValueFromPipeline=$true)]\r\n     [Alias('CimInstance')]\r\n     [ciminstance]\r\n  $InputObject, \r\n     [Parameter(ParameterSetName='QueryComputerSet', Mandatory=$true, ValueFromPipelineByPropertyName=$true)]\r\n     [Parameter(ParameterSetName='QuerySessionSet', Mandatory=$true, ValueFromPipelineByPropertyName=$true)]\r\n     [string]\r\n  $Query, \r\n     [Parameter(ParameterSetName='QueryComputerSet', ValueFromPipelineByPropertyName=$true)]\r\n     [Parameter(ParameterSetName='QuerySessionSet', ValueFromPipelineByPropertyName=$true)]\r\n     [Parameter(ParameterSetName='ClassNameSessionSet', ValueFromPipelineByPropertyName=$true)]\r\n     [Parameter(ParameterSetName='ClassNameComputerSet', ValueFromPipelineByPropertyName=$true)]\r\n     [string]\r\n  $QueryDialect, \r\n     [Parameter(ParameterSetName='ResourceUriSessionSet')]\r\n     [Parameter(ParameterSetName='QueryComputerSet')]\r\n     [Parameter(ParameterSetName='QuerySessionSet')]\r\n     [Parameter(ParameterSetName='ResourceUriComputerSet')]\r\n     [Parameter(ParameterSetName='ClassNameComputerSet')]\r\n     [Parameter(ParameterSetName='ClassNameSessionSet')]\r\n     [switch]\r\n  $Shallow, \r\n     [Parameter(ParameterSetName='ClassNameSessionSet', ValueFromPipelineByPropertyName=$true)]\r\n     [Parameter(ParameterSetName='ClassNameComputerSet', ValueFromPipelineByPropertyName=$true)]\r\n     [Parameter(ParameterSetName='ResourceUriSessionSet', ValueFromPipelineByPropertyName=$true)]\r\n     [Parameter(ParameterSetName='ResourceUriComputerSet', ValueFromPipelineByPropertyName=$true)]\r\n     [string]\r\n  $Filter, \r\n     [Parameter(ParameterSetName='ClassNameComputerSet', ValueFromPipelineByPropertyName=$true)]\r\n     [Parameter(ParameterSetName='ResourceUriComputerSet', ValueFromPipelineByPropertyName=$true)]\r\n     [Parameter(ParameterSetName='ClassNameSessionSet', ValueFromPipelineByPropertyName=$true)]\r\n     [Parameter(ParameterSetName='ResourceUriSessionSet', ValueFromPipelineByPropertyName=$true)]\r\n     [Alias('SelectProperties')]\r\n     [string[]]\r\n  $Property) \r\n begin\r\n {\r\n     try {\r\n         $outBuffer = $null\r\n         if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))\r\n         {\r\n             $PSBoundParameters['OutBuffer'] = 1\r\n         }\r\n         $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Get-CimInstance', [System.Management.Automation.CommandTypes]::Cmdlet)\r\n         $scriptCmd = {&amp; $wrappedCmd @PSBoundParameters }\r\n         $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)\r\n         $steppablePipeline.Begin($PSCmdlet)\r\n     } catch {\r\n         throw\r\n     }\r\n }\r\n \r\n process\r\n {\r\n     try {\r\n         $steppablePipeline.Process($_)\r\n     } catch {\r\n         throw\r\n     }\r\n }\r\n \r\n end\r\n {\r\n     try {\r\n         $steppablePipeline.End()\r\n     } catch {\r\n         throw\r\n     }\r\n }\r\n &lt;#\r\n \r\n .Synopsis\r\n PUT SYNTAX HERE\r\n .Description\r\n PUT DESCRIPTION HERE\r\n .Notes\r\n Created:\t9\/8\/2014 \r\n \r\n .Example\r\n PS C:\\&gt; Get-CimOS\r\n \r\n .Link\r\n Get-CimInstance\r\n \r\n #&gt;\r\n \r\n\r\n} #end function Get-CimOS<\/pre>\n<p>As with any PowerShell scripting project, you have to think about who will run your command and what expectations they might have. In my example, I simply want to be able to specify a computer name or a CIM Session and retrieve information from the Win32_Operatingsystem class. So to begin with I can delete all the parameter definitions except Computername and CIMSession. I'll also keep the OperationTimeOut parameter just in case. As you can see in the code sample, Get-CimInstance also has a number of parameter sets. Again, I can delete references to ones I'm not going to use.<\/p>\n<p>Here's my revised parameter definition.<\/p>\n<pre class=\"lang:ps decode:true \">[CmdletBinding(DefaultParameterSetName='ClassNameComputerSet')]\r\nparam(\r\n    [Parameter(Position=0,ParameterSetName='CimInstanceSessionSet', Mandatory=$true, ValueFromPipeline=$true)]\r\n    [Microsoft.Management.Infrastructure.CimSession[]]$CimSession,\r\n\r\n    [Parameter(Position=0,ParameterSetName='ClassNameComputerSet', ValueFromPipelineByPropertyName=$true)]\r\n    [Alias('CN','ServerName')]\r\n    [string[]]$ComputerName = $env:Computername,\r\n\r\n    [Alias('OT')]\r\n    [uint32]$OperationTimeoutSec\r\n    )<\/pre>\n<p>One change I made was to give the computername a default value for the local computer. I amd doing this so that the PSComputername property will always have a value.<\/p>\n<pre class=\"lang:ps decode:true \">PS C:\\&gt; get-ciminstance win32_bios | select name,pscomputername\r\n\r\nname                                                        PSComputerName\r\n----                                                        --------------\r\n76CN38WW\r\n\r\n\r\nPS C:\\&gt; get-ciminstance win32_bios -comp $env:computername | select name,pscomputername\r\n\r\nname                                                        PSComputerName\r\n----                                                        --------------\r\n76CN38WW                                                    WIN81-ENT-01<\/pre>\n<p>But you may be wondering, what about the classname? This is where the fun begins. I am going to hard-code other parameters into the function.<\/p>\n<pre class=\"lang:ps decode:true \">#Add hard-coded parameters\r\n$PSBoundParameters.Add(\"Classname\",\"win32_operatingsystem\")\r\n$PSBoundParameters.Add(\"Namespace\",\"root\\cimv2\")\r\n\r\n$wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Get-CimInstance', [System.Management.Automation.CommandTypes]::Cmdlet)\r\n<\/pre>\n<p>When the wrapped command is executed it will use these values which is what I want. At this point, I could save the function and run it. But the output would be the same as if I had run Get-Ciminstance and I have a specific output in mind. Here's how.<\/p>\n<p>First, copy and paste a new version of the $scriptCmd line. Comment out the original line.<\/p>\n<pre class=\"lang:ps decode:true \"># $scriptCmd = {&amp; $wrappedCmd @PSBoundParameters }<\/pre>\n<p>What I need to do is create my own script command, which must be a single pipelined expression.<\/p>\n<pre class=\"lang:ps decode:true \">$scriptCmd = {\r\n    #select whatever Win32_OperatingSystem properties you need\r\n    &amp; $wrappedCmd @PSBoundParameters | \r\n    Select-Object @{Name=\"Computername\";Expression={$_.CSName}},\r\n    @{Name=\"OS\";Expression={$_.Caption}},Version,\r\n    @{Name=\"64bit\";Expression={\r\n    if ($_.OSArchitecture -match \"64\") {\r\n        $True\r\n    }\r\n    else {\r\n        $False\r\n    }}}, \r\n    @{Name=\"SvcPack\";Expression={$_.CSDVersion}},InstallDate\r\n} #scriptcmd<\/pre>\n<p>I still want the wrapped Get-Ciminstance command to run but then I'm going to pipe the results to Select-Object and specify some custom properties. That is the extent of my major changes, although I also will add some additional Write-Verbose lines for tracing and troubleshooting. After updating comment based help, here's my final command.<\/p>\n<pre class=\"lang:ps decode:true \">#requires -version 4.0\r\n\r\n#this version selects the properties I want\r\n\r\nFunction Get-CIMOS {\r\n\r\n&lt;#\r\n.Synopsis\r\nGet operating system information.\r\n.Description\r\nThis is a proxy version of Get-CimInstance designed to get operating system information from one or more computers.\r\n.Notes\r\nLast Updated:\t9\/4\/2014 \r\n\r\nLearn more:\r\n PowerShell in Depth: An Administrator's Guide (http:\/\/www.manning.com\/jones6\/)\r\n PowerShell Deep Dives (http:\/\/manning.com\/hicks\/)\r\n Learn PowerShell in a Month of Lunches (http:\/\/manning.com\/jones3\/)\r\n Learn PowerShell Toolmaking in a Month of Lunches (http:\/\/manning.com\/jones4\/)\r\n PowerShell and WMI (http:\/\/www.manning.com\/siddaway2\/)\r\n\r\n  ****************************************************************\r\n  * DO NOT USE IN A PRODUCTION ENVIRONMENT UNTIL YOU HAVE TESTED *\r\n  * THOROUGHLY IN A LAB ENVIRONMENT. USE AT YOUR OWN RISK.  IF   *\r\n  * YOU DO NOT UNDERSTAND WHAT THIS SCRIPT DOES OR HOW IT WORKS, *\r\n  * DO NOT USE IT OUTSIDE OF A SECURE, TEST SETTING.             *\r\n  ****************************************************************\r\n\r\n.Example\r\nPS C:&gt; get-cimos chi-dc04\r\n\r\nComputername   : CHI-DC04\r\nOS             : Microsoft Windows Server 2012 Datacenter\r\nVersion        : 6.2.9200\r\nSvcPack        :\r\nInstallDate    : 9\/10\/2012 12:41:57 PM\r\n\r\n.Example\r\nPS C:\\&gt; get-cimsession | get-cimos | out-gridview -title \"OS Report\"\r\n.Link\r\nGet-CimInstance\r\n#&gt;\r\n\r\n[CmdletBinding(DefaultParameterSetName='ClassNameComputerSet')]\r\nparam(\r\n    [Parameter(Position=0,ParameterSetName='CimInstanceSessionSet', Mandatory=$true, ValueFromPipeline=$true)]\r\n    [Microsoft.Management.Infrastructure.CimSession[]]$CimSession,\r\n\r\n    [Parameter(Position=0,ParameterSetName='ClassNameComputerSet', ValueFromPipelineByPropertyName=$true)]\r\n    [Alias('CN','ServerName')]\r\n    [string[]]$ComputerName = $env:Computername,\r\n\r\n    [Alias('OT')]\r\n    [uint32]$OperationTimeoutSec\r\n    )\r\n\r\nbegin\r\n{\r\n    #add my own verbose output\r\n    Write-Verbose -Message \"Starting $($MyInvocation.Mycommand)\"  \r\n    Write-verbose $PSCmdlet.ParameterSetName\r\n\r\n    try {\r\n        $outBuffer = $null\r\n        if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))\r\n        {\r\n            $PSBoundParameters['OutBuffer'] = 1\r\n        }\r\n\r\n        #Add hard-coded parameters\r\n        $PSBoundParameters.Add(\"Classname\",\"win32_operatingsystem\")\r\n        $PSBoundParameters.Add(\"Namespace\",\"root\\cimv2\")\r\n\r\n        $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Get-CimInstance', [System.Management.Automation.CommandTypes]::Cmdlet)\r\n       \r\n       #the original line\r\n       # $scriptCmd = {&amp; $wrappedCmd @PSBoundParameters }\r\n\r\n       #my modified scriptblock. The scriptblock can only contain a single pipelined expression\r\n        $scriptCmd = {\r\n         #select whatever Win32_OperatingSystem properties you need\r\n         &amp; $wrappedCmd @PSBoundParameters | \r\n         Select-Object @{Name=\"Computername\";Expression={$_.CSName}},\r\n         @{Name=\"OS\";Expression={$_.Caption}},Version,\r\n         @{Name=\"64bit\";Expression={\r\n          if ($_.OSArchitecture -match \"64\") {\r\n            $True\r\n          }\r\n          else {\r\n            $False\r\n          }}}, \r\n         @{Name=\"SvcPack\";Expression={$_.CSDVersion}},InstallDate\r\n         } #scriptcmd\r\n\r\n        $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)\r\n\r\n        Write-Verbose \"Begin steppable pipeline\"\r\n        $steppablePipeline.Begin($PSCmdlet)\r\n    } catch {\r\n        throw\r\n    }\r\n} #begin block\r\n\r\nprocess\r\n{\r\n    try {\r\n        Write-Verbose \"Processing\"\r\n        if ($PSCmdlet.ParameterSetName -eq 'ClassNameComputerSet') {\r\n            $inputs = $ComputerName\r\n        }\r\n        else {\r\n            $inputs = $cimSession.Computername\r\n        }\r\n\r\n        foreach ($computer in $inputs) {\r\n            Write-Verbose \"...$computer\"\r\n        }\r\n        \r\n   \r\n        $steppablePipeline.Process($_) \r\n\r\n    } catch {\r\n        throw\r\n    }\r\n} #process block\r\n\r\nend\r\n{\r\n    Write-Verbose -Message \"Ending $($MyInvocation.Mycommand)\" \r\n\r\n    try {\r\n        $steppablePipeline.End() \r\n    } catch {\r\n        throw\r\n    }\r\n} #end block\r\n} #end function Get-CIMOS\r\n<\/pre>\n<p>Now to test it out:<\/p>\n<pre class=\"lang:ps decode:true \">PS C:\\&gt; get-cimos\r\n\r\nComputername : WIN81-ENT-01\r\nOS           : Microsoft Windows 8.1 Enterprise\r\nVersion      : 6.3.9600\r\n64bit        : True\r\nSvcPack      :\r\nInstallDate  : 11\/26\/2013 1:08:31 PM<\/pre>\n<p>I can specify a computername:<\/p>\n<pre class=\"lang:ps decode:true \" >PS C:\\&gt; get-cimos -ComputerName chi-dc04\r\n\r\nComputername : CHI-DC04\r\nOS           : Microsoft Windows Server 2012 Datacenter\r\nVersion      : 6.2.9200\r\n64bit        : True\r\nSvcPack      :\r\nInstallDate  : 9\/10\/2012 12:41:57 PM<\/pre>\n<p>Or use CIMSessions.<\/p>\n<pre class=\"lang:ps decode:true \" >PS C:\\&gt; get-cimsession | get-cimos |out-gridview -title \"OS Report\"<\/pre>\n<p><a href=\"http:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2014\/09\/osreport.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2014\/09\/osreport-1024x327.png\" alt=\"osreport\" width=\"474\" height=\"151\" class=\"aligncenter size-large wp-image-4007\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2014\/09\/osreport-1024x327.png 1024w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2014\/09\/osreport-300x96.png 300w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2014\/09\/osreport.png 1187w\" sizes=\"auto, (max-width: 474px) 100vw, 474px\" \/><\/a><\/p>\n<p>I didn't have to write any code to use the CIMSessions. I let the wrapped cmdlet handle everything for me. The end result is that I now have a very complete PowerShell tool that didn't take much time to create. I probably spent more time getting the comment-based help written than anything.<\/p>\n<p>Hopefully this gives you an idea of how to take your PowerShell toolmaking to the next level.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last week, I posted a PowerShell function that you could use as an accelerator to create your own PowerShell tools. My tool takes command metadata from an existing PowerShell cmdlet and gives you the structure to create your own tool wrapped around what is in essence a proxy function. The advantage, besides saving a lot&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"fresh blog: Creating Your Own #PowerShell Commands http:\/\/bit.ly\/ZeUjlJ","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[4,8,19],"tags":[534,476,540],"class_list":["post-4005","post","type-post","status-publish","format-standard","hentry","category-powershell","category-scripting","category-wmi","tag-powershell","tag-proxy-functions","tag-scripting"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Creating Your Own PowerShell Command &#8226; The Lonely Administrator<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/jdhitsolutions.com\/blog\/powershell\/4005\/creating-your-own-powershell-command\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Creating Your Own PowerShell Command &#8226; The Lonely Administrator\" \/>\n<meta property=\"og:description\" content=\"Last week, I posted a PowerShell function that you could use as an accelerator to create your own PowerShell tools. My tool takes command metadata from an existing PowerShell cmdlet and gives you the structure to create your own tool wrapped around what is in essence a proxy function. The advantage, besides saving a lot...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/jdhitsolutions.com\/blog\/powershell\/4005\/creating-your-own-powershell-command\/\" \/>\n<meta property=\"og:site_name\" content=\"The Lonely Administrator\" \/>\n<meta property=\"article:published_time\" content=\"2014-09-10T15:09:07+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2014-09-10T15:36:08+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2013\/02\/atomicps-150x150.jpg\" \/>\n<meta name=\"author\" content=\"Jeffery Hicks\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@JeffHicks\" \/>\n<meta name=\"twitter:site\" content=\"@JeffHicks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jeffery Hicks\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/4005\\\/creating-your-own-powershell-command\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/4005\\\/creating-your-own-powershell-command\\\/\"},\"author\":{\"name\":\"Jeffery Hicks\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\"},\"headline\":\"Creating Your Own PowerShell Command\",\"datePublished\":\"2014-09-10T15:09:07+00:00\",\"dateModified\":\"2014-09-10T15:36:08+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/4005\\\/creating-your-own-powershell-command\\\/\"},\"wordCount\":525,\"commentCount\":2,\"publisher\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\"},\"image\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/4005\\\/creating-your-own-powershell-command\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/jdhitsolutions.com\\\/blog\\\/wp-content\\\/uploads\\\/2013\\\/02\\\/atomicps-150x150.jpg\",\"keywords\":[\"PowerShell\",\"Proxy functions\",\"Scripting\"],\"articleSection\":[\"PowerShell\",\"Scripting\",\"WMI\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/4005\\\/creating-your-own-powershell-command\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/4005\\\/creating-your-own-powershell-command\\\/\",\"url\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/4005\\\/creating-your-own-powershell-command\\\/\",\"name\":\"Creating Your Own PowerShell Command &#8226; The Lonely Administrator\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/4005\\\/creating-your-own-powershell-command\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/4005\\\/creating-your-own-powershell-command\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/jdhitsolutions.com\\\/blog\\\/wp-content\\\/uploads\\\/2013\\\/02\\\/atomicps-150x150.jpg\",\"datePublished\":\"2014-09-10T15:09:07+00:00\",\"dateModified\":\"2014-09-10T15:36:08+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/4005\\\/creating-your-own-powershell-command\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/4005\\\/creating-your-own-powershell-command\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/4005\\\/creating-your-own-powershell-command\\\/#primaryimage\",\"url\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/wp-content\\\/uploads\\\/2013\\\/02\\\/atomicps.jpg\",\"contentUrl\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/wp-content\\\/uploads\\\/2013\\\/02\\\/atomicps.jpg\",\"width\":373,\"height\":468},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/4005\\\/creating-your-own-powershell-command\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"PowerShell\",\"item\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/category\\\/powershell\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Creating Your Own PowerShell Command\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/\",\"name\":\"The Lonely Administrator\",\"description\":\"Practical Advice for the Automating IT Pro\",\"publisher\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\",\"name\":\"Jeffery Hicks\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\",\"caption\":\"Jeffery Hicks\"},\"logo\":{\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Creating Your Own PowerShell Command &#8226; The Lonely Administrator","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/jdhitsolutions.com\/blog\/powershell\/4005\/creating-your-own-powershell-command\/","og_locale":"en_US","og_type":"article","og_title":"Creating Your Own PowerShell Command &#8226; The Lonely Administrator","og_description":"Last week, I posted a PowerShell function that you could use as an accelerator to create your own PowerShell tools. My tool takes command metadata from an existing PowerShell cmdlet and gives you the structure to create your own tool wrapped around what is in essence a proxy function. The advantage, besides saving a lot...","og_url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/4005\/creating-your-own-powershell-command\/","og_site_name":"The Lonely Administrator","article_published_time":"2014-09-10T15:09:07+00:00","article_modified_time":"2014-09-10T15:36:08+00:00","og_image":[{"url":"http:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2013\/02\/atomicps-150x150.jpg","type":"","width":"","height":""}],"author":"Jeffery Hicks","twitter_card":"summary_large_image","twitter_creator":"@JeffHicks","twitter_site":"@JeffHicks","twitter_misc":{"Written by":"Jeffery Hicks","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/4005\/creating-your-own-powershell-command\/#article","isPartOf":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/4005\/creating-your-own-powershell-command\/"},"author":{"name":"Jeffery Hicks","@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9"},"headline":"Creating Your Own PowerShell Command","datePublished":"2014-09-10T15:09:07+00:00","dateModified":"2014-09-10T15:36:08+00:00","mainEntityOfPage":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/4005\/creating-your-own-powershell-command\/"},"wordCount":525,"commentCount":2,"publisher":{"@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9"},"image":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/4005\/creating-your-own-powershell-command\/#primaryimage"},"thumbnailUrl":"http:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2013\/02\/atomicps-150x150.jpg","keywords":["PowerShell","Proxy functions","Scripting"],"articleSection":["PowerShell","Scripting","WMI"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/jdhitsolutions.com\/blog\/powershell\/4005\/creating-your-own-powershell-command\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/4005\/creating-your-own-powershell-command\/","url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/4005\/creating-your-own-powershell-command\/","name":"Creating Your Own PowerShell Command &#8226; The Lonely Administrator","isPartOf":{"@id":"https:\/\/jdhitsolutions.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/4005\/creating-your-own-powershell-command\/#primaryimage"},"image":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/4005\/creating-your-own-powershell-command\/#primaryimage"},"thumbnailUrl":"http:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2013\/02\/atomicps-150x150.jpg","datePublished":"2014-09-10T15:09:07+00:00","dateModified":"2014-09-10T15:36:08+00:00","breadcrumb":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/4005\/creating-your-own-powershell-command\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/jdhitsolutions.com\/blog\/powershell\/4005\/creating-your-own-powershell-command\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/4005\/creating-your-own-powershell-command\/#primaryimage","url":"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2013\/02\/atomicps.jpg","contentUrl":"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2013\/02\/atomicps.jpg","width":373,"height":468},{"@type":"BreadcrumbList","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/4005\/creating-your-own-powershell-command\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"PowerShell","item":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},{"@type":"ListItem","position":2,"name":"Creating Your Own PowerShell Command"}]},{"@type":"WebSite","@id":"https:\/\/jdhitsolutions.com\/blog\/#website","url":"https:\/\/jdhitsolutions.com\/blog\/","name":"The Lonely Administrator","description":"Practical Advice for the Automating IT Pro","publisher":{"@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/jdhitsolutions.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9","name":"Jeffery Hicks","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg","url":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg","caption":"Jeffery Hicks"},"logo":{"@id":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg"}}]}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":3990,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/3990\/friday-fun-creating-powershell-scripts-with-powershell\/","url_meta":{"origin":4005,"position":0},"title":"Friday Fun: Creating PowerShell Scripts with PowerShell","author":"Jeffery Hicks","date":"September 5, 2014","format":false,"excerpt":"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,\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"012914_1704_CreatingCIM1.png","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2014\/01\/012914_1704_CreatingCIM1-150x150.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":3987,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/3987\/making-the-shell-work-for-you-revisited\/","url_meta":{"origin":4005,"position":1},"title":"Making the Shell Work for You Revisited","author":"Jeffery Hicks","date":"September 3, 2014","format":false,"excerpt":"The other day, I posted an article about creating your own commands to simplify your life at the PowerShell prompt. Most of the time, creating your own wrapper function for an existing PowerShell command isn't too difficult. Personally, this is the approach I usually take. But PowerShell is all about\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"blocks","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2014\/09\/blocks-150x150.jpg?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":9057,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/9057\/using-powershell-your-way\/","url_meta":{"origin":4005,"position":2},"title":"Using PowerShell Your Way","author":"Jeffery Hicks","date":"June 6, 2022","format":false,"excerpt":"I've often told people that I spend my day in a PowerShell prompt. I run almost my entire day with PowerShell. I've shared many of the tools I use daily on Github. Today, I want to share another way I have PowerShell work the way I need it, with minimal\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/06\/dl.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/06\/dl.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/06\/dl.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/06\/dl.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":4018,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/4018\/more-powershell-toolmaking-fun\/","url_meta":{"origin":4005,"position":3},"title":"More PowerShell Toolmaking Fun","author":"Jeffery Hicks","date":"September 15, 2014","format":false,"excerpt":"I am having so much fun making my own PowerShell tools that I just can't stop. I've been using my Get-Commandmetadata function that I wrote about a few weeks ago. A driving force in all of this is to have a toolset that I can use efficiently from the console.\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"blacksmith","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2014\/09\/blacksmith.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":6348,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/6348\/building-more-powershell-functions\/","url_meta":{"origin":4005,"position":4},"title":"Building More PowerShell Functions","author":"Jeffery Hicks","date":"January 3, 2019","format":false,"excerpt":"In a recent post I discussed the the process you might go through in developing a PowerShell function. By the end, I not only had a new tool for my PowerShell toolbox, but I had a function outline that I could re-use. If you read the previous article then you\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/01\/image_thumb-3.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/01\/image_thumb-3.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/01\/image_thumb-3.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2019\/01\/image_thumb-3.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":6855,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell-7\/6855\/powershell-scripting-for-linux-is-still-about-the-objects\/","url_meta":{"origin":4005,"position":5},"title":"PowerShell Scripting for Linux is Still About the Objects","author":"Jeffery Hicks","date":"October 8, 2019","format":false,"excerpt":"I've been trying to increase my Linux skills, especially as I begin to write PowerShell scripts and tools that can work cross-platform. One very important concept I want to make sure you don't overlook is that even when scripting for non-Windows platforms, you must still be thinking about objects. The\u2026","rel":"","context":"In &quot;PowerShell 7&quot;","block_context":{"text":"PowerShell 7","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell-7\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/4005","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/comments?post=4005"}],"version-history":[{"count":0,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/4005\/revisions"}],"wp:attachment":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/media?parent=4005"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/categories?post=4005"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/tags?post=4005"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}