{"id":252,"date":"2014-12-04T00:01:00","date_gmt":"2014-12-04T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2014\/12\/04\/trace-your-commands-by-using-trace-command\/"},"modified":"2022-06-21T14:43:43","modified_gmt":"2022-06-21T21:43:43","slug":"trace-your-commands-by-using-trace-command","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/trace-your-commands-by-using-trace-command\/","title":{"rendered":"Trace Your Commands by Using Trace-Command"},"content":{"rendered":"<p><b style=\"font-size:12px\">Summary<\/b><span style=\"font-size:12px\">: Boe Prox uses <\/span><b style=\"font-size:12px\">Trace-Command<\/b><span style=\"font-size:12px\"> to understand commands.<\/span><\/p>\n<p>Honorary Scripting Guy and Windows PowerShell MVP, Boe Prox, here today filling in for my good friend, The Scripting Guy. This is the fourth part in a series of five posts about troubleshooting PowerShell scripts\/functions. The series includes:<\/p>\n<ol>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/scripting\/provide-support-by-using-verbose-and-debug-streams\/\" target=\"_blank\" rel=\"noopener\">Provide Support by Using Verbose and Debug Streams<\/a><\/li>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/scripting\/troubleshoot-by-using-set-psdebug\/\" target=\"_blank\" rel=\"noopener\">Troubleshoot by Using Set-PSDebug<\/a><\/li>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/scripting\/enforce-better-script-practices-by-using-set-strictmode\/\" target=\"_blank\" rel=\"noopener\">Enforce Better Script Practices by Using Set-StrictMode<\/a><\/li>\n<li><strong>Trace Your Commands by Using Trace-Command<\/strong> (this post)<\/li>\n<li>Use the PowerShell Debugger<\/li>\n<\/ol>\n<p>Today I am talking about using <strong>Trace-Command<\/strong> to look at your commands and to help better understand how they are working behind the scenes.<\/p>\n<p>Have you ever noticed that you can type <strong>Get<\/strong> without the actual verb and get cmdlets? And what is really happening when you pipe objects into a cmdlet and the cmdlet magically finds the right parameter value (well, sometimes)? I will show you this and some other things during the course of this post by using <strong>Trace-Command<\/strong> and a number of supporting parameters.<\/p>\n<h2>Discovering commands<\/h2>\n<p>When you type a command in Windows PowerShell, it first goes through a command discovery that attempts to locate the command that you have typed. If found, Windows PowerShell attempts to run the command. For instance, using <strong>Ping<\/strong> initiates a command discovery to locate Ping.exe prior to running the command. To see this, I am going to use <strong>Trace-Command<\/strong> and supply a few parameters:<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"85\" valign=\"top\">\n<p>\n          \u00a0<strong>Name<\/strong>\n        <\/p>\n<\/td>\n<td width=\"553\" valign=\"top\">\n<p>\n          \u00a0Determines which Windows PowerShell components are traced.\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"85\" valign=\"top\">\n<p>\n          \u00a0<strong>Expression<\/strong>\n        <\/p>\n<\/td>\n<td width=\"553\" valign=\"top\">\n<p>\n          \u00a0A script block with the command that will be traced.\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"85\" valign=\"top\">\n<p>\n          \u00a0<strong>PSHost<\/strong>\n        <\/p>\n<\/td>\n<td width=\"553\" valign=\"top\">\n<p>\n          \u00a0Outputs the trace messages to the Windows PowerShell console.\n        <\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Knowing this, I will construct my trace command to look at how ping.exe is discovered:<\/p>\n<p style=\"margin-left:30px\">\n  Trace-Command \u2013Name CommandDiscovery \u2013Expression {ping localhost} -PSHost\n<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/TraceCommand1.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/TraceCommand1.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>In this image, you can see that a scan is done for <strong>Ping<\/strong> with various extensions against multiple paths until ping.exe is found. Then it is run using the parameters provided.<\/p>\n<p>I mentioned previously that the <strong>Get<\/strong> cmdlets can run without specifying the actual verb, so let&#8217;s use this same approach to see what happens:<\/p>\n<p style=\"margin-left:30px\">\n  Trace-Command \u2013Name CommandDiscovery \u2013Expression {service} -PSHost\n<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/TraceCommand2.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/TraceCommand2.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>I\u2019ll save you from the rather large amount of trace output and get to the very end of it. First all, of the items that we looked for in the previous command (which means various extensions and paths) are traversed. At the end (when nothing has been found), Windows PowerShell appends <strong>Get-<\/strong> to the command\u2014and just like that, we have <strong>Get-Service<\/strong>, which then runs.<\/p>\n<h2>What am I piping to another cmdlet?<\/h2>\n<p>When piping output from one cmdlet to another (or piping some sort of data to another cmdlet), we know that Windows PowerShell will work its magic. It will process that input to the cmdlet and then produce something\u2014whether it is output or some other kind of change.<\/p>\n<p>To better see what is happening behind the scenes, we can look at <strong>ParameterBinding<\/strong>, <strong>ParameterBinderBase<\/strong>, <strong>ParameterBinderController<\/strong>, and <strong>TypeConversion<\/strong>:<\/p>\n<p style=\"margin-left:30px\">\n  $Names = @(\n<\/p>\n<p style=\"margin-left:30px\">\n  &#8216;ParameterBinderBase&#8217;,\n<\/p>\n<p style=\"margin-left:30px\">\n  &#8216;ParameterBinderController&#8217;,\n<\/p>\n<p style=\"margin-left:30px\">\n  &#8216;ParameterBinding&#8217;,\n<\/p>\n<p style=\"margin-left:30px\">\n  &#8216;TypeConversion&#8217;\n<\/p>\n<p style=\"margin-left:30px\">\n  )\n<\/p>\n<p style=\"margin-left:30px\">\n  Trace-Command -Name $Names -Expression {&#8217;10\/10\/2014&#8242; | Get-Date} -PSHost\n<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/TraceCommand3.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/TraceCommand3.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>There is a lot of stuff happening here with all of the trace information. We can see the <strong>ParameterSetName<\/strong> for the <strong>Get-Date<\/strong> cmdlet, and then it begins to check mandatory parameters. From there, the process begins working through a set of checks to try to map the input to the parameter that supports the pipeline. In this case, it is the <strong>\u2013Date<\/strong> parameter, which is looking for a <strong>[datetime]<\/strong> object.<\/p>\n<p>The following list shows the flow of checks for data coming through the pipeline (named parameters are always binded first).<\/p>\n<p>Order of parameter binding process from pipeline:<\/p>\n<ol>\n<li>Bind parameter by <strong>Value<\/strong> with same Type (no coercion)<\/li>\n<li>Bind parameter by <strong>PropertyName<\/strong> with same Type (no coercion)<\/li>\n<li>Bind parameter by <strong>Value<\/strong> with type conversion (coercion)<\/li>\n<li>Bind parameter by <strong>PropertyName<\/strong> with type conversion (coercion)<\/li>\n<\/ol>\n<p>Knowing how this works can help ensure that you are properly sending the right data to another command and that the proper parameter is being used in the binding of the data.<\/p>\n<p>Now let\u2019s take a look at an issue that I have seen people having: taking files and folders from <strong>Get-ChildItem<\/strong> and attempting to move the data without specifying a parameter name.<\/p>\n<p style=\"margin-left:30px\">\n  PS C:\\> Get-ChildItem | Select -first 1 | Move-Item C:\\OneDriveTemp \u2013WhatIf\n<\/p>\n<p style=\"margin-left:30px\">\n  Move-Item : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the\u00a0<span style=\"font-size:12px\">parameters that take pipeline input.<\/span>\n<\/p>\n<p style=\"margin-left:30px\">\n  At line:1 char:35\n<\/p>\n<p style=\"margin-left:30px\">\n  + Get-ChildItem | Select -first 1 | Move-Item C:\\OneDriveTemp -WhatIf\n<\/p>\n<p style=\"margin-left:30px\">\n  +\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 + CategoryInfo\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 : InvalidArgument: (PoshAsyncJob:PSObject) [Move-Item], ParameterBindingException\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 + FullyQualifiedErrorId : InputObjectNotBound,Microsoft.PowerShell.Commands.MoveItemCommand\n<\/p>\n<p>So what happened here? Wouldn\u2019t the input be passed through and then move to the specified location? Time to check out the trace of this command and find out!<\/p>\n<p>Trace-Command -Name ParameterBinding -Expression {Get-ChildItem | Select -first 1 | Move-Item C:\\OneDriveTemp -WhatIf} -PSHost<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/TraceCommand4.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/TraceCommand4.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>This is where positional parameters come into play. The path specified is binding first to the first parameter in the list (in this case, <strong>\u2013Path<\/strong>). That means that the incoming data from <strong>Get-ChildItem<\/strong> now has to find a parameter to bind to because <strong>Path<\/strong> has been taken, and it ends up failing. We need to specify the <strong>\u2013Destination<\/strong> parameter for the destination path for this to properly work:<\/p>\n<p style=\"margin-left:30px\">\n  PS C:\\> Get-ChildItem | Select -first 1 | Move-Item -Destination C:\\OneDriveTemp \u2013WhatIf\n<\/p>\n<p style=\"margin-left:30px\">\n  What if: Performing the operation &#8220;Move Directory&#8221; on target &#8220;Item: C:\\Users\\proxb\\Desktop\\PoshAsyncJob Destination: C:\\OneDriveTemp\\PoshAsyncJob&#8221;.\n<\/p>\n<p>It works like a champ now!<\/p>\n<p>Tomorrow, I will wrap-up this week of using built-in Windows PowerShell commands to help troubleshoot scripts by working with the Windows PowerShell debugger in the console and the ISE.<\/p>\n<p>We invite you to follow the Scripting Guy on\u00a0<a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\" rel=\"noopener\">Twitter<\/a>\u00a0and\u00a0<a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\" rel=\"noopener\">Facebook<\/a>. If you have any questions, send email to the Scripting Guy at\u00a0<a href=\"mailto:scripter@microsoft.com\" target=\"_blank\" rel=\"noopener\">scripter@microsoft.com<\/a>, or post your questions on the\u00a0<a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\" rel=\"noopener\">Official Scripting Guys Forum<\/a>. Until then, see ya!<\/p>\n<p><strong>Boe Prox<\/strong>, Windows PowerShell MVP and Honorary Scripting Guy<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Boe Prox uses Trace-Command to understand commands. Honorary Scripting Guy and Windows PowerShell MVP, Boe Prox, here today filling in for my good friend, The Scripting Guy. This is the fourth part in a series of five posts about troubleshooting PowerShell scripts\/functions. The series includes: Provide Support by Using Verbose and Debug Streams Troubleshoot [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[162,295,3,557,134,45],"class_list":["post-252","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-boe-prox","tag-debug","tag-scripting-guy","tag-trace","tag-troubleshooting","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Boe Prox uses Trace-Command to understand commands. Honorary Scripting Guy and Windows PowerShell MVP, Boe Prox, here today filling in for my good friend, The Scripting Guy. This is the fourth part in a series of five posts about troubleshooting PowerShell scripts\/functions. The series includes: Provide Support by Using Verbose and Debug Streams Troubleshoot [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/252","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\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=252"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/252\/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=252"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=252"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=252"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}