{"id":30,"date":"2010-03-21T21:56:11","date_gmt":"2010-03-22T03:56:11","guid":{"rendered":"http:\/\/jameskovacs.com\/2010\/03\/22\/Pow+Biff+Wham+Splat"},"modified":"2010-03-21T21:56:11","modified_gmt":"2010-03-22T03:56:11","slug":"pow-biff-wham-splat","status":"publish","type":"post","link":"https:\/\/www.jameskovacs.com\/index.php\/2010\/03\/21\/pow-biff-wham-splat\/","title":{"rendered":"Pow! Biff! Wham! Splat!"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" style=\"border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px\" title=\"Batman\" border=\"0\" alt=\"Batman\" align=\"right\" src=\"\/wp-content\/uploads\/WindowsLiveWriter\/PowBiffWhamSplat_11DF4\/image_c0754516-379e-4a7c-9bda-68f6eb869ce1.png\" width=\"240\" height=\"320\">No, this post is not a tribute to the fabulously kitschy <a href=\"http:\/\/www.imdb.com\/title\/tt0059968\/\" target=\"_blank\" rel=\"noopener\">Batman TV series<\/a> (1966-1968) starring Adam West and Burt Ward. Or a tribute to the onomatopoeic sounds for which it and the Batman comics were famous. This show did however come to mind when I was trying to solve a PowerShell problem and ran across the wonderfully-named splatting (@) operator introduced in PowerShell v2. Before we get to the splatting operator, let\u2019s look at the problem that it was designed to solve.<\/p>\n<p>With <a href=\"http:\/\/code.google.com\/p\/psake\" target=\"_blank\" rel=\"noopener\">psake<\/a> v2 came the change from a PowerShell script to a PowerShell module. Modules provide a lot of advantages over a simple script. For psake the compelling advantages were better control over scoping and better integration with PowerShell\u2019s help system. One disadvantage was that you now had to first import the module before you could use psake.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" style=\"border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px\" title=\"image\" border=\"0\" alt=\"image\" src=\"\/wp-content\/uploads\/WindowsLiveWriter\/PowBiffWhamSplat_11DF4\/image_e4611b6b-bb9b-4d57-b577-0108f94ef395.png\" width=\"725\" height=\"295\"><\/p>\n<p>ASIDE: If you\u2019re wondering about the \u201cJames@EDDINGS psake [master +0 ~1 -0]&gt;\u201d stuff, I\u2019ve installed <a href=\"http:\/\/www.markembling.info\" target=\"_blank\" rel=\"noopener\">Mark Embling<\/a>\u2019s awesome <a href=\"http:\/\/www.markembling.info\/view\/my-ideal-powershell-prompt-with-git-integration\" target=\"_blank\" rel=\"noopener\">PowerShell Git Prompt<\/a>, which is simply a custom PowerShell prompt. It tells me that my user is James, I\u2019m logged into my main dev machine (EDDINGS), I\u2019m in the psake directory (c:\\dev\\oss\\psake) \u2013 though I only display the last part of the path for brevity, I\u2019m on the \u201cmaster\u201d branch, I have no pending additions (+0), no pending changes (~0), and no pending deletions (-0). (I need to see if I can hack in how many commits forward or back I am from a tracked remote.) Everything in brackets is omitted if it isn\u2019t a Git directory. Another good set of Git\/PowerShell scripts is <a href=\"http:\/\/www.jeremyskinner.co.uk\" target=\"_blank\" rel=\"noopener\">Jeremy Skinner<\/a>\u2019s <a href=\"http:\/\/www.jeremyskinner.co.uk\/2010\/03\/07\/using-git-with-windows-powershell\/\" target=\"_blank\" rel=\"noopener\">PowerShell Git Tab Expansion<\/a> for completing common command names, branch names, and remote names. If you are using Git and PowerShell, I would highly recommend both Mark\u2019s and Jeremy\u2019s scripts. If you don\u2019t want to copy\/paste them together, you can grab them from my random collection of PowerShell scripts <a href=\"http:\/\/github.com\/JamesKovacs\/scripts\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/p>\n<p>Note how we had to first call \u201cimport-module\u201d before we could use psake. For some people, they install the latest version of psake in some well-known location, import the module, and then run it from there until the next update comes out. For others (e.g. me), we like to version psake along with our source code and other dependencies. Importing a project-specific copy of psake becomes a headache very quickly. So I wrote a little shim script to register psake, run it, and then unregister it.<\/p>\n<p><pre># Helper script for those who want to run\n# psake without importing the module.\nimport-module .\\psake.psm1\n<strong><font color=\"#008000\">invoke-psake $args<\/font><\/strong>\nremove-module psake\n<\/pre>\n<\/p>\n<p>Seems reasonable enough. We simply pass along the script arguments ($args) to the invoke-psake command and everything should be fine.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" style=\"border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px\" title=\"image\" border=\"0\" alt=\"image\" src=\"\/wp-content\/uploads\/WindowsLiveWriter\/PowBiffWhamSplat_11DF4\/image_b90563c7-1c56-42e1-9813-078f2c79d853.png\" width=\"1029\" height=\"206\"> <\/p>\n<p>OK. What happened? PowerShell did what we told it to. It called the function, invoke-psake, with an array as its first parameter rather than using the array as the list of parameters as we intended. Let\u2019s fix that.<\/p>\n<p><pre># Helper script for those who want to run\n# psake without importing the module.\nimport-module .\\psake.psm1\n<strong><font color=\"#008000\">invoke-psake $args[0] $args[1]<\/font><\/strong>\nremove-module psake\n<\/pre>\n<\/p>\n<p>One little problem.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" style=\"border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px\" title=\"image\" border=\"0\" alt=\"image\" src=\"\/wp-content\/uploads\/WindowsLiveWriter\/PowBiffWhamSplat_11DF4\/image_f2f69bd1-7d90-4b85-9923-a36fc532a1db.png\" width=\"725\" height=\"139\"> <\/p>\n<p>Note that we left out the task (\u201cclean\u201d previously) so that psake would use the default. Rather than using the default, invoke-psake has been passed a null argument for the task. We could fix this by detecting null arguments in invoke-psake and explicitly specifying the defaults. It\u2019s ugly because we couldn\u2019t use PowerShell\u2019s syntax for specifying defaults, but it would work. Another problem is that we would need to add as many $args[N] as we expected to receive arguments. A messy solution all around.<\/p>\n<p>Fortunately PowerShell v2 has an elegant solution to this problem called the splatting operator, denoted by @. The splatting operator binds an array to the argument list of a function.<\/p>\n<p><pre># Helper script for those who want to run\n# psake without importing the module.\nimport-module .\\psake.psm1\n<strong><font color=\"#008000\">invoke-psake @args<\/font><\/strong>\nremove-module psake\n<\/pre>\n<\/p>\n<p>Note the subtle change. Rather than using $args we use @args.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" style=\"border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px\" title=\"image\" border=\"0\" alt=\"image\" src=\"\/wp-content\/uploads\/WindowsLiveWriter\/PowBiffWhamSplat_11DF4\/image_97fe0546-5e4a-4f9c-97cd-5b4bdc5845cd.png\" width=\"725\" height=\"343\"> <\/p>\n<p>Success! And it\u2019s not just for passing arguments from one script to another. You can create arr<\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" style=\"border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px\" title=\"image\" border=\"0\" alt=\"image\" src=\"\/wp-content\/uploads\/WindowsLiveWriter\/PowBiffWhamSplat_11DF4\/image_6444396b-81dd-4278-bf84-3d163a618d80.png\" width=\"725\" height=\"199\"> <\/p>\n<p>Note the call to \u201cAdd $addends\u201d where PowerShell called the Add function once for every item in the array. Not what we intended. \u201cAdd @addends\u201d using the splatting operator gave us the expected result. You can even use a hashtable to splat named parameters.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" style=\"border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px\" title=\"image\" border=\"0\" alt=\"image\" src=\"\/wp-content\/uploads\/WindowsLiveWriter\/PowBiffWhamSplat_11DF4\/image_9c6aaf14-bce9-4d92-950c-be877b0326b8.png\" width=\"725\" height=\"199\"> <\/p>\n<p>Note that the answer was 1 (e.g. 11 % 10) and not 10 (e.g. 10 % 11). The splatting operator properly bound the value 11 to the x parameter and 10 to the y parameter, just as it was in the hashtable.<\/p>\n<p>The splatting operator provides us with a tremendous amount of flexibility in manipulating function and script arguments. It\u2019s a useful tool to add to your PowerShell arsenal. Go forth and SPLAT!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>No, this post is not a tribute to the fabulously kitschy Batman TV series (1966-1968) starring Adam West and Burt Ward. Or a tribute to the onomatopoeic sounds for which it and the Batman comics were famous. This show did however come to mind when I was trying to solve a PowerShell problem and ran [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[16],"tags":[],"class_list":["post-30","post","type-post","status-publish","format-standard","hentry","category-powershell"],"_links":{"self":[{"href":"https:\/\/www.jameskovacs.com\/index.php\/wp-json\/wp\/v2\/posts\/30","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.jameskovacs.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.jameskovacs.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.jameskovacs.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.jameskovacs.com\/index.php\/wp-json\/wp\/v2\/comments?post=30"}],"version-history":[{"count":0,"href":"https:\/\/www.jameskovacs.com\/index.php\/wp-json\/wp\/v2\/posts\/30\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.jameskovacs.com\/index.php\/wp-json\/wp\/v2\/media?parent=30"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.jameskovacs.com\/index.php\/wp-json\/wp\/v2\/categories?post=30"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.jameskovacs.com\/index.php\/wp-json\/wp\/v2\/tags?post=30"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}