Closed MycroBeat closed 3 years ago
Is the first pattern working? That's the one you want to be using. The WebHostBuilder windows host should still work but will be considered deprecated since the generic host supports windows services as well.
On .NET Core 3.1, yes, it's working correctly, but on .NET 5 return that error.
You have 2 code samples, which one doesn't work on .NET 5?
Both not working on .NET 5
RunAsService
is going to be obsolete and the other method is the recommended approach. Transferring to the Runtime repo for UseWindowsService
.
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.
Tagging subscribers to this area: @eerhardt, @maryamariyan See info in area-owners.md if you want to be subscribed.
Author: | MycroBeat |
---|---|
Assignees: | - |
Labels: | `area-Extensions-Hosting`, `untriaged` |
Milestone: | - |
@MycroBeat - this is working fine for me locally. Do you have a repro project and exact steps to run to reproduce?
One thing to note is that if you are copying the application around, you need to ensure you copy the runtimes
folder with the application. System.ServiceProcess.ServiceController.dll
is a bit special in that there is a Windows-specific build, which works. And a "default" build which throws PNSE. You want to ensure you are loading and running the Windows-specific version of the assembly that gets placed here:
You can try debugging your application by putting System.Diagnostics.Debugger.Launch();
as the first line in Main
, and then starting the app under Windows Services. This will prompt you to attach a debugger. Then you can continue the app, and look in the "Modules" window of Visual Studio to see which path/version of that assembly is getting loaded.
The repo is a normal .NET 5 Template, without any modification. I just create template on Visual Studio, then I took the steps exactly as I said in my original post. Then i publish the application with the following configuration:
Target location: bin\Release\net5.0\publish\
Delete existing files: False
Configuration: Relase
Target Framework: net5.0
Target runtime: Portable
Now I found where the error is, although it is a strange error.
Portable
and i have .UseWindowsService()
or .RunAsService()
, the publish create a runtimes
folder and throw the error if i'm using Windows Service method.Win-x64
, the runtimes
folder is not created and the application run normally.Publishing Portable
works for me as well:
Can you .zip up your publish folder and post it on this issue? That might help me spot the issue. It may be a .deps.json
issue.
Yes. Very weird.. Now I published first as Portable
and then i republish (i don't know if visual studio delete all .dll files) with Win-x64
and after i published using Win-x64
over „Portable„ throw the error again.
Thanks for the .zip of your publish directory. It definitely makes it easier to understand what is happening.
Using your instructions, I now understand the difference and am able to reproduce the problem myself.
Using .csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.ServiceProcess.ServiceController" Version="5.0.0" />
</ItemGroup>
</Project>
and Program.cs:
using System;
using System.ServiceProcess;
namespace Repro48620
{
class Program
{
public static void Main(string[] args)
{
Console.WriteLine(new Service());
}
class Service : ServiceBase
{
}
}
}
win-x64
, leave 'Framework-dependent` the same, and publish againUnhandled exception. System.PlatformNotSupportedException: ServiceController enables manipulating and accessing Windows services and it is not applicable for other operating systems.
at System.ServiceProcess.ServiceBase..ctor()
at Repro48620.Program.Service..ctor()
at Repro48620.Program.Main(String[] args) in C:\Users\eerhardt\source\repos\Repro48620\Repro48620\Program.cs:line 10
Notice that if you delete the bin
and obj
folders and just publish directly for win-x64
, and run the published app, it works just fine. So for now, my suggestion is to ensure your publish directory is cleaned before publishing. That will help you avoid the problem.
The issue is that the first "portable" Publish
is laying down the PNSE version of System.ServiceProcess.ServiceController.dll
directly in the publish
directory, which is correct because this is a "portable" app. The windows-specific version is going into runtimes\win\lib\netstandard2.0
, where it is getting picked up correctly at runtime.
However, the 2nd framework-dependent / win-x64
publish is not overwriting the PNSE version of the file. But it should be, because this is no longer a "portable" publish. It is windows specific. So the windows specific assembly should be going directly to the publish
folder, and not into a runtimes\...
folder. I'm not exactly sure why publish isn't working correctly.
Since this is a "publish" bug, and not a runtime bug, I'm moving it to dotnet/sdk
.
cc @dsplaisted
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.
cc @vijayrkn
@eerhardt - Does it repro will 'dotnet publish' in commandline as well or is it specific to VS?
It repros as well on the commandline, but it is a bit harder to make it happen:
❯ dotnet publish -c Release -o C:\temp\Repro48620
❯ dotnet publish -c Release -r win-x64 -o C:\temp\Repro48620
❯ C:\temp\Repro48620\Repro48620.exe
Unhandled exception. System.PlatformNotSupportedException: ServiceController enables manipulating and accessing Windows services and it is not applicable for other operating systems.
at System.ServiceProcess.ServiceBase..ctor()
at Repro48620.Program.Service..ctor()
at Repro48620.Program.Main(String[] args) in C:\Users\eerhardt\source\repos\Repro48620\Repro48620\Program.cs:line 10
In order to repro it on the command line you need to publish to the same directory both times (by default they will go to different directories since you are setting -r
).
@eerhardt - Ah! that makes sense. Now I see why it surfaces more in the VS case since the same profile is updated. Do you know if 2 dlls have the same timestamp? May be msbuild is just skipping because it might be set to 'update only if newer'.
@marcpopMSFT - Based on the above response, I think some one from the sdk needs to take a look. This issue is not specific to VS. May be 'dotnet publish' should always overwrite all files. /cc @dsplaisted
@vijayrkn Should the UI change the target location as you change your target runtime? The command line repro while simple, is fairly niche and so may not be something we investigate.
@marcpopMSFT - I think this is not about the UI but about the correctness of a publish operation. Irrespective of what location the bits are copied to, I think it is the job of publish to copy the correct bits.
I understand it is more common in VS because of the same location but I don't think that should be the reason to move it out.
@vijayrkn if the issue is that the timestamps affect the order here, then this is the behavior of incremental publish that is hard for us to fix without getting rid of incremental publish. We're not sure how we'd fix it but the UI could specify different folders to ensure the customer doesn't hit this in that flow. So basically, we're not sure we can fix it.
Is it possible to introduce a force flag that would overwrite all files irrespective of the timestamp. This way we can retain the incremental behavior by default but allows for the "correct" behavior as well.
I don't know if incremental behavior is valuable by itself if we can't guarantee correctness. We can definitely make the UI changes on the VS side to reduce the impact surface area.
Hello again. Thanks to all the Microsoft employees who worked to fix this issue. With the latest stable version of Visual Studio (16.9.2 when i write this) this error is fixed, but I find another publish bug in this release.
The project is the same, but the publish method is different.
Target location: C:\Test
Delete existing files: False
Configuration: Release
Target Framework: net5.0
Target runtime: win-x86
If i publish using this publish configuration and the application is set to use Framework-Dependent
, the application return:
Unhandled exception. System.BadImageFormatException: Could not load file or assembly 'C:\Test\WebApplication1.dll'. An attempt was made to load a program with an incorrect format.
I also tried to publish via command line using this command line dotnet publish -r win-x86 -c Release -o "C:\Test\"
, which is the command for Self-Contained
the application returns the error below, even if the dll is present. (This error also is returned if i'm using Self-Contained
on the GUI)
Failed to load the dll from [C:\Test\hostpolicy.dll], HRESULT: 0x800700C1
An error occurred while loading required library hostpolicy.dll from [C:\Test\]
@MycroBeat if you delete all files in the c:\test folder and then publish, do you still see this issue? It may just be another symptom of the same issue where we assume you are publishing to different folders and so do not always overwrite/clean the target folder.
@marcpopMSFT Yes, i still see that issue.
Also, i run more tests on Framework Dependent
and Self-Contained
and i discovered this:
Framework Dependent
on Deployment Mode
Portable
: Working
win-x64
: Working
win-x86
: Returns System.BadImageFormatException
(error described by me)Portable
: Working
win-x64
: Working
win-x86
: Returns System.BadImageFormatException
(error described by me)Self-Contained
on Deployment Mode
win-x64
: Working
win-x86
: Returns Failed to load the dll from [C:\Test\hostpolicy.dll], HRESULT: 0x800700C1
(error described by me)win-x64
: Working
win-x86
: Returns Failed to load the dll from [C:\Test\hostpolicy.dll], HRESULT: 0x800700C1
(error described by me)To clarify, are you deleting the files in between each publish? For performance reasons, we do not overwrite every file in the publish folder as those are typically different folders. What about if you just publish to different directories for each RID?
@marcpopMSFT Yes, all files has been deleted after each publish.
What about if you just publish to different directories for each RID
Unfortunately, I get the same result as the one described above depending on deployment mode.
Can you try deleting the obj folder in between executions as well to narrow this down? We think maybe it's picking up a file from there instead.
Unfortunately, I get the same result. See a video below.
Ok, with your latest video we were able to sort out what's happening as the original publish to the same folder was a red herring. When you publish for x86, we expect you to run the project using the .exe. You can use dotnet.exe to run it but you have to use the dotnet.exe that matches the bitness you are trying to run and it's less recommended for a published self-contained application.
So in your case, you can run WebApplication1.exe or run "\Program Files (x86)\dotnet\dotnet.exe" WebApplication1.dll (if you have the x86 version installed). Do those options work for you?
When you publish for x86, we expect you to run the project using the .exe.
I haven't noticed that I can use .exe to start the web application. I only knew about Windows Services, putting the application as a service.
So in your case, you can run WebApplication1.exe or run "\Program Files (x86)\dotnet\dotnet.exe" WebApplication1.dll (if you have the x86 version installed). Do those options work for you?
Yes. If i run the x86 binary, the both deployment modes it's working correctly.
We switched to including an exe file for all .net Core builds in 3.1 I believe and it's really just a host for the .dll that sits next to it. Thanks for confirming that using the x86 dotnet.exe worked. If you're now unblocked, can this issue be closed?
Yeah, this issue can now be closed. Thank everyone for your help. <3
OK can someone basically summarise what it is you have to do to get this to work... I've been reading this thread for about 5 minutes and I'm still not there.
OK worked it out....
If you publish with "Framework-dependent" then realise you should have picked "Self-contained", before you publish again you need to delete the contents of the Publish folder using file explorer.
Visual Studio for other project types usually has an option to delete the contents before publishing... however there's no such option in this Visual Studio dialog...
Hello. Recently, i wanted to upgrade my websites from .net core 3.1 to .net 5, but i notice the visual studio return an warning (CA1416) on the host.RunAsService().
Describe the bug
The .NET 5 return Platform Not Supported if you try to use .NET 5 as a Windows Service application. Even if the
OperatingSystem.IsWindows
return true, the application return errors when i try to start on services.msc. This does not happen in .net core 3.1.To Reproduce
See @eerhardt's notes in https://github.com/dotnet/sdk/issues/16049#issuecomment-785189111 for simplified set of repro steps
To Reproduce Original
Windows Services via
IHostBuilder
On
Host.CreateDefaultBuilder
add .UseWindowsService()Main Program looks like this
Create service on cmd via
sc create
Windows Services via
IWebHostBuilder
The process is identical up to point 2, inclusive.
Use this code via WebHost to create Windows Service Run.
Create service on cmd via
sc create
The application will return
Exception Info: System.PlatformNotSupportedException: ServiceController enables manipulating and accessing Windows services and it is not applicable for other operating systems.
Further technical details
Visual Studio 16.8.5