|
| 1 | +TOPIC |
| 2 | + about_PSScriptAnalyzer |
| 3 | + |
| 4 | +SHORT DESCRIPTION |
| 5 | + PSScriptAnalyzer is a static code checker for PowerShell modules and scripts. |
| 6 | + |
| 7 | +LONG DESCRIPTION |
| 8 | + PSScriptAnalyzer checks the quality of Windows PowerShell code by running a |
| 9 | + set of rules. The rules are based on PowerShell best practices identified by |
| 10 | + PowerShell Team and the community. These rules can help you create more |
| 11 | + readable, maintainable and reliable scripts. PSScriptAnalyzer generates |
| 12 | + DiagnosticResults (errors and warnings) to inform users about potential code |
| 13 | + defects and suggests possible solutions for improvements. |
| 14 | + |
| 15 | + PSScriptAnalyzer is shipped with a collection of built-in rules that checks |
| 16 | + various aspects of PowerShell code such as presence of uninitialized |
| 17 | + variables, usage of PSCredential Type, usage of Invoke-Expression etc. |
| 18 | + Additional functionalities such as exclude/include specific rules are also |
| 19 | + supported. |
| 20 | + |
| 21 | +RUNNING SCRIPT ANALYZER |
| 22 | + |
| 23 | + There are two commands provided by the PSScriptAnalyzer module, those are: |
| 24 | + |
| 25 | + Get-ScriptAnalyzerRule [-CustomizedRulePath <string[]>] [-Name <string[]>] |
| 26 | + [-Severity <string[]>] |
| 27 | + [<CommonParameters>] |
| 28 | + |
| 29 | + Invoke-ScriptAnalyzer [-Path] <string> [-CustomizedRulePath <string[]>] |
| 30 | + [-ExcludeRule <string[]>] [-IncludeRule<string[]>] |
| 31 | + [-Severity <string[]>] [-Recurse] [-SuppressedOnly] |
| 32 | + [<CommonParameters>] |
| 33 | + |
| 34 | + To run the script analyzer against a single script file execute: |
| 35 | + |
| 36 | + PS C:\> Invoke-ScriptAnalyzer -Path myscript.ps1 |
| 37 | + |
| 38 | + That will analyze your script against every built-in rule. As you may find |
| 39 | + if your script is sufficiently large, that could result in a lot of warnings |
| 40 | + and/or errors. See the next section on recommendations for running against |
| 41 | + an existing script or module. |
| 42 | + |
| 43 | + To run the script analyzer against a whole directory, specify the folder |
| 44 | + containing the script, module and DSC files you want analyzed. Specify |
| 45 | + the Recurse parameter if you also want sub-directories searched for scripts |
| 46 | + to analyze. |
| 47 | + |
| 48 | + PS C:\> Invoke-ScriptAnalyzer -Path . -Recurse |
| 49 | + |
| 50 | + To see all the built-in rules execute: |
| 51 | + |
| 52 | + PS C:\> Get-ScriptAnalyzerRule |
| 53 | + |
| 54 | +RUNNING SCRIPT ANALYZER ON A NEW SCRIPT, MODULE OR DSC RESOURCE |
| 55 | + |
| 56 | + If you have the luxury of starting a new script, module or DSC resource, it |
| 57 | + is in your best interest to run the script analyzer with all the rules |
| 58 | + enabled. Be sure to evaluate your script often to address rule violations as |
| 59 | + soon as they occur. |
| 60 | + |
| 61 | + Over time, you may find rules that you don't find value in or have a need to |
| 62 | + violate the rule. Suppress those rules as necessary but try to avoid |
| 63 | + "knee jerk" rule suppression. Analyze the diagnostic output and the part of |
| 64 | + your script that violates the rule to be sure you understand the reason for |
| 65 | + the warning and that it is indeed OK to suppress the rule. |
| 66 | + |
| 67 | + There are several ways to suppress rules. You can suppress a rule globally |
| 68 | + by using the ExcludeRule parameter when invoking the script analyzer e.g.: |
| 69 | + |
| 70 | + PS C:\> Invoke-ScriptAnalyzer -Path . -ExcludeRule ` |
| 71 | + PSProvideDefaultParameterValue, PSAvoidUsingWMICmdlet |
| 72 | + |
| 73 | + Note that ExcludeRule parameter takes an array of strings i.e. rule names. |
| 74 | + |
| 75 | + Sometimes you want to suppress a rule for part of your script but not for |
| 76 | + the entire script. PSScriptAnalyzer allows you to suppress rules at the |
| 77 | + function level as well. You can use the .NET Framework |
| 78 | + System.Diagnoctics.CodeAnalysis.SuppressMesssageAttribute in your script |
| 79 | + like so: |
| 80 | + |
| 81 | + function Commit-Change() { |
| 82 | + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseApprovedVerbs", |
| 83 | + "", Scope="Function", |
| 84 | + Target="*")] |
| 85 | + param() |
| 86 | + } |
| 87 | + |
| 88 | +RUNNING SCRIPT ANALYZER ON AN EXISTING SCRIPT, MODULE OR DSC RESOURCE |
| 89 | + |
| 90 | + If you have existing scripts, they are not likely following all of these best |
| 91 | + practices, practices that have just found their way into books, web sites, |
| 92 | + blog posts and now the PSScriptAnalyer in the past few years. |
| 93 | + |
| 94 | + For these existing scripts, if you just run the script analyzer without |
| 95 | + limiting the set of rules executed, you may get deluged with diagnostics |
| 96 | + output in the form of information, warning and error messages. You should |
| 97 | + try running the script analyzer with all the rules enabled (the default) and |
| 98 | + see if the output is "manageable". If it isn't, then you will want to "ease |
| 99 | + into" things by starting with the most serious violations first - errors. |
| 100 | + |
| 101 | + You may be temtped to use the Invoke-ScriptAnalyzer command's Severity |
| 102 | + parameter with the argument Error to do this - don't. This will run every |
| 103 | + built-in rule and then filter the results during output. The more rules the |
| 104 | + script analyzer runs, the longer it will take to analyze a file. You can |
| 105 | + easily get Invoke-ScriptAnalyzer to run just the rules that are of severity |
| 106 | + Error like so: |
| 107 | + |
| 108 | + PS C:\> $errorRules = Get-ScriptAnalyzer -Severity Error |
| 109 | + PS C:\> Invoke-ScriptAnalyzer -Path . -IncludeRule $errorRules |
| 110 | + |
| 111 | + The output should be much shorter (hopefully) and more importantly, these rules |
| 112 | + typically indicate serious issues in your script that should be addressed. |
| 113 | + |
| 114 | + Once you have addressed the errors in the script, you are ready to tackle |
| 115 | + warnings. This is likely what generated the most output when you ran the |
| 116 | + first time with all the rules enabled. Now not all of the warnings generated |
| 117 | + by the script analyzer are of equal importance. For the existing script |
| 118 | + scenario, try running error and warning rules included but with a few rules |
| 119 | + "excluded": |
| 120 | + |
| 121 | + PS C:\> $rules = Get-ScriptAnalyzerRule -Severity Error,Warning |
| 122 | + PS C:\> Invoke-ScriptAnalyzer -Path . -IncludeRule $rules -ExcludeRule ` |
| 123 | + PSAvoidUsingCmdletAliases, PSAvoidUsingPositionalParameters |
| 124 | + |
| 125 | + The PSAvoidUsingCmdletAliases and PSAvoidUsingPositionalParameters warnings |
| 126 | + are likely to generate prodigious amounts of output. While these rules have |
| 127 | + their reason for being many existing scripts violate these rules over and |
| 128 | + over again. It would be a shame if you let a flood of warnings from these two |
| 129 | + rules, dissuade you from looking at potentially more serious warnings. |
| 130 | + |
| 131 | + There may be other rules that generate a lot of output that you don't care |
| 132 | + about - at least not yet. As you examine the remaining diagnostics output, |
| 133 | + it is often helpful to group output by rule. You may decide that the one or |
| 134 | + two rules generating 80% of the output are rules you don't care about. You |
| 135 | + can get this view of your output easily: |
| 136 | + |
| 137 | + PS C:\> $rules = Get-ScriptAnalyzerRule -Severity Error,Warning |
| 138 | + PS C:\> $res = Invoke-ScriptAnalyzer -Path . -IncludeRule $rules -ExcludeRule ` |
| 139 | + PSAvoidUsingPositionalParameters, PSAvoidUsingCmdletAliases |
| 140 | + PS C:\> $res | Group RuleName | Sort Count -Desc | Format-Table Count, Name |
| 141 | + |
| 142 | + This renders output like the following: |
| 143 | + |
| 144 | + Count Name |
| 145 | + ----- ---- |
| 146 | + 23 PSAvoidUsingInvokeExpression |
| 147 | + 8 PSUseDeclaredVarsMoreThanAssigments |
| 148 | + 8 PSProvideDefaultParameterValue |
| 149 | + 6 PSAvoidUninitializedVariable |
| 150 | + 3 PSPossibleIncorrectComparisonWithNull |
| 151 | + 1 PSAvoidUsingComputerNameHardcoded |
| 152 | + |
| 153 | + I may decide to table the PSAvoidUsingInvokeExpression for the moment and |
| 154 | + focus on the rest, especially the PSUseDeclaredVarsMoreThanAssigments, |
| 155 | + PSAvoidUninitializedVariable and PSPossibleIncorrectComparisonWithNull rules. |
| 156 | + |
| 157 | + As you fix rules, go back and enable more rules as you have time to address |
| 158 | + the issues. While getting a completely clean run through every rule is a |
| 159 | + noble goal, it may not always be feasible. You have to weigh the gain of |
| 160 | + passing the rule and eliminating a "potential" issue with changing script |
| 161 | + and possibly introducing a new problem. In the end, for existing scripts, |
| 162 | + it is usually best to have evaluated the rule violations that you deem the |
| 163 | + most valuable to address. |
| 164 | + |
| 165 | +EXTENSIBILITY |
| 166 | + |
| 167 | + PSScriptAnalyzer has been designed to allow you to create your own rules via |
| 168 | + a custom .NET assembly or PowerShell module. PSScriptAnalyzer also allows |
| 169 | + you to plug in a custom logger (implemented as a .NET assembly). |
| 170 | + |
| 171 | +CONTRIBUTE |
| 172 | + |
| 173 | + PSScriptAnalyzer is open source on GitHub: |
| 174 | + |
| 175 | + https://github.com/PowerShell/PSScriptAnalyzer |
| 176 | + |
| 177 | + As you run the script analyzer and find what you believe to be are bugs, |
| 178 | + please submit them to: |
| 179 | + |
| 180 | + https://github.com/PowerShell/PSScriptAnalyzer/issues |
| 181 | + |
| 182 | + Better yet, fix the bug and submit a pull request. |
| 183 | + |
| 184 | +SEE ALSO |
| 185 | + Get-ScriptAnalyzerRule |
| 186 | + Invoke-ScriptAnalyzer |
| 187 | + Set-StrictMode |
| 188 | + about_Pester |
| 189 | + |
0 commit comments