diff --git a/Engine/Commands/GetScriptAnalyzerRuleCommand.cs b/Engine/Commands/GetScriptAnalyzerRuleCommand.cs
index 21883302e..6ba2003ea 100644
--- a/Engine/Commands/GetScriptAnalyzerRuleCommand.cs
+++ b/Engine/Commands/GetScriptAnalyzerRuleCommand.cs
@@ -10,17 +10,14 @@
// THE SOFTWARE.
//
+using Microsoft.PowerShell.Commands;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System;
using System.Collections.Generic;
-using System.ComponentModel.Composition;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Management.Automation;
-using System.Resources;
-using System.Threading;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.Commands
{
@@ -50,12 +47,27 @@ public string[] CustomizedRulePath
[Parameter(Mandatory = false)]
[ValidateNotNullOrEmpty]
[SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
- public string[] Name
+ public string[] RuleName
{
get { return name; }
set { name = value; }
}
private string[] name;
+
+ ///
+ /// Severity: Array of the severity types to be enabled.
+ ///
+ ///
+ [ValidateSet("Warning", "Error", "Information", IgnoreCase = true)]
+ [Parameter(Mandatory = false)]
+ [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
+ public string[] Severity
+ {
+ get { return severity; }
+ set { severity = value; }
+ }
+ private string[] severity;
+
#endregion Parameters
#region Private Members
@@ -128,9 +140,16 @@ protected override void ProcessRecord()
}
else
{
+ if (severity != null)
+ {
+ var ruleSeverity = severity.Select(item => Enum.Parse(typeof (RuleSeverity), item));
+ rules = rules.Where(item => ruleSeverity.Contains(item.GetSeverity())).ToList();
+ }
+
foreach (IRule rule in rules)
{
- WriteObject(new RuleInfo(rule.GetName(), rule.GetCommonName(), rule.GetDescription(), rule.GetSourceType(), rule.GetSourceName()));
+ WriteObject(new RuleInfo(rule.GetName(), rule.GetCommonName(), rule.GetDescription(),
+ rule.GetSourceType(), rule.GetSourceName(), rule.GetSeverity()));
}
}
}
diff --git a/Engine/Commands/InvokeScriptAnalyzerCommand.cs b/Engine/Commands/InvokeScriptAnalyzerCommand.cs
index cd04f621e..fb1272d04 100644
--- a/Engine/Commands/InvokeScriptAnalyzerCommand.cs
+++ b/Engine/Commands/InvokeScriptAnalyzerCommand.cs
@@ -10,6 +10,7 @@
// THE SOFTWARE.
//
+using System.Text.RegularExpressions;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System;
using System.Collections.Generic;
@@ -272,7 +273,28 @@ private void AnalyzeFile(string filePath)
IEnumerable funcDefAsts;
// Use a List of KVP rather than dictionary, since for a script containing inline functions with same signature, keys clash
- List> cmdInfoTable = new List>();
+ List> cmdInfoTable = new List>();
+
+ //Check wild card input for the Include/ExcludeRules and create regex match patterns
+ List includeRegexList = new List();
+ List excludeRegexList = new List();
+ if (includeRule != null)
+ {
+ foreach (string rule in includeRule)
+ {
+ Regex includeRegex = new Regex(String.Format("^{0}$", Regex.Escape(rule).Replace(@"\*", ".*")), RegexOptions.IgnoreCase);
+ includeRegexList.Add(includeRegex);
+ }
+ }
+ if (excludeRule != null)
+ {
+ foreach (string rule in excludeRule)
+ {
+ Regex excludeRegex = new Regex(String.Format("^{0}$", Regex.Escape(rule).Replace(@"\*", ".*")), RegexOptions.IgnoreCase);
+ excludeRegexList.Add(excludeRegex);
+ }
+ }
+
//Parse the file
if (File.Exists(filePath))
@@ -316,12 +338,30 @@ private void AnalyzeFile(string filePath)
#region Run ScriptRules
//Trim down to the leaf element of the filePath and pass it to Diagnostic Record
string fileName = System.IO.Path.GetFileName(filePath);
+
if (ScriptAnalyzer.Instance.ScriptRules != null)
{
foreach (IScriptRule scriptRule in ScriptAnalyzer.Instance.ScriptRules)
{
- if ((includeRule == null || includeRule.Contains(scriptRule.GetName(), StringComparer.OrdinalIgnoreCase)) &&
- (excludeRule == null || !excludeRule.Contains(scriptRule.GetName(), StringComparer.OrdinalIgnoreCase)))
+ bool includeRegexMatch = false;
+ bool excludeRegexMatch = false;
+ foreach (Regex include in includeRegexList)
+ {
+ if (include.IsMatch(scriptRule.GetName()))
+ {
+ includeRegexMatch = true;
+ break;
+ }
+ }
+ foreach (Regex exclude in excludeRegexList)
+ {
+ if (exclude.IsMatch(scriptRule.GetName()))
+ {
+ excludeRegexMatch = true;
+ break;
+ }
+ }
+ if ((includeRule == null || includeRegexMatch) && (excludeRule == null || !excludeRegexMatch))
{
WriteVerbose(string.Format(CultureInfo.CurrentCulture, Strings.VerboseRunningMessage, scriptRule.GetName()));
@@ -334,7 +374,6 @@ private void AnalyzeFile(string filePath)
catch (Exception scriptRuleException)
{
WriteError(new ErrorRecord(scriptRuleException, Strings.RuleError, ErrorCategory.InvalidOperation, filePath));
- continue;
}
}
}
@@ -379,8 +418,25 @@ private void AnalyzeFile(string filePath)
{
foreach (ICommandRule commandRule in ScriptAnalyzer.Instance.CommandRules)
{
- if ((includeRule == null || includeRule.Contains(commandRule.GetName(), StringComparer.OrdinalIgnoreCase)) &&
- (excludeRule == null || !excludeRule.Contains(commandRule.GetName(), StringComparer.OrdinalIgnoreCase)))
+ bool includeRegexMatch = false;
+ bool excludeRegexMatch = false;
+ foreach (Regex include in includeRegexList)
+ {
+ if (include.IsMatch(commandRule.GetName()))
+ {
+ includeRegexMatch = true;
+ break;
+ }
+ }
+ foreach (Regex exclude in excludeRegexList)
+ {
+ if (exclude.IsMatch(commandRule.GetName()))
+ {
+ excludeRegexMatch = true;
+ break;
+ }
+ }
+ if ((includeRule == null || includeRegexMatch) && (excludeRule == null || !excludeRegexMatch))
{
foreach (KeyValuePair commandInfo in cmdInfoTable)
{
@@ -395,7 +451,6 @@ private void AnalyzeFile(string filePath)
catch (Exception commandRuleException)
{
WriteError(new ErrorRecord(commandRuleException, Strings.RuleError, ErrorCategory.InvalidOperation, fileName));
- continue;
}
}
}
@@ -410,8 +465,25 @@ private void AnalyzeFile(string filePath)
{
foreach (ITokenRule tokenRule in ScriptAnalyzer.Instance.TokenRules)
{
- if ((includeRule == null || includeRule.Contains(tokenRule.GetName(), StringComparer.OrdinalIgnoreCase)) &&
- (excludeRule == null || !excludeRule.Contains(tokenRule.GetName(), StringComparer.OrdinalIgnoreCase)))
+ bool includeRegexMatch = false;
+ bool excludeRegexMatch = false;
+ foreach (Regex include in includeRegexList)
+ {
+ if (include.IsMatch(tokenRule.GetName()))
+ {
+ includeRegexMatch = true;
+ break;
+ }
+ }
+ foreach (Regex exclude in excludeRegexList)
+ {
+ if (exclude.IsMatch(tokenRule.GetName()))
+ {
+ excludeRegexMatch = true;
+ break;
+ }
+ }
+ if ((includeRule == null || includeRegexMatch) && (excludeRule == null || !excludeRegexMatch))
{
WriteVerbose(string.Format(CultureInfo.CurrentCulture, Strings.VerboseRunningMessage, tokenRule.GetName()));
@@ -424,7 +496,6 @@ private void AnalyzeFile(string filePath)
catch (Exception tokenRuleException)
{
WriteError(new ErrorRecord(tokenRuleException, Strings.RuleError, ErrorCategory.InvalidOperation, fileName));
- continue;
}
}
}
@@ -438,8 +509,25 @@ private void AnalyzeFile(string filePath)
// Run DSC Class rule
foreach (IDSCResourceRule dscResourceRule in ScriptAnalyzer.Instance.DSCResourceRules)
{
- if ((includeRule == null || includeRule.Contains(dscResourceRule.GetName(), StringComparer.OrdinalIgnoreCase)) &&
- (excludeRule == null || !excludeRule.Contains(dscResourceRule.GetName(), StringComparer.OrdinalIgnoreCase)))
+ bool includeRegexMatch = false;
+ bool excludeRegexMatch = false;
+ foreach (Regex include in includeRegexList)
+ {
+ if (include.IsMatch(dscResourceRule.GetName()))
+ {
+ includeRegexMatch = true;
+ break;
+ }
+ }
+ foreach (Regex exclude in excludeRegexList)
+ {
+ if (exclude.IsMatch(dscResourceRule.GetName()))
+ {
+ excludeRegexMatch = true;
+ break;
+ }
+ }
+ if ((includeRule == null || includeRegexMatch) && (excludeRule == null || excludeRegexMatch))
{
WriteVerbose(string.Format(CultureInfo.CurrentCulture, Strings.VerboseRunningMessage, dscResourceRule.GetName()));
@@ -452,7 +540,6 @@ private void AnalyzeFile(string filePath)
catch (Exception dscResourceRuleException)
{
WriteError(new ErrorRecord(dscResourceRuleException, Strings.RuleError, ErrorCategory.InvalidOperation, filePath));
- continue;
}
}
}
@@ -480,8 +567,24 @@ private void AnalyzeFile(string filePath)
// Run all DSC Rules
foreach (IDSCResourceRule dscResourceRule in ScriptAnalyzer.Instance.DSCResourceRules)
{
- if ((includeRule == null || includeRule.Contains(dscResourceRule.GetName(), StringComparer.OrdinalIgnoreCase)) &&
- (excludeRule == null || !excludeRule.Contains(dscResourceRule.GetName(), StringComparer.OrdinalIgnoreCase)))
+ bool includeRegexMatch = false;
+ bool excludeRegexMatch = false;
+ foreach (Regex include in includeRegexList)
+ {
+ if (include.IsMatch(dscResourceRule.GetName()))
+ {
+ includeRegexMatch = true;
+ break;
+ }
+ }
+ foreach (Regex exclude in excludeRegexList)
+ {
+ if (exclude.IsMatch(dscResourceRule.GetName()))
+ {
+ excludeRegexMatch = true;
+ }
+ }
+ if ((includeRule == null || includeRegexMatch) && (excludeRule == null || !excludeRegexMatch))
{
WriteVerbose(string.Format(CultureInfo.CurrentCulture, Strings.VerboseRunningMessage, dscResourceRule.GetName()));
@@ -494,7 +597,6 @@ private void AnalyzeFile(string filePath)
catch (Exception dscResourceRuleException)
{
WriteError(new ErrorRecord(dscResourceRuleException, Strings.RuleError, ErrorCategory.InvalidOperation, filePath));
- continue;
}
}
}
diff --git a/Engine/Generic/AvoidCmdletGeneric.cs b/Engine/Generic/AvoidCmdletGeneric.cs
index 7946f7895..1ae87fa31 100644
--- a/Engine/Generic/AvoidCmdletGeneric.cs
+++ b/Engine/Generic/AvoidCmdletGeneric.cs
@@ -93,5 +93,11 @@ public IEnumerable AnalyzeScript(Ast ast, string fileName)
///
/// The source type of the rule.
public abstract SourceType GetSourceType();
+
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public abstract RuleSeverity GetSeverity();
}
}
diff --git a/Engine/Generic/AvoidParameterGeneric.cs b/Engine/Generic/AvoidParameterGeneric.cs
index 7f6a0bf96..89eb433fc 100644
--- a/Engine/Generic/AvoidParameterGeneric.cs
+++ b/Engine/Generic/AvoidParameterGeneric.cs
@@ -104,5 +104,7 @@ public IEnumerable AnalyzeScript(Ast ast, string fileName)
///
/// The source type of the rule.
public abstract SourceType GetSourceType();
+
+ public abstract RuleSeverity GetSeverity();
}
}
diff --git a/Engine/Generic/ExternalRule.cs b/Engine/Generic/ExternalRule.cs
index 43b849401..934bbc831 100644
--- a/Engine/Generic/ExternalRule.cs
+++ b/Engine/Generic/ExternalRule.cs
@@ -55,6 +55,12 @@ public SourceType GetSourceType()
return SourceType.Module;
}
+ //Set the community rule level as warning as the current implementation does not require user to specify rule severity when defining their functions in PS scripts
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
public string GetSourceName()
{
return this.srcName;
diff --git a/Engine/Generic/IRule.cs b/Engine/Generic/IRule.cs
index e4c3f3bc6..e9ddbbf8e 100644
--- a/Engine/Generic/IRule.cs
+++ b/Engine/Generic/IRule.cs
@@ -10,12 +10,6 @@
// THE SOFTWARE.
//
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.Generic
{
///
@@ -52,5 +46,12 @@ public interface IRule
///
/// The source type of the rule.
SourceType GetSourceType();
+
+ ///
+ /// GetSeverity: Retrieves severity of the rule.
+ ///
+ ///
+ RuleSeverity GetSeverity();
+
}
}
diff --git a/Engine/Generic/RuleInfo.cs b/Engine/Generic/RuleInfo.cs
index 1848599e5..666c84afa 100644
--- a/Engine/Generic/RuleInfo.cs
+++ b/Engine/Generic/RuleInfo.cs
@@ -29,12 +29,13 @@ public class RuleInfo
private string description;
private SourceType sourceType;
private string sourceName;
+ private RuleSeverity ruleSeverity;
///
/// Name: The name of the rule.
///
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
- public string Name
+ public string RuleName
{
get { return name; }
private set { name = value; }
@@ -81,6 +82,16 @@ public string SourceName
private set { sourceName = value; }
}
+ ///
+ /// Severity : The severity of the rule violation.
+ ///
+ [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ public RuleSeverity Severity
+ {
+ get { return ruleSeverity; }
+ private set { ruleSeverity = value; }
+ }
+
///
/// Constructor for a RuleInfo.
///
@@ -89,13 +100,14 @@ public string SourceName
/// Description of the rule.
/// Source type of the rule.
/// Source name of the rule.
- public RuleInfo(string name, string commonName, string description, SourceType sourceType, string sourceName)
+ public RuleInfo(string name, string commonName, string description, SourceType sourceType, string sourceName, RuleSeverity severity)
{
- Name = name;
+ RuleName = name;
CommonName = commonName;
Description = description;
SourceType = sourceType;
SourceName = sourceName;
+ Severity = severity;
}
}
}
diff --git a/Engine/Generic/RuleSeverity.cs b/Engine/Generic/RuleSeverity.cs
new file mode 100644
index 000000000..75496ed43
--- /dev/null
+++ b/Engine/Generic/RuleSeverity.cs
@@ -0,0 +1,35 @@
+//
+// Copyright (c) Microsoft Corporation.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+namespace Microsoft.Windows.Powershell.ScriptAnalyzer.Generic
+{
+ ///
+ /// Represents the severity of a PSScriptAnalyzer rule
+ ///
+ public enum RuleSeverity : uint
+ {
+ ///
+ /// Information: This warning is trivial, but may be useful. They are recommended by PowerShell best practice.
+ ///
+ Information = 0,
+
+ ///
+ /// WARNING: This warning may cause a problem or does not follow PowerShell's recommended guidelines.
+ ///
+ Warning = 1,
+
+ ///
+ /// ERROR: This warning is likely to cause a problem or does not follow PowerShell's required guidelines.
+ ///
+ Error = 2,
+ };
+}
diff --git a/Engine/Generic/SkipTypeDefinition.cs b/Engine/Generic/SkipTypeDefinition.cs
index 25214c50f..c95d772fe 100644
--- a/Engine/Generic/SkipTypeDefinition.cs
+++ b/Engine/Generic/SkipTypeDefinition.cs
@@ -16,9 +16,9 @@
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.Generic
{
///
- /// This class extends AstVisitor2 and will skip any typedefinitionast
+ /// This class extends AstVisitor and will skip any typedefinitionast
///
- public class SkipTypeDefinition : AstVisitor2
+ public class SkipTypeDefinition : AstVisitor
{
///
/// File name
@@ -30,14 +30,5 @@ public class SkipTypeDefinition : AstVisitor2
///
public List DiagnosticRecords = new List();
- ///
- /// Skip typedefinition
- ///
- ///
- ///
- public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefAst)
- {
- return AstVisitAction.SkipChildren;
- }
}
}
diff --git a/Engine/Helper.cs b/Engine/Helper.cs
index 70bd69f6b..41c0a326a 100644
--- a/Engine/Helper.cs
+++ b/Engine/Helper.cs
@@ -700,7 +700,8 @@ public object VisitScriptBlock(ScriptBlockAst scriptBlockAst)
VariableAnalysis previousOuter = OuterAnalysis;
- // We already run variable analysis in these cases so check
+ // We already run variable analysis if the parent is a function so skip these.
+ // Otherwise, we have to do variable analysis using the outer scope variables.
if (!(scriptBlockAst.Parent is FunctionDefinitionAst) && !(scriptBlockAst.Parent is FunctionMemberAst))
{
OuterAnalysis = Helper.Instance.InitializeVariableAnalysisHelper(scriptBlockAst, OuterAnalysis);
@@ -726,8 +727,15 @@ public object VisitScriptBlock(ScriptBlockAst scriptBlockAst)
scriptBlockAst.EndBlock.Visit(this);
}
+ VariableAnalysis innerAnalysis = OuterAnalysis;
OuterAnalysis = previousOuter;
+ if (!(scriptBlockAst.Parent is FunctionDefinitionAst) && !(scriptBlockAst.Parent is FunctionMemberAst))
+ {
+ // Update the variable analysis of the outer script block
+ VariableAnalysis.UpdateOuterAnalysis(OuterAnalysis, innerAnalysis);
+ }
+
return null;
}
@@ -889,6 +897,13 @@ public object VisitCatchClause(CatchClauseAst catchClauseAst)
///
public object VisitCommand(CommandAst commandAst)
{
+ if (commandAst == null) return null;
+
+ foreach (CommandElementAst ceAst in commandAst.CommandElements)
+ {
+ ceAst.Visit(this);
+ }
+
return null;
}
@@ -1219,12 +1234,19 @@ public object VisitParenExpression(ParenExpressionAst parenExpressionAst)
}
///
- /// Do nothing
+ /// Visit pipeline
///
///
///
public object VisitPipeline(PipelineAst pipelineAst)
{
+ if (pipelineAst == null) return null;
+
+ foreach (var command in pipelineAst.PipelineElements)
+ {
+ command.Visit(this);
+ }
+
return null;
}
diff --git a/Engine/ScriptAnalyzer.cs b/Engine/ScriptAnalyzer.cs
index 1dacd3d63..5f995abce 100644
--- a/Engine/ScriptAnalyzer.cs
+++ b/Engine/ScriptAnalyzer.cs
@@ -33,7 +33,6 @@ internal class ScriptAnalyzer
#region Private memebers
private CompositionContainer container;
- private const string baseName = "Microsoft.Windows.Powershell.ScriptAnalyzer.Properties.Strings";
#endregion
@@ -91,7 +90,7 @@ public static ScriptAnalyzer Instance
public void Initialize()
{
// Clear external rules for each invoke.
- this.ExternalRules = new List();
+ ExternalRules = new List();
// Initialize helper
Helper.Instance.Initialize();
@@ -129,7 +128,7 @@ public void Initilaize(Dictionary> result)
List paths = new List();
// Clear external rules for each invoke.
- this.ExternalRules = new List();
+ ExternalRules = new List();
// Initialize helper
Helper.Instance.Initialize();
diff --git a/Engine/ScriptAnalyzer.format.ps1xml b/Engine/ScriptAnalyzer.format.ps1xml
index d13b8f71c..188b73ecc 100644
--- a/Engine/ScriptAnalyzer.format.ps1xml
+++ b/Engine/ScriptAnalyzer.format.ps1xml
@@ -10,15 +10,15 @@
35
-
+
- 10
+ 12
10
-
+
5
@@ -62,19 +62,19 @@
- 30
-
+ 35
+
- 33
-
+ 15
+
- 45
+ 60
- 8
+ 10
@@ -83,10 +83,10 @@
- Name
+ RuleName
- CommonName
+ Severity
Description
diff --git a/Engine/ScriptAnalyzer.types.ps1xml b/Engine/ScriptAnalyzer.types.ps1xml
index 47bf4b417..ded4e0922 100644
--- a/Engine/ScriptAnalyzer.types.ps1xml
+++ b/Engine/ScriptAnalyzer.types.ps1xml
@@ -41,8 +41,8 @@
DefaultDisplayPropertySet
- Name
- CommonName
+ RuleName
+ Severity
Description
SourceName
diff --git a/Engine/ScriptAnalyzerEngine.csproj b/Engine/ScriptAnalyzerEngine.csproj
index 990354497..169da7260 100644
--- a/Engine/ScriptAnalyzerEngine.csproj
+++ b/Engine/ScriptAnalyzerEngine.csproj
@@ -1,4 +1,4 @@
-
+
Debug
@@ -63,6 +63,7 @@
+
@@ -99,4 +100,4 @@ copy /y "$(ProjectDir)\*.ps1xml" "$(SolutionDir)$(SolutionName)"
copy /y "$(ProjectDir)\*.psd1" "$(SolutionDir)$(SolutionName)"
copy /y "$(TargetPath)" "$(SolutionDir)$(SolutionName)"
-
+
\ No newline at end of file
diff --git a/Engine/VariableAnalysis.cs b/Engine/VariableAnalysis.cs
index bbfa309cf..352ab40ef 100644
--- a/Engine/VariableAnalysis.cs
+++ b/Engine/VariableAnalysis.cs
@@ -255,6 +255,31 @@ public void AnalyzeImpl(Ast ast, VariableAnalysis outerAnalysis)
}
}
+ ///
+ /// Updates the variablesdictionary of the outeranalysis based on that of the inneranalysis
+ ///
+ ///
+ ///
+ internal static void UpdateOuterAnalysis(VariableAnalysis OuterAnalysis, VariableAnalysis InnerAnalysis)
+ {
+ if (OuterAnalysis == null || InnerAnalysis == null)
+ {
+ return;
+ }
+
+ foreach (var key in InnerAnalysis.VariablesDictionary.Keys)
+ {
+ if (OuterAnalysis.VariablesDictionary.ContainsKey(key))
+ {
+ OuterAnalysis.VariablesDictionary[key] = InnerAnalysis.VariablesDictionary[key];
+ }
+ else
+ {
+ OuterAnalysis.VariablesDictionary.Add(key, InnerAnalysis.VariablesDictionary[key]);
+ }
+ }
+ }
+
///
/// Return variableanalysisdetails for VarTarget.
/// This function should only be called after Block.SparseSimpleConstants are called.
diff --git a/Engine/VariableAnalysisBase.cs b/Engine/VariableAnalysisBase.cs
index 5f136b99b..17e7cc6c8 100644
--- a/Engine/VariableAnalysisBase.cs
+++ b/Engine/VariableAnalysisBase.cs
@@ -2957,10 +2957,6 @@ public object VisitScriptBlockExpression(ScriptBlockExpressionAst scriptBlockExp
{
// Don't recurse into the script block, it's variables are distinct from the script block
// we're currently analyzing.
- if (scriptBlockExpressionAst != null)
- {
- scriptBlockExpressionAst.ScriptBlock.Visit(this.Decorator);
- }
return null;
}
diff --git a/README.md b/README.md
index a45d0f7e4..97fc1146e 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ PSScriptAnalyzer is shipped with a collection of built-in rules that checks vari
PSScriptAnalyzer cmdlets
======================
```
-Get-ScriptAnalyzerRule [-CustomizedRulePath ] [-Name ] []
+Get-ScriptAnalyzerRule [-CustomizedRulePath ] [-Name ] [] [-Severity ]
Invoke-ScriptAnalyzer [-Path] [-CustomizedRulePath ] [-ExcludeRule ] [-IncludeRule ] [-Severity ] [-Recurse] []
```
@@ -46,6 +46,7 @@ Pester-based ScriptAnalyzer Tests are located in ```/PSScriptAnalyzer/Te
.\InvokeScriptAnalyzer.tests.ps1
* Run Tests for Built-in rules:
.\*.ps1 (Example - .\ AvoidConvertToSecureStringWithPlainText.ps1)
+*You can also run all tests under \Engine or \Rules by calling Invoke-Pester in the Engine/Rules directory.
Contributing to ScriptAnalyzer
diff --git a/Rules/AvoidAlias.cs b/Rules/AvoidAlias.cs
index 3d012e782..76c963e5c 100644
--- a/Rules/AvoidAlias.cs
+++ b/Rules/AvoidAlias.cs
@@ -11,19 +11,11 @@
//
using System;
-using System.Collections.ObjectModel;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Management.Automation;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -97,6 +89,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
///
/// GetSourceName: Retrieves the name of the module/assembly the rule is from.
///
diff --git a/Rules/AvoidDefaultTrueValueSwitchParameter.cs b/Rules/AvoidDefaultTrueValueSwitchParameter.cs
index 29feba72f..de4a44637 100644
--- a/Rules/AvoidDefaultTrueValueSwitchParameter.cs
+++ b/Rules/AvoidDefaultTrueValueSwitchParameter.cs
@@ -11,19 +11,12 @@
//
using System;
-using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Management.Automation;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -91,6 +84,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
///
/// GetSourceName: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/AvoidEmptyCatchBlock.cs b/Rules/AvoidEmptyCatchBlock.cs
index 34db3c9c4..1c9c57b76 100644
--- a/Rules/AvoidEmptyCatchBlock.cs
+++ b/Rules/AvoidEmptyCatchBlock.cs
@@ -11,19 +11,11 @@
//
using System;
-using System.Collections.ObjectModel;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Management.Automation;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -91,6 +83,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
///
/// Method: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/AvoidGlobalVars.cs b/Rules/AvoidGlobalVars.cs
index b7f983854..9158beb62 100644
--- a/Rules/AvoidGlobalVars.cs
+++ b/Rules/AvoidGlobalVars.cs
@@ -12,16 +12,10 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -93,6 +87,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
///
/// Method: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/AvoidInvokingEmptyMembers.cs b/Rules/AvoidInvokingEmptyMembers.cs
index 5331b67ca..562f335fd 100644
--- a/Rules/AvoidInvokingEmptyMembers.cs
+++ b/Rules/AvoidInvokingEmptyMembers.cs
@@ -11,19 +11,12 @@
//
using System;
-using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Management.Automation;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -105,6 +98,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
///
/// GetSourceName: Retrieves the name of the module/assembly the rule is from.
///
diff --git a/Rules/AvoidPositionalParameters.cs b/Rules/AvoidPositionalParameters.cs
index db39e021f..cc82105ab 100644
--- a/Rules/AvoidPositionalParameters.cs
+++ b/Rules/AvoidPositionalParameters.cs
@@ -11,20 +11,11 @@
//
using System;
-using System.Collections.ObjectModel;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Management.Automation;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
-using Microsoft.Windows.Powershell.ScriptAnalyzer;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -97,6 +88,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
///
/// Method: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/AvoidReservedCharInCmdlet.cs b/Rules/AvoidReservedCharInCmdlet.cs
index 0a1ad4a66..c19c0e980 100644
--- a/Rules/AvoidReservedCharInCmdlet.cs
+++ b/Rules/AvoidReservedCharInCmdlet.cs
@@ -11,19 +11,13 @@
//
using System;
-using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Management.Automation;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -85,6 +79,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
///
/// GetSourceName: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/AvoidReservedParams.cs b/Rules/AvoidReservedParams.cs
index 106a37984..b0211f4f9 100644
--- a/Rules/AvoidReservedParams.cs
+++ b/Rules/AvoidReservedParams.cs
@@ -13,15 +13,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
using System.Management.Automation;
using System.Management.Automation.Internal;
@@ -106,6 +101,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
///
/// Method: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/AvoidShouldContinueWithoutForce.cs b/Rules/AvoidShouldContinueWithoutForce.cs
index e6e622d56..ca91b62b0 100644
--- a/Rules/AvoidShouldContinueWithoutForce.cs
+++ b/Rules/AvoidShouldContinueWithoutForce.cs
@@ -11,19 +11,11 @@
//
using System;
-using System.Collections.ObjectModel;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Management.Automation;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -119,6 +111,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
///
/// GetSourceName: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/AvoidTrapStatement.cs b/Rules/AvoidTrapStatement.cs
index 5fdd8196a..0dc9b43b1 100644
--- a/Rules/AvoidTrapStatement.cs
+++ b/Rules/AvoidTrapStatement.cs
@@ -11,19 +11,11 @@
//
using System;
-using System.Collections.ObjectModel;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Management.Automation;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -89,6 +81,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
///
/// GetSourceName: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/AvoidUnitializedVariable.cs b/Rules/AvoidUnitializedVariable.cs
index 337a7d955..8c1a0a440 100644
--- a/Rules/AvoidUnitializedVariable.cs
+++ b/Rules/AvoidUnitializedVariable.cs
@@ -11,20 +11,11 @@
//
using System;
-using System.Collections.ObjectModel;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Management.Automation;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
-using Microsoft.Windows.Powershell.ScriptAnalyzer;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -112,6 +103,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
///
/// Method: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/AvoidUserNameAndPasswordParams.cs b/Rules/AvoidUserNameAndPasswordParams.cs
index c9cceef18..a593b1ae7 100644
--- a/Rules/AvoidUserNameAndPasswordParams.cs
+++ b/Rules/AvoidUserNameAndPasswordParams.cs
@@ -11,18 +11,12 @@
//
using System;
-using System.Collections.ObjectModel;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Management.Automation;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
@@ -129,6 +123,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Error;
+ }
+
///
/// GetSourceName: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/AvoidUsingComputerNameHardcoded.cs b/Rules/AvoidUsingComputerNameHardcoded.cs
index 3563e864a..dab94246a 100644
--- a/Rules/AvoidUsingComputerNameHardcoded.cs
+++ b/Rules/AvoidUsingComputerNameHardcoded.cs
@@ -11,19 +11,10 @@
//
using System;
-using System.Collections.ObjectModel;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Management.Automation;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -131,6 +122,15 @@ public override SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public override RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Error;
+ }
+
///
/// GetSourceName: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/AvoidUsingConvertToSecureStringWithPlainText.cs b/Rules/AvoidUsingConvertToSecureStringWithPlainText.cs
index e7a884b6b..090dcb059 100644
--- a/Rules/AvoidUsingConvertToSecureStringWithPlainText.cs
+++ b/Rules/AvoidUsingConvertToSecureStringWithPlainText.cs
@@ -11,19 +11,12 @@
//
using System;
-using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Management.Automation;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -44,7 +37,7 @@ public override bool CommandCondition(CommandAst CmdAst)
{
if (CTSTCmdlet == null)
{
- CTSTCmdlet = Microsoft.Windows.Powershell.ScriptAnalyzer.Helper.Instance.CmdletNameAndAliases("convertto-securestring");
+ CTSTCmdlet = Helper.Instance.CmdletNameAndAliases("convertto-securestring");
}
return CmdAst != null && CmdAst.GetCommandName() != null && CTSTCmdlet.Contains(CmdAst.GetCommandName(), StringComparer.OrdinalIgnoreCase);
@@ -107,6 +100,15 @@ public override SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public override RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Error;
+ }
+
///
/// GetSourceName: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/AvoidUsingInternalURLs.cs b/Rules/AvoidUsingInternalURLs.cs
index c165d7672..095cd5412 100644
--- a/Rules/AvoidUsingInternalURLs.cs
+++ b/Rules/AvoidUsingInternalURLs.cs
@@ -13,15 +13,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
using System.IO;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
@@ -119,6 +114,12 @@ public IEnumerable AnalyzeScript(Ast ast, string fileName)
if (!firstPartURL.Contains("."))
{
isInternalURL = true;
+ //Add a check to exclude potential SDDL format. Check if a string have four components separated by ":"
+ var count = firstPartURL.Count(x => x == ':');
+ if (count == 3 || count == 4 )
+ {
+ isInternalURL = false;
+ }
}
}
if (isInternalURL)
@@ -170,6 +171,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
///
/// Method: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/AvoidUsingInvokeExpression.cs b/Rules/AvoidUsingInvokeExpression.cs
index 99c51f799..81db6dc7a 100644
--- a/Rules/AvoidUsingInvokeExpression.cs
+++ b/Rules/AvoidUsingInvokeExpression.cs
@@ -11,17 +11,9 @@
//
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -84,6 +76,15 @@ public override SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity:Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public override RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
///
/// Method: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/AvoidUsingPlainTextForPassword.cs b/Rules/AvoidUsingPlainTextForPassword.cs
index 7933ff47f..a4f6e0d9d 100644
--- a/Rules/AvoidUsingPlainTextForPassword.cs
+++ b/Rules/AvoidUsingPlainTextForPassword.cs
@@ -11,18 +11,11 @@
//
using System;
-using System.Collections.ObjectModel;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Management.Automation;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
@@ -107,6 +100,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
///
/// GetSourceName: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/AvoidUsingWMIObjectCmdlet.cs b/Rules/AvoidUsingWMIObjectCmdlet.cs
new file mode 100644
index 000000000..6c71f1646
--- /dev/null
+++ b/Rules/AvoidUsingWMIObjectCmdlet.cs
@@ -0,0 +1,138 @@
+//
+// Copyright (c) Microsoft Corporation.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+using System;
+using System.Collections.ObjectModel;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Management.Automation;
+using System.Management.Automation.Language;
+using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
+using System.ComponentModel.Composition;
+using System.Resources;
+using System.Globalization;
+using System.Threading;
+using System.Reflection;
+
+namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
+{
+ ///
+ /// AvoidUsingWMIObjectCmdlet: Verify that Get-WMIObject, Remove-WMIObject are not used
+ ///
+ [Export(typeof(IScriptRule))]
+ public class AvoidUsingWMIObjectCmdlet : IScriptRule
+ {
+ ///
+ /// AnalyzeScript: Verify that Get-WMIObject, Remove-WMIObject are not used
+ ///
+ public IEnumerable AnalyzeScript(Ast ast, string fileName)
+ {
+ if (ast == null) throw new ArgumentNullException(Strings.NullAstErrorMessage);
+
+ // Rule is applicable only when PowerShell Version is < 3.0, since Get-CIMInstance was introduced in 3.0
+ int majorPSVersion = GetPSMajorVersion(ast);
+ if (!(3 > majorPSVersion && 0 < majorPSVersion))
+ {
+ // Finds all CommandAsts.
+ IEnumerable commandAsts = ast.FindAll(testAst => testAst is CommandAst, true);
+
+ // Iterate all CommandAsts and check the command name
+ foreach (CommandAst cmdAst in commandAsts)
+ {
+ if (cmdAst.GetCommandName() != null && (String.Equals(cmdAst.GetCommandName(), "get-wmiobject", StringComparison.OrdinalIgnoreCase) || String.Equals(cmdAst.GetCommandName(), "remove-wmiobject", StringComparison.OrdinalIgnoreCase)))
+ {
+ yield return new DiagnosticRecord(String.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingWMIObjectCmdletError, System.IO.Path.GetFileName(fileName)),
+ cmdAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName);
+ }
+ }
+ }
+ }
+
+ ///
+ /// GetPSMajorVersion: Retrieves Major PowerShell Version when supplied using #requires keyword in the script
+ ///
+ /// The name of this rule
+ private int GetPSMajorVersion(Ast ast)
+ {
+ if (ast == null) throw new ArgumentNullException(Strings.NullAstErrorMessage);
+
+ IEnumerable scriptBlockAsts = ast.FindAll(testAst => testAst is ScriptBlockAst, true);
+
+ foreach (ScriptBlockAst scriptBlockAst in scriptBlockAsts)
+ {
+ if (null != scriptBlockAst.ScriptRequirements && null != scriptBlockAst.ScriptRequirements.RequiredPSVersion)
+ {
+ return scriptBlockAst.ScriptRequirements.RequiredPSVersion.Major;
+ }
+ }
+
+ // return a non valid Major version if #requires -Version is not supplied in the Script
+ return -1;
+ }
+
+ ///
+ /// GetName: Retrieves the name of this rule.
+ ///
+ /// The name of this rule
+ public string GetName()
+ {
+ return string.Format(CultureInfo.CurrentCulture, Strings.NameSpaceFormat, GetSourceName(), Strings.AvoidUsingWMIObjectCmdletName);
+ }
+
+ ///
+ /// GetCommonName: Retrieves the common name of this rule.
+ ///
+ /// The common name of this rule
+ public string GetCommonName()
+ {
+ return string.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingWMIObjectCmdletCommonName);
+ }
+
+ ///
+ /// GetDescription: Retrieves the description of this rule.
+ ///
+ /// The description of this rule
+ public string GetDescription()
+ {
+ return string.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingWMIObjectCmdletDescription);
+ }
+
+ ///
+ /// GetSourceType: Retrieves the type of the rule: builtin, managed or module.
+ ///
+ public SourceType GetSourceType()
+ {
+ return SourceType.Builtin;
+ }
+
+
+ ///
+ /// GetSeverity:Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
+
+ ///
+ /// GetSourceName: Retrieves the module/assembly name the rule is from.
+ ///
+ public string GetSourceName()
+ {
+ return string.Format(CultureInfo.CurrentCulture, Strings.SourceName);
+ }
+ }
+}
diff --git a/Rules/AvoidUsingWriteHost.cs b/Rules/AvoidUsingWriteHost.cs
index b5126a608..597d7cf4a 100644
--- a/Rules/AvoidUsingWriteHost.cs
+++ b/Rules/AvoidUsingWriteHost.cs
@@ -11,19 +11,11 @@
//
using System;
-using System.Collections.ObjectModel;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Management.Automation;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -105,6 +97,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
///
/// GetSourceName: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/MissingModuleManifestField.cs b/Rules/MissingModuleManifestField.cs
index 6816878f3..8caa7e3ff 100644
--- a/Rules/MissingModuleManifestField.cs
+++ b/Rules/MissingModuleManifestField.cs
@@ -12,18 +12,11 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Management.Automation.Language;
using System.Management.Automation;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
-using System.IO;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -110,6 +103,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
///
/// Method: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/PossibleIncorrectComparisonWithNull.cs b/Rules/PossibleIncorrectComparisonWithNull.cs
index 149deebe8..507832322 100644
--- a/Rules/PossibleIncorrectComparisonWithNull.cs
+++ b/Rules/PossibleIncorrectComparisonWithNull.cs
@@ -11,19 +11,11 @@
//
using System;
-using System.Collections.ObjectModel;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Management.Automation;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -87,6 +79,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
///
/// GetSourceName: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/ProvideCommentHelp.cs b/Rules/ProvideCommentHelp.cs
index b6f0e4c02..fbb03b2b9 100644
--- a/Rules/ProvideCommentHelp.cs
+++ b/Rules/ProvideCommentHelp.cs
@@ -13,15 +13,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
using System.Management.Automation;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
@@ -235,6 +230,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Information;
+ }
+
///
/// Method: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/ProvideVerboseMessage.cs b/Rules/ProvideVerboseMessage.cs
index 5f695966d..a69447c0e 100644
--- a/Rules/ProvideVerboseMessage.cs
+++ b/Rules/ProvideVerboseMessage.cs
@@ -12,16 +12,10 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -117,6 +111,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Information;
+ }
+
///
/// Method: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/ReturnCorrectTypesForDSCFunctions.cs b/Rules/ReturnCorrectTypesForDSCFunctions.cs
index 3879e8aea..2890660fb 100644
--- a/Rules/ReturnCorrectTypesForDSCFunctions.cs
+++ b/Rules/ReturnCorrectTypesForDSCFunctions.cs
@@ -11,20 +11,12 @@
//
using System;
-using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Management.Automation;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
-using Microsoft.Windows.Powershell.ScriptAnalyzer;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -217,6 +209,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Information;
+ }
+
///
/// GetSourceName: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/ScriptAnalyzerBuiltinRules.csproj b/Rules/ScriptAnalyzerBuiltinRules.csproj
index 9e57fe94f..e85c892d0 100644
--- a/Rules/ScriptAnalyzerBuiltinRules.csproj
+++ b/Rules/ScriptAnalyzerBuiltinRules.csproj
@@ -66,6 +66,7 @@
+
diff --git a/Rules/Strings.Designer.cs b/Rules/Strings.Designer.cs
index 7b6c6133a..1ec732308 100644
--- a/Rules/Strings.Designer.cs
+++ b/Rules/Strings.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:4.0.30319.35317
+// Runtime Version:4.0.30319.34014
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -717,6 +717,42 @@ internal static string AvoidUsingPositionalParametersName {
}
}
+ ///
+ /// Looks up a localized string similar to Avoid Using Get-WMIObject, Remove-WMIObject.
+ ///
+ internal static string AvoidUsingWMIObjectCmdletCommonName {
+ get {
+ return ResourceManager.GetString("AvoidUsingWMIObjectCmdletCommonName", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Depricated. Starting in Windows PowerShell 3.0, these cmdlets have been superseded by CimInstance cmdlets..
+ ///
+ internal static string AvoidUsingWMIObjectCmdletDescription {
+ get {
+ return ResourceManager.GetString("AvoidUsingWMIObjectCmdletDescription", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to File '{0}' uses WMIObject cmdlet. For PowerShell 3.0 and above, this is not recommended because the cmdlet is based on a non-standard DCOM protocol. Use CIMInstance cmdlet instead. This is CIM and WS-Man standards compliant and works in a heterogeneous environment..
+ ///
+ internal static string AvoidUsingWMIObjectCmdletError {
+ get {
+ return ResourceManager.GetString("AvoidUsingWMIObjectCmdletError", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to AvoidUsingWMIObjectCmdlet.
+ ///
+ internal static string AvoidUsingWMIObjectCmdletName {
+ get {
+ return ResourceManager.GetString("AvoidUsingWMIObjectCmdletName", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Avoid Using Write-Host.
///
diff --git a/Rules/Strings.resx b/Rules/Strings.resx
index f8d13de1b..f7501a45c 100644
--- a/Rules/Strings.resx
+++ b/Rules/Strings.resx
@@ -666,4 +666,16 @@
UseShouldProcessForStateChangingFunctions
+
+ Avoid Using Get-WMIObject, Remove-WMIObject
+
+
+ Depricated. Starting in Windows PowerShell 3.0, these cmdlets have been superseded by CimInstance cmdlets.
+
+
+ File '{0}' uses WMIObject cmdlet. For PowerShell 3.0 and above, this is not recommended because the cmdlet is based on a non-standard DCOM protocol. Use CIMInstance cmdlet instead. This is CIM and WS-Man standards compliant and works in a heterogeneous environment.
+
+
+ AvoidUsingWMIObjectCmdlet
+
\ No newline at end of file
diff --git a/Rules/UseApprovedVerbs.cs b/Rules/UseApprovedVerbs.cs
index 9df853532..e59d57dee 100644
--- a/Rules/UseApprovedVerbs.cs
+++ b/Rules/UseApprovedVerbs.cs
@@ -11,18 +11,13 @@
//
using System;
-using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Management.Automation;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
@@ -102,6 +97,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
///
/// GetSourceName: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/UseCmdletCorrectly.cs b/Rules/UseCmdletCorrectly.cs
index f1de7b4cd..a5e854b0b 100644
--- a/Rules/UseCmdletCorrectly.cs
+++ b/Rules/UseCmdletCorrectly.cs
@@ -11,21 +11,13 @@
//
using System;
-using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Management.Automation.Runspaces;
using System.Management.Automation;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using Microsoft.Windows.Powershell.ScriptAnalyzer;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -197,6 +189,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
///
/// GetSourceName: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/UseDeclaredVarsMoreThanAssignments.cs b/Rules/UseDeclaredVarsMoreThanAssignments.cs
index 6cbd7d883..69e3f0bc3 100644
--- a/Rules/UseDeclaredVarsMoreThanAssignments.cs
+++ b/Rules/UseDeclaredVarsMoreThanAssignments.cs
@@ -11,19 +11,11 @@
//
using System;
-using System.Collections.ObjectModel;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Management.Automation;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -95,7 +87,7 @@ public IEnumerable AnalyzeScript(Ast ast, string fileName)
assignments.Remove(varKey);
}
//Check if variable belongs to PowerShell builtin variables
- if (Microsoft.Windows.Powershell.ScriptAnalyzer.Helper.Instance.HasSpecialVars(varKey))
+ if (Helper.Instance.HasSpecialVars(varKey))
{
assignments.Remove(varKey);
}
@@ -144,6 +136,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
///
/// GetSourceName: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/UseIdenticalMandatoryParametersDSC.cs b/Rules/UseIdenticalMandatoryParametersDSC.cs
index fb0ac20f4..93309e30d 100644
--- a/Rules/UseIdenticalMandatoryParametersDSC.cs
+++ b/Rules/UseIdenticalMandatoryParametersDSC.cs
@@ -153,6 +153,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Information;
+ }
+
///
/// GetSourceName: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/UseIdenticalParametersDSC.cs b/Rules/UseIdenticalParametersDSC.cs
index 5f69f6c68..ff33d03c7 100644
--- a/Rules/UseIdenticalParametersDSC.cs
+++ b/Rules/UseIdenticalParametersDSC.cs
@@ -11,19 +11,12 @@
//
using System;
-using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Management.Automation;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -167,6 +160,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
///
/// GetSourceName: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/UsePSCredentialType.cs b/Rules/UsePSCredentialType.cs
index 070910e2d..a932686d4 100644
--- a/Rules/UsePSCredentialType.cs
+++ b/Rules/UsePSCredentialType.cs
@@ -11,19 +11,12 @@
//
using System;
-using System.Collections.ObjectModel;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Management.Automation;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -126,6 +119,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
///
/// GetSourceName: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/UseShouldProcessCorrectly.cs b/Rules/UseShouldProcessCorrectly.cs
index f1cb785e4..de40351cc 100644
--- a/Rules/UseShouldProcessCorrectly.cs
+++ b/Rules/UseShouldProcessCorrectly.cs
@@ -11,19 +11,11 @@
//
using System;
-using System.Collections.ObjectModel;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Management.Automation;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -114,6 +106,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
///
/// GetSourceName: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/UseShouldProcessForStateChangingFunctions.cs b/Rules/UseShouldProcessForStateChangingFunctions.cs
index cca236a4a..28c50aca4 100644
--- a/Rules/UseShouldProcessForStateChangingFunctions.cs
+++ b/Rules/UseShouldProcessForStateChangingFunctions.cs
@@ -118,6 +118,16 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
+
///
/// GetSourceName: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/UseSingularNouns.cs b/Rules/UseSingularNouns.cs
index 162a36437..570cadebb 100644
--- a/Rules/UseSingularNouns.cs
+++ b/Rules/UseSingularNouns.cs
@@ -11,19 +11,13 @@
//
using System;
-using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Management.Automation;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -91,6 +85,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Warning;
+ }
+
///
/// GetSourceName: Retrieves the module/assembly name the rule is from.
///
diff --git a/Rules/UseStandardDSCFunctionsInResource.cs b/Rules/UseStandardDSCFunctionsInResource.cs
index 548eac8fa..60e729cde 100644
--- a/Rules/UseStandardDSCFunctionsInResource.cs
+++ b/Rules/UseStandardDSCFunctionsInResource.cs
@@ -11,19 +11,12 @@
//
using System;
-using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Management.Automation;
using System.Management.Automation.Language;
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
using System.ComponentModel.Composition;
-using System.Resources;
using System.Globalization;
-using System.Threading;
-using System.Reflection;
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
@@ -133,6 +126,15 @@ public SourceType GetSourceType()
return SourceType.Builtin;
}
+ ///
+ /// GetSeverity: Retrieves the severity of the rule: error, warning of information.
+ ///
+ ///
+ public RuleSeverity GetSeverity()
+ {
+ return RuleSeverity.Error;
+ }
+
///
/// GetSourceName: Retrieves the module/assembly name the rule is from.
///
diff --git a/Tests/Engine/GetScriptAnalyzerRule.tests.ps1 b/Tests/Engine/GetScriptAnalyzerRule.tests.ps1
index dbbc97f08..8c32e9b4b 100644
--- a/Tests/Engine/GetScriptAnalyzerRule.tests.ps1
+++ b/Tests/Engine/GetScriptAnalyzerRule.tests.ps1
@@ -108,4 +108,16 @@ Describe "Test RuleExtension" {
}
}
+}
+
+Describe "TestSeverity" {
+ It "filters rules based on the specified rule severity" {
+ $rules = Get-ScriptAnalyzerRule -Severity Error
+ $rules.Count | Should be 4
+ }
+
+ It "filters rules based on multiple severity inputs"{
+ $rules = Get-ScriptAnalyzerRule -Severity Error,Information
+ $rules.Count | Should be 8
+ }
}
\ No newline at end of file
diff --git a/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 b/Tests/Engine/InvokeScriptAnalyzer.tests.ps1
index 53ddb9a02..9cc6ccdbd 100644
--- a/Tests/Engine/InvokeScriptAnalyzer.tests.ps1
+++ b/Tests/Engine/InvokeScriptAnalyzer.tests.ps1
@@ -3,6 +3,8 @@ $sa = Get-Command Invoke-ScriptAnalyzer
$directory = Split-Path -Parent $MyInvocation.MyCommand.Path
$singularNouns = "PSUseSingularNouns"
$rules = $singularNouns, "PSUseApprovedVerbs"
+$avoidRules = "PSAvoid*"
+$useRules = "PSUse*"
Describe "Test available parameters" {
$params = $sa.Parameters
@@ -103,6 +105,12 @@ Describe "Test ExcludeRule" {
}
}
+ Context "Support wild card" {
+ It "supports wild card exclusions of input rules"{
+ $excludeWildCard = Invoke-ScriptAnalyzer $directory\..\Rules\BadCmdlet.ps1 -ExcludeRule $avoidRules | Where-Object {$_.RuleName -match $avoidRules}
+ }
+ }
+
}
Describe "Test IncludeRule" {
@@ -124,6 +132,18 @@ Describe "Test IncludeRule" {
$wrongInclude.Count | Should Be 0
}
}
+
+ Context "IncludeRule supports wild card" {
+ It "includes 1 wildcard rule"{
+ $includeWildcard = Invoke-ScriptAnalyzer $directory\..\Rules\BadCmdlet.ps1 -IncludeRule $avoidRules
+ $includeWildcard.Count | Should be 5
+ }
+
+ it "includes 2 wildcardrules" {
+ $includeWildcard = Invoke-ScriptAnalyzer $directory\..\Rules\BadCmdlet.ps1 -IncludeRule $avoidRules, $useRules
+ $includeWildcard.Count | Should be 7
+ }
+ }
}
Describe "Test Exclude And Include" {
diff --git a/Tests/Rules/AvoidGlobalOrUnitializedVars.ps1 b/Tests/Rules/AvoidGlobalOrUnitializedVars.ps1
index e9979a297..ef6988ad9 100644
--- a/Tests/Rules/AvoidGlobalOrUnitializedVars.ps1
+++ b/Tests/Rules/AvoidGlobalOrUnitializedVars.ps1
@@ -19,4 +19,7 @@ while ($false) {
$a;
# $d may not be initialized too
-$d;
\ No newline at end of file
+$d;
+
+# error must be raised here
+Invoke-Command -ScriptBlock {$a; }
\ No newline at end of file
diff --git a/Tests/Rules/AvoidGlobalOrUnitializedVars.tests.ps1 b/Tests/Rules/AvoidGlobalOrUnitializedVars.tests.ps1
index 537f57024..bad960927 100644
--- a/Tests/Rules/AvoidGlobalOrUnitializedVars.tests.ps1
+++ b/Tests/Rules/AvoidGlobalOrUnitializedVars.tests.ps1
@@ -31,8 +31,8 @@ Describe "AvoidGlobalVars" {
Describe "AvoidUnitializedVars" {
Context "When there are violations" {
- It "has 4 avoid using unitialized variable violations" {
- $nonInitializedViolations.Count | Should Be 4
+ It "has 5 avoid using unitialized variable violations" {
+ $nonInitializedViolations.Count | Should Be 5
}
It "has the correct description message" {
diff --git a/Tests/Rules/AvoidGlobalOrUnitializedVarsNoViolations.ps1 b/Tests/Rules/AvoidGlobalOrUnitializedVarsNoViolations.ps1
index ca914bce5..b5206cd68 100644
--- a/Tests/Rules/AvoidGlobalOrUnitializedVarsNoViolations.ps1
+++ b/Tests/Rules/AvoidGlobalOrUnitializedVarsNoViolations.ps1
@@ -22,6 +22,8 @@ stop-process 12,23 -ErrorVariable ev -ErrorAction SilentlyContinue
if($null -ne $ev)
{
Write-host $ev[0]
+ # no error should be raised here
+ Invoke-Command {$b}
}
get-process notepad | tee-object -variable proc
diff --git a/Tests/Rules/AvoidUsingInternalURLsNoViolations.ps1 b/Tests/Rules/AvoidUsingInternalURLsNoViolations.ps1
index 73825de70..cdd8b7cc5 100644
--- a/Tests/Rules/AvoidUsingInternalURLsNoViolations.ps1
+++ b/Tests/Rules/AvoidUsingInternalURLsNoViolations.ps1
@@ -1,3 +1,4 @@
$correctPath = "www.bing.com"
$externalSite = "//outside.co/test"
-rmdir /s /q ".\Directory"
\ No newline at end of file
+rmdir /s /q ".\Directory"
+$sd = "O:BAG:BAD:(A;;0x800;;;WD)(A;;0x120fff;;;SY)(A;;0x120fff;;;LS)(A;;0x120fff;;;NS)(A;;0x120fff;;;BA)(A;;0xee5;;;LU)(A;;LC;;;MU)(A;;0x800;;;AG)"
\ No newline at end of file
diff --git a/Tests/Rules/AvoidUsingWMIObjectCmdlet.ps1 b/Tests/Rules/AvoidUsingWMIObjectCmdlet.ps1
new file mode 100644
index 000000000..13f0412c9
--- /dev/null
+++ b/Tests/Rules/AvoidUsingWMIObjectCmdlet.ps1
@@ -0,0 +1,13 @@
+#Script violates the rule because Get-CIMInstance is available on PS 3.0 and needs to use that
+
+#requires -version 3.0
+
+function TestFunction
+{
+ Get-WmiObject -Class Win32_ComputerSystem
+
+}
+
+TestFunction
+
+Remove-WmiObject -Class Win32_OperatingSystem -Verbose
\ No newline at end of file
diff --git a/Tests/Rules/AvoidUsingWMIObjectCmdlet.tests.ps1 b/Tests/Rules/AvoidUsingWMIObjectCmdlet.tests.ps1
new file mode 100644
index 000000000..0a96ad16e
--- /dev/null
+++ b/Tests/Rules/AvoidUsingWMIObjectCmdlet.tests.ps1
@@ -0,0 +1,24 @@
+Import-Module PSScriptAnalyzer
+$wmiObjectRuleName = "PSAvoidUsingWMIObjectCmdlet"
+$violationMessage = "File 'AvoidUsingWMIObjectCmdlet.ps1' uses WMIObject cmdlet. For PowerShell 3.0 and above, this is not recommended because the cmdlet is based on a non-standard DCOM protocol. Use CIMInstance cmdlet instead. This is CIM and WS-Man standards compliant and works in a heterogeneous environment."
+$directory = Split-Path -Parent $MyInvocation.MyCommand.Path
+$violations = Invoke-ScriptAnalyzer $directory\AvoidUsingWMIObjectCmdlet.ps1 | Where-Object {$_.RuleName -eq $wmiObjectRuleName}
+$noViolations = Invoke-ScriptAnalyzer $directory\AvoidUsingWMIObjectCmdletNoViolations.ps1 | Where-Object {$_.RuleName -eq $wmiObjectRuleName}
+
+Describe "AvoidUsingWMIObjectCmdlet" {
+ Context "Script contains references to WMIObject cmdlets - Violation" {
+ It "Have 2 WMIObject cmdlet Violations" {
+ $violations.Count | Should Be 2
+ }
+
+ It "has the correct description message for WMIObject rule violation" {
+ $violations[0].Message | Should Match $violationMessage
+ }
+ }
+
+ Context "Script contains no calls to WMIObject cmdlet - No violation" {
+ It "results in no rule violations" {
+ $noViolations.Count | Should Be 0
+ }
+ }
+}
\ No newline at end of file
diff --git a/Tests/Rules/AvoidUsingWMIObjectCmdletNoViolations.ps1 b/Tests/Rules/AvoidUsingWMIObjectCmdletNoViolations.ps1
new file mode 100644
index 000000000..b5d2e6f14
--- /dev/null
+++ b/Tests/Rules/AvoidUsingWMIObjectCmdletNoViolations.ps1
@@ -0,0 +1,14 @@
+# No Rule violations since this script requires PS 2.0 and Get-CIMInstance is not available for this version
+# So using Get-WMIObject is OK
+
+#requires -Version 2.0
+
+function TestFunction
+{
+ Remove-WmiObject -Class Win32_ComputerSystem
+
+}
+
+TestFunction
+
+Get-WmiObject -Class Win32_OperatingSystem -Verbose
\ No newline at end of file
diff --git a/Tests/Rules/UseShouldProcessForStateChangingFunctions.ps1 b/Tests/Rules/UseShouldProcessForStateChangingFunctions.ps1
index 925a1b809..9898f7f87 100644
--- a/Tests/Rules/UseShouldProcessForStateChangingFunctions.ps1
+++ b/Tests/Rules/UseShouldProcessForStateChangingFunctions.ps1
@@ -1,11 +1,11 @@
-function Get-Service
-{
- param ([string]$c)
-}
-
-function Get-MyObject{
+function Set-MyObject{
[CmdletBinding(SupportsShouldProcess = $false)]
param([string]$c, [int]$d)
}
+function Set-MyObject{
+ [CmdletBinding()]
+ param([string]$c, [int]$d)
+
+}
\ No newline at end of file
diff --git a/Tests/Rules/UseShouldProcessForStateChangingFunctions.tests.ps1 b/Tests/Rules/UseShouldProcessForStateChangingFunctions.tests.ps1
index e5998e00e..0cbdecc5e 100644
--- a/Tests/Rules/UseShouldProcessForStateChangingFunctions.tests.ps1
+++ b/Tests/Rules/UseShouldProcessForStateChangingFunctions.tests.ps1
@@ -1,15 +1,14 @@
Import-Module PSScriptAnalyzer
-$violationMessage = "Function ’Get-Service’ has verb that could change system state. Therefore, the function has to support 'ShouldProcess'"
+$violationMessage = "Function ’Set-MyObject’ has verb that could change system state. Therefore, the function has to support 'ShouldProcess'"
$violationName = "PSUseShouldProcessForStateChangingFunctions"
-$violationName = "PS.UseShouldProcessForStateChangingFunctions"
$directory = Split-Path -Parent $MyInvocation.MyCommand.Path
$violations = Invoke-ScriptAnalyzer $directory\UseShouldProcessForStateChangingFunctions.ps1 | Where-Object {$_.RuleName -eq $violationName}
$noViolations = Invoke-ScriptAnalyzer $directory\UseShouldProcessForStateChangingFunctionsNoViolations.ps1 | Where-Object {$_.RuleName -eq $violationName}
-Describe "" {
+Describe "It checks UseShouldProcess is enabled when there are state changing verbs in the function names" {
Context "When there are violations" {
It "has 2 violations where ShouldProcess is not supported" {
- $violations.Count | Should Be 3
+ $violations.Count | Should Be 2
}
It "has the correct description message" {
diff --git a/Tests/Rules/UseShouldProcessForStateChangingFunctionsNoViolations.ps1 b/Tests/Rules/UseShouldProcessForStateChangingFunctionsNoViolations.ps1
index cb4b2cfc9..a9f3d8aee 100644
--- a/Tests/Rules/UseShouldProcessForStateChangingFunctionsNoViolations.ps1
+++ b/Tests/Rules/UseShouldProcessForStateChangingFunctionsNoViolations.ps1
@@ -1,6 +1,6 @@
-function Get-Service
+function Set-Service
{
- [CmdletBinding(SupportShouldSuppress= $false)]
+ [CmdletBinding(SupportsShouldProcess = $true)]
param ([string]$c)
}