{"id":3613,"date":"2014-01-15T15:14:40","date_gmt":"2014-01-15T20:14:40","guid":{"rendered":"http:\/\/jdhitsolutions.com\/blog\/?p=3613"},"modified":"2014-01-15T15:37:50","modified_gmt":"2014-01-15T20:37:50","slug":"updated-powershell-script-profiler","status":"publish","type":"post","link":"https:\/\/jdhitsolutions.com\/blog\/powershell\/3613\/updated-powershell-script-profiler\/","title":{"rendered":"Updated PowerShell  Script Profiler"},"content":{"rendered":"<p>Last year I wrote a sidebar for the Scripting Guy, Ed Wilson and an update to his PowerShell Best Practices book. I wrote a script using the new parser in PowerShell 3.0 to that would analyze a script and prepare a report showing what commands it would run, necessary parameters, and anything that might pose a danger. I also wrote an <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2013\/09\/24\/are-you-safe.aspx\" title=\"read the original article\" target=\"_blank\">article with the script<\/a> for the Hey Scripting Guy blog.<\/p>\n<p>During my PowerShell training class last week we were talking about how to look at someone else's code and figure out what it might do. I also demonstrated my script. During the coure of that demonstration I realized I needed to make a few revisions. Here is version 2 of Get-ASTScriptProfile.ps1.<\/p>\n<pre class=\"lang:ps decode:true \" >\r\n#requires -version 3.0\r\n\r\n#Get-ASTScriptProfile.ps1\r\n\r\n&lt;#\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#&gt;\r\n\r\n&lt;#\r\n.Synopsis\r\nProfile a PowerShell Script\r\n.Description\r\nThis script will parse a PowerShell script using the AST to identify elements \r\nand any items that might be dangerous. The output is a text report which by \r\ndefault is turned into a help topic stored in your Windows PowerShell folder\r\nunder Documents, although you can specify an alternate location.\r\n\r\nDETAILS\r\nThe script takes the name of a script to profile. You can specify a ps1 or \r\npsm1 filename. Using the AST the script will prepare a text report showing \r\nyou any script requirements, script parameters, commands and type names. You \r\nwill see all commands used including those that can't be resolved as well as \r\nthose that I thought might be considered potentially dangerous such as cmdlets \r\nthat use the verbs Remove or Stop. Because some people might invoke methods \r\nfrom .NET classes directly I've also captured all typenames. Most of them will\r\nprobably be related to parameters but as least you'll know what to look for. \r\n\r\nThe report won't detail parameters from nested functions but you'll still see \r\nwhat commands they will use. The script uses Get-Command to identify commands \r\nwhich might entail loading a module. Most of the time this shouldn't be an \r\nissue but you still might want to profile the script in virtualized or test \r\nenvironment. \r\n\r\nAny unresolved command you see is either from a module that couldn't be loaded\r\nor it might be an internally defined command. Once you know what to look for \r\nyou can open the script in your favorite editor and search for the mystery \r\ncommands.\r\n\r\nNote that if the script uses application names like Main or Control for function\r\nnames, they might be misinterpreted. In that case, search the script for the name,\r\nie \"main\". \r\n\r\nThis version will only analyze files with an extension of .ps1, .psm1 or .txt.\r\n.Parameter Path\r\nThe path to the script file. It should have an extension of .ps1, .psm1 or\r\n.bat.\r\n.Parameter FilePath\r\nThe path for the report file. The default is your WindowsPowerShell folder.\r\nThis paramter has aliases of fp and out.\r\n.Example\r\nPS C:\\&gt; c:\\scripts\\Get-ASTScriptProfile c:\\download\\UnknownScript.ps1 \r\n\r\nThis will analyze the script UnknownScript.ps1 and show the results in a\r\nhelp window. It will also create a text file in your Documents\\WindowsPowerShell \r\nfolder called UnknownScript.help.txt.\r\n.Example\r\nPS C:\\&gt; c:\\scripts\\Get-ASTScriptProfile c:\\download\\UnknownScript.ps1 -filepath c:\\work\r\n\r\nThis command is the same as the first example except the help file will be created\r\nin C:\\Work.\r\n\r\n.Notes\r\nVersion 2.0\r\nLast Updated January 14, 2014\r\nJeffery Hicks (http:\/\/twitter.com\/jeffhicks)\r\n\r\nLearn more:\r\n PowerShell in Depth: An Administrator's Guide (http:\/\/www.manning.com\/jones2\/)\r\n PowerShell Deep Dives (http:\/\/manning.com\/hicks\/)\r\n Learn PowerShell 3 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 \r\n.Inputs\r\nNone\r\n.Outputs\r\nHelp topic\r\n.Link\r\nGet-Command\r\nGet-Alias\r\n#&gt;\r\n\r\n[cmdletbinding()]\r\nParam(\r\n[Parameter(Position=0,Mandatory,HelpMessage=\"Enter the path of a PowerShell script\")]\r\n[ValidateScript({Test-Path $_})]\r\n[ValidatePattern( \"\\.(ps1|psm1|txt)$\")]\r\n[string]$Path,\r\n[ValidateScript({Test-Path $_})]\r\n[Alias(\"fp\",\"out\")]\r\n[string]$FilePath = \"$env:userprofile\\Documents\\WindowsPowerShell\"\r\n)\r\n\r\nWrite-Verbose \"Starting $($myinvocation.MyCommand)\"\r\n\r\n#region setup profiling\r\n#need to resolve full path and convert it\r\n$Path = (Resolve-Path -Path $Path).Path | Convert-Path\r\nWrite-Verbose \"Analyzing $Path\"\r\n\r\nWrite-Verbose \"Parsing File for AST\"\r\nNew-Variable astTokens -force\r\nNew-Variable astErr -force\r\n\r\n$AST = [System.Management.Automation.Language.Parser]::ParseFile($Path,[ref]$astTokens,[ref]$astErr)\r\n\r\n#endregion\r\n\r\n#region generate AST data\r\n\r\n#include PowerShell version information\r\nWrite-Verbose \"PSVersionTable\"\r\nWrite-Verbose ($PSversionTable | Out-String)\r\n\r\n$report=@\"\r\nScript Profile report for: $Path\r\n\r\n******************\r\n* PSVersionTable *\r\n******************\r\n$(($PSversionTable | Out-String).TrimEnd())\r\n\r\n\"@\r\n\r\nWrite-Verbose \"Getting requirements and parameters\"\r\n$report+=@\"\r\n\r\n******************\r\n*  Requirements  *\r\n******************\r\n$(($ast.ScriptRequirements | out-string).Trim())\r\n\r\n******************\r\n*  Parameters    *\r\n******************\r\n$(($ast.ParamBlock.Parameters | \r\n Select Name,DefaultValue,StaticType,Attributes |\r\n Format-List | Out-String).Trim())\r\n \r\n\"@\r\n\r\nWrite-Verbose \"Getting all command elements\"\r\n\r\n$commands = @()\r\n$unresolved = @()\r\n\r\n$genericCommands = $astTokens | \r\nwhere {$_.tokenflags -eq 'commandname' -AND $_.kind -eq 'generic'} \r\n\r\n$aliases = $astTokens | \r\nwhere {$_.tokenflags -eq 'commandname' -AND $_.kind -eq 'identifier'} \r\n\r\nWrite-Verbose \"Parsing commands\"\r\nforeach ($command in $genericCommands) {\r\n    Try {\r\n       $commands+= Get-Command -Name $command.text -ErrorAction Stop\r\n    }\r\n    Catch {\r\n      $unresolved+= $command.Text\r\n    }\r\n}\r\n\r\nforeach ($command in $aliases) {\r\nTry {\r\n       $commands+= Get-Command -Name $command.text -erroraction Stop |\r\n       foreach { \r\n         #get the resolved command\r\n         Get-Command -Name $_.Definition  \r\n       }\r\n    }\r\n    Catch {\r\n        $unresolved+= $command.Text\r\n    }\r\n}\r\n\r\nWrite-Verbose \"All commands\"\r\n$report+=@\"\r\n\r\n******************\r\n*  All Commands  *\r\n******************\r\n$(($Commands | Sort -Unique | Format-Table -autosize | Out-String).Trim())\r\n\r\n\"@\r\n\r\nWrite-Verbose \"Unresolved commands\"\r\n$report+=@\"\r\n\r\n******************\r\n*  Unresolved    *\r\n******************\r\n$($Unresolved | Sort -Unique | Format-Table -autosize | Out-String)\r\n\"@\r\n\r\nWrite-Verbose \"Potentially dangerous commands\"\r\n#identify dangerous commands\r\n$danger=\"Remove\",\"Stop\",\"Disconnect\",\"Suspend\",\"Block\",\r\n\"Disable\",\"Deny\",\"Unpublish\",\"Dismount\",\"Reset\",\"Resize\",\r\n\"Rename\",\"Redo\",\"Lock\",\"Hide\",\"Clear\"\r\n\r\n$danger = $commands | where {$danger -contains $_.verb}\r\n\r\n#get type names, some of which may come from parameters\r\nWrite-Verbose \"Typenames\"\r\n$report+=@\"\r\n\r\n******************\r\n*  TypeNames     *\r\n******************\r\n$($asttokens | where {$_.tokenflags -eq 'TypeName'} | \r\nSort @{expression={$_.text.toupper()}} -unique | \r\nSelect -ExpandProperty Text | Out-String)\r\n\"@\r\n\r\n$report+=@\"\r\n\r\n******************\r\n*  Warning       *\r\n******************\r\n$($danger | Format-Table -AutoSize | Out-String)\r\n\"@\r\n\r\n#endregion\r\n\r\nWrite-Verbose \"Display results\"\r\n#region create and display the result\r\n\r\n#create a help topic file using the script basename\r\n$basename = (Get-Item $Path).basename     \r\n#stored in the Documents folder\r\n$reportFile = Join-Path -Path $FilePath -ChildPath \"$basename.help.txt\"\r\n\r\nWrite-Verbose \"Saving report to $reportFile\"\r\n#insert the Topic line so help recognizes it\r\n\"TOPIC\" | Out-File -FilePath $reportFile -Encoding ascii \r\n\r\n#create the report\r\n$report | Out-File -FilePath $reportFile -Encoding ascii -Append\r\n\r\n#view the report with Get-Help and -ShowWindow\r\nGet-Help (Join-Path -Path $FilePath -ChildPath $basename) -ShowWindow\r\n\r\n#endregion\r\n\r\nWrite-Verbose \"Profiling complete.\"\r\n\r\n#end of script<\/pre>\n<p>One thing I discovered was that the AST didn't like parsing a file without an absolute and resolved path. I was running into errors because the script was on a PSDrive like Scripts: that resolved to C:\\Scripts. The solution was to resolve it, in the event of using a path like .\\file.ps1 and then convert the path.<\/p>\n<pre class=\"lang:batch decode:true \" >\r\n$Path = (Resolve-Path -Path $Path).Path | Convert-Path\r\n<\/pre>\n<p>I also discovered that if the script contains functions with a name like Main or Control, the parser, at the least the way I am using it, will detect it as an application like main.cpl. There's a reason you should give your function a meaningful and standard name and try to avoid using a name that *might* be misinterepted. A function called Notepad probably isn't a good idea. I modified the help to indicate this potential misinterpretation. I'm not sure there's much else I can do. <\/p>\n<p>The few other changes I made were for the sake of flexibility and clarity. I now include the PSVersion information in the report. Parameter information is now displayed as a list to avoid losing any data. I added a validation parameter for the script file so that you can only analzye a .ps1, .psm1 or .txt file. <\/p>\n<p>Finally, I added a parameter so that you can specify the folder for the output file. The default is Documents\\WindowsPowerShell. You don't specify the filename, just the path like C:\\Scripts or $env:temp.<\/p>\n<pre class=\"lang:batch decode:true \" >PS Scripts:\\&gt; .\\Get-ASTScriptProfile.ps1 .\\Convert-WindowsImage.ps1 -out c:\\work<\/pre>\n<p>This will result in a help topic report like this:<\/p>\n<p><a href=\"http:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2014\/01\/script-profile-report.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2014\/01\/script-profile-report.png\" alt=\"script-profile-report\" width=\"560\" height=\"849\" class=\"alignleft size-full wp-image-3618\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2014\/01\/script-profile-report.png 560w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2014\/01\/script-profile-report-197x300.png 197w\" sizes=\"auto, (max-width: 560px) 100vw, 560px\" \/><\/a><br \/>\nSo download the new version and try it out on your scripts. Find some files online and try it out on them. Let me know what you think.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last year I wrote a sidebar for the Scripting Guy, Ed Wilson and an update to his PowerShell Best Practices book. I wrote a script using the new parser in PowerShell 3.0 to that would analyze a script and prepare a report showing what commands it would run, necessary parameters, and anything that might pose&#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":"Updated #PowerShell Script Profiler http:\/\/wp.me\/p1nF6U-Wh","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],"tags":[447,534,540],"class_list":["post-3613","post","type-post","status-publish","format-standard","hentry","category-powershell","category-scripting","tag-ast","tag-powershell","tag-scripting"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Updated PowerShell Script Profiler &#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\/3613\/updated-powershell-script-profiler\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Updated PowerShell Script Profiler &#8226; The Lonely Administrator\" \/>\n<meta property=\"og:description\" content=\"Last year I wrote a sidebar for the Scripting Guy, Ed Wilson and an update to his PowerShell Best Practices book. I wrote a script using the new parser in PowerShell 3.0 to that would analyze a script and prepare a report showing what commands it would run, necessary parameters, and anything that might pose...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/jdhitsolutions.com\/blog\/powershell\/3613\/updated-powershell-script-profiler\/\" \/>\n<meta property=\"og:site_name\" content=\"The Lonely Administrator\" \/>\n<meta property=\"article:published_time\" content=\"2014-01-15T20:14:40+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2014-01-15T20:37:50+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2014\/01\/script-profile-report.png\" \/>\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\\\/3613\\\/updated-powershell-script-profiler\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/3613\\\/updated-powershell-script-profiler\\\/\"},\"author\":{\"name\":\"Jeffery Hicks\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\"},\"headline\":\"Updated PowerShell Script Profiler\",\"datePublished\":\"2014-01-15T20:14:40+00:00\",\"dateModified\":\"2014-01-15T20:37:50+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/3613\\\/updated-powershell-script-profiler\\\/\"},\"wordCount\":408,\"commentCount\":2,\"publisher\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\"},\"image\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/3613\\\/updated-powershell-script-profiler\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/jdhitsolutions.com\\\/blog\\\/wp-content\\\/uploads\\\/2014\\\/01\\\/script-profile-report.png\",\"keywords\":[\"AST\",\"PowerShell\",\"Scripting\"],\"articleSection\":[\"PowerShell\",\"Scripting\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/3613\\\/updated-powershell-script-profiler\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/3613\\\/updated-powershell-script-profiler\\\/\",\"url\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/3613\\\/updated-powershell-script-profiler\\\/\",\"name\":\"Updated PowerShell Script Profiler &#8226; The Lonely Administrator\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/3613\\\/updated-powershell-script-profiler\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/3613\\\/updated-powershell-script-profiler\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/jdhitsolutions.com\\\/blog\\\/wp-content\\\/uploads\\\/2014\\\/01\\\/script-profile-report.png\",\"datePublished\":\"2014-01-15T20:14:40+00:00\",\"dateModified\":\"2014-01-15T20:37:50+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/3613\\\/updated-powershell-script-profiler\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/3613\\\/updated-powershell-script-profiler\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/3613\\\/updated-powershell-script-profiler\\\/#primaryimage\",\"url\":\"http:\\\/\\\/jdhitsolutions.com\\\/blog\\\/wp-content\\\/uploads\\\/2014\\\/01\\\/script-profile-report.png\",\"contentUrl\":\"http:\\\/\\\/jdhitsolutions.com\\\/blog\\\/wp-content\\\/uploads\\\/2014\\\/01\\\/script-profile-report.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/3613\\\/updated-powershell-script-profiler\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"PowerShell\",\"item\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/category\\\/powershell\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Updated PowerShell Script Profiler\"}]},{\"@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":"Updated PowerShell Script Profiler &#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\/3613\/updated-powershell-script-profiler\/","og_locale":"en_US","og_type":"article","og_title":"Updated PowerShell Script Profiler &#8226; The Lonely Administrator","og_description":"Last year I wrote a sidebar for the Scripting Guy, Ed Wilson and an update to his PowerShell Best Practices book. I wrote a script using the new parser in PowerShell 3.0 to that would analyze a script and prepare a report showing what commands it would run, necessary parameters, and anything that might pose...","og_url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/3613\/updated-powershell-script-profiler\/","og_site_name":"The Lonely Administrator","article_published_time":"2014-01-15T20:14:40+00:00","article_modified_time":"2014-01-15T20:37:50+00:00","og_image":[{"url":"http:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2014\/01\/script-profile-report.png","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\/3613\/updated-powershell-script-profiler\/#article","isPartOf":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/3613\/updated-powershell-script-profiler\/"},"author":{"name":"Jeffery Hicks","@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9"},"headline":"Updated PowerShell Script Profiler","datePublished":"2014-01-15T20:14:40+00:00","dateModified":"2014-01-15T20:37:50+00:00","mainEntityOfPage":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/3613\/updated-powershell-script-profiler\/"},"wordCount":408,"commentCount":2,"publisher":{"@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9"},"image":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/3613\/updated-powershell-script-profiler\/#primaryimage"},"thumbnailUrl":"http:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2014\/01\/script-profile-report.png","keywords":["AST","PowerShell","Scripting"],"articleSection":["PowerShell","Scripting"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/jdhitsolutions.com\/blog\/powershell\/3613\/updated-powershell-script-profiler\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/3613\/updated-powershell-script-profiler\/","url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/3613\/updated-powershell-script-profiler\/","name":"Updated PowerShell Script Profiler &#8226; The Lonely Administrator","isPartOf":{"@id":"https:\/\/jdhitsolutions.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/3613\/updated-powershell-script-profiler\/#primaryimage"},"image":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/3613\/updated-powershell-script-profiler\/#primaryimage"},"thumbnailUrl":"http:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2014\/01\/script-profile-report.png","datePublished":"2014-01-15T20:14:40+00:00","dateModified":"2014-01-15T20:37:50+00:00","breadcrumb":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/3613\/updated-powershell-script-profiler\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/jdhitsolutions.com\/blog\/powershell\/3613\/updated-powershell-script-profiler\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/3613\/updated-powershell-script-profiler\/#primaryimage","url":"http:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2014\/01\/script-profile-report.png","contentUrl":"http:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2014\/01\/script-profile-report.png"},{"@type":"BreadcrumbList","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/3613\/updated-powershell-script-profiler\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"PowerShell","item":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},{"@type":"ListItem","position":2,"name":"Updated PowerShell Script Profiler"}]},{"@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":2848,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/2848\/wmi-explorer-from-the-powershell-guy\/","url_meta":{"origin":3613,"position":0},"title":"WMI Explorer from The PowerShell Guy","author":"Jeffery Hicks","date":"March 8, 2013","format":false,"excerpt":"Several years ago, The PowerShell Guy, aka MoW, wrote a fantastic graphical PowerShell script that was a WMI Explorer. With this script you could connect to a computer and namespace, browse classes and view instances. A great way for discovering things about WMI. However Marc has moved on to other\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"wmibrowser","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2013\/03\/wmibrowser-1024x552.png?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2013\/03\/wmibrowser-1024x552.png?resize=350%2C200 1x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2013\/03\/wmibrowser-1024x552.png?resize=525%2C300 1.5x"},"classes":[]},{"id":3455,"url":"https:\/\/jdhitsolutions.com\/blog\/scripting\/3455\/friday-fun-color-my-web\/","url_meta":{"origin":3613,"position":1},"title":"Friday Fun Color My Web","author":"Jeffery Hicks","date":"September 20, 2013","format":false,"excerpt":"Awhile ago I posted an article demonstrating using Invoke-Webrequest which is part of PowerShell 3.0. I used the page at Manning.com to display the Print and MEAP bestsellers. By the way, thanks to all of you who keep making PowerShell books popular. My original script simply wrote the results to\u2026","rel":"","context":"In &quot;Books&quot;","block_context":{"text":"Books","link":"https:\/\/jdhitsolutions.com\/blog\/category\/books\/"},"img":{"alt_text":"get-manningbestseller1","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2013\/09\/get-manningbestseller1-1024x606.png?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2013\/09\/get-manningbestseller1-1024x606.png?resize=350%2C200 1x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2013\/09\/get-manningbestseller1-1024x606.png?resize=525%2C300 1.5x"},"classes":[]},{"id":4713,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/4713\/a-festive-christmas-message\/","url_meta":{"origin":3613,"position":2},"title":"A Festive Christmas Message","author":"Jeffery Hicks","date":"December 24, 2015","format":false,"excerpt":"The year is winding down and it is getting harder and harder to remain productive.\u00a0 So I'm trying to combine having some fun while still trying to help you learn PowerShell. I wrote a simple PowerShell script that randomly selects a Christmas themed quote and displays in a colorful fashion.\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"A Christmas Message","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2015\/12\/image_thumb-8.png?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2015\/12\/image_thumb-8.png?resize=350%2C200 1x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2015\/12\/image_thumb-8.png?resize=525%2C300 1.5x"},"classes":[]},{"id":826,"url":"https:\/\/jdhitsolutions.com\/blog\/scripting\/826\/friday-the-13-script-blocks\/","url_meta":{"origin":3613,"position":3},"title":"Friday the 13 Script Blocks","author":"Jeffery Hicks","date":"August 13, 2010","format":false,"excerpt":"In celebration of Friday the 13th and to help ward off any triskaidekaphobia I thought I'd offer up 13 PowerShell scriptblocks. These are scriptblocks that might solve a legitimate business need like finding how long a server has been running to the more mercurial such as how many hours before\u2026","rel":"","context":"In &quot;PowerShell v2.0&quot;","block_context":{"text":"PowerShell v2.0","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell-v2-0\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1729,"url":"https:\/\/jdhitsolutions.com\/blog\/scripting\/1729\/ise-scripting-geek-module\/","url_meta":{"origin":3613,"position":4},"title":"ISE Scripting Geek Module","author":"Jeffery Hicks","date":"October 27, 2011","format":false,"excerpt":"Over the last year I've posted functions I've written to extend the Windows PowerShell ISE. I have finally pulled everything together into a module I'm calling the ISE Scripting Geek. Download and extract the zip file (below) to your modules folder. You should end up with a path like 'C:\\Users\\Jeff\\Documents\\WindowsPowerShell\\Modules\\ISEScriptingGeek'.\u2026","rel":"","context":"In &quot;PowerShell ISE&quot;","block_context":{"text":"PowerShell ISE","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell-ise\/"},"img":{"alt_text":"ISE Scripting Geek add-on menu","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2011\/10\/isescriptinggeek-300x200.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":3661,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/3661\/creating-cim-scripts-without-scripting\/","url_meta":{"origin":3613,"position":5},"title":"Creating CIM Scripts without Scripting","author":"Jeffery Hicks","date":"January 29, 2014","format":false,"excerpt":"When Windows 8 and Windows Server 2012 came out, along with PowerShell 3.0, we got our hands on some terrific technology in the form of the CIM cmdlets. Actually, we got much more than people realize. One of the reasons there was a big bump in the number of shipping\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/3613","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=3613"}],"version-history":[{"count":0,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/3613\/revisions"}],"wp:attachment":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/media?parent=3613"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/categories?post=3613"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/tags?post=3613"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}