From 23cbc5bd4c2f6ad1fe0ea88415da662b60dc3c48 Mon Sep 17 00:00:00 2001 From: GoodOlClint Date: Wed, 6 May 2015 21:45:33 -0500 Subject: [PATCH 01/50] Added script to build module --- build.cmd | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 build.cmd diff --git a/build.cmd b/build.cmd new file mode 100644 index 000000000..10cff4ee4 --- /dev/null +++ b/build.cmd @@ -0,0 +1,6 @@ +@echo off +setlocal +call "%VS120COMNTOOLS%\VsDevCmd.bat" +msbuild .\PSScriptAnalyzer.sln +if NOT [%ERRORLEVEL%]==[0] pause +endlocal \ No newline at end of file From ca4504b710def2bbb59ac9bb407000e583ffadd1 Mon Sep 17 00:00:00 2001 From: "Raghu Shantha [MSFT]" Date: Thu, 7 May 2015 15:39:12 -0700 Subject: [PATCH 02/50] Added waffle links for in progress and backlog items --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b2a3b6996..bb89aaf04 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,11 @@ Project Management Dashboard You can track issues, pull requests, backlog items here: -[![Stories in Ready](https://badge.waffle.io/PowerShell/PSScriptAnalyzer.png?label=ready&title=Ready)](https://waffle.io/PowerShell/PSScriptAnalyzer) +[![Stories in progress](https://badge.waffle.io/PowerShell/PSScriptAnalyzer.png?label=In%20Progress&title=In%20Progress)](https://waffle.io/PowerShell/PSScriptAnalyzer) + +[![Stories in ready](https://badge.waffle.io/PowerShell/PSScriptAnalyzer.png?label=ready&title=Ready)](https://waffle.io/PowerShell/PSScriptAnalyzer) + +[![Stories in backlog](https://badge.waffle.io/PowerShell/PSScriptAnalyzer.png?label=BackLog&title=BackLog)](https://waffle.io/PowerShell/PSScriptAnalyzer) Contributing to ScriptAnalyzer From 156b04d86c23fbdead655403d2bd2ebbc9daa8eb Mon Sep 17 00:00:00 2001 From: Raghu Shantha Date: Thu, 7 May 2015 15:44:38 -0700 Subject: [PATCH 03/50] Updated build version for the module --- Engine/PSScriptAnalyzer.psd1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Engine/PSScriptAnalyzer.psd1 b/Engine/PSScriptAnalyzer.psd1 index 2c95981f9..bfa38cf53 100644 --- a/Engine/PSScriptAnalyzer.psd1 +++ b/Engine/PSScriptAnalyzer.psd1 @@ -11,7 +11,7 @@ Author = 'Microsoft Corporation' RootModule = 'Microsoft.Windows.Powershell.ScriptAnalyzer.dll' # Version number of this module. -ModuleVersion = '1.0' +ModuleVersion = '1.0.1' # ID used to uniquely identify this module GUID = '324fc715-36bf-4aee-8e58-72e9b4a08ad9' From 1a146136df98747554ae7cf967a9c6418b4f3224 Mon Sep 17 00:00:00 2001 From: GoodOlClint Date: Thu, 7 May 2015 17:59:02 -0500 Subject: [PATCH 04/50] Check for VS Build tools --- build.cmd | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/build.cmd b/build.cmd index 10cff4ee4..5097a90dd 100644 --- a/build.cmd +++ b/build.cmd @@ -1,6 +1,15 @@ @echo off setlocal +if "%VS120COMNTOOLS%"=="" GOTO NOTOOLS call "%VS120COMNTOOLS%\VsDevCmd.bat" msbuild .\PSScriptAnalyzer.sln if NOT [%ERRORLEVEL%]==[0] pause + +GOTO END + +:NOTOOLS +echo The Visual Studio 2012 tools are not installed +pause + +:END endlocal \ No newline at end of file From 2db020006bfb5fc1d0e214f24b94a74bb91165c1 Mon Sep 17 00:00:00 2001 From: GoodOlClint Date: Thu, 7 May 2015 17:59:44 -0500 Subject: [PATCH 05/50] Specify build configuration and logging --- build.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.cmd b/build.cmd index 5097a90dd..70dd889a3 100644 --- a/build.cmd +++ b/build.cmd @@ -2,7 +2,7 @@ setlocal if "%VS120COMNTOOLS%"=="" GOTO NOTOOLS call "%VS120COMNTOOLS%\VsDevCmd.bat" -msbuild .\PSScriptAnalyzer.sln +msbuild .\PSScriptAnalyzer.sln /p:Configuration=Debug /l:FileLogger,Microsoft.Build.Engine;logfile=PSScriptAnalyzer_Build.log;append=true if NOT [%ERRORLEVEL%]==[0] pause GOTO END From 6a8fbe8e60199019b9c66698c7378e5f469acc51 Mon Sep 17 00:00:00 2001 From: GoodOlClint Date: Thu, 7 May 2015 18:04:51 -0500 Subject: [PATCH 06/50] Corrected visual studio version name --- build.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.cmd b/build.cmd index 70dd889a3..e51842115 100644 --- a/build.cmd +++ b/build.cmd @@ -8,7 +8,7 @@ if NOT [%ERRORLEVEL%]==[0] pause GOTO END :NOTOOLS -echo The Visual Studio 2012 tools are not installed +echo The Visual Studio 2013 tools are not installed pause :END From b36c88449fdcb52308807d6df0c2bec0c7da67da Mon Sep 17 00:00:00 2001 From: "Raghu Shantha [MSFT]" Date: Fri, 8 May 2015 16:02:29 -0700 Subject: [PATCH 07/50] Update CHANGELOG.MD --- CHANGELOG.MD | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.MD b/CHANGELOG.MD index 1602860be..f21e6edf7 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -1,4 +1,4 @@ -## Unreleased (May.7, 2015) +## Released (May.8, 2015) ###Features: - Integrated with waffle.io for Project Management. - Added documentation for writing script rules. @@ -12,11 +12,12 @@ - PSProvideVerboseMessage only throws warnings in non-advanced functions. - Fix the issue in importing customized rule +- Fix Function Member Ast cast error -##Relesed on Apr.24, 2015 +##Released on Apr.24, 2015 ###Features: - Finalized three levels of Severity - Error/Warning/Information. From b3bab7e06138fb0b05671d7ae3670f2e324d4598 Mon Sep 17 00:00:00 2001 From: "Raghu Shantha [MSFT]" Date: Fri, 8 May 2015 16:02:49 -0700 Subject: [PATCH 08/50] Update CHANGELOG.MD --- CHANGELOG.MD | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.MD b/CHANGELOG.MD index f21e6edf7..4bec47113 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -1,4 +1,4 @@ -## Released (May.8, 2015) +## Released v1.0.1 (May.8, 2015) ###Features: - Integrated with waffle.io for Project Management. - Added documentation for writing script rules. @@ -17,7 +17,7 @@ -##Released on Apr.24, 2015 +##Released v1.0.0 on Apr.24, 2015 ###Features: - Finalized three levels of Severity - Error/Warning/Information. From 19b7d2ab2bb1caa07f9b794bd419e77b04f9750c Mon Sep 17 00:00:00 2001 From: "Raghu Shantha [MSFT]" Date: Mon, 11 May 2015 12:11:27 -0700 Subject: [PATCH 09/50] Added throughput graph --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index bb89aaf04..1708364fc 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,10 @@ You can track issues, pull requests, backlog items here: [![Stories in backlog](https://badge.waffle.io/PowerShell/PSScriptAnalyzer.png?label=BackLog&title=BackLog)](https://waffle.io/PowerShell/PSScriptAnalyzer) +Throughput Graph + +[![Throughput Graph](https://graphs.waffle.io/powershell/psscriptanalyzer/throughput.svg)](https://waffle.io/powershell/psscriptanalyzer/metrics) + Contributing to ScriptAnalyzer ============================== From 2d91cdb1be1d6f2fc6b7bc04fcd74d7d8cc4586e Mon Sep 17 00:00:00 2001 From: Yuting Chen Date: Mon, 11 May 2015 13:39:15 -0700 Subject: [PATCH 10/50] Modify DSC rule severity --- Rules/UseIdenticalMandatoryParametersDSC.cs | 4 ++-- Rules/UseIdenticalParametersDSC.cs | 4 ++-- Rules/UseStandardDSCFunctionsInResource.cs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Rules/UseIdenticalMandatoryParametersDSC.cs b/Rules/UseIdenticalMandatoryParametersDSC.cs index 93309e30d..b2aaa3c16 100644 --- a/Rules/UseIdenticalMandatoryParametersDSC.cs +++ b/Rules/UseIdenticalMandatoryParametersDSC.cs @@ -98,7 +98,7 @@ public IEnumerable AnalyzeDSCResource(Ast ast, string fileName { List functionsNotContainingParam = expectedTargetResourceFunctionNames.Except(mandatoryParameters[paramName]).ToList(); yield return new DiagnosticRecord(string.Format(CultureInfo.InvariantCulture, Strings.UseIdenticalMandatoryParametersDSCError, paramName, string.Join(", ", functionsNotContainingParam.ToArray())), - ast.Extent, GetName(), DiagnosticSeverity.Information, fileName); + ast.Extent, GetName(), DiagnosticSeverity.Error, fileName); } } @@ -159,7 +159,7 @@ public SourceType GetSourceType() /// public RuleSeverity GetSeverity() { - return RuleSeverity.Information; + return RuleSeverity.Error; } /// diff --git a/Rules/UseIdenticalParametersDSC.cs b/Rules/UseIdenticalParametersDSC.cs index ff33d03c7..8318c6155 100644 --- a/Rules/UseIdenticalParametersDSC.cs +++ b/Rules/UseIdenticalParametersDSC.cs @@ -67,7 +67,7 @@ public IEnumerable AnalyzeDSCResource(Ast ast, string fileName || !CompareParamAsts(paramAst, paramNames[paramAst.Name.VariablePath.UserPath])) { yield return new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.UseIdenticalParametersDSCError), - paramAst.Extent, GetName(), DiagnosticSeverity.Information, fileName); + paramAst.Extent, GetName(), DiagnosticSeverity.Error, fileName); } } } @@ -166,7 +166,7 @@ public SourceType GetSourceType() /// public RuleSeverity GetSeverity() { - return RuleSeverity.Warning; + return RuleSeverity.Error; } /// diff --git a/Rules/UseStandardDSCFunctionsInResource.cs b/Rules/UseStandardDSCFunctionsInResource.cs index 60e729cde..67e9728df 100644 --- a/Rules/UseStandardDSCFunctionsInResource.cs +++ b/Rules/UseStandardDSCFunctionsInResource.cs @@ -54,7 +54,7 @@ public IEnumerable AnalyzeDSCResource(Ast ast, string fileName if (!targetResourceFunctionNamesInAst.Contains(expectedTargetResourceFunctionName, StringComparer.CurrentCultureIgnoreCase)) { yield return new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.UseStandardDSCFunctionsInResourceError, expectedTargetResourceFunctionName), - ast.Extent, GetName(), DiagnosticSeverity.Information, fileName); + ast.Extent, GetName(), DiagnosticSeverity.Error, fileName); } } } @@ -85,7 +85,7 @@ item is TypeDefinitionAst if (!functions.Any(function => String.Equals(resourceFunctionName, (function as FunctionMemberAst).Name))) { yield return new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.UseStandardDSCFunctionsInClassError, resourceFunctionName), - dscClass.Extent, GetName(), DiagnosticSeverity.Information, fileName); + dscClass.Extent, GetName(), DiagnosticSeverity.Error, fileName); } } } From bf670a1bd03ec14096a7a3b74da0d2da5b9ae222 Mon Sep 17 00:00:00 2001 From: "Yuting Chen[MSFT]" Date: Mon, 11 May 2015 13:52:44 -0700 Subject: [PATCH 11/50] Update ReturnCorrectTypeDSCFunctions.md --- RuleDocumentation/ReturnCorrectTypeDSCFunctions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RuleDocumentation/ReturnCorrectTypeDSCFunctions.md b/RuleDocumentation/ReturnCorrectTypeDSCFunctions.md index 0ea962afd..a530b7c85 100644 --- a/RuleDocumentation/ReturnCorrectTypeDSCFunctions.md +++ b/RuleDocumentation/ReturnCorrectTypeDSCFunctions.md @@ -1,5 +1,5 @@ #ReturnCorrectTypeDSCFunctions -**Severity Level: Error** +**Severity Level: Information** ##Description From f64e1ae213b6f8d063f49d993aa2593d867a310c Mon Sep 17 00:00:00 2001 From: "Yuting Chen[MSFT]" Date: Mon, 11 May 2015 14:02:53 -0700 Subject: [PATCH 12/50] Update ProvideVerboseMessage.md --- RuleDocumentation/ProvideVerboseMessage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RuleDocumentation/ProvideVerboseMessage.md b/RuleDocumentation/ProvideVerboseMessage.md index 99d8e73ca..343c046eb 100644 --- a/RuleDocumentation/ProvideVerboseMessage.md +++ b/RuleDocumentation/ProvideVerboseMessage.md @@ -1,5 +1,5 @@ #ProvideVerboseMessage -**Severity Level: Warning** +**Severity Level: Information** ##Description From 4b467f7ad6160344b960412ebd7094386de13c7b Mon Sep 17 00:00:00 2001 From: "Yuting Chen[MSFT]" Date: Mon, 11 May 2015 14:05:23 -0700 Subject: [PATCH 13/50] Update UseCmdletCorrectly.md --- RuleDocumentation/UseCmdletCorrectly.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RuleDocumentation/UseCmdletCorrectly.md b/RuleDocumentation/UseCmdletCorrectly.md index 8899080b5..6bc94d9de 100644 --- a/RuleDocumentation/UseCmdletCorrectly.md +++ b/RuleDocumentation/UseCmdletCorrectly.md @@ -1,5 +1,5 @@ #UseCmdletCorrectly -**Severity Level: Error** +**Severity Level: Warning** ##Description From d03ffdabdbe124e30f7b5785f4b990054a60aefb Mon Sep 17 00:00:00 2001 From: "Yuting Chen[MSFT]" Date: Mon, 11 May 2015 14:07:03 -0700 Subject: [PATCH 14/50] Update AvoidUsingPositionalParameters.md --- RuleDocumentation/AvoidUsingPositionalParameters.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RuleDocumentation/AvoidUsingPositionalParameters.md b/RuleDocumentation/AvoidUsingPositionalParameters.md index 9fa5f0bbe..ecc71053c 100644 --- a/RuleDocumentation/AvoidUsingPositionalParameters.md +++ b/RuleDocumentation/AvoidUsingPositionalParameters.md @@ -1,5 +1,5 @@ #AvoidUsingPositionalParameters -**Severity Level: Info** +**Severity Level: Warning** ##Description From 9609bb19b00bf911725ad0477adb240db64e0862 Mon Sep 17 00:00:00 2001 From: "Yuting Chen[MSFT]" Date: Mon, 11 May 2015 14:08:45 -0700 Subject: [PATCH 15/50] Update UseDeclaredVarsMoreThanAssignments.md --- RuleDocumentation/UseDeclaredVarsMoreThanAssignments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RuleDocumentation/UseDeclaredVarsMoreThanAssignments.md b/RuleDocumentation/UseDeclaredVarsMoreThanAssignments.md index 82d76b644..e80d276f4 100644 --- a/RuleDocumentation/UseDeclaredVarsMoreThanAssignments.md +++ b/RuleDocumentation/UseDeclaredVarsMoreThanAssignments.md @@ -1,5 +1,5 @@ #UseDeclaredVarsMoreThanAssignments -**Severity Level: Info** +**Severity Level: Warning** ##Description From 7a29d197db8dc90591742c247c25097cc950b648 Mon Sep 17 00:00:00 2001 From: "Yuting Chen[MSFT]" Date: Mon, 11 May 2015 14:14:16 -0700 Subject: [PATCH 16/50] Update UseShouldProcessCorrectly.md --- RuleDocumentation/UseShouldProcessCorrectly.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RuleDocumentation/UseShouldProcessCorrectly.md b/RuleDocumentation/UseShouldProcessCorrectly.md index 40ab429b6..336f22a02 100644 --- a/RuleDocumentation/UseShouldProcessCorrectly.md +++ b/RuleDocumentation/UseShouldProcessCorrectly.md @@ -1,5 +1,5 @@ #UseShouldProcessCorrectly -**Severity Level: Error** +**Severity Level: Warning** ##Description From 9d20c229290db0e83e97dac246cf2d887c5698c5 Mon Sep 17 00:00:00 2001 From: Yuting Chen Date: Mon, 11 May 2015 14:17:23 -0700 Subject: [PATCH 17/50] Modified best practice. --- PowerShellBestPractices.md | 134 +++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 PowerShellBestPractices.md diff --git a/PowerShellBestPractices.md b/PowerShellBestPractices.md new file mode 100644 index 000000000..44b924a92 --- /dev/null +++ b/PowerShellBestPractices.md @@ -0,0 +1,134 @@ +#PowerShell Best Practices + +The following guidelines come from a combined effort from both the PowerShell team and the community. We will use this guideline to define rules for PSScriptAnalyzer. Please feel free to propose additional guidelines and rules for PSScriptAnalyzer. +**Note: The hyperlink next to each guidelines will redirect to documentation page for the rule that is already implemented. + +##Cmdlet Design Rules +###Severity: Error +###Severity: Warning + - Use Only Approved Verbs [UseApprovedVerbs](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/UseApprovedVerbs.md) + - Cmdlets Names: Characters that cannot be Used [AvoidReservedCharInCmdlet](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidReservedCharInCmdlet.md) + - Parameter Names that cannot be Used [AvoidReservedParams](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidReservedParams.md) + - Support Confirmation Requests [UseShouldProcessCorrectly](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/UseShouldProcessCorrectly.md) and [UseShouldProcessForStateChangingFunctions](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/UseShouldProcessForStateChangingFunctions.md) + - Nouns should be singular [UseSingularNouns](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/UseSingularNouns.md) + - Module Manifest Fields [MissingModuleManifestField](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/MissingModuleManifestField.md) + - Version + - Author + - Description + - LicenseUri (for PowerShell Gallery) + - Must call ShouldProcess when ShouldProcess attribute is present and vice versa.[UseShouldProcessCorrectly](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/UseShouldProcessCorrectly.md) + - Switch parameters should not default to true  [AvoidDefaultTrueValueSwtichParameter](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidDefaultTrueValueSwitchParameter.md) + +###Severity: Information + +###Severity: TBD + - Support Force Parameter for Interactive Session + - If your cmdlet is used interactively, always provide a Force parameter to override the interactive actions, such as prompts or reading lines of input). This is important because it allows your cmdlet to be used in non-interactive scripts and hosts. The following methods can be implemented by an interactive host. + - Document Output Objects + - Module must be loadable + - No syntax errors + - Unresolved dependencies are an error + - Derive from the Cmdlet or PSCmdlet Classes + - Specify the Cmdlet Attribute + - Override an Input Processing Method + - Specify the OutputType Attribute + - Write Single Records to the Pipeline + - Make Cmdlets Case-Insensitive and Case-Preserving + + +##Script Functions +###Severity: Error + +###Severity: Warning + - Avoid using alias [AvoidAlias](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidAlias.md) + - Avoid using deprecated WMI cmdlets [AvoidUsingWMICmdlet](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidUsingWMICmdlet.md) + - Empty catch block should not be used [AvoidEmptyCatchBlock](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidEmptyCatchBlock.md) + - Invoke existing cmdlet with correct parameters [UseCmdletCorrectly](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/UseCmdletCorrectly.md) + - Cmdlets should have ShouldProcess/ShouldContinue and Force param if certain system-modding verbs are present (Update, Set, Remove, New)[UseShouldProcessForStateChangingFunctions](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/UseShouldProcessForStateChangingFunctions.md) + - Positional parameters should be avoided [AvoidUsingPositionalParameters](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidUsingPositionalParameters.md) + - Non-global variables must be initialized. Those that are supposed to be global and not initialized must have “global:” (includes for loop initializations)[AvoidUninitializedVariable](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidUninitializedVariable.md) + - Global variables should be avoided. [AvoidGlobalVars](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidGlobalVars.md) + - Declared variables must be used in more than just their assignment. [UseDeclaredVarsMoreThanAssignments](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/UseDeclaredVarsMoreThanAssignments.md) + - No trap statments should be used [AvoidTrapStatement](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidTrapStatement.md) + - No Invoke-Expression [AvoidUsingInvokeExpression](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidUsingInvokeExpression.md) + +###Severity: Information + +###Severity: TBD + - Clear-Host should not be used + - File paths should not be used (UNC) + - Error Handling + - Use -ErrorAction Stop when calling cmdlets + - Use $ErrorActionPreference = 'Stop'/' Continue' when calling non-cmdlets + - Avoid using flags to handle errors + - Avoid using $? + - Avoid testing for a null variable as an error condition + - Copy $Error[0] to your own variable + - Avoid using pipelines in scripts + - If a return type is declared, the cmdlet must return that type. If a type is returned, a return type must be declared. + + + +##Scripting Style +###Severity: Error + +###Severity: Warning + - Don't use write-host unless writing to the host is all you want to do [AvoidUsingWriteHost](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidUsingWriteHost.md) + +###Severity: Information + - Write comment-based help [ProvideCommentHelp](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/ProvideCommentHelp.md) + - Use write-verbose to give information to someone running your script [ProvideVerboseMessage](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/ProvideVerboseMessage.md) +###Severity: TBD + - Provide usage Examples + - Use the Notes section for detail on how the tool work + - Should have help on every exported command (including parameter documentation + - Document the version of PowerShell that script was written for + - Indent your code + - Avoid backticks + + +##Script Security +###Severity: Error + - Password should be secure string [AvoidUsingPlainTextForPassword](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidUsingPlainTextForPassword.md)- Should never have both -Username and -Password parameters (should take credentials)[UsePSCredentialType](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/UsePSCredentialType.md) + - -ComputerName hardcoded should not be used (information disclosure)[AvoidUsingComputerNameHardcoded](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidUsingComputerNameHardcoded.md) + - - ConvertTo-SecureString with plaintext should not be used (information disclosure) + - +###Severity: Warning +- Password = 'string' should not be used. (information disclosure) [AvoidUsingUsernameAndPasswordParams](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidUsingUsernameAndPasswordParams.md) +- Internal URLs should not be used (information disclosure)[AvoidUsingFilePath](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidUsingFilePath.md) + +###Severity: Information + +###Severity: TBD + - APIKey and Credentials variables that are initialized (information disclosure) + + +##DSC Related Rules +###Severity: Error + - Use standard DSC methods [UseStandardDSCFunctionsInResource](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/UseStandardDSC FunctionsInResource.md) + - Use identical mandatory parameters for all DSC methods [UseIdenticalMandatoryParametersDSC](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/UseIdenticalMandatoryParametersDSC.md) + - Use identical parameters for Set and Test DSC methods [UseIdenticalParametersDSC](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/UseIdenticalParametersDSC.md) + +###Severity: Warning + +###Severity: Information + - All of the following three rule are grouped by: [ReturnCorrectTypeDSCFunctions](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/ReturnCorrectTypeDSCFunctions.md) + - Avoid return any object from a Set-TargetResource function + - Returning a Boolean object from a Test-TargetResource function + - Returning an object from a Get-TargetResource function + - DSC resources should have DSC tests [DSCTestsPresent](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/DscTestsPresent.md) + - DSC resources should have DSC examples [DSCExamplesPresent](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/DscExamplesPresent.md) + +###Severity: TBD + - For PowerShell V4: Resource module contains .psd1 file and schema.mof for every resource + - MOF has description for each element [IssueOpened](https://github.com/PowerShell/PSScriptAnalyzer/issues/131) + - Resource module must alwasy contain .psd1 file and schema.mof (for non-class resource). + - Use ShouldProcess for a Set DSC method + - Resource module contains Resources folder which contains the resources [IssueOpened](https://github.com/PowerShell/PSScriptAnalyzer/issues/130) + + + +###Reference: +Cmdlet Development Guidelines from MSDN site (Cmdlet Development Guidelines) + +The Community Book of PowerShell Practices (Compiled by Don Jones and Matt Penny and the Windows PowerShell Community) \ No newline at end of file From 515b7d8aea8428ff85a7a1a0c1de9c52ec5a7c27 Mon Sep 17 00:00:00 2001 From: Yuting Chen Date: Mon, 11 May 2015 14:18:55 -0700 Subject: [PATCH 18/50] Updated format --- PowerShellBestPractices.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/PowerShellBestPractices.md b/PowerShellBestPractices.md index 44b924a92..a30bd672b 100644 --- a/PowerShellBestPractices.md +++ b/PowerShellBestPractices.md @@ -22,18 +22,18 @@ The following guidelines come from a combined effort from both the PowerShell te ###Severity: Information ###Severity: TBD - - Support Force Parameter for Interactive Session - - If your cmdlet is used interactively, always provide a Force parameter to override the interactive actions, such as prompts or reading lines of input). This is important because it allows your cmdlet to be used in non-interactive scripts and hosts. The following methods can be implemented by an interactive host. - - Document Output Objects - - Module must be loadable - - No syntax errors - - Unresolved dependencies are an error - - Derive from the Cmdlet or PSCmdlet Classes - - Specify the Cmdlet Attribute - - Override an Input Processing Method - - Specify the OutputType Attribute - - Write Single Records to the Pipeline - - Make Cmdlets Case-Insensitive and Case-Preserving + - Support Force Parameter for Interactive Session + - If your cmdlet is used interactively, always provide a Force parameter to override the interactive actions, such as prompts or reading lines of input). This is important because it allows your cmdlet to be used in non-interactive scripts and hosts. The following methods can be implemented by an interactive host. + - Document Output Objects + - Module must be loadable + - No syntax errors + - Unresolved dependencies are an error + - Derive from the Cmdlet or PSCmdlet Classes + - Specify the Cmdlet Attribute + - Override an Input Processing Method + - Specify the OutputType Attribute + - Write Single Records to the Pipeline + - Make Cmdlets Case-Insensitive and Case-Preserving ##Script Functions From 6c388d1dbc8339327061877eceed237d2fdb0030 Mon Sep 17 00:00:00 2001 From: Yuting Chen Date: Mon, 11 May 2015 14:36:37 -0700 Subject: [PATCH 19/50] Add rule documentation for AvoidUsingCovertToSecureString --- ...ToSecureStringWithPlainTextNoViolations.md | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 RuleDocumentation/AvoidUsingConvertToSecureStringWithPlainTextNoViolations.md diff --git a/RuleDocumentation/AvoidUsingConvertToSecureStringWithPlainTextNoViolations.md b/RuleDocumentation/AvoidUsingConvertToSecureStringWithPlainTextNoViolations.md new file mode 100644 index 000000000..1b5fa2edd --- /dev/null +++ b/RuleDocumentation/AvoidUsingConvertToSecureStringWithPlainTextNoViolations.md @@ -0,0 +1,30 @@ +#AvoidUsingConvertToSecureStringWithPlainTextNoViolations +**Severity Level: Error** + + +##Description + +Information in the script should be protected properly. Using ConvertTo-SecureString with plain text will expose secure information. + +##How to Fix + +To fix a violation of this rule, please use a standard encrypted variable to do the conversion. + +##Example + +Wrong: + +``` +$notsecure = convertto-securestring "abc" -asplaintext -force + +New-Object System.Management.Automation.PSCredential -ArgumentList "username", (ConvertTo-SecureString "notsecure" -AsPlainText -Force) + +``` + +Correct: + +``` +$secure = read-host -assecurestring +$encrypted = convertfrom-securestring -securestring $secure +convertto-securestring -string $encrypted +``` From 23fbab472f68cfc8b6692f937708d00f85c4c05c Mon Sep 17 00:00:00 2001 From: "Yuting Chen[MSFT]" Date: Mon, 11 May 2015 14:55:51 -0700 Subject: [PATCH 20/50] Update PowerShellBestPractices.md --- PowerShellBestPractices.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/PowerShellBestPractices.md b/PowerShellBestPractices.md index a30bd672b..e9939f992 100644 --- a/PowerShellBestPractices.md +++ b/PowerShellBestPractices.md @@ -12,10 +12,10 @@ The following guidelines come from a combined effort from both the PowerShell te - Support Confirmation Requests [UseShouldProcessCorrectly](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/UseShouldProcessCorrectly.md) and [UseShouldProcessForStateChangingFunctions](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/UseShouldProcessForStateChangingFunctions.md) - Nouns should be singular [UseSingularNouns](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/UseSingularNouns.md) - Module Manifest Fields [MissingModuleManifestField](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/MissingModuleManifestField.md) - - Version - - Author - - Description - - LicenseUri (for PowerShell Gallery) + - Version + - Author + - Description + - LicenseUri (for PowerShell Gallery) - Must call ShouldProcess when ShouldProcess attribute is present and vice versa.[UseShouldProcessCorrectly](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/UseShouldProcessCorrectly.md) - Switch parameters should not default to true  [AvoidDefaultTrueValueSwtichParameter](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidDefaultTrueValueSwitchParameter.md) @@ -34,7 +34,6 @@ The following guidelines come from a combined effort from both the PowerShell te - Specify the OutputType Attribute - Write Single Records to the Pipeline - Make Cmdlets Case-Insensitive and Case-Preserving - ##Script Functions ###Severity: Error @@ -91,8 +90,8 @@ The following guidelines come from a combined effort from both the PowerShell te ###Severity: Error - Password should be secure string [AvoidUsingPlainTextForPassword](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidUsingPlainTextForPassword.md)- Should never have both -Username and -Password parameters (should take credentials)[UsePSCredentialType](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/UsePSCredentialType.md) - -ComputerName hardcoded should not be used (information disclosure)[AvoidUsingComputerNameHardcoded](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidUsingComputerNameHardcoded.md) - - - ConvertTo-SecureString with plaintext should not be used (information disclosure) - - + - ConvertTo-SecureString with plaintext should not be used (information disclosure) + ###Severity: Warning - Password = 'string' should not be used. (information disclosure) [AvoidUsingUsernameAndPasswordParams](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidUsingUsernameAndPasswordParams.md) - Internal URLs should not be used (information disclosure)[AvoidUsingFilePath](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidUsingFilePath.md) @@ -131,4 +130,4 @@ The following guidelines come from a combined effort from both the PowerShell te ###Reference: Cmdlet Development Guidelines from MSDN site (Cmdlet Development Guidelines) -The Community Book of PowerShell Practices (Compiled by Don Jones and Matt Penny and the Windows PowerShell Community) \ No newline at end of file +The Community Book of PowerShell Practices (Compiled by Don Jones and Matt Penny and the Windows PowerShell Community) From c24e54b1ab0d5572195e01b7d409d12e8b6c75a8 Mon Sep 17 00:00:00 2001 From: "Yuting Chen[MSFT]" Date: Mon, 11 May 2015 15:56:29 -0700 Subject: [PATCH 21/50] Rename AvoidUsingConvertToSecureStringWithPlainTextNoViolations.md to AvoidUsingConvertToSecureStringWithPlainText.md --- ...lations.md => AvoidUsingConvertToSecureStringWithPlainText.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename RuleDocumentation/{AvoidUsingConvertToSecureStringWithPlainTextNoViolations.md => AvoidUsingConvertToSecureStringWithPlainText.md} (100%) diff --git a/RuleDocumentation/AvoidUsingConvertToSecureStringWithPlainTextNoViolations.md b/RuleDocumentation/AvoidUsingConvertToSecureStringWithPlainText.md similarity index 100% rename from RuleDocumentation/AvoidUsingConvertToSecureStringWithPlainTextNoViolations.md rename to RuleDocumentation/AvoidUsingConvertToSecureStringWithPlainText.md From c1d558dc315b0c0bc14053139c088f59a8223425 Mon Sep 17 00:00:00 2001 From: "Yuting Chen[MSFT]" Date: Mon, 11 May 2015 15:57:07 -0700 Subject: [PATCH 22/50] Update AvoidUsingConvertToSecureStringWithPlainText.md --- .../AvoidUsingConvertToSecureStringWithPlainText.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RuleDocumentation/AvoidUsingConvertToSecureStringWithPlainText.md b/RuleDocumentation/AvoidUsingConvertToSecureStringWithPlainText.md index 1b5fa2edd..38bad47d7 100644 --- a/RuleDocumentation/AvoidUsingConvertToSecureStringWithPlainText.md +++ b/RuleDocumentation/AvoidUsingConvertToSecureStringWithPlainText.md @@ -1,4 +1,4 @@ -#AvoidUsingConvertToSecureStringWithPlainTextNoViolations +#AvoidUsingConvertToSecureStringWithPlainText **Severity Level: Error** From 4e1a573e8cbf0d38d10f6472f8a1e4f3daa61632 Mon Sep 17 00:00:00 2001 From: "Yuting Chen[MSFT]" Date: Mon, 11 May 2015 15:57:50 -0700 Subject: [PATCH 23/50] Update PowerShellBestPractices.md --- PowerShellBestPractices.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PowerShellBestPractices.md b/PowerShellBestPractices.md index e9939f992..b6fa559ce 100644 --- a/PowerShellBestPractices.md +++ b/PowerShellBestPractices.md @@ -90,7 +90,7 @@ The following guidelines come from a combined effort from both the PowerShell te ###Severity: Error - Password should be secure string [AvoidUsingPlainTextForPassword](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidUsingPlainTextForPassword.md)- Should never have both -Username and -Password parameters (should take credentials)[UsePSCredentialType](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/UsePSCredentialType.md) - -ComputerName hardcoded should not be used (information disclosure)[AvoidUsingComputerNameHardcoded](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidUsingComputerNameHardcoded.md) - - ConvertTo-SecureString with plaintext should not be used (information disclosure) + - ConvertTo-SecureString with plaintext should not be used (information disclosure) [AvoidUsingConvertToSecureStringWithPlainText](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidUsingConvertToSecureStringWithPlainText.md) ###Severity: Warning - Password = 'string' should not be used. (information disclosure) [AvoidUsingUsernameAndPasswordParams](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/RuleDocumentation/AvoidUsingUsernameAndPasswordParams.md) From 27298af620e3c91ca4e5d2c8e27100b6d572067f Mon Sep 17 00:00:00 2001 From: "Yuting Chen[MSFT]" Date: Mon, 11 May 2015 15:59:13 -0700 Subject: [PATCH 24/50] Rename CustomizedRuleDocumentation.md to ScriptRuleDocumentation.md --- CustomizedRuleDocumentation.md => ScriptRuleDocumentation.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename CustomizedRuleDocumentation.md => ScriptRuleDocumentation.md (100%) diff --git a/CustomizedRuleDocumentation.md b/ScriptRuleDocumentation.md similarity index 100% rename from CustomizedRuleDocumentation.md rename to ScriptRuleDocumentation.md From 5b69c744549034897eb4f3b24ea8f2d48f455101 Mon Sep 17 00:00:00 2001 From: Yuting Chen Date: Tue, 12 May 2015 11:39:30 -0700 Subject: [PATCH 25/50] Add .gitignore file --- .gitignore | 205 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..2736e4c26 --- /dev/null +++ b/.gitignore @@ -0,0 +1,205 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Visual Studo 2015 cache/options directory +.vs/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding addin-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt \ No newline at end of file From ebddf80cac05d55b17917f4e1b27a5793b32565d Mon Sep 17 00:00:00 2001 From: Raghu Shantha Date: Tue, 12 May 2015 12:00:06 -0700 Subject: [PATCH 26/50] Fix for including ProgressPreference built-in variable in the list of approved uninitialized variables --- Engine/SpecialVars.cs | 7 ++++-- .../AvoidUsingUninitializedVariable.Tests.ps1 | 24 +++++++++++++++++++ .../Rules/AvoidUsingUninitializedVariable.ps1 | 10 ++++++++ ...UsingUninitializedVariableNoViolations.ps1 | 11 +++++++++ 4 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 Tests/Rules/AvoidUsingUninitializedVariable.Tests.ps1 create mode 100644 Tests/Rules/AvoidUsingUninitializedVariable.ps1 create mode 100644 Tests/Rules/AvoidUsingUninitializedVariableNoViolations.ps1 diff --git a/Engine/SpecialVars.cs b/Engine/SpecialVars.cs index 2c3e506b5..f616234cc 100644 --- a/Engine/SpecialVars.cs +++ b/Engine/SpecialVars.cs @@ -91,6 +91,7 @@ static SpecialVars() internal const string WhatIfPreference = "WhatIfPreference"; internal const string WarningPreference = "WarningPreference"; internal const string ConfirmPreference = "ConfirmPreference"; + internal const string ProgressPreference = "ProgressPreference"; internal static readonly string[] PreferenceVariables = new string[] { @@ -99,7 +100,8 @@ static SpecialVars() ErrorActionPreference, WhatIfPreference, WarningPreference, - ConfirmPreference, + ConfirmPreference, + ProgressPreference }; internal static readonly Type[] PreferenceVariableTypes = new Type[] @@ -109,7 +111,8 @@ static SpecialVars() /* ErrorPreference */ typeof(ActionPreference), /* WhatIfPreference */ typeof(SwitchParameter), /* WarningPreference */ typeof(ActionPreference), - /* ConfirmPreference */ typeof(ConfirmImpact), + /* ConfirmPreference */ typeof(ConfirmImpact), + /* ProgressPreference */ typeof(Enum), }; internal enum AutomaticVariable diff --git a/Tests/Rules/AvoidUsingUninitializedVariable.Tests.ps1 b/Tests/Rules/AvoidUsingUninitializedVariable.Tests.ps1 new file mode 100644 index 000000000..11db9a196 --- /dev/null +++ b/Tests/Rules/AvoidUsingUninitializedVariable.Tests.ps1 @@ -0,0 +1,24 @@ +#Import-Module PSScriptAnalyzer +$AvoidUninitializedVariable = "PSAvoidUninitializedVariable" +$violationMessage = "Variable 'MyProgressPreference' is not initialized. Non-global variables must be initialized. To fix a violation of this rule, please initialize non-global variables." +$directory = Split-Path -Parent $MyInvocation.MyCommand.Path +$violations = Invoke-ScriptAnalyzer $directory\AvoidUsingUninitializedVariable.ps1 -IncludeRule $AvoidUninitializedVariable +$noViolations = Invoke-ScriptAnalyzer $directory\AvoidUsingUninitializedVariableNoViolations.ps1 -IncludeRule $AvoidUninitializedVariable + +Describe "AvoidUsingUninitializedVariable" { + Context "Script uses uninitialized variables - Violation" { + It "Have 3 rule violations" { + $violations.Count | Should Be 3 + } + + It "has the correct description message for UninitializedVariable rule violation" { + $violations[0].Message | Should Be $violationMessage + } + } + + Context "Script uses initialized variables - No violation" { + It "results in no rule violations" { + $noViolations.Count | Should Be 0 + } + } +} \ No newline at end of file diff --git a/Tests/Rules/AvoidUsingUninitializedVariable.ps1 b/Tests/Rules/AvoidUsingUninitializedVariable.ps1 new file mode 100644 index 000000000..980a01d70 --- /dev/null +++ b/Tests/Rules/AvoidUsingUninitializedVariable.ps1 @@ -0,0 +1,10 @@ +# Script has uninitialized variables +# Must result in AvoidUsingUninitializedVariablerule violations along with other violations + +function Test-MyPreference +{ + Write-Verbose $MyProgressPreference + Write-Verbose $MyVerbosePreference +} + +Write-Verbose $MyProgressPreference \ No newline at end of file diff --git a/Tests/Rules/AvoidUsingUninitializedVariableNoViolations.ps1 b/Tests/Rules/AvoidUsingUninitializedVariableNoViolations.ps1 new file mode 100644 index 000000000..046126997 --- /dev/null +++ b/Tests/Rules/AvoidUsingUninitializedVariableNoViolations.ps1 @@ -0,0 +1,11 @@ +# Script uses built-in preference variables +# Must not result in AvoidUsingUninitializedVariablerule violations +# However there are other violations in this script - Write-Verbose is not using positional parameters + +function Test-Preference +{ + Write-Verbose $ProgressPreference + Write-Verbose $VerbosePreference +} + +Write-Verbose $ProgressPreference \ No newline at end of file From 30f434b03269e71e881d359a40894ec0c4b1f570 Mon Sep 17 00:00:00 2001 From: Yuting Chen Date: Tue, 12 May 2015 12:05:06 -0700 Subject: [PATCH 27/50] Added binplace location --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 2736e4c26..ae004a34e 100644 --- a/.gitignore +++ b/.gitignore @@ -202,4 +202,7 @@ FakesAssemblies/ *.plg # Visual Studio 6 workspace options file -*.opt \ No newline at end of file +*.opt + +##Our project binplace location +PSScriptAnalyzer/ \ No newline at end of file From e52216e2fbcaf6928b1f6609b53905bd03f4613e Mon Sep 17 00:00:00 2001 From: Raghu Shantha Date: Tue, 12 May 2015 12:08:52 -0700 Subject: [PATCH 28/50] Forgot to import our module --- Tests/Rules/AvoidUsingUninitializedVariable.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Rules/AvoidUsingUninitializedVariable.Tests.ps1 b/Tests/Rules/AvoidUsingUninitializedVariable.Tests.ps1 index 11db9a196..3fb75b360 100644 --- a/Tests/Rules/AvoidUsingUninitializedVariable.Tests.ps1 +++ b/Tests/Rules/AvoidUsingUninitializedVariable.Tests.ps1 @@ -1,4 +1,4 @@ -#Import-Module PSScriptAnalyzer +Import-Module PSScriptAnalyzer $AvoidUninitializedVariable = "PSAvoidUninitializedVariable" $violationMessage = "Variable 'MyProgressPreference' is not initialized. Non-global variables must be initialized. To fix a violation of this rule, please initialize non-global variables." $directory = Split-Path -Parent $MyInvocation.MyCommand.Path From c8a53958e823dc33aa7322ef1ef80ec77607987e Mon Sep 17 00:00:00 2001 From: Yuting Chen Date: Tue, 12 May 2015 14:39:07 -0700 Subject: [PATCH 29/50] Fix severity ignore case bug --- Engine/Commands/GetScriptAnalyzerRuleCommand.cs | 2 +- Engine/Commands/InvokeScriptAnalyzerCommand.cs | 2 +- Tests/Engine/GetScriptAnalyzerRule.tests.ps1 | 11 ++++++++--- Tests/Engine/InvokeScriptAnalyzer.tests.ps1 | 5 +++++ 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Engine/Commands/GetScriptAnalyzerRuleCommand.cs b/Engine/Commands/GetScriptAnalyzerRuleCommand.cs index 33ec3f1a6..b749bc6e9 100644 --- a/Engine/Commands/GetScriptAnalyzerRuleCommand.cs +++ b/Engine/Commands/GetScriptAnalyzerRuleCommand.cs @@ -142,7 +142,7 @@ protected override void ProcessRecord() { if (severity != null) { - var ruleSeverity = severity.Select(item => Enum.Parse(typeof (RuleSeverity), item)); + var ruleSeverity = severity.Select(item => Enum.Parse(typeof (RuleSeverity), item, true)); rules = rules.Where(item => ruleSeverity.Contains(item.GetSeverity())).ToList(); } diff --git a/Engine/Commands/InvokeScriptAnalyzerCommand.cs b/Engine/Commands/InvokeScriptAnalyzerCommand.cs index cdfd7bd4e..5629cb48e 100644 --- a/Engine/Commands/InvokeScriptAnalyzerCommand.cs +++ b/Engine/Commands/InvokeScriptAnalyzerCommand.cs @@ -601,7 +601,7 @@ private void AnalyzeFile(string filePath) if (severity != null) { - var diagSeverity = severity.Select(item => Enum.Parse(typeof(DiagnosticSeverity), item)); + var diagSeverity = severity.Select(item => Enum.Parse(typeof(DiagnosticSeverity), item, true)); diagnostics = diagnostics.Where(item => diagSeverity.Contains(item.Severity)).ToList(); } diff --git a/Tests/Engine/GetScriptAnalyzerRule.tests.ps1 b/Tests/Engine/GetScriptAnalyzerRule.tests.ps1 index 46f4ad5e9..8aed2010d 100644 --- a/Tests/Engine/GetScriptAnalyzerRule.tests.ps1 +++ b/Tests/Engine/GetScriptAnalyzerRule.tests.ps1 @@ -113,12 +113,17 @@ Describe "Test RuleExtension" { Describe "TestSeverity" { It "filters rules based on the specified rule severity" { $rules = Get-ScriptAnalyzerRule -Severity Error - $rules.Count | Should be 4 + $rules.Count | Should be 6 } It "filters rules based on multiple severity inputs"{ $rules = Get-ScriptAnalyzerRule -Severity Error,Information - $rules.Count | Should be 8 + $rules.Count | Should be 9 + } + + It "takes lower case inputs" { + $rules = Get-ScriptAnalyzerRule -Severity error + $rules.Count | Should be 6 } } @@ -130,6 +135,6 @@ Describe "TestWildCard" { It "filters rules based on wild card input and severity"{ $rules = Get-ScriptAnalyzerRule -Name PSDSC* -Severity Information - $rules.Count | Should be 2 + $rules.Count | Should be 1 } } \ No newline at end of file diff --git a/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 b/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 index 9cc6ccdbd..d32ce54fe 100644 --- a/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 +++ b/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 @@ -169,6 +169,11 @@ Describe "Test Severity" { $errors = Invoke-ScriptAnalyzer $directory\TestScript.ps1 -Severity Information, Warning $errors.Count | Should Be 2 } + + It "works with lowercase argument"{ + $errors = Invoke-ScriptAnalyzer $directory\TestScript.ps1 -Severity information, warning + $errors.Count | Should Be 2 + } } Context "When used incorrectly" { From 818108a968d89fd3f127a2920f7136f2d1679411 Mon Sep 17 00:00:00 2001 From: "Raghu Shantha [MSFT]" Date: Tue, 12 May 2015 16:26:54 -0700 Subject: [PATCH 30/50] Suppress warnings emitted during the execution of Test-ModuleManifest --- Rules/MissingModuleManifestField.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Rules/MissingModuleManifestField.cs b/Rules/MissingModuleManifestField.cs index 8caa7e3ff..012c18069 100644 --- a/Rules/MissingModuleManifestField.cs +++ b/Rules/MissingModuleManifestField.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Management.Automation.Language; using System.Management.Automation; using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic; @@ -44,6 +45,10 @@ public IEnumerable AnalyzeScript(Ast ast, string fileName) { ps.AddCommand("Test-ModuleManifest"); ps.AddParameter("Path", fileName); + + // Suppress warnings emitted during the execution of Test-ModuleManifest + // ModuleManifest rule must catch any violations (warnings/errors) and generate DiagnosticRecord(s) + ps.AddParameter("WarningAction", ActionPreference.SilentlyContinue); ps.Invoke(); } catch { } From 231ba91d30f4cc6641edb057f4eb5749fd7f91ec Mon Sep 17 00:00:00 2001 From: KarolKaczmarek Date: Wed, 13 May 2015 13:14:27 -0700 Subject: [PATCH 31/50] Update PowerShellBestPractices.md --- PowerShellBestPractices.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/PowerShellBestPractices.md b/PowerShellBestPractices.md index b6fa559ce..996e95fae 100644 --- a/PowerShellBestPractices.md +++ b/PowerShellBestPractices.md @@ -121,13 +121,15 @@ The following guidelines come from a combined effort from both the PowerShell te ###Severity: TBD - For PowerShell V4: Resource module contains .psd1 file and schema.mof for every resource - MOF has description for each element [IssueOpened](https://github.com/PowerShell/PSScriptAnalyzer/issues/131) - - Resource module must alwasy contain .psd1 file and schema.mof (for non-class resource). + - Resource module must contain .psd1 file (always) and schema.mof (for non-class resource). [IssueOpened](https://github.com/PowerShell/PSScriptAnalyzer/issues/116) - Use ShouldProcess for a Set DSC method - - Resource module contains Resources folder which contains the resources [IssueOpened](https://github.com/PowerShell/PSScriptAnalyzer/issues/130) + - Resource module contains DscResources folder which contains the resources [IssueOpened](https://github.com/PowerShell/PSScriptAnalyzer/issues/130) ###Reference: -Cmdlet Development Guidelines from MSDN site (Cmdlet Development Guidelines) +* Cmdlet Development Guidelines from MSDN site (Cmdlet Development Guidelines) -The Community Book of PowerShell Practices (Compiled by Don Jones and Matt Penny and the Windows PowerShell Community) +* The Community Book of PowerShell Practices (Compiled by Don Jones and Matt Penny and the Windows PowerShell Community) + +* [PowerShell DSC Resource Design and Testing Checklist](http://blogs.msdn.com/b/powershell/archive/2014/11/18/powershell-dsc-resource-design-and-testing-checklist.aspx) From c05bcf2248c9fcf60c02c2141f46ae2c8581047a Mon Sep 17 00:00:00 2001 From: Yuting Chen Date: Wed, 13 May 2015 17:37:04 -0700 Subject: [PATCH 32/50] Change the check to !isSingular() to avoid confusions --- Rules/UseSingularNouns.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rules/UseSingularNouns.cs b/Rules/UseSingularNouns.cs index d71cce214..503e7162b 100644 --- a/Rules/UseSingularNouns.cs +++ b/Rules/UseSingularNouns.cs @@ -49,7 +49,7 @@ public IEnumerable AnalyzeScript(Ast ast, string fileName) { String noun = funcNamePieces[1]; var ps = System.Data.Entity.Design.PluralizationServices.PluralizationService.CreateService(CultureInfo.GetCultureInfo("en-us")); - if (ps.IsPlural(noun)) + if (!ps.IsSingular(noun)) { yield return new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.UseSingularNounsError, funcAst.Name), funcAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName); From 2cca80ce6c18c07eeec25f7bb0e3a0f597de8c37 Mon Sep 17 00:00:00 2001 From: GoodOlClint Date: Wed, 13 May 2015 22:51:31 -0500 Subject: [PATCH 33/50] Added failing test for issue #158 --- Tests/Rules/AvoidDefaultTrueValueSwitchParameter.ps1 | 6 +++++- Tests/Rules/AvoidDefaultTrueValueSwitchParameter.tests.ps1 | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Tests/Rules/AvoidDefaultTrueValueSwitchParameter.ps1 b/Tests/Rules/AvoidDefaultTrueValueSwitchParameter.ps1 index 49881156c..a9190ed48 100644 --- a/Tests/Rules/AvoidDefaultTrueValueSwitchParameter.ps1 +++ b/Tests/Rules/AvoidDefaultTrueValueSwitchParameter.ps1 @@ -13,7 +13,11 @@ # Param2 help description [switch] - $switch=$true + $switch=$true, + + # Param3 help description + [System.Management.Automation.SwitchParameter] + $switch2 = $true ) Begin diff --git a/Tests/Rules/AvoidDefaultTrueValueSwitchParameter.tests.ps1 b/Tests/Rules/AvoidDefaultTrueValueSwitchParameter.tests.ps1 index 469dc6a66..a3fda1d5d 100644 --- a/Tests/Rules/AvoidDefaultTrueValueSwitchParameter.tests.ps1 +++ b/Tests/Rules/AvoidDefaultTrueValueSwitchParameter.tests.ps1 @@ -7,8 +7,8 @@ $noViolations = Invoke-ScriptAnalyzer $directory\AvoidDefaultTrueValueSwitchPara Describe "AvoidDefaultTrueValueSwitchParameter" { Context "When there are violations" { - It "has 1 avoid using switch parameter default to true violation" { - $violations.Count | Should Be 1 + It "has 2 avoid using switch parameter default to true violation" { + $violations.Count | Should Be 2 } It "has the correct description message" { From 19d2c93daca5b7c2d9a05d86b2eeb8042980a009 Mon Sep 17 00:00:00 2001 From: GoodOlClint Date: Wed, 13 May 2015 23:07:12 -0500 Subject: [PATCH 34/50] Correct PSAvoidDefaultTrueValueSwitchParameter rule to work with both [switch] and [System.Management.Automation.SwitchParameter] attributes --- Rules/AvoidDefaultTrueValueSwitchParameter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rules/AvoidDefaultTrueValueSwitchParameter.cs b/Rules/AvoidDefaultTrueValueSwitchParameter.cs index de4a44637..3f12c7e81 100644 --- a/Rules/AvoidDefaultTrueValueSwitchParameter.cs +++ b/Rules/AvoidDefaultTrueValueSwitchParameter.cs @@ -39,7 +39,7 @@ public IEnumerable AnalyzeScript(Ast ast, string fileName) // Iterrates all ParamAsts and check if any are switch. foreach (ParameterAst paramAst in paramAsts) { - if (paramAst.Attributes.Any(attr => String.Equals(attr.TypeName.FullName, "switch", StringComparison.OrdinalIgnoreCase)) + if (paramAst.Attributes.Any(attr => attr.TypeName.FullName.ToLower().Contains("switch")) && paramAst.DefaultValue != null && String.Equals(paramAst.DefaultValue.Extent.Text, "$true", StringComparison.OrdinalIgnoreCase)) { yield return new DiagnosticRecord( From 5f72980055e42b69cbe3290f84c7c4e001872c2c Mon Sep 17 00:00:00 2001 From: GoodOlClint Date: Wed, 13 May 2015 23:25:01 -0500 Subject: [PATCH 35/50] Add failing test for #157 --- Tests/Rules/GoodCmdlet.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/Rules/GoodCmdlet.ps1 b/Tests/Rules/GoodCmdlet.ps1 index b10b830a4..24106a3f5 100644 --- a/Tests/Rules/GoodCmdlet.ps1 +++ b/Tests/Rules/GoodCmdlet.ps1 @@ -91,6 +91,7 @@ function Get-File { if ($pscmdlet.ShouldContinue("Yes", "No")) { } + [System.Void] $Param3 } } From 76822d924d19cb4c4e759914ae599261856ffbc3 Mon Sep 17 00:00:00 2001 From: GoodOlClint Date: Wed, 13 May 2015 23:30:29 -0500 Subject: [PATCH 36/50] Suppress PSUseOutputTypeCorrectly warning when function outputs System.Void --- Rules/UseOutputTypeCorrectly.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Rules/UseOutputTypeCorrectly.cs b/Rules/UseOutputTypeCorrectly.cs index f79ccea15..5d04de225 100644 --- a/Rules/UseOutputTypeCorrectly.cs +++ b/Rules/UseOutputTypeCorrectly.cs @@ -110,6 +110,7 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun || String.Equals(typeof(Unreached).FullName, typeName, StringComparison.OrdinalIgnoreCase) || String.Equals(typeof(Undetermined).FullName, typeName, StringComparison.OrdinalIgnoreCase) || String.Equals(typeof(object).FullName, typeName, StringComparison.OrdinalIgnoreCase) + || String.Equals(typeof(void).FullName, typeName, StringComparison.OrdinalIgnoreCase) || outputTypes.Contains(typeName, StringComparer.OrdinalIgnoreCase)) { continue; From 42a8f45daddc3eb59bcc558eb4a1f1ad9aeb45e0 Mon Sep 17 00:00:00 2001 From: GoodOlClint Date: Thu, 14 May 2015 00:16:42 -0500 Subject: [PATCH 37/50] More robust method of detecting SwitchParameter types --- Rules/AvoidDefaultTrueValueSwitchParameter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rules/AvoidDefaultTrueValueSwitchParameter.cs b/Rules/AvoidDefaultTrueValueSwitchParameter.cs index 3f12c7e81..2572a1fb9 100644 --- a/Rules/AvoidDefaultTrueValueSwitchParameter.cs +++ b/Rules/AvoidDefaultTrueValueSwitchParameter.cs @@ -39,7 +39,7 @@ public IEnumerable AnalyzeScript(Ast ast, string fileName) // Iterrates all ParamAsts and check if any are switch. foreach (ParameterAst paramAst in paramAsts) { - if (paramAst.Attributes.Any(attr => attr.TypeName.FullName.ToLower().Contains("switch")) + if (paramAst.Attributes.Any(attr => string.Equals(attr.TypeName.GetReflectionType().FullName, "system.management.automation.switchparameter", StringComparison.OrdinalIgnoreCase)) && paramAst.DefaultValue != null && String.Equals(paramAst.DefaultValue.Extent.Text, "$true", StringComparison.OrdinalIgnoreCase)) { yield return new DiagnosticRecord( From 71efc2b8334b6e2525ae796684555ff789c3624a Mon Sep 17 00:00:00 2001 From: Yuting Chen Date: Thu, 14 May 2015 11:33:31 -0700 Subject: [PATCH 38/50] Fix the uninitialized variable throw warning at preference variable --- Engine/VariableAnalysis.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Engine/VariableAnalysis.cs b/Engine/VariableAnalysis.cs index 352ab40ef..5445df4bc 100644 --- a/Engine/VariableAnalysis.cs +++ b/Engine/VariableAnalysis.cs @@ -339,7 +339,8 @@ public bool IsUninitialized(VariableExpressionAst varTarget) } return analysis.DefinedBlock == null - && !SpecialVars.InitializedVariables.Contains(analysis.Name, StringComparer.OrdinalIgnoreCase) + && !(SpecialVars.InitializedVariables.Contains(analysis.Name, StringComparer.OrdinalIgnoreCase) || + SpecialVars.InitializedVariables.Contains(analysis.RealName, StringComparer.OrdinalIgnoreCase)) && !IsGlobalOrEnvironment(varTarget); } From 93aaa59b24e0040604f490e9e896d6f560a11490 Mon Sep 17 00:00:00 2001 From: Yuting Chen Date: Thu, 14 May 2015 11:47:00 -0700 Subject: [PATCH 39/50] Add test changes --- ...oidGlobalOrUnitializedVarsNoViolations.ps1 | 71 +++++++++++-------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/Tests/Rules/AvoidGlobalOrUnitializedVarsNoViolations.ps1 b/Tests/Rules/AvoidGlobalOrUnitializedVarsNoViolations.ps1 index b5206cd68..432dd1a91 100644 --- a/Tests/Rules/AvoidGlobalOrUnitializedVarsNoViolations.ps1 +++ b/Tests/Rules/AvoidGlobalOrUnitializedVarsNoViolations.ps1 @@ -1,30 +1,41 @@ -function Test { - $initialized = "Initialized" - $noglobal = "local" - $env:ShouldNotRaiseError -} - -$a = 3; - -if ($true) { - $a = 4; - $c = 3; -} else { - $b = 5; - $c = 4; -} - -$b = 6; -$a; -$b; - -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 -$proc[0] \ No newline at end of file +function Test { + $initialized = "Initialized" + $noglobal = "local" + $env:ShouldNotRaiseError +} + +$a = 3; + +if ($true) { + $a = 4; + $c = 3; +} else { + $b = 5; + $c = 4; +} + +$b = 6; +$a; +$b; + +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 +$proc[0] + +function Test-PreferenceVariable +{ + + if (-not $PSBoundParameters.ContainsKey('Verbose')) { + $VerbosePreference = $PSCmdlet.GetVariableValue('VerbosePreference') -as + [System.Management.Automation.ActionPreference] + } + + $VerbosePreference + } \ No newline at end of file From a74b7c4aaa6d2a7893e51179e73a65992299972f Mon Sep 17 00:00:00 2001 From: "Raghu Shantha [MSFT]" Date: Thu, 14 May 2015 13:47:42 -0700 Subject: [PATCH 40/50] Create appveyor.yml --- appveyor.yml | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 000000000..9617f85b4 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,47 @@ +# WS2012R2 image with April WMF5.0 +os: unstable + +# Install Pester +install: + - cinst -y pester + +# Build PSScriptAnalyzer using msbuild +build: true + +# branches to build +branches: + # whitelist + only: + - master + - bugfixes + - development + +# Run Pester tests and store the results +test_script: + - SET PATH=c:\Program Files\WindowsPowerShell\Modules\;%PATH%; + - ps: | + copy "C:\projects\psscriptanalyzer\PSScriptAnalyzer" "$Env:ProgramFiles\WindowsPowerShell\Modules\" -Recurse -Force + $engineTestResultsFile = ".\EngineTestResults.xml" + $ruleTestResultsFile = ".\RuleTestResults.xml" + $engineTestResults = Invoke-Pester -Script "C:\projects\psscriptanalyzer\Tests\Engine" -OutputFormat NUnitXml -OutputFile $engineTestResultsFile -PassThru + (New-Object 'System.Net.WebClient').UploadFile("https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path $engineTestResultsFile)) + if ($engineTestResults.FailedCount -gt 0) { + throw "$($engineTestResults.FailedCount) tests failed." + } + $ruleTestResults = Invoke-Pester -Script "C:\projects\psscriptanalyzer\Tests\Rules" -OutputFormat NUnitXml -OutputFile $ruleTestResultsFile -PassThru + (New-Object 'System.Net.WebClient').UploadFile("https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path $ruleTestResultsFile)) + if ($ruleTestResults.FailedCount -gt 0) { + throw "$($ruleTestResults.FailedCount) tests failed." + } + +# Upload the project along with TestResults as a zip archive +on_finish: + - ps: | + $stagingDirectory = (Resolve-Path ..).Path + $zipFile = Join-Path $stagingDirectory "$(Split-Path $pwd -Leaf).zip" + Add-Type -assemblyname System.IO.Compression.FileSystem + [System.IO.Compression.ZipFile]::CreateFromDirectory($pwd, $zipFile) + @( + # You can add other artifacts here + (ls $zipFile) + ) | % { Push-AppveyorArtifact $_.FullName } From 400fd78543e64ad2daa53b9d8489de6070a5eb8b Mon Sep 17 00:00:00 2001 From: "Raghu Shantha [MSFT]" Date: Thu, 14 May 2015 13:56:21 -0700 Subject: [PATCH 41/50] Update README.md --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 1708364fc..69376225a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,12 @@ +Build Status +------------ + +| |Master Branch | +|---------|:------:|:------:|:-------:|:-------:| +|**Debug Version**|[![Build status](https://ci.appveyor.com/api/projects/status/6anth3x81y6bd5dr/branch/master?svg=true)](https://ci.appveyor.com/project/raghushantha/psscriptanalyzer-pfrhl/branch/master) | + + Introduction ============ From 8a6e030c77e7d9c593056b6b1cdc8e4e83b0d7bd Mon Sep 17 00:00:00 2001 From: "Raghu Shantha [MSFT]" Date: Thu, 14 May 2015 13:57:50 -0700 Subject: [PATCH 42/50] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 69376225a..16bf11b62 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Build Status | |Master Branch | |---------|:------:|:------:|:-------:|:-------:| -|**Debug Version**|[![Build status](https://ci.appveyor.com/api/projects/status/6anth3x81y6bd5dr/branch/master?svg=true)](https://ci.appveyor.com/project/raghushantha/psscriptanalyzer-pfrhl/branch/master) | +|**Debug Version**|[![Build status](https://ci.appveyor.com/api/projects/status/6anth3x81y6bd5dr/branch/master?svg=true)](https://ci.appveyor.com/project/powershell/psscriptanalyzer-pfrhl/branch/master) | Introduction From 2260344d30e6a4f54cf44a94f42c41c8a05f5366 Mon Sep 17 00:00:00 2001 From: "Raghu Shantha [MSFT]" Date: Thu, 14 May 2015 14:06:04 -0700 Subject: [PATCH 43/50] Update appveyor.yml --- appveyor.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 9617f85b4..28eb6cfa6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,9 @@ # WS2012R2 image with April WMF5.0 os: unstable +# clone directory +clone_folder: c:\projects\psscriptanalyzer + # Install Pester install: - cinst -y pester From 25446780925e13ce2c8e552fc70dc0fb9471ddb9 Mon Sep 17 00:00:00 2001 From: Yuting Chen Date: Thu, 14 May 2015 14:08:37 -0700 Subject: [PATCH 44/50] modify tests --- Tests/Engine/GetScriptAnalyzerRule.tests.ps1 | 6 +++--- Tests/Engine/InvokeScriptAnalyzer.tests.ps1 | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Tests/Engine/GetScriptAnalyzerRule.tests.ps1 b/Tests/Engine/GetScriptAnalyzerRule.tests.ps1 index 8aed2010d..e299b45e2 100644 --- a/Tests/Engine/GetScriptAnalyzerRule.tests.ps1 +++ b/Tests/Engine/GetScriptAnalyzerRule.tests.ps1 @@ -118,7 +118,7 @@ Describe "TestSeverity" { It "filters rules based on multiple severity inputs"{ $rules = Get-ScriptAnalyzerRule -Severity Error,Information - $rules.Count | Should be 9 + $rules.Count | Should be 12 } It "takes lower case inputs" { @@ -130,11 +130,11 @@ Describe "TestSeverity" { Describe "TestWildCard" { It "filters rules based on the -Name wild card input" { $rules = Get-ScriptAnalyzerRule -Name PSDSC* - $rules.Count | Should be 4 + $rules.Count | Should be 6 } It "filters rules based on wild card input and severity"{ $rules = Get-ScriptAnalyzerRule -Name PSDSC* -Severity Information - $rules.Count | Should be 1 + $rules.Count | Should be 3 } } \ No newline at end of file diff --git a/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 b/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 index d32ce54fe..f5303a2f4 100644 --- a/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 +++ b/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 @@ -141,7 +141,7 @@ Describe "Test IncludeRule" { it "includes 2 wildcardrules" { $includeWildcard = Invoke-ScriptAnalyzer $directory\..\Rules\BadCmdlet.ps1 -IncludeRule $avoidRules, $useRules - $includeWildcard.Count | Should be 7 + $includeWildcard.Count | Should be 9 } } } From b83765edd1267dce662bcbf5c92766cdfc36a3e7 Mon Sep 17 00:00:00 2001 From: "Raghu Shantha [MSFT]" Date: Thu, 14 May 2015 14:17:13 -0700 Subject: [PATCH 45/50] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 16bf11b62..41a828dc7 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Build Status | |Master Branch | |---------|:------:|:------:|:-------:|:-------:| -|**Debug Version**|[![Build status](https://ci.appveyor.com/api/projects/status/6anth3x81y6bd5dr/branch/master?svg=true)](https://ci.appveyor.com/project/powershell/psscriptanalyzer-pfrhl/branch/master) | +|**Debug Version**|[![Build status](https://ci.appveyor.com/api/projects/status/6anth3x81y6bd5dr/branch/master?svg=true)](https://ci.appveyor.com/project/powershell/psscriptanalyzer/branch/master) | Introduction From 0a6fef29f45354cfe80a67ca652183a2d474af18 Mon Sep 17 00:00:00 2001 From: "Raghu Shantha [MSFT]" Date: Thu, 14 May 2015 15:04:16 -0700 Subject: [PATCH 46/50] Update README.md --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 41a828dc7..c12d79e11 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,4 @@ -Build Status ------------- - -| |Master Branch | -|---------|:------:|:------:|:-------:|:-------:| -|**Debug Version**|[![Build status](https://ci.appveyor.com/api/projects/status/6anth3x81y6bd5dr/branch/master?svg=true)](https://ci.appveyor.com/project/powershell/psscriptanalyzer/branch/master) | - - Introduction ============ @@ -78,6 +70,14 @@ Throughput Graph [![Throughput Graph](https://graphs.waffle.io/powershell/psscriptanalyzer/throughput.svg)](https://waffle.io/powershell/psscriptanalyzer/metrics) +Build Status +------------ + +| |Master Branch | +|---------|:------:|:------:|:-------:|:-------:| +|**Debug Version**|[![Build status](https://ci.appveyor.com/api/projects/status/6anth3x81y6bd5dr/branch/master?svg=true)](https://ci.appveyor.com/project/powershell/psscriptanalyzer/branch/master) | + + Contributing to ScriptAnalyzer ============================== From c347cb7e45b6762515d1da7fd94d523e1bcfd37b Mon Sep 17 00:00:00 2001 From: "Raghu Shantha [MSFT]" Date: Thu, 14 May 2015 15:18:18 -0700 Subject: [PATCH 47/50] Update README.md --- README.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index c12d79e11..5acabe8bc 100644 --- a/README.md +++ b/README.md @@ -37,10 +37,19 @@ To confirm installation: run ```Get-ScriptAnalyzerRule``` in the PowerShell cons Building the Code ================= -Use Visual Studio to build "ScriptAnalyzer.sln". Use ~/PSScriptAnalyzer/ folder to load PSScriptAnalyzer.psd1 +Use Visual Studio to build "PSScriptAnalyzer.sln". Use ~/PSScriptAnalyzer/ folder to load PSScriptAnalyzer.psd1 **Note: If there are any build errors, please refer to Requirements section and make sure all dependencies are properly installed** + +Build Status +============== + +| |Master Branch | +|---------|:------:|:------:|:-------:|:-------:| +|**Debug Version**|[![Build status](https://ci.appveyor.com/api/projects/status/h5mot3vqtvxw5d7l?svg=true)](https://ci.appveyor.com/project/PowerShell/psscriptanalyzer) | + + Running Tests ============= @@ -70,13 +79,6 @@ Throughput Graph [![Throughput Graph](https://graphs.waffle.io/powershell/psscriptanalyzer/throughput.svg)](https://waffle.io/powershell/psscriptanalyzer/metrics) -Build Status ------------- - -| |Master Branch | -|---------|:------:|:------:|:-------:|:-------:| -|**Debug Version**|[![Build status](https://ci.appveyor.com/api/projects/status/6anth3x81y6bd5dr/branch/master?svg=true)](https://ci.appveyor.com/project/powershell/psscriptanalyzer/branch/master) | - Contributing to ScriptAnalyzer ============================== From 478206d25d20f71ef7bb20c82dd18f8ad48d05b1 Mon Sep 17 00:00:00 2001 From: "Raghu Shantha [MSFT]" Date: Thu, 14 May 2015 15:44:44 -0700 Subject: [PATCH 48/50] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5acabe8bc..25d4aea1a 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ Build Status | |Master Branch | |---------|:------:|:------:|:-------:|:-------:| -|**Debug Version**|[![Build status](https://ci.appveyor.com/api/projects/status/h5mot3vqtvxw5d7l?svg=true)](https://ci.appveyor.com/project/PowerShell/psscriptanalyzer) | +|**Debug Version**|[![Build status](https://ci.appveyor.com/api/projects/status/h5mot3vqtvxw5d7l/branch/master?svg=true)](https://ci.appveyor.com/project/PowerShell/psscriptanalyzer/branch/master) | Running Tests From 23e70aafafc60c3297e5db2aa2aba7611818871a Mon Sep 17 00:00:00 2001 From: "Raghu Shantha [MSFT]" Date: Fri, 15 May 2015 11:12:32 -0700 Subject: [PATCH 49/50] Fixed crash in Script Rule discovery logic --- Engine/ScriptAnalyzer.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Engine/ScriptAnalyzer.cs b/Engine/ScriptAnalyzer.cs index de3e0c23e..715575a6e 100644 --- a/Engine/ScriptAnalyzer.cs +++ b/Engine/ScriptAnalyzer.cs @@ -231,6 +231,12 @@ public List GetExternalRule(string[] moduleNames) string script = string.Format(CultureInfo.CurrentCulture, "Get-Module -Name '{0}' -ListAvailable", moduleName); shortModuleName = posh.AddScript(script).Invoke().First().Name; + // Invokes Update-Help for this module + // Required since when invoking Get-Help later on, the cmdlet prompts for Update-Help interactively + // By invoking Update-Help first, Get-Help will not prompt for downloading help later + script = string.Format(CultureInfo.CurrentCulture, "Update-Help -Module '{0}' -Force", shortModuleName); + posh.AddScript(script).Invoke(); + // Invokes Get-Command and Get-Help for each functions in the module. script = string.Format(CultureInfo.CurrentCulture, "Get-Command -Module '{0}'", shortModuleName); var psobjects = posh.AddScript(script).Invoke(); From 75996058e11c8d3c5c79e98ae8ae233120fc08ad Mon Sep 17 00:00:00 2001 From: "Raghu Shantha [MSFT]" Date: Fri, 15 May 2015 12:09:11 -0700 Subject: [PATCH 50/50] Added test for ScriptRule parsing crash bugfix --- Tests/Engine/CustomizedRule.tests.ps1 | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Tests/Engine/CustomizedRule.tests.ps1 b/Tests/Engine/CustomizedRule.tests.ps1 index 2c5777bfd..f7fac7213 100644 --- a/Tests/Engine/CustomizedRule.tests.ps1 +++ b/Tests/Engine/CustomizedRule.tests.ps1 @@ -22,6 +22,27 @@ Describe "Test importing customized rules with null return results" { } Describe "Test importing correct customized rules" { + + Context "Test Get-Help functionality in ScriptRule parsing logic" { + It "ScriptRule help section must be correctly processed when Get-Help is called for the first time" { + + # Force Get-Help to prompt for interactive input to download help using Update-Help + # By removing this registry key we force to turn on Get-Help interactivity logic during ScriptRule parsing + $null,"Wow6432Node" | ForEach-Object { + try + { + Remove-ItemProperty -Name "DisablePromptToUpdateHelp" -Path "HKLM:\SOFTWARE\$($_)\Microsoft\PowerShell" -ErrorAction Stop + } catch { + #Ignore for cases when tests are running in non-elevated more or registry key does not exist or not accessible + } + } + + $customizedRulePath = Invoke-ScriptAnalyzer $directory\TestScript.ps1 -CustomizedRulePath $directory\samplerule\samplerule.psm1 | Where-Object {$_.Message -eq $message} + $customizedRulePath.Count | Should Be 1 + } + + } + Context "Test Get-ScriptAnalyzer with customized rules" { It "will show the customized rule" { $customizedRulePath = Get-ScriptAnalyzerRule -CustomizedRulePath $directory\samplerule\samplerule.psm1 | Where-Object {$_.RuleName -eq $measure}