en-us/about_ScriptCop_Rules.help.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
ScriptCop rules can help you detect problems in your scripts, and can even 
help you repair them.  

There are two flavors of ScriptCop rules: Tests and Repairs.  Each rule
is a single PowerShell command (either a function or a script file).  

    To Register a ScriptCop rule, use Register-ScriptCopRule

    To Unregister a ScriptCop rule, use Unregister-ScriptCopRule

Both Test and Repair functions work by using some very specific parameter set 
to pass down information to the command.   Any PowerShell function or script 
that accepts this set of parameters can be used as a rule in ScriptCop.

Any Test can report a problem with the command in a few ways:

- It can write an error with information about major problems with command
- It can write a warning with information about minor problems with the command
- It can write a detail message with information about how to fix it

Let's take a look at the signatures, and then at some of the examples: The simplest signature that a Test command can have is the TestCommandInfo [Parameter(ParameterSetName='TestCommandInfo',Mandatory=$true,ValueFromPipeline=$true)] [Management.Automation.CommandInfo] $CommandInfo The CommandInfo object in PowerShell is what comes back from Get-Command. There are 8 types of CommandInfo objects, and a command that accepts this could report any issue from any one of them. Each of the individual types can also be used as a signature for the Test: TestFunctionInfo (this will only work on functions, not script files) [Parameter(ParameterSetName='TestFunctionInfo',Mandatory=$true,ValueFromPipeline=$true)] [Management.Automation.FunctionInfo] $FunctionInfo TestScriptInfo (this will only work on script files (.ps1)) [Parameter(ParameterSetName='TestScriptInfo',Mandatory=$true,ValueFromPipeline=$true)] [Management.Automation.ExternalScriptInfo] $ScriptInfo TestCmdletInfo (this will work only on compiled cmdlets) [Parameter(ParameterSetName='TestCmdletInfo',Mandatory=$true,ValueFromPipeline=$true)] [Management.Automation.CmdletInfo] $CmdletInfo TestApplicationInfo (this will work on PowerShell module (.psm1), PowerShell data (.psd1) or other files) [Parameter(ParameterSetName='TestApplicationInfo',Mandatory=$true,ValueFromPipeline=$true)] [Management.Automation.ApplicationInfo] $ApplicationInfo You can also make a rule that returns information about a module: [Parameter(ParameterSetName='TestModuleInfo',Mandatory=$true,ValueFromPipeline=$true)] [Management.Automation.PSModuleInfo] $ModuleInfo Each of these simple types leaves open a lot of possibility, but requiring that all rules conform to these signatures doesn't help us write rules that are fast.  

For instance, if you need to write a lot of rules that used help content, those rules
would be very slow to run because each rule would need to continue to get the help content

To make rules that do advanced things (like interact with help content or tokenize the script) can use
some more advanced parameter sets:

TestScriptToken will only be passed tokens from complete PowerShell scripts.

    [Parameter(ParameterSetName='TestScriptToken',Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
    [Management.Automation.PSToken[]]
    $ScriptToken,
    
    [Parameter(ParameterSetName='TestScriptToken',Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
    [Management.Automation.CommandInfo]
    $ScriptTokenCommand,
    
    [Parameter(ParameterSetName='TestScriptToken',Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
    [Management.Automation.CommandInfo]
    $ScriptText,
    

TestHelpContent will be passed a sumarized help object (the result of Get-Help)

    [Parameter(ParameterSetName='TestHelpContent',ValueFromPipelineByPropertyName=$true)]   
    $HelpContent,
    
    [Parameter(ParameterSetName='TestHelpContent',Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
    [Management.Automation.CommandInfo]
    $HelpCommand

    
    
The signature for a repair function is a lot simpler.

Each repair requires three pieces of data, which are returned from Test-Command.

    # The error parameter contains the error returned from a test
    [Parameter(ParameterSetName='RepairScriptCopIssue',Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
    [Management.Automation.ErrorRecord]
    $ScriptCopError,
    
    [Parameter(ParameterSetName='RepairScriptCopIssue',Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
    [Management.Automation.CommandInfo]
    $Rule,    
    
    [Parameter(ParameterSetName='RepairScriptCopIssue',Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
    [PSObject]
    $Source,
        
    [Parameter(ParameterSetName='RepairScriptCopIssue',ValueFromPipelineByPropertyName=$true)]        
    [Switch]
    $Silent,
    
    [Parameter(ParameterSetName='RepairScriptCopIssue',ValueFromPipelineByPropertyName=$true)]        
    [Switch]
    $WhatIf,
    
    [Parameter(ParameterSetName='RepairScriptCopIssue',ValueFromPipelineByPropertyName=$true)]        
    [Switch]
    $Confirm
    
The error parameter contains the error returned from a test

The rule parameter contains the rule that generated the error

The source parameter contains the command or module that generated the error

The silent parameter indicates if the test can interact with the user.  
    
While the variety of signatures that you can use to write a ScriptCop rule are quite complicated,
writing one isn't. You write a function that uses one or more of the parameter sets above. Your put it into the Rules directory. Then it is a scriptcop rule. When ScriptCop is run, it will run each function you've registered.  If that function outputs an error,
then ScriptCop displays that error to the user.

To see a few concrete examples, run:

    Get-Help writing_a_scriptcop_rule.walkthru