Skip to content

Avoid using wmi cmdlet rule #98

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 5, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,19 @@
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
{
/// <summary>
/// AvoidUsingWMIObjectCmdlet: Verify that Get-WMIObject, Remove-WMIObject are not used
/// AvoidUsingWMICmdlet: Avoid Using Get-WMIObject, Remove-WMIObject, Invoke-WmiMethod, Register-WmiEvent, Set-WmiInstance
/// </summary>
[Export(typeof(IScriptRule))]
public class AvoidUsingWMIObjectCmdlet : IScriptRule
public class AvoidUsingWMICmdlet : IScriptRule
{
/// <summary>
/// AnalyzeScript: Verify that Get-WMIObject, Remove-WMIObject are not used
/// AnalyzeScript: Avoid Using Get-WMIObject, Remove-WMIObject, Invoke-WmiMethod, Register-WmiEvent, Set-WmiInstance
/// </summary>
public IEnumerable<DiagnosticRecord> 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
// Rule is applicable only when PowerShell Version is < 3.0, since CIM cmdlet was introduced in 3.0
int majorPSVersion = GetPSMajorVersion(ast);
if (!(3 > majorPSVersion && 0 < majorPSVersion))
{
Expand All @@ -50,9 +50,15 @@ public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
// 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)))
if (cmdAst.GetCommandName() != null &&
(String.Equals(cmdAst.GetCommandName(), "get-wmiobject", StringComparison.OrdinalIgnoreCase)
|| String.Equals(cmdAst.GetCommandName(), "remove-wmiobject", StringComparison.OrdinalIgnoreCase)
|| String.Equals(cmdAst.GetCommandName(), "invoke-wmimethod", StringComparison.OrdinalIgnoreCase)
|| String.Equals(cmdAst.GetCommandName(), "register-wmievent", StringComparison.OrdinalIgnoreCase)
|| String.Equals(cmdAst.GetCommandName(), "set-wmiinstance", StringComparison.OrdinalIgnoreCase))
)
{
yield return new DiagnosticRecord(String.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingWMIObjectCmdletError, System.IO.Path.GetFileName(fileName)),
yield return new DiagnosticRecord(String.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingWMICmdletError, System.IO.Path.GetFileName(fileName)),
cmdAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName);
}
}
Expand Down Expand Up @@ -87,7 +93,7 @@ private int GetPSMajorVersion(Ast ast)
/// <returns>The name of this rule</returns>
public string GetName()
{
return string.Format(CultureInfo.CurrentCulture, Strings.NameSpaceFormat, GetSourceName(), Strings.AvoidUsingWMIObjectCmdletName);
return string.Format(CultureInfo.CurrentCulture, Strings.NameSpaceFormat, GetSourceName(), Strings.AvoidUsingWMICmdletName);
}

/// <summary>
Expand All @@ -96,7 +102,7 @@ public string GetName()
/// <returns>The common name of this rule</returns>
public string GetCommonName()
{
return string.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingWMIObjectCmdletCommonName);
return string.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingWMICmdletCommonName);
}

/// <summary>
Expand All @@ -105,7 +111,7 @@ public string GetCommonName()
/// <returns>The description of this rule</returns>
public string GetDescription()
{
return string.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingWMIObjectCmdletDescription);
return string.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingWMICmdletDescription);
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion Rules/ScriptAnalyzerBuiltinRules.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
<Compile Include="AvoidUsingInternalURLs.cs" />
<Compile Include="AvoidUsingInvokeExpression.cs" />
<Compile Include="AvoidUsingPlainTextForPassword.cs" />
<Compile Include="AvoidUsingWMIObjectCmdlet.cs" />
<Compile Include="AvoidUsingWMICmdlet.cs" />
<Compile Include="AvoidUsingWriteHost.cs" />
<Compile Include="MissingModuleManifestField.cs" />
<Compile Include="PossibleIncorrectComparisonWithNull.cs" />
Expand Down
16 changes: 8 additions & 8 deletions Rules/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -666,16 +666,16 @@
<data name="UseShouldProcessForStateChangingFunctionsName" xml:space="preserve">
<value>UseShouldProcessForStateChangingFunctions</value>
</data>
<data name="AvoidUsingWMIObjectCmdletCommonName" xml:space="preserve">
<value>Avoid Using Get-WMIObject, Remove-WMIObject</value>
<data name="AvoidUsingWMICmdletCommonName" xml:space="preserve">
<value>Avoid Using Get-WMIObject, Remove-WMIObject, Invoke-WmiMethod, Register-WmiEvent, Set-WmiInstance</value>
</data>
<data name="AvoidUsingWMIObjectCmdletDescription" xml:space="preserve">
<value>Depricated. Starting in Windows PowerShell 3.0, these cmdlets have been superseded by CimInstance cmdlets.</value>
<data name="AvoidUsingWMICmdletDescription" xml:space="preserve">
<value>Depricated. Starting in Windows PowerShell 3.0, these cmdlets have been superseded by CIM cmdlets.</value>
</data>
<data name="AvoidUsingWMIObjectCmdletError" xml:space="preserve">
<value>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.</value>
<data name="AvoidUsingWMICmdletError" xml:space="preserve">
<value>File '{0}' uses WMI cmdlet. For PowerShell 3.0 and above, use CIM cmdlet which perform the same tasks as the WMI cmdlets. The CIM cmdlets comply with WS-Management (WSMan) standards and with the Common Information Model (CIM) standard, which enables the cmdlets to use the same techniques to manage Windows computers and those running other operating systems.</value>
</data>
<data name="AvoidUsingWMIObjectCmdletName" xml:space="preserve">
<value>AvoidUsingWMIObjectCmdlet</value>
<data name="AvoidUsingWMICmdletName" xml:space="preserve">
<value>AvoidUsingWMICmdlet</value>
</data>
</root>
18 changes: 18 additions & 0 deletions Tests/Rules/AvoidUsingWMICmdlet.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#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

Invoke-WMIMethod -Path Win32_Process -Name Create -ArgumentList notepad.exe

Register-WMIEvent -Class Win32_ProcessStartTrace -SourceIdentifier "ProcessStarted"

Set-WMIInstance -Class Win32_Environment -Argument @{Name='MyEnvVar';VariableValue='VarValue';UserName='<SYSTEM>'}
}

TestFunction

Remove-WmiObject -Class Win32_OperatingSystem -Verbose
24 changes: 24 additions & 0 deletions Tests/Rules/AvoidUsingWMICmdlet.tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Import-Module PSScriptAnalyzer
$WMIRuleName = "PSAvoidUsingWMICmdlet"
$violationMessage = "File 'AvoidUsingWMICmdlet.ps1' uses WMI cmdlet. For PowerShell 3.0 and above, use CIM cmdlet which perform the same tasks as the WMI cmdlets. The CIM cmdlets comply with WS-Management (WSMan) standards and with the Common Information Model (CIM) standard, which enables the cmdlets to use the same techniques to manage Windows computers and those running other operating systems."
$directory = Split-Path -Parent $MyInvocation.MyCommand.Path
$violations = Invoke-ScriptAnalyzer $directory\AvoidUsingWMICmdlet.ps1 -IncludeRule $WMIRuleName
$noViolations = Invoke-ScriptAnalyzer $directory\AvoidUsingWMICmdletNoViolations.ps1 -IncludeRule $WMIRuleName

Describe "AvoidUsingWMICmdlet" {
Context "Script contains references to WMI cmdlets - Violation" {
It "Have 5 WMI cmdlet Violations" {
$violations.Count | Should Be 5
}

It "has the correct description message for WMI rule violation" {
$violations[0].Message | Should Be $violationMessage
}
}

Context "Script contains no calls to WMI cmdlet - No violation" {
It "results in no rule violations" {
$noViolations.Count | Should Be 0
}
}
}
19 changes: 19 additions & 0 deletions Tests/Rules/AvoidUsingWMICmdletNoViolations.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# 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

Invoke-WMIMethod -Path Win32_Process -Name Create -ArgumentList notepad.exe

function TestFunction
{
Get-WmiObject -Class Win32_ComputerSystem

Register-WMIEvent -Class Win32_ProcessStartTrace -SourceIdentifier "ProcessStarted"

Set-WMIInstance -Class Win32_Environment -Argument @{Name='MyEnvVar';VariableValue='VarValue';UserName='<SYSTEM>'}
}

TestFunction

Remove-WmiObject -Class Win32_OperatingSystem -Verbose
13 changes: 0 additions & 13 deletions Tests/Rules/AvoidUsingWMIObjectCmdlet.ps1

This file was deleted.

24 changes: 0 additions & 24 deletions Tests/Rules/AvoidUsingWMIObjectCmdlet.tests.ps1

This file was deleted.

14 changes: 0 additions & 14 deletions Tests/Rules/AvoidUsingWMIObjectCmdletNoViolations.ps1

This file was deleted.