{"id":16771,"date":"2010-10-19T00:01:00","date_gmt":"2010-10-19T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2010\/10\/19\/automatically-create-custom-powershell-functions\/"},"modified":"2010-10-19T00:01:00","modified_gmt":"2010-10-19T00:01:00","slug":"automatically-create-custom-powershell-functions","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/automatically-create-custom-powershell-functions\/","title":{"rendered":"Automatically Create Custom PowerShell Functions"},"content":{"rendered":"<p>&nbsp;<\/p>\n<p><strong>Summary<\/strong>: Learn how to automatically create custom Windows PowerShell functions by using a free tool that writes your code for you.<\/p>\n<p>&nbsp;<\/p>\n<p><img decoding=\"async\" title=\"Hey, Scripting Guy! Question\" height=\"34\" alt=\"Hey, Scripting Guy! Question\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\" \/><\/p>\n<p>Hey, Scripting Guy! I wish there was a good way to modify Windows PowerShell commands. I can modify the names of commands by creating an alias for the command. I wish I could create an alias that also modified the way the command runs. I guess I would have to create some sort of function, but that tends to be an awful lot of work. Is there an easier way to do this?<\/p>\n<p>&#8212; MB<\/p>\n<p>&nbsp;<\/p>\n<p><img decoding=\"async\" title=\"Hey, Scripting Guy! Answer\" height=\"34\" alt=\"Hey, Scripting Guy! Answer\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\" \/><\/p>\n<p> Hello MB, <\/p>\n<p>Microsoft Scripting Guy Ed Wilson here. James Brundage has been talking to me about his <strong>New-ScriptCmdlet<\/strong> function since he wrote it and sent me a copy back when I was working on all the Windows PowerShell scripts for the <a href=\"http:\/\/bit.ly\/Win7_ResKit\">Windows 7 Resource Kit<\/a>. It was so cool, he decided to include it in the <a href=\"http:\/\/code.msdn.microsoft.com\/PowerShellPack\">PowerShellPack<\/a> (the PowerShellPack was so cool, I decided to include that in the Windows 7 Resource Kit). MB, your question will provide James a perfect opportunity to talk about the <strong>New-ScriptCmdlet<\/strong> function. <\/p>\n<p>James Brundage is the founder of Start-Automating (<a href=\"http:\/\/www.start-automating.com\">http:\/\/www.start-automating.com<\/a>), a company dedicated to saving people time and money by helping them automate. Start-Automating offers Windows PowerShell training and custom Windows PowerShell and .NET Framework development. James formerly worked on the Windows PowerShell team at Microsoft, and he is the author of the PowerShellPack (<a href=\"http:\/\/code.msdn.microsoft.com\/PowerShellPack\">http:\/\/code.msdn.microsoft.com\/PowerShellPack<\/a> ), a collection of Windows PowerShell scripts to enable building user interfaces, interact with RSS feeds, get system information, and more.<\/p>\n<h4>A Series on Splatting (and Stuff)<\/h4>\n<h5>Part 2 &ndash; Wrapping a Command with Splatting <\/h5>\n<p>Welcome back to A Series on Splatting (and Stuff). In <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2010\/10\/18\/use-splatting-to-simplify-your-powershell-scripts.aspx\">yesterday&rsquo;s blog post<\/a>, I covered the basics of what splatting was, and showed you how to use it. We created some handy shortcuts for common <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa394582(VS.85).aspx\">WMI<\/a> queries in yesterday&rsquo;s post. Here is one of those examples to refresh your memory:<\/p>\n<blockquote>\n<div class=\"code\"><span style=\"color: #2b91af\">$ComputerSystem<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">@{Query<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\">&#8220;Select * From Win32_ComputerSystem&#8221;<\/span><span style=\"color: #000000\">}<\/span><span style=\"color: #808080\">       <br \/><\/span><span style=\"color: #0000ff\">Get-WmiObject<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">@ComputerSystem<\/span> <\/div>\n<\/blockquote>\n<p>Now we&rsquo;ll put that to practical use by building some wrapper functions, which call other functions. In this post, we&rsquo;ll learn how to take the <strong>Get-WmiObject<\/strong> example and turn it into a <strong>Get-ComputerSystem<\/strong> command, while still keeping all of the <strong>Get-WmiObject<\/strong> command parameters like such as <strong>-AsJob<\/strong>, <strong>-ComputerName<\/strong>, and <strong>-Credential<\/strong>.<\/p>\n<p>Building wrapper functions involves using splatting and using a built-in variable that&rsquo;s there to help enable proxy commands. Proxy commands are the type of scripts you deal with if you ever use implicit <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/tags\/windows+powershell\/getting+started\/remoting\/\">remoting<\/a> (see <a href=\"http:\/\/www.bing.com\/visualsearch?g=powershell_cmdlets&amp;qpvt=Windows+PowerShell&amp;FORM=Z9GE38#category=9&amp;r=10\">Export-PSSession<\/a>). Implicit remoting gives you a command that you interact with as if it were running locally, but really runs against a remote machine. An example might be running <strong>Get-Process<\/strong>, but really returning the processes on machine X. In order for this to work, the local command has to be able to pass all of its parameters perfectly down to the remote command. In order to enable this, a variable was introduced in <a href=\"http:\/\/technet.microsoft.com\/en-us\/scriptcenter\/powershell.aspx\">Windows PowerShell version 2.0<\/a> called <strong>$psBoundParameters<\/strong>.<\/p>\n<p>The Microsoft Scripting Guys have written <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/tags\/windows+powershell\/getting+started\/remoting\/\">a number of Hey, Scripting Guy! Blog posts that discuss remoting<\/a>. They have even had a couple of guest blogger posts on the subject. Needless to say, remoting is cool!<\/p>\n<p><strong>$psBoundParameters<\/strong> contains all of the parameters that were passed to the function. It does not contain default values (don&rsquo;t forget this fact; we&rsquo;ll keep coming back to it). If you use <strong>$psBoundParameters<\/strong> with splatting, you can basically make a function that simply calls another, but preserves all of the capabilities of the underlying function.<\/p>\n<p>Let&rsquo;s see how <strong>$psBoundParameters<\/strong> works in isolation, by making a small function:<\/p>\n<blockquote>\n<div class=\"code\"><span style=\"color: #000000\">function<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">foo(<\/span><span style=\"color: #2b91af\">$a<\/span><span style=\"color: #000000\">,<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$b<\/span><span style=\"color: #000000\">,<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$c<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\"> &#8220;d&#8221;<\/span><span style=\"color: #000000\">)<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">{<\/span><span style=\"color: #808080\">       <br \/>&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #2b91af\">$psBoundParameters<\/span><span style=\"color: #808080\">       <br \/><\/span><span style=\"color: #000000\">}<\/span> <\/div>\n<\/blockquote>\n<p>When we call <strong>foo<\/strong> with no parameters, it returns nothing:<\/p>\n<blockquote>\n<div class=\"code\"><span style=\"color: #000000\">foo<\/span> <\/div>\n<\/blockquote>\n<p>When we call <strong>foo<\/strong> with values for <strong>$a<\/strong>, <strong>$b<\/strong>, or <strong>$c<\/strong>, it contains the data:<\/p>\n<blockquote>\n<div class=\"code\"><span style=\"color: #000000\">foo<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-a<\/span><span style=\"color: #808080\"> &#8220;a&#8221; <\/span><span style=\"color: #000000\">-b<\/span><span style=\"color: #808080\"> &#8220;b&#8221; <\/span><span style=\"color: #000000\">-c<\/span><span style=\"color: #808080\"> &#8220;c&#8221;<\/span> <\/div>\n<\/blockquote>\n<p>It doesn&rsquo;t&#8217; matter if the value for <strong>$a<\/strong>, <strong>$b<\/strong>, or <strong>$c<\/strong> was supplied explicitly. In this simple function, a, b, and c can also be supplied by position, and <strong>$psBoundParameters<\/strong> will still work:<\/p>\n<blockquote>\n<div class=\"code\"><span style=\"color: #000000\">foo<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">a<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">b<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">c<\/span> <\/div>\n<\/blockquote>\n<p>So how can we use this with splatting? Well, let&#8217;s go back to the WMI example. In our example, we&#8217;re only providing one parameter for <strong>Get-WmiObject<\/strong>. By only providing the query, I can still use any of the other parameters <strong>Get-WmiObject<\/strong> has:<\/p>\n<blockquote>\n<div class=\"code\"><span style=\"color: #0000ff\">Get-WmiObject<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">@ComputerSystem<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-ComputerName<\/span><span style=\"color: #808080\"> &#8220;localhost&#8221;<\/span> <\/div>\n<\/blockquote>\n<p>If I want to build a function that just gets me the computer system information, but still allows me to use other parameters such as <strong>-ComputerName<\/strong> and <strong>-AsJob<\/strong>, I can write a function that wraps <strong>Get-WmiObject<\/strong>, but omits the query parameter (and anything else that could confuse the <strong>&ndash;Query<\/strong> parameter, such as <strong>&ndash;Class<\/strong> and <strong>&ndash;Namespace<\/strong>).<\/p>\n<p>There&rsquo;s a nifty function in the PowerShellPack called <strong>New-ScriptCmdlet<\/strong> that will make it easier to write this sort of simple wrapper. <\/p>\n<p>To use the <strong>New-ScriptCmdlet<\/strong> function, you need to download the PowerShell pack, install the module, and import the module into your current Windows PowerShell session. To import the module, use the command <strong>Import-Module<\/strong> PowerShellPack. <\/p>\n<p>The <strong>New-ScriptCmdlet<\/strong> function requires the name of the command you&#8217;re going to create, the command it&#8217;s based on, the parameters you want to remove from the original command, and the process block. It then produces a new advanced function (script cmdlet was the name for advanced function that was used in the beta of <a href=\"http:\/\/support.microsoft.com\/kb\/968929\">Windows PowerShell 2.0<\/a>) that will wrap the original one. The use of the <strong>New-ScriptCmdlet<\/strong> function is seen here:<\/p>\n<blockquote>\n<div class=\"code\"><span style=\"color: #2b91af\">$newScriptCmdletParameters<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">@{<\/span><span style=\"color: #808080\">       <br \/>&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #000000\">Name<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\"> &#8220;Get-ComputerSystem&#8221;       <br \/>&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #000000\">FromCommand<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">Get-Command<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">Get-WmiObject<\/span><span style=\"color: #808080\">       <br \/>&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #000000\">RemoveParameter<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\"> &#8220;Namespace&#8221;<\/span><span style=\"color: #000000\">,<\/span><span style=\"color: #808080\"> &#8220;Class&#8221;<\/span><span style=\"color: #000000\">,<\/span><span style=\"color: #808080\"> &#8220;Query&#8221;       <br \/>&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #000000\">ProcessBlock<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">{<\/span><span style=\"color: #808080\">       <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #2b91af\">$getWmiObjectParameters<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$psBoundParameters<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">+<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">@{<\/span><span style=\"color: #808080\">       <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #000000\">Query<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\">&#8220;Select * From Win32_ComputerSystem&#8221;       <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #000000\">}<\/span><span style=\"color: #808080\">       <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #0000ff\">Get-WmiObject<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">@GetWmiObjectParameters<\/span><span style=\"color: #808080\">       <br \/>&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #000000\">}<\/span><span style=\"color: #808080\">       <br \/><\/span><span style=\"color: #000000\">}<\/span><span style=\"color: #808080\">       <\/p>\n<p><\/span><span style=\"color: #000000\">New-ScriptCmdlet<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">@newScriptCmdletParameters<\/span> <\/div>\n<\/blockquote>\n<p>That&#8217;s pretty nifty, isn&#8217;t it? A really astoundingly small amount of code makes a function that&#8217;s much bigger. Let&#8217;s make a quick <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/topics\/winpsh\/manual\/pipe.mspx\">pipeline<\/a> to figure out how much code is created.<\/p>\n<p>The pipeline is a fun Windows PowerShell learning experience in and of itself. I could write the whole pipeline in several lines, but it&rsquo;s always an interesting Windows PowerShell exercise to make a pure pipeline. To store the output of <strong>New-ScriptCmdlet<\/strong> into a variable, I pipe the result into <strong>Set-Variable<\/strong>. I add a <strong>&ndash;PassThru<\/strong> to return back the result of <strong>Set-Variable<\/strong>. Because <strong>Set-Variable<\/strong> returns a variable, and I want to measure the words and lines in that variable, I use <strong>Select-Object &ndash;ExpandProperty Value<\/strong> to get back to the value. Then I pipe this into <strong>Measure-Object &ndash;Word &ndash;Line &ndash;Character<\/strong> to see how much text was generated:<\/p>\n<blockquote>\n<div class=\"code\"><span style=\"color: #2b91af\">$newScriptCmdletParameters<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">@{<\/span><span style=\"color: #808080\">       <br \/>&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #000000\">Name<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\"> &#8220;Get-ComputerSystem&#8221;       <br \/>&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #000000\">FromCommand<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">Get-Command<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">Get-WmiObject<\/span><span style=\"color: #808080\">       <br \/>&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #000000\">RemoveParameter<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\"> &#8220;Namespace&#8221;<\/span><span style=\"color: #000000\">,<\/span><span style=\"color: #808080\"> &#8220;Class&#8221;<\/span><span style=\"color: #000000\">,<\/span><span style=\"color: #808080\"> &#8220;Query&#8221;       <br \/>&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #000000\">ProcessBlock<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">{<\/span><span style=\"color: #808080\">       <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #2b91af\">$getWmiObjectParameters<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$psBoundParameters<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">+<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">@{<\/span><span style=\"color: #808080\">       <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #000000\">Query<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\">&#8220;Select * From Win32_ComputerSystem&#8221;       <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #000000\">}<\/span><span style=\"color: #808080\">       <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #0000ff\">Get-WmiObject<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">@GetWmiObjectParameters<\/span><span style=\"color: #808080\">       <br \/>&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #000000\">}<\/span><span style=\"color: #808080\">       <br \/><\/span><span style=\"color: #000000\">}<\/span><span style=\"color: #808080\">       <\/p>\n<p><\/span><span style=\"color: #000000\">New-ScriptCmdlet<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">@newScriptCmdletParameters<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">|<\/span><span style=\"color: #808080\">       <br \/>&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #0000ff\">Set-Variable<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-Name<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">GetComputerSystem<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-PassThru<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">|<\/span><span style=\"color: #808080\">       <br \/>&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #0000ff\">Select-Object<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-ExpandProperty<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">Value<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">|<\/span><span style=\"color: #808080\">       <br \/>&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #0000ff\">Measure-Object<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-Word<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-Line<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-Character<\/span> <\/div>\n<\/blockquote>\n<p>Wow! About 15 lines generated over 100 lines. That&rsquo;s a time saver.<\/p>\n<p><strong>New-ScriptCmdlet<\/strong> produces text, so if I want to turn this into a function I&#8217;m going to use, I can do one of two things. I can either pipe it into <strong>Set-Content<\/strong> and then <a href=\"http:\/\/blogs.technet.com\/heyscriptingguy\/archive\/2009\/12\/23\/hey-scripting-guy-december-23-2009.aspx\">dot-source<\/a> the file to import the function, or I can declare a script block that contains the data and dot-source that script block. Because more readers are probably familiar with the first approach and not with the second, I&#8217;ll show both.<\/p>\n<p>The previous example used the <strong>Set-Variable<\/strong> cmdlet to create a variable named <strong>$GetComputerSystem<\/strong>. Here&rsquo;s an example of outputting the contents of that variable to a Windows PowerShell script file, dot-sourcing that file, and then using the newly imported <strong>Get-ComputerSystem<\/strong> function:<\/p>\n<blockquote>\n<p class=\"CodeBlockScreened\" style=\"background: none transparent scroll repeat 0% 0%;margin: 15pt 17.3pt 0.25in 0in;line-height: 10pt;list-style-type: disc\"><span><span style=\"font-family: 'Lucida Sans Typewriter'\"><span style=\"font-size: 10pt;color: #000000\">           <\/span><\/span><\/span><\/p>\n<div class=\"code\"><span style=\"font-family: 'Lucida Sans Typewriter'\"><span style=\"font-size: 10pt;color: #000000\"><span style=\"color: #2b91af\">$GetComputerSystem<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">|<\/span><span style=\"color: #808080\">&nbsp; <br \/>&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #0000ff\">Set-Content<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">.\\Get-ComputerSystem.ps1<\/span><span style=\"color: #808080\">               <\/p>\n<p><\/span><span style=\"color: #000000\">.<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">.\\Get-ComputerSystem.ps1<\/span><span style=\"color: #808080\">               <\/p>\n<p><\/span><span style=\"color: #000000\">Get-ComputerSystem<\/span> <\/span><\/span><\/div>\n<p><span style=\"font-family: 'Lucida Sans Typewriter'\"><span style=\"font-size: 10pt;color: #000000\">         <\/span><\/span>        <\/p>\n<p>&nbsp;<\/p>\n<\/blockquote>\n<p>Here&rsquo;s an example of dynamically creating a function by using the <strong>create<\/strong> method from the <strong>scriptblock<\/strong> class is illustrated here. The <strong>scriptblock<\/strong> class is contained in the <strong>System.Management.Automation<\/strong> .NET Framework namespace. Luckily, the Windows PowerShell team created the <strong>[scriptblock]<\/strong> type accelerator to make it easy to use this class:<\/p>\n<blockquote>\n<div class=\"code\"><span style=\"color: #000000\">.<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">([ScriptBlock]::Create(<\/span><span style=\"color: #2b91af\">$GetComputerSystem<\/span><span style=\"color: #000000\">))<\/span><span style=\"color: #808080\">       <br \/><\/span><span style=\"color: #000000\">Get-ComputerSystem<\/span> <\/div>\n<\/blockquote>\n<p>As you can see in the following image, the output looks just like <strong>Get-WmiObject Win32_ComputerSystem<\/strong> (because it really is), but you can now refer to it by a more convenient command. <\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/5125.HSG-10-19-10-1_47C9E996.jpg\"><img decoding=\"async\" title=\"Image of output\" style=\"border-right: 0px;padding-right: 0px;border-top: 0px;padding-left: 0px;border-left: 0px;padding-top: 0px;border-bottom: 0px\" height=\"166\" alt=\"Image of output\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2475.HSG-10-19-10-1_thumb_1E066EA3.jpg\" width=\"604\" border=\"0\" \/><\/a><\/p>\n<p>You can make simple wrappers like this for all sorts of cases. You can use either technique for creating the function you&rsquo;d like. The dynamic technique is great to know when you just want to play around, but if you used it on a production machine, you&rsquo;d need to have <strong>New-ScriptCmdlet<\/strong> loaded, so I tend to use the first technique when I&rsquo;m working in a production environment.<\/p>\n<p>Great! Now you know how to wrap commands. Let&rsquo;s do one more for performance counters, just to recap:<\/p>\n<blockquote>\n<div class=\"code\"><span style=\"color: #0000ff\">#<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">Create<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">a<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">set<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">of<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">parameters<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">for<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">New-ScriptCmdlet<\/span><span style=\"color: #808080\">&nbsp; <br \/><\/span><span style=\"color: #2b91af\">$newScriptCmdletParameters<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">@{<\/span><span style=\"color: #808080\">       <br \/>&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #0000ff\">#<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">The<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">name<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">of<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">the<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">command<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">will<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">be<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">Watch-ProcessorPerformance<\/span><span style=\"color: #808080\">       <br \/>&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #000000\">Name<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\"> &#8220;Watch-ProcessorPerformance&#8221;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br \/>&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #0000ff\">#<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">It<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">will<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">be<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">based<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">off<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">of<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">Get-Counter<\/span><span style=\"color: #808080\">       <br \/>&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #000000\">FromCommand<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">Get-Command<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">Get-Counter<\/span><span style=\"color: #808080\">       <br \/>&nbsp;&nbsp;&nbsp; <\/span><span style=\"color: #0000ff\">#<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">We<\/span><span style=\"color: #808080\">&#8216;ll remove the ListSet parameter and the Counter Parameter       <br \/>&nbsp;&nbsp;&nbsp; RemoveParameter = &#8220;ListSet&#8221;, &#8220;Counter&#8221;        <br \/>&nbsp;&nbsp;&nbsp; # The process block of the commands will simply call Get-Counter with the parameters        <br \/>&nbsp;&nbsp;&nbsp; ProcessBlock = {        <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $getCounterParameters= $psBoundParameters + @{        <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Counter=&#8217;<\/span><span style=\"color: #000000\">\\Processor(_total)\\%<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">Processor<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">Time<\/span><span style=\"color: #808080\">&#8216;       <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }        <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Get-Counter @getCounterParameters        <br \/>&nbsp;&nbsp;&nbsp; }        <br \/>}        <\/p>\n<p># Run New-ScriptCmdlet and save the value into a variable        <br \/>New-ScriptCmdlet @newScriptCmdletParameters |        <br \/>&nbsp;&nbsp;&nbsp; Set-Variable -Name GetCounter        <br \/>&nbsp;&nbsp;&nbsp;&nbsp; <br \/># Create a script block with that variable and dot-source it (import it)        <br \/>. ([ScriptBlock]::Create($GetCounter))        <\/p>\n<p># Call the Watch-ProcessorPerformance command        <br \/>Watch-ProcessorPerformance -MaxSamples 3<\/span> <\/div>\n<\/blockquote>\n<p>You can get a lot more complicated with the information you try to get from WMI or the performance counters, but this technique will help you anytime you want to go and build up some commands that wrap other commands.<\/p>\n<p>Splatting (and the stuff related to splatting) opens up an incredibly large number of doors because it&rsquo;s one of the best ways to approach taking myriad general purpose cmdlets and turning them into the specific tool you need. From there on it, it&rsquo;s a lot easier to discover and use. I know that I have an easier time remembering something like <strong>Watch-ProcessorPerformance<\/strong> than something <strong>like Get-Counter &lsquo;\\Processor(_total)\\% Processor Time&rsquo;<\/strong>.<\/p>\n<p>Now you know how you can build a convenient representation of a single cmdlet. In the next article, we&rsquo;ll cover building a bridge between two commands.<\/p>\n<p>MB, that is all there is to using splatting to wrap more complicated Windows PowerShell commands. Guest Blogger Week will continue tomorrow when James will talk about splatting and command metadata. <\/p>\n<p>We invite you to follow us on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\">Facebook<\/a>. If you have any questions, send email to us at <a href=\"mailto:scripter@microsoft.com\">scripter@microsoft.com<\/a>, or post them on the <a href=\"http:\/\/social.technet.microsoft.com\/Forums\/en\/ITCG\/threads\/\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp; Summary: Learn how to automatically create custom Windows PowerShell functions by using a free tool that writes your code for you. &nbsp; Hey, Scripting Guy! I wish there was a good way to modify Windows PowerShell commands. I can modify the names of commands by creating an alias for the command. I wish I [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[51,56,184,3,4,170,45],"class_list":["post-16771","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-getting-started","tag-guest-blogger","tag-james-brundage","tag-scripting-guy","tag-scripting-techniques","tag-splatting","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>&nbsp; Summary: Learn how to automatically create custom Windows PowerShell functions by using a free tool that writes your code for you. &nbsp; Hey, Scripting Guy! I wish there was a good way to modify Windows PowerShell commands. I can modify the names of commands by creating an alias for the command. I wish I [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/16771","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=16771"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/16771\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=16771"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=16771"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=16771"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}