mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Remove DCOM support from *-Computer cmdlets (#5277)
Since DCOM is not supported in corefx there was a great deal of dead code in the computer cmdlets. This PR removes all vestiges of DCOM support from: - Rename-Computer - Restart-Computer - Stop-Computer removing about 4500 lines of dead code. Also, tests are updated to provide more complete coverage. I also removed test-connection completely to make way for @iSazonov upcoming PR to improve coverage in tests, I created some test hook code which will test the cmdlet code without actually calling the WMI method to restart/rename/stop the system
This commit is contained in:
committed by
Aditya Patwardhan
parent
6cbcf5dd3e
commit
d43b2cf958
File diff suppressed because it is too large
Load Diff
@@ -357,18 +357,6 @@
|
||||
<data name="RestartComputerSkipped" xml:space="preserve">
|
||||
<value>The computer {0} is skipped. Fail to retrieve its LastBootUpTime via the WMI service with the following error message: {1}.</value>
|
||||
</data>
|
||||
<data name="InvalidParameterForDCOM" xml:space="preserve">
|
||||
<value>Parameter WsmanAuthentication should not be specified when the DCOM protocol is in use. {0}</value>
|
||||
</data>
|
||||
<data name="InvalidParameterForWSMan" xml:space="preserve">
|
||||
<value>Parameters DcomAuthentication and Impersonation should not be specified when the WSMan protocol is in use. {0}</value>
|
||||
</data>
|
||||
<data name="ParameterConfliction" xml:space="preserve">
|
||||
<value>Parameter WsmanAuthentication should not be specified with DcomAuthentication and Impersonation at the same time. {0}</value>
|
||||
</data>
|
||||
<data name="ParameterUsage" xml:space="preserve">
|
||||
<value>Parameter WsmanAuthentication is valid only if the WSMan protocol is used. Parameters DcomAuthentication (Authentication) and Impersonation are valid only if the DCOM protocol is used.</value>
|
||||
</data>
|
||||
<data name="FailToTestSecureChannel" xml:space="preserve">
|
||||
<value>Cannot verify the secure channel for the local computer. Operation failed with the following exception: {0}.</value>
|
||||
</data>
|
||||
@@ -396,24 +384,6 @@
|
||||
<data name="FailToRetrieveLastRestorePoint" xml:space="preserve">
|
||||
<value>Cannot validate the time interval for restore point creation. It failed to retrieve the last restore point with the following error message: {0}.</value>
|
||||
</data>
|
||||
<data name="RenameCommandWsmanAuthParamConflict" xml:space="preserve">
|
||||
<value>Parameter WsmanAuthentication cannot be specified with the DCOM protocol. Parameter WSManAuthentication is valid only when the WSMan protocol is used.</value>
|
||||
</data>
|
||||
<data name="StopCommandAuthProtocolConflict" xml:space="preserve">
|
||||
<value>Parameters DcomAuthentication and Impersonation cannot be specified with the WSMan protocol. {0}</value>
|
||||
</data>
|
||||
<data name="StopCommandParamMessage" xml:space="preserve">
|
||||
<value>Parameter WsmanAuthentication is valid only when the WSMan protocol is used. Parameters DcomAuthentication and Impersonation are valid only when the DCOM protocol is used.</value>
|
||||
</data>
|
||||
<data name="StopCommandParamWSManAuthConflict" xml:space="preserve">
|
||||
<value>Parameter WsmanAuthentication cannot be specified with DcomAuthentication or Impersonation parameters. {0}</value>
|
||||
</data>
|
||||
<data name="StopCommandWSManAuthProtocolConflict" xml:space="preserve">
|
||||
<value>Parameter WsmanAuthentication cannot be specified with the DCOM protocol. {0}</value>
|
||||
</data>
|
||||
<data name="InvalidParameterDCOMNotSupported" xml:space="preserve">
|
||||
<value>DcomAuthentication is not supported. Please use WsmanAuthentication instead.</value>
|
||||
</data>
|
||||
<data name="InvalidParameterSetAsJob" xml:space="preserve">
|
||||
<value>The AsJob Parameter Set is not supported.</value>
|
||||
</data>
|
||||
|
||||
-1
@@ -59,7 +59,6 @@ CmdletsToExport=@("Add-Content",
|
||||
"Remove-Service",
|
||||
"Set-Content",
|
||||
"Set-ItemProperty",
|
||||
"Test-Connection",
|
||||
"Restart-Computer",
|
||||
"Stop-Computer",
|
||||
"Rename-Computer",
|
||||
|
||||
@@ -1416,6 +1416,14 @@ namespace System.Management.Automation.Internal
|
||||
internal static bool UseDebugAmsiImplementation;
|
||||
internal static bool BypassAppLockerPolicyCaching;
|
||||
internal static bool BypassOnlineHelpRetrieval;
|
||||
|
||||
// Stop/Restart/Rename Computer tests
|
||||
internal static bool TestStopComputer;
|
||||
internal static bool TestWaitStopComputer;
|
||||
internal static bool TestRenameComputer;
|
||||
internal static int TestStopComputerResults;
|
||||
internal static int TestRenameComputerResults;
|
||||
|
||||
// It's useful to test that we don't depend on the ScriptBlock and AST objects and can use a re-parsed version.
|
||||
internal static bool IgnoreScriptBlockCache;
|
||||
// Simulate 'System.Diagnostics.Stopwatch.IsHighResolution is false' to test Get-Uptime throw
|
||||
@@ -1423,7 +1431,7 @@ namespace System.Management.Automation.Internal
|
||||
internal static bool DisableGACLoading;
|
||||
|
||||
/// <summary>This member is used for internal test purposes.</summary>
|
||||
public static void SetTestHook(string property, bool value)
|
||||
public static void SetTestHook(string property, object value)
|
||||
{
|
||||
var fieldInfo = typeof(InternalTestHooks).GetField(property, BindingFlags.Static | BindingFlags.NonPublic);
|
||||
if (fieldInfo != null)
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
$RenameTesthook = "TestRenameComputer"
|
||||
$RenameResultName = "TestRenameComputerResults"
|
||||
$DefaultResultValue = 0
|
||||
|
||||
try
|
||||
{
|
||||
# set up for testing
|
||||
$PSDefaultParameterValues["it:skip"] = ! $IsWindows
|
||||
Enable-Testhook -testhookName $RenameTesthook
|
||||
# we also set TestStopComputer
|
||||
Enable-Testhook -testhookName TestStopComputer
|
||||
|
||||
# TEST START HERE
|
||||
Describe "Rename-Computer" -Tag Feature {
|
||||
# if we throw in BeforeEach, the test will fail and the stop will not be called
|
||||
BeforeEach {
|
||||
if ( ! (Test-TesthookIsSet -testhookName $RenameTesthook) ) {
|
||||
throw "Testhook '${TesthookName}' is not set"
|
||||
}
|
||||
}
|
||||
|
||||
AfterEach {
|
||||
Set-TesthookResult -testhookName $RenameResultName -value $defaultResultValue
|
||||
}
|
||||
|
||||
It "Should rename the local computer" {
|
||||
Set-TesthookResult -testhookName $RenameResultName -value $defaultResultValue
|
||||
$newname = "mynewname"
|
||||
$result = Rename-Computer -ErrorAction Stop -ComputerName . -NewName "$newname" -Pass -WarningAction SilentlyContinue
|
||||
$result.HasSucceeded | should be $true
|
||||
$result.NewComputerName | should be $newname
|
||||
}
|
||||
|
||||
# we can't really look for the string "reboot" as it will change
|
||||
# when translated. We are guaranteed that the old computer name will
|
||||
# be present, so we'll look for that
|
||||
It "Should produce a reboot warning when renaming computer" {
|
||||
Set-TesthookResult -testhookName $RenameResultName -value $defaultResultValue
|
||||
$newname = "mynewname"
|
||||
$result = Rename-Computer -ErrorAction Stop -ComputerName . -NewName "$newname" -Pass -WarningAction SilentlyContinue -WarningVariable WarnVar
|
||||
$WarnVar.Message | should match $result.OldComputerName
|
||||
}
|
||||
|
||||
It "Should not produce a reboot warning when renaming a computer with the reboot flag" {
|
||||
Set-TesthookResult -testhookName $RenameResultName -value $defaultResultValue
|
||||
$newname = "mynewname"
|
||||
$result = Rename-Computer -ErrorAction Stop -ComputerName . -NewName "$newname" -Pass -WarningAction SilentlyContinue -WarningVariable WarnVar -Restart
|
||||
$result.HasSucceeded | should be $true
|
||||
$result.NewComputerName | should be $newname
|
||||
$WarnVar | should BeNullOrEmpty
|
||||
}
|
||||
|
||||
|
||||
Context "Rename-Computer Error Conditions" {
|
||||
$testcases =
|
||||
@{ OldName = "." ; NewName = "localhost" ; ExpectedError = "FailToRenameComputer,Microsoft.PowerShell.Commands.RenameComputerCommand" },
|
||||
@{ OldName = "." ; NewName = "." ; ExpectedError = "InvalidNewName,Microsoft.PowerShell.Commands.RenameComputerCommand" },
|
||||
@{ OldName = "." ; NewName = "::1" ; ExpectedError = "InvalidNewName,Microsoft.PowerShell.Commands.RenameComputerCommand" },
|
||||
@{ OldName = "." ; NewName = "127.0.0.1" ; ExpectedError = "InvalidNewName,Microsoft.PowerShell.Commands.RenameComputerCommand" },
|
||||
@{ OldName = "." ; NewName = ${env:ComputerName} ; ExpectedError = "NewNameIsOldName,Microsoft.PowerShell.Commands.RenameComputerCommand" },
|
||||
@{ OldName = "." ; NewName = ${env:ComputerName} + "." + ${env:USERDNSDOMAIN} ; ExpectedError = "InvalidNewName,Microsoft.PowerShell.Commands.RenameComputerCommand" },
|
||||
@{ OldName = ".\$#" ; NewName = "NewName"; ExpectedError = "AddressResolutionException,Microsoft.PowerShell.Commands.RenameComputerCommand" }
|
||||
|
||||
It "Renaming '<OldName>' to '<NewName>' creates the right error" -testcase $testcases {
|
||||
param ( $OldName, $NewName, $ExpectedError )
|
||||
Set-TesthookResult -testhookName $RenameResultName -value 0x1
|
||||
{ Rename-Computer -ComputerName $OldName -NewName $NewName -ErrorAction Stop } | ShouldBeErrorId $ExpectedError
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
$PSDefaultParameterValues.Remove("it:skip")
|
||||
Disable-Testhook -testhookName $RenameTestHook
|
||||
Disable-Testhook -testhookName TestStopComputer
|
||||
Set-TesthookResult -testhookName $RenameResultName -value 0
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
# the testhook for restart-computer is the same as for stop-computer
|
||||
$restartTesthookName = "TestStopComputer"
|
||||
$restartTesthookResultName = "TestStopComputerResults"
|
||||
$DefaultResultValue = 0
|
||||
|
||||
try
|
||||
{
|
||||
# set up for testing
|
||||
$PSDefaultParameterValues["it:skip"] = ! $IsWindows
|
||||
Enable-Testhook -testhookName $restartTesthookName
|
||||
|
||||
Describe "Restart-Computer" -Tag Feature {
|
||||
# if we throw in BeforeEach, the test will fail and the restart will not be called
|
||||
BeforeEach {
|
||||
if ( ! (Test-TesthookIsSet -testhookName $restartTesthookName) ) {
|
||||
throw "Testhook '${restartTesthookName}' is not set"
|
||||
}
|
||||
}
|
||||
|
||||
AfterEach {
|
||||
Set-TesthookResult -testhookName $restartTesthookResultName -value $defaultResultValue
|
||||
}
|
||||
|
||||
It "Should restart the local computer" {
|
||||
Set-TesthookResult -testhookName $restartTesthookResultName -value $defaultResultValue
|
||||
Restart-Computer -ErrorAction Stop| Should BeNullOrEmpty
|
||||
}
|
||||
|
||||
It "Should support -computer parameter" {
|
||||
Set-TesthookResult -testhookName $restartTesthookResultName -value $defaultResultValue
|
||||
$computerNames = "localhost","${env:COMPUTERNAME}"
|
||||
Restart-Computer -Computer $computerNames -ErrorAction Stop| Should BeNullOrEmpty
|
||||
}
|
||||
|
||||
It "Should support WsmanAuthentication types" {
|
||||
$authChoices = "Default","Basic","Negotiate","CredSSP","Digest","Kerberos"
|
||||
foreach ( $auth in $authChoices ) {
|
||||
Restart-Computer -WsmanAuthentication $auth | Should BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
# this requires setting a test hook, so we wrap the execution with try/finally of the
|
||||
# set operation. Internally, we want to suppress the progress, so
|
||||
# that is also wrapped in try/finally
|
||||
It "Should wait for a remote system" {
|
||||
try
|
||||
{
|
||||
Enable-Testhook -testhookname TestWaitStopComputer
|
||||
$timeout = 3
|
||||
try
|
||||
{
|
||||
$pPref = $ProgressPreference
|
||||
$ProgressPreference="SilentlyContinue"
|
||||
$duration = Measure-Command {
|
||||
Restart-Computer -computer localhost -Wait -Timeout $timeout -ErrorAction stop | Should BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
$ProgressPreference=$pPref
|
||||
}
|
||||
$duration.TotalSeconds | Should BeGreaterThan $timeout
|
||||
}
|
||||
finally
|
||||
{
|
||||
Disable-Testhook -testhookname TestWaitStopComputer
|
||||
}
|
||||
}
|
||||
|
||||
Context "Restart-Computer Error Conditions" {
|
||||
It "Should return the proper error when it occurs" {
|
||||
Set-TesthookResult -testhookName $restartTesthookResultName -value 0x300000
|
||||
Restart-Computer -ErrorVariable RestartError 2>$null
|
||||
$RestartError.Exception.Message | Should match 0x300000
|
||||
}
|
||||
|
||||
It "Should produce an error when 'Delay' is specified" {
|
||||
{ Restart-Computer -Delay 30 } | ShouldBeErrorId "RestartComputerInvalidParameter,Microsoft.PowerShell.Commands.RestartComputerCommand"
|
||||
}
|
||||
|
||||
It "Should not support timeout on localhost" {
|
||||
Set-TesthookResult -testhookName $restartTesthookResultName -value $defaultResultValue
|
||||
{ Restart-Computer -timeout 3 -ErrorAction Stop } | ShouldBeErrorId "RestartComputerInvalidParameter,Microsoft.PowerShell.Commands.RestartComputerCommand"
|
||||
}
|
||||
|
||||
It "Should not support timeout on localhost" {
|
||||
Set-TesthookResult -testhookName $restartTesthookResultName -value $defaultResultValue
|
||||
{ Restart-Computer -timeout 3 -ErrorAction Stop } | ShouldBeErrorId "RestartComputerInvalidParameter,Microsoft.PowerShell.Commands.RestartComputerCommand"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
$PSDefaultParameterValues.Remove("it:skip")
|
||||
Disable-Testhook -testhookName $restartTesthookName
|
||||
Set-TesthookResult -testhookName $restartTesthookResultName -value 0
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
# note these will manipulate private data in the PowerShell engine which will
|
||||
# enable us to not actually stop the system, but return right before we do
|
||||
$stopTesthook = "TestStopComputer"
|
||||
$stopTesthookResultName = "TestStopComputerResults"
|
||||
$DefaultResultValue = 0
|
||||
|
||||
try
|
||||
{
|
||||
# set up for testing
|
||||
$PSDefaultParameterValues["it:skip"] = ! $IsWindows
|
||||
Enable-Testhook -testhookName $stopTesthook
|
||||
|
||||
Describe "Stop-Computer" -Tag Feature {
|
||||
# if we throw in BeforeEach, the test will fail and the stop will not be called
|
||||
BeforeEach {
|
||||
if ( ! (Test-TesthookIsSet -testhookName $stopTesthook) ) {
|
||||
throw "Testhook '${stopTesthook}' is not set"
|
||||
}
|
||||
}
|
||||
|
||||
AfterEach {
|
||||
Set-TesthookResult -testhookName $stopTesthookResultName -Value $defaultResultValue
|
||||
}
|
||||
|
||||
It "Should stop the local computer" {
|
||||
Set-TesthookResult -testhookName $stopTesthookResultName -Value $defaultResultValue
|
||||
Stop-Computer -ErrorAction Stop| Should BeNullOrEmpty
|
||||
}
|
||||
|
||||
It "Should support -Computer parameter" {
|
||||
Set-TesthookResult -testhookName $stopTesthookResultName -Value $defaultResultValue
|
||||
$computerNames = "localhost","${env:COMPUTERNAME}"
|
||||
Stop-Computer -Computer $computerNames -ErrorAction Stop| Should BeNullOrEmpty
|
||||
}
|
||||
|
||||
It "Should support WsmanAuthentication types" {
|
||||
$authChoices = "Default","Basic","Negotiate","CredSSP","Digest","Kerberos"
|
||||
foreach ( $auth in $authChoices ) {
|
||||
Stop-Computer -WsmanAuthentication $auth | Should BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context "Stop-Computer Error Conditions" {
|
||||
It "Should return the proper error when it occurs" {
|
||||
Set-TesthookResult -testhookName $stopTesthookResultName -Value 0x300000
|
||||
Stop-Computer -ErrorVariable StopError 2>$null
|
||||
$StopError.Exception.Message | Should match 0x300000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
$PSDefaultParameterValues.Remove("it:skip")
|
||||
Disable-Testhook -testhookName $stopTesthook
|
||||
Set-TesthookResult -testhookName $stopTesthookResultName -Value $DefaultResultValue
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
Describe "Test-Connection" -Tags "CI" {
|
||||
BeforeAll {
|
||||
$originalDefaultParameterValues = $PSDefaultParameterValues.Clone()
|
||||
if ( ! $IsWindows )
|
||||
{
|
||||
$PSDefaultParameterValues["it:skip"] = $true
|
||||
}
|
||||
else
|
||||
{
|
||||
$countCases = @(
|
||||
@{count = 2}
|
||||
@{count = 3}
|
||||
)
|
||||
|
||||
$quietTests = @(
|
||||
@{computerName = 'localhost'; message = 'online' ; result = $true}
|
||||
@{computerName = '_fake_computer_namex'; message = 'offline' ; result = $false}
|
||||
)
|
||||
}
|
||||
}
|
||||
AfterAll {
|
||||
$global:PSDefaultParameterValues = $originalDefaultParameterValues
|
||||
}
|
||||
It "Gets the right IP Address" {
|
||||
$localHost = Test-Connection -ComputerName localhost -Count 1
|
||||
$localHost.IPV4Address | Should Be '127.0.0.1'
|
||||
$localhost.IPV6Address | Should Be '::1'
|
||||
}
|
||||
|
||||
It "The count parameter counting to <count>" -TestCases $countCases {
|
||||
param($count)
|
||||
(Test-Connection -ComputerName localhost -Count $count).Count | Should Be $count
|
||||
}
|
||||
|
||||
It "The quiet parameter on a <message> computer" -TestCases $quietTests {
|
||||
param($computername, $result)
|
||||
Test-Connection -ComputerName $computername -Count 1 -Quiet | Should Be $result
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,6 @@ Describe "Unimplemented Management Cmdlet Tests" -Tags "CI" {
|
||||
|
||||
"Get-ComputerInfo",
|
||||
|
||||
"Test-Connection",
|
||||
|
||||
"Set-TimeZone"
|
||||
)
|
||||
|
||||
|
||||
@@ -435,7 +435,6 @@ Describe "Verify approved aliases list" -Tags "CI" {
|
||||
"Cmdlet", "Suspend-Service", , $($FullCLR -or $CoreWindows )
|
||||
"Cmdlet", "Tee-Object", , $($FullCLR -or $CoreWindows -or $CoreUnix)
|
||||
"Cmdlet", "Test-ComputerSecureChannel", , $($FullCLR )
|
||||
"Cmdlet", "Test-Connection", , $($FullCLR -or $CoreWindows )
|
||||
"Cmdlet", "Test-FileCatalog", , $($FullCLR -or $CoreWindows )
|
||||
"Cmdlet", "Test-ModuleManifest", , $($FullCLR -or $CoreWindows -or $CoreUnix)
|
||||
"Cmdlet", "Test-Path", , $($FullCLR -or $CoreWindows -or $CoreUnix)
|
||||
|
||||
@@ -16,5 +16,5 @@ Copyright = 'Copyright (c) Microsoft Corporation. All rights reserved.'
|
||||
|
||||
Description = 'Temporary module contains functions for using in tests'
|
||||
|
||||
FunctionsToExport = 'Wait-UntilTrue', 'Test-IsElevated', 'ShouldBeErrorId', 'Wait-FileToBePresent', 'Get-RandomFileName'
|
||||
FunctionsToExport = 'Wait-UntilTrue', 'Test-IsElevated', 'ShouldBeErrorId', 'Wait-FileToBePresent', 'Get-RandomFileName', 'Enable-Testhook', 'Disable-Testhook', 'Set-TesthookResult', 'Test-TesthookIsSet'
|
||||
}
|
||||
|
||||
@@ -82,3 +82,58 @@ function Get-RandomFileName
|
||||
{
|
||||
[System.IO.Path]::GetFileNameWithoutExtension([IO.Path]::GetRandomFileName())
|
||||
}
|
||||
|
||||
#
|
||||
# Testhook setting functions
|
||||
# note these manipulate private data in the PowerShell engine which will
|
||||
# enable us to not actually alter the system or mock returned data
|
||||
#
|
||||
$SCRIPT:TesthookType = [system.management.automation.internal.internaltesthooks]
|
||||
function Test-TesthookIsSet
|
||||
{
|
||||
param (
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Parameter(Mandatory=$true)]
|
||||
$testhookName
|
||||
)
|
||||
try {
|
||||
return ${Script:TesthookType}.GetField($testhookName, "NonPublic,Static").GetValue($null)
|
||||
}
|
||||
catch {
|
||||
# fall through
|
||||
}
|
||||
return $false
|
||||
}
|
||||
|
||||
function Enable-Testhook
|
||||
{
|
||||
param (
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Parameter(Mandatory=$true)]
|
||||
$testhookName
|
||||
)
|
||||
${Script:TesthookType}::SetTestHook($testhookName, $true)
|
||||
}
|
||||
|
||||
function Disable-Testhook
|
||||
{
|
||||
param (
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Parameter(Mandatory=$true)]
|
||||
$testhookName
|
||||
)
|
||||
${Script:TesthookType}::SetTestHook($testhookName, $false)
|
||||
}
|
||||
|
||||
function Set-TesthookResult
|
||||
{
|
||||
param (
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Parameter(Mandatory=$true)]
|
||||
$testhookName,
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Parameter(Mandatory=$true)]
|
||||
$value
|
||||
)
|
||||
${Script:TesthookType}::SetTestHook($testhookName, $value)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user