Powershell: Updating System.ServiceProcess.ServiceController to its .Net Core 3-preview6 version breaks 2 tests

Created on 6 Jul 2019  路  8Comments  路  Source: PowerShell/PowerShell

Updating the 2 NuGet package System.ServiceProcess.ServiceController (or Microsoft.Windows.Compatibility, which is depending on it) from 4.5.0 (.Net Core 2.1) to 4.6.0-preview6.19303.8 (.Net Core 3-preview6) breaks 2 tests and the reason for their failure seems to be unclear (i.e. whether it is a problem of PowerShell itself that is now being exposed or a regression in the System.ServiceProcess.ServiceController NuGet package itself), therefore their update was deferred in PR 9888

Steps to reproduce

Update the System.ServiceProcess.ServiceController NuGet package to 4.6.0-preview6.19303.8

Expected behavior

All tests pass.

Actual behavior

There are 2 failures on Windows:

  • Set/New/Remove-Service cmdlet tests.Set-Service can accept a ServiceController as positional input:
Expected strings to be the same, but they were different.
String lengths are both 14.
Strings differ at index 0.
Expected: 'newdisplayname'
But was:  'testsetservice'
at <ScriptBlock>, D:\a\1\s\test\powershell\Modules\Microsoft.PowerShell.Management\Set-Service.Tests.ps1: line 321
321:             $service.DisplayName | Should -BeExactly $newdisplayname

It is worthwhile noting that the first Windows service test throws an ObjectDisposedException before it fails:

        Set-Service : Cannot access a disposed object.
Object name: 'ServiceController'.
At C:\Users\cberg\git\PowerShell\test\powershell\Modules\Microsoft.PowerShell.Management\Set-Service.Tests.ps1:318 char:25
+ ...       $script = { Set-Service $service -DisplayName $newdisplayname }
+                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : ObjectNotFound: (:) [Set-Service], ObjectDisposedException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.SetServiceCommand

image

  • Get-WinEvent.Get-WinEvent can retrieve events.Get-WinEvent can use the simplest of filters
Cannot convert argument "value", with value: "System.Diagnostics.Eventing.Reader.EventLogRecord", for "TryAdd" to type "System.Diagnostics.Eventing.Reader.EventLogRecord": "Cannot convert the "System.Diagnostics.Eventing.Reader.EventLogRecord" value of type "System.Diagnostics.Eventing.Reader.EventLogRecord" to type "System.Diagnostics.Eventing.Reader.EventLogRecord"."
at <ScriptBlock>, D:\a\1\s\test\powershell\Modules\Microsoft.PowerShell.Diagnostics\Get-WinEvent.Tests.ps1: line 61
61:                 $testEventDict.TryAdd($te.Id, $te)

Environment data

Windows

Issue-Question Resolution-Fixed

Most helpful comment

Yes, it seems wrong to me that we dispose the ServiceController object in New-Service. I'm not sure if that's on purpose though ... See this is why we need good comment in code :)

All 8 comments

I looked at history of the source code and I don't see any changes. I guess root of the issue in another place. New-Service disposes the object before write to pipeline. Perhaps GC was updated in Preview6.

For the first failure, it's caused by this line, which was added by https://github.com/dotnet/corefx/pull/32072 in .NET Core 3.0.
Simply put it, before .NET Core 3, ServiceController.ServiceName returns a string even if the object has been disposed. In .NET Core 3, the call to GetDataBaseHandleWithConnectAccess causes it to throw ObjectDisposedException when the object has been disposed.
This looks like a change by design, and we just need to update our test.

For the second failure, it's more problematic. The new NuGet package System.Diagnostics.EventLog includes a few more namespaces than the 4.5.0 version, including System.Diagnostics.Eventing.Reader, which has EventLogRecord type. However, our Microsoft.PowerShell.CoreCLR.Eventing.dll, which contains the ported .NET code for EventProvider also contains that type. So there is a conflict now.

This looks like a change by design, and we just need to update our test.

Why do we dispose only in one cmdlet (New-Service)?
https://github.com/PowerShell/PowerShell/blob/17fb524adb85566aa5cb6041db279905c2700e6d/src/Microsoft.PowerShell.Commands.Management/commands/management/Service.cs#L2276-L2281

our Microsoft.PowerShell.CoreCLR.Eventing.dll, which contains the ported .NET code for EventProvider also contains that type. So there is a conflict now.

For reference https://github.com/Microsoft/referencesource/blob/master/System.Core/System/Diagnostics/Eventing/Reader/EventLogRecord.cs - at first look it is the same code as in PowerShell repo.

GitHub
Source from the Microsoft .NET Reference Source that represent a subset of the .NET Framework - microsoft/referencesource

Why do we dispose only in one cmdlet (New-Service)?

Good question. No idea why doing that. Seems wrong to me.

Good question. No idea why doing that. Seems wrong to me.

Wrong that we dispose in New-Service?

Yes, it seems wrong to me that we dispose the ServiceController object in New-Service. I'm not sure if that's on purpose though ... See this is why we need good comment in code :)

:tada:This issue was addressed in #10305, which has now been successfully released as v7.0.0-preview.3.:tada:

Handy links:

Was this page helpful?
0 / 5 - 0 ratings