Skip to content

Commit f00cfa6

Browse files
committed
Merge pull request #98 from PowerShell/AvoidUsingWMICmdletBranch
Avoid using wmi cmdlet rule
2 parents 5b0785b + dcb5d6e commit f00cfa6

9 files changed

+85
-69
lines changed

Rules/AvoidUsingWMIObjectCmdlet.cs renamed to Rules/AvoidUsingWMICmdlet.cs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,19 @@
2828
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
2929
{
3030
/// <summary>
31-
/// AvoidUsingWMIObjectCmdlet: Verify that Get-WMIObject, Remove-WMIObject are not used
31+
/// AvoidUsingWMICmdlet: Avoid Using Get-WMIObject, Remove-WMIObject, Invoke-WmiMethod, Register-WmiEvent, Set-WmiInstance
3232
/// </summary>
3333
[Export(typeof(IScriptRule))]
34-
public class AvoidUsingWMIObjectCmdlet : IScriptRule
34+
public class AvoidUsingWMICmdlet : IScriptRule
3535
{
3636
/// <summary>
37-
/// AnalyzeScript: Verify that Get-WMIObject, Remove-WMIObject are not used
37+
/// AnalyzeScript: Avoid Using Get-WMIObject, Remove-WMIObject, Invoke-WmiMethod, Register-WmiEvent, Set-WmiInstance
3838
/// </summary>
3939
public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
4040
{
4141
if (ast == null) throw new ArgumentNullException(Strings.NullAstErrorMessage);
4242

43-
// Rule is applicable only when PowerShell Version is < 3.0, since Get-CIMInstance was introduced in 3.0
43+
// Rule is applicable only when PowerShell Version is < 3.0, since CIM cmdlet was introduced in 3.0
4444
int majorPSVersion = GetPSMajorVersion(ast);
4545
if (!(3 > majorPSVersion && 0 < majorPSVersion))
4646
{
@@ -50,9 +50,15 @@ public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
5050
// Iterate all CommandAsts and check the command name
5151
foreach (CommandAst cmdAst in commandAsts)
5252
{
53-
if (cmdAst.GetCommandName() != null && (String.Equals(cmdAst.GetCommandName(), "get-wmiobject", StringComparison.OrdinalIgnoreCase) || String.Equals(cmdAst.GetCommandName(), "remove-wmiobject", StringComparison.OrdinalIgnoreCase)))
53+
if (cmdAst.GetCommandName() != null &&
54+
(String.Equals(cmdAst.GetCommandName(), "get-wmiobject", StringComparison.OrdinalIgnoreCase)
55+
|| String.Equals(cmdAst.GetCommandName(), "remove-wmiobject", StringComparison.OrdinalIgnoreCase)
56+
|| String.Equals(cmdAst.GetCommandName(), "invoke-wmimethod", StringComparison.OrdinalIgnoreCase)
57+
|| String.Equals(cmdAst.GetCommandName(), "register-wmievent", StringComparison.OrdinalIgnoreCase)
58+
|| String.Equals(cmdAst.GetCommandName(), "set-wmiinstance", StringComparison.OrdinalIgnoreCase))
59+
)
5460
{
55-
yield return new DiagnosticRecord(String.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingWMIObjectCmdletError, System.IO.Path.GetFileName(fileName)),
61+
yield return new DiagnosticRecord(String.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingWMICmdletError, System.IO.Path.GetFileName(fileName)),
5662
cmdAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName);
5763
}
5864
}
@@ -87,7 +93,7 @@ private int GetPSMajorVersion(Ast ast)
8793
/// <returns>The name of this rule</returns>
8894
public string GetName()
8995
{
90-
return string.Format(CultureInfo.CurrentCulture, Strings.NameSpaceFormat, GetSourceName(), Strings.AvoidUsingWMIObjectCmdletName);
96+
return string.Format(CultureInfo.CurrentCulture, Strings.NameSpaceFormat, GetSourceName(), Strings.AvoidUsingWMICmdletName);
9197
}
9298

9399
/// <summary>
@@ -96,7 +102,7 @@ public string GetName()
96102
/// <returns>The common name of this rule</returns>
97103
public string GetCommonName()
98104
{
99-
return string.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingWMIObjectCmdletCommonName);
105+
return string.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingWMICmdletCommonName);
100106
}
101107

102108
/// <summary>
@@ -105,7 +111,7 @@ public string GetCommonName()
105111
/// <returns>The description of this rule</returns>
106112
public string GetDescription()
107113
{
108-
return string.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingWMIObjectCmdletDescription);
114+
return string.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingWMICmdletDescription);
109115
}
110116

111117
/// <summary>

Rules/ScriptAnalyzerBuiltinRules.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
<Compile Include="AvoidUsingInternalURLs.cs" />
6767
<Compile Include="AvoidUsingInvokeExpression.cs" />
6868
<Compile Include="AvoidUsingPlainTextForPassword.cs" />
69-
<Compile Include="AvoidUsingWMIObjectCmdlet.cs" />
69+
<Compile Include="AvoidUsingWMICmdlet.cs" />
7070
<Compile Include="AvoidUsingWriteHost.cs" />
7171
<Compile Include="MissingModuleManifestField.cs" />
7272
<Compile Include="PossibleIncorrectComparisonWithNull.cs" />

Rules/Strings.resx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -666,16 +666,16 @@
666666
<data name="UseShouldProcessForStateChangingFunctionsName" xml:space="preserve">
667667
<value>UseShouldProcessForStateChangingFunctions</value>
668668
</data>
669-
<data name="AvoidUsingWMIObjectCmdletCommonName" xml:space="preserve">
670-
<value>Avoid Using Get-WMIObject, Remove-WMIObject</value>
669+
<data name="AvoidUsingWMICmdletCommonName" xml:space="preserve">
670+
<value>Avoid Using Get-WMIObject, Remove-WMIObject, Invoke-WmiMethod, Register-WmiEvent, Set-WmiInstance</value>
671671
</data>
672-
<data name="AvoidUsingWMIObjectCmdletDescription" xml:space="preserve">
673-
<value>Depricated. Starting in Windows PowerShell 3.0, these cmdlets have been superseded by CimInstance cmdlets.</value>
672+
<data name="AvoidUsingWMICmdletDescription" xml:space="preserve">
673+
<value>Depricated. Starting in Windows PowerShell 3.0, these cmdlets have been superseded by CIM cmdlets.</value>
674674
</data>
675-
<data name="AvoidUsingWMIObjectCmdletError" xml:space="preserve">
676-
<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>
675+
<data name="AvoidUsingWMICmdletError" xml:space="preserve">
676+
<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>
677677
</data>
678-
<data name="AvoidUsingWMIObjectCmdletName" xml:space="preserve">
679-
<value>AvoidUsingWMIObjectCmdlet</value>
678+
<data name="AvoidUsingWMICmdletName" xml:space="preserve">
679+
<value>AvoidUsingWMICmdlet</value>
680680
</data>
681681
</root>

Tests/Rules/AvoidUsingWMICmdlet.ps1

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#Script violates the rule because Get-CIMInstance is available on PS 3.0 and needs to use that
2+
3+
#requires -version 3.0
4+
5+
function TestFunction
6+
{
7+
Get-WmiObject -Class Win32_ComputerSystem
8+
9+
Invoke-WMIMethod -Path Win32_Process -Name Create -ArgumentList notepad.exe
10+
11+
Register-WMIEvent -Class Win32_ProcessStartTrace -SourceIdentifier "ProcessStarted"
12+
13+
Set-WMIInstance -Class Win32_Environment -Argument @{Name='MyEnvVar';VariableValue='VarValue';UserName='<SYSTEM>'}
14+
}
15+
16+
TestFunction
17+
18+
Remove-WmiObject -Class Win32_OperatingSystem -Verbose
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
Import-Module PSScriptAnalyzer
2+
$WMIRuleName = "PSAvoidUsingWMICmdlet"
3+
$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."
4+
$directory = Split-Path -Parent $MyInvocation.MyCommand.Path
5+
$violations = Invoke-ScriptAnalyzer $directory\AvoidUsingWMICmdlet.ps1 -IncludeRule $WMIRuleName
6+
$noViolations = Invoke-ScriptAnalyzer $directory\AvoidUsingWMICmdletNoViolations.ps1 -IncludeRule $WMIRuleName
7+
8+
Describe "AvoidUsingWMICmdlet" {
9+
Context "Script contains references to WMI cmdlets - Violation" {
10+
It "Have 5 WMI cmdlet Violations" {
11+
$violations.Count | Should Be 5
12+
}
13+
14+
It "has the correct description message for WMI rule violation" {
15+
$violations[0].Message | Should Be $violationMessage
16+
}
17+
}
18+
19+
Context "Script contains no calls to WMI cmdlet - No violation" {
20+
It "results in no rule violations" {
21+
$noViolations.Count | Should Be 0
22+
}
23+
}
24+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# No Rule violations since this script requires PS 2.0 and Get-CIMInstance is not available for this version
2+
# So using Get-WMIObject is OK
3+
4+
#requires -Version 2.0
5+
6+
Invoke-WMIMethod -Path Win32_Process -Name Create -ArgumentList notepad.exe
7+
8+
function TestFunction
9+
{
10+
Get-WmiObject -Class Win32_ComputerSystem
11+
12+
Register-WMIEvent -Class Win32_ProcessStartTrace -SourceIdentifier "ProcessStarted"
13+
14+
Set-WMIInstance -Class Win32_Environment -Argument @{Name='MyEnvVar';VariableValue='VarValue';UserName='<SYSTEM>'}
15+
}
16+
17+
TestFunction
18+
19+
Remove-WmiObject -Class Win32_OperatingSystem -Verbose

Tests/Rules/AvoidUsingWMIObjectCmdlet.ps1

Lines changed: 0 additions & 13 deletions
This file was deleted.

Tests/Rules/AvoidUsingWMIObjectCmdlet.tests.ps1

Lines changed: 0 additions & 24 deletions
This file was deleted.

Tests/Rules/AvoidUsingWMIObjectCmdletNoViolations.ps1

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)