Skip to content
Merged
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
@@ -0,0 +1,173 @@
Describe "Set/New-Service cmdlet tests" -Tags "Feature", "RequireAdminOnWindows" {
BeforeAll {
$originalDefaultParameterValues = $PSDefaultParameterValues.Clone()
if ( -not $IsWindows ) {
$PSDefaultParameterValues["it:skip"] = $true
}
}
AfterAll {
$global:PSDefaultParameterValues = $originalDefaultParameterValues
}

It "SetServiceCommand can be used as API for '<parameter>' with '<value>'" -TestCases @(
@{parameter = "ComputerName"; value = "foo"},
@{parameter = "Name" ; value = "bar"},
@{parameter = "DisplayName" ; value = "hello"},
@{parameter = "Description" ; value = "hello world"},
@{parameter = "StartupType" ; value = "Automatic"},
@{parameter = "StartupType" ; value = "Boot"},
@{parameter = "StartupType" ; value = "Disabled"},
@{parameter = "StartupType" ; value = "Manual"},
@{parameter = "StartupType" ; value = "System"},
@{parameter = "Status" ; value = "Running"},
@{parameter = "Status" ; value = "Stopped"},
@{parameter = "Status" ; value = "Paused"},
@{parameter = "InputObject" ; value = (Get-Service | Select-Object -First 1)},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is failed on Unix #4800
We should move (Get-Service | Select-Object -First 1) to BeforeAll.

# cmdlet inherits this property, but it's not exposed as parameter so it should be $null
@{parameter = "Include" ; value = "foo", "bar" ; expectedNull = $true},
# cmdlet inherits this property, but it's not exposed as parameter so it should be $null
@{parameter = "Exclude" ; value = "foo", "bar" ; expectedNull = $true}
) {
param($parameter, $value, $expectedNull)

$setServiceCommand = [Microsoft.PowerShell.Commands.SetServiceCommand]::new()
$setServiceCommand.$parameter = $value
if ($expectedNull -eq $true) {
$setServiceCommand.$parameter | Should BeNullOrEmpty
}
else {
$setServiceCommand.$parameter | Should Be $value
}
}

It "Set-Service parameter validation for invalid values: <script>" -TestCases @(
@{
script = {Set-Service foo -StartupType bar};
errorid = "CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.SetServiceCommand"
}
) {
param($script, $errorid)
{ & $script } | ShouldBeErrorId $errorid
}

It "Set-Service can change '<parameter>' to '<value>'" -TestCases @(
@{parameter = "Description"; value = "hello"},
@{parameter = "DisplayName"; value = "test spooler"},
@{parameter = "StartupType"; value = "Disabled"},
@{parameter = "Status" ; value = "running" ; expected = "OK"}
) {
param($parameter, $value, $expected)
$currentService = Get-CimInstance -ClassName Win32_Service -Filter "Name='spooler'"
try {
$setServiceCommand = [Microsoft.PowerShell.Commands.SetServiceCommand]::new()
$setServiceCommand.Name = "Spooler"
$setServiceCommand.$parameter = $value
$setServiceCommand.Invoke()
$updatedService = Get-CimInstance -ClassName Win32_Service -Filter "Name='spooler'"
if ($expected -eq $null) {
$expected = $value
}
if ($parameter -eq "StartupType") {
$updatedService.StartMode | Should Be $expected
}
else {
$updatedService.$parameter | Should Be $expected
}
}
finally {
if ($parameter -eq "StartupType") {
$setServiceCommand.StartupType = $currentService.StartMode
}
else {
$setServiceCommand.$parameter = $currentService.$parameter
}
$setServiceCommand.Invoke()
$updatedService = Get-CimInstance -ClassName Win32_Service -Filter "Name='spooler'"
$updatedService.$parameter | Should Be $currentService.$parameter
}
}

It "NewServiceCommand can be used as API for '<parameter>' with '<value>'" -TestCases @(
@{parameter = "Name" ; value = "bar"},
@{parameter = "BinaryPathName" ; value = "hello"},
@{parameter = "DisplayName" ; value = "hello world"},
@{parameter = "Description" ; value = "this is a test"},
@{parameter = "StartupType" ; value = "Automatic"},
@{parameter = "StartupType" ; value = "Boot"},
@{parameter = "StartupType" ; value = "Disabled"},
@{parameter = "StartupType" ; value = "Manual"},
@{parameter = "StartupType" ; value = "System"},
@{parameter = "Credential" ; value = (
[System.Management.Automation.PSCredential]::new("username",
(ConvertTo-SecureString "PlainTextPassword" -AsPlainText -Force)))
}
@{parameter = "DependsOn" ; value = "foo", "bar"}
) {
param($parameter, $value)

$newServiceCommand = [Microsoft.PowerShell.Commands.NewServiceCommand]::new()
$newServiceCommand.$parameter = $value
$newServiceCommand.$parameter | Should Be $value
}

It "New-Service can create a new service called '<name>'" -TestCases @(
@{name = "testautomatic"; startupType = "Automatic"; description = "foo" ; displayname = "one"},
@{name = "testmanual" ; startupType = "Manual" ; description = "bar" ; displayname = "two"},
@{name = "testdisabled" ; startupType = "Disabled" ; description = $null ; displayname = $null}
) {
param($name, $startupType, $description, $displayname)
try {
$parameters = @{
Name = $name;
BinaryPathName = "$PSHOME\powershell.exe";
StartupType = $startupType;
}
if ($description) {
$parameters += @{description = $description}
}
if ($displayname) {
$parameters += @{displayname = $displayname}
}
$service = New-Service @parameters
$service | Should Not BeNullOrEmpty
$service = Get-CimInstance Win32_Service -Filter "name='$name'"
$service | Should Not BeNullOrEmpty
$service.Name | Should Be $name
$service.Description | Should Be $description
$expectedStartup = $(
switch ($startupType) {
"Automatic" {"Auto"}
"Manual" {"Manual"}
"Disabled" {"Disabled"}
default { throw "Unsupported StartupType in TestCases" }
}
)
$service.StartMode | Should Be $expectedStartup
if ($displayname -eq $null) {
$service.DisplayName | Should Be $name
}
else {
$service.DisplayName | Should Be $displayname
}
}
finally {
$service = Get-CimInstance Win32_Service -Filter "name='$name'"
if ($service -ne $null) {
$service | Remove-CimInstance
}
}
}

It "New-Service with bad parameters will fail for '<name>' where '<parameter>' = '<value>'" -TestCases @(
@{name = 'credtest' ; parameter = "Credential" ; value = (
[System.Management.Automation.PSCredential]::new("username",
(ConvertTo-SecureString "PlainTextPassword" -AsPlainText -Force)))
},
@{name = 'badstarttype'; parameter = "StartupType"; value = "System"},
@{name = 'winmgmt' ; parameter = "DisplayName"; value = "foo"}
) {
param($name, $parameter, $value)
$parameters = @{$parameter = $value; Name = $name; Binary = "$PSHOME\powershell.exe"; ErrorAction = "Stop"}
{ New-Service @parameters } | ShouldBeErrorId "CouldNotNewService,Microsoft.PowerShell.Commands.NewServiceCommand"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SteveL-MSFT We skipped -ErrorAction Stop 😕 #4800

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@iSazonov it's there in the @parameter hash literal. The porblem is with the TestCase

@{name = 'badstarttype'; parameter = "StartupType"; value = "System"}
-------------------------------------------------------------^

System is actually valid for StartupType so that would not result in a Throw. I'm not sure if this is a faulty TestCase or if there is something wrong with New-Service

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The New-Service code doesn't allow System.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll submit a PR soon

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If that's the case, then there is a bug in New-Service that is not throwing CouldNotNewService,Microsoft.PowerShell.Commands.NewServiceCommand when System is provided.

https://ci.appveyor.com/project/PowerShell/powershell/build/6.0.0-beta.6-5148/tests

Running

New-Service -StartupType System -Name badstarttype -BinaryPathName "$PSHOME\powershell.exe" -ErrorAction Stop

Yields this for me

FailFast: bad StartupType

   at System.Diagnostics.Debug.Assert(Boolean condition, String message, String detailMessage)
   at System.Management.Automation.Diagnostics.Assert(Boolean condition, String whyThisShouldNeverHappen, String detailMessage) in C:\github\PowerShell\src\System.Management.Automation\utils\assert.cs:line 196
   at System.Management.Automation.Diagnostics.Assert(Boolean condition, String whyThisShouldNeverHappen) in C:\github\PowerShell\src\System.Management.Automation\utils\assert.cs:line 131
   at Microsoft.PowerShell.Commands.NewServiceCommand.BeginProcessing() in C:\github\PowerShell\src\Microsoft.PowerShell.Commands.Management\commands\management\Service.cs:line 2018
   at System.Management.Automation.Cmdlet.DoBeginProcessing() in C:\github\PowerShell\src\System.Management.Automation\engine\cmdlet.cs:line 164
   at System.Management.Automation.CommandProcessorBase.DoBegin() in C:\github\PowerShell\src\System.Management.Automation\engine\CommandProcessorBase.cs:line 500
   at System.Management.Automation.CommandProcessor.DoBegin() in C:\github\PowerShell\src\System.Management.Automation\engine\CommandProcessor.cs:line 272
   at System.Management.Automation.Internal.PipelineProcessor.Start(Boolean incomingStream) in C:\github\PowerShell\src\System.Management.Automation\engine\pipeline.cs:line 1050
   at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input) in C:\github\PowerShell\src\System.Management.Automation\engine\pipeline.cs:line 489
   at System.Management.Automation.PipelineOps.InvokePipeline(Object input, Boolean ignoreInput, CommandParameterInternal[][] pipeElements, CommandBaseAst[] pipeElementAsts, CommandRedirection[][] commandRedirections, FunctionContext funcContext) in C:\github\PowerShell\src\System.Management.Automation\engine\runtime\Operations\MiscOps.cs:line 455
   at System.Management.Automation.Interpreter.ActionCallInstruction`6.Run(InterpretedFrame frame) in C:\github\PowerShell\src\System.Management.Automation\engine\interpreter\CallInstruction.Generated.cs:line 569
   at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame) in C:\github\PowerShell\src\System.Management.Automation\engine\interpreter\ControlFlowInstructions.cs:line 356
   at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame) in C:\github\PowerShell\src\System.Management.Automation\engine\interpreter\ControlFlowInstructions.cs:line 356
   at System.Management.Automation.Interpreter.Interpreter.Run(InterpretedFrame frame) in C:\github\PowerShell\src\System.Management.Automation\engine\interpreter\Interpreter.cs:line 111
   at System.Management.Automation.Interpreter.LightLambda.RunVoid1[T0](T0 arg0) in C:\github\PowerShell\src\System.Management.Automation\engine\interpreter\LightLambda.Generated.cs:line 78
   at System.Management.Automation.DlrScriptCommandProcessor.RunClause(Action`1 clause, Object dollarUnderbar, Object inputToProcess) in C:\github\PowerShell\src\System.Management.Automation\engine\ScriptCommandProcessor.cs:line 516
   at System.Management.Automation.DlrScriptCommandProcessor.Complete() in C:\github\PowerShell\src\System.Management.Automation\engine\ScriptCommandProcessor.cs:line 417
   at System.Management.Automation.CommandProcessorBase.DoComplete() in C:\github\PowerShell\src\System.Management.Automation\engine\CommandProcessorBase.cs:line 614
   at System.Management.Automation.Internal.PipelineProcessor.DoCompleteCore(CommandProcessorBase commandRequestingUpstreamCommandsToStop) in C:\github\PowerShell\src\System.Management.Automation\engine\pipeline.cs:line 607
   at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input) in C:\github\PowerShell\src\System.Management.Automation\engine\pipeline.cs:line 519
   at System.Management.Automation.Runspaces.LocalPipeline.InvokeHelper() in C:\github\PowerShell\src\System.Management.Automation\engine\hostifaces\LocalPipeline.cs:line 426
   at System.Management.Automation.Runspaces.LocalPipeline.InvokeThreadProc() in C:\github\PowerShell\src\System.Management.Automation\engine\hostifaces\LocalPipeline.cs:line 622
   at System.Threading.Thread.ThreadMain_ThreadStart()
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)

   at System.Environment.FailFast(System.String, System.Exception)
   at System.Management.Automation.Diagnostics.Assert(Boolean, System.String, System.String)
   at System.Management.Automation.Diagnostics.Assert(Boolean, System.String)
   at Microsoft.PowerShell.Commands.NewServiceCommand.BeginProcessing()
   at System.Management.Automation.Cmdlet.DoBeginProcessing()
   at System.Management.Automation.CommandProcessorBase.DoBegin()
   at System.Management.Automation.CommandProcessor.DoBegin()
   at System.Management.Automation.Internal.PipelineProcessor.Start(Boolean)
   at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(System.Object)
   at System.Management.Automation.PipelineOps.InvokePipeline(System.Object, Boolean, System.Management.Automation.CommandParameterInternal[][], System.Management.Automation.Language.CommandBaseAst[], System.Management.Automation.CommandRedirection[][], System.Management.Automation.Language.FunctionContext)
   at System.Management.Automation.Interpreter.ActionCallInstruction`6[[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Run(System.Management.Automation.Interpreter.InterpretedFrame)
   at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(System.Management.Automation.Interpreter.InterpretedFrame)
   at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(System.Management.Automation.Interpreter.InterpretedFrame)
   at System.Management.Automation.Interpreter.Interpreter.Run(System.Management.Automation.Interpreter.InterpretedFrame)
   at System.Management.Automation.Interpreter.LightLambda.RunVoid1[[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.__Canon)
   at System.Management.Automation.DlrScriptCommandProcessor.RunClause(System.Action`1<System.Management.Automation.Language.FunctionContext>, System.Object, System.Object)
   at System.Management.Automation.DlrScriptCommandProcessor.Complete()
   at System.Management.Automation.CommandProcessorBase.DoComplete()
   at System.Management.Automation.Internal.PipelineProcessor.DoCompleteCore(System.Management.Automation.CommandProcessorBase)
   at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(System.Object)
   at System.Management.Automation.Runspaces.LocalPipeline.InvokeHelper()
   at System.Management.Automation.Runspaces.LocalPipeline.InvokeThreadProc()
   at System.Threading.Thread.ThreadMain_ThreadStart()
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)

and then crashes PowerShell.

If I build for Release, it creates the service with Automatic StartType.

So.. successful test! It's failing because there is a bug in New-Service.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't repro locally for me on WS2016. AppVeyor is using WS2012R2, will need to investigate this later. Leaving for a flight to Open Source Summit.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@markekraus can you open an issue? Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SteveL-MSFT Have fun! Issue #4803 created

}
}