如何从 VS 2022 创建的 gRPC 服务器创建 Windows 服务?

Vel*_*dge 5 c# windows-services grpc

我通过选择“ASP NET Core gRPC Service”模板和.Net 6 Core,在 Visual Studio 2022 Community Preview 中创建了一个 gRPC 服务器。我打算替换四个现有的.Net Framework Windows 服务,它们都使用WCF。因此,我并不是在寻找如何创建 Windows 服务的替代方法。

从 VS 2022 生成的代码创建了一个program.cs(无注释),如下所示:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc();
var app = builder.Build();
app.MapGrpcService<GreeterService>();
app.MapGet("/", () => "Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");
app.Run();
Run Code Online (Sandbox Code Playgroud)

我能找到的每个示例均与该program.cs 的内容不匹配。此外,所有示例都包含生成的startup.cs 文件。我的项目没有创建startup.cs 文件。所有示例均显示包括 NuGet 包 Microsoft.Extensions.Hosting.WindowsServices 并添加 UseWindowsServices 参数。

Host.CreateDefaultBuilder(args)
    .UseWindowsService()
    ...
Run Code Online (Sandbox Code Playgroud)

我没有 Host 或 CreateDefaultBuilder 方法。我尝试添加以下行:

builder.Host.UseWindowsService();
Run Code Online (Sandbox Code Playgroud)

该程序在 VS 或命令行中运行时可以完美编译并运行。我可以使用 netstat 查看端口:

netstat -an | find "6276"
C:\Users\Steve>netstat -an | find "6276"
  TCP    127.0.0.1:6276         0.0.0.0:0              LISTENING
  TCP    [::1]:6276             [::]:0                 LISTENING
Run Code Online (Sandbox Code Playgroud)

但是当我将它作为 Windows 服务运行时,它没有侦听指定的端口。

netstat -an | find "6276"
C:\Users\Steve>
Run Code Online (Sandbox Code Playgroud)

我尝试了 .Net 6.0 和 .Net 7.0 预览版 7,在后者上选中和取消选中“不要使用顶级语句”。行为没有改变。

因此,显然 Visual Studio 更改了 gRPC 的模板输出,但还没有人用它创建 Windows 服务……或者至少没有显示它是如何完成的。

有谁知道如何获取最新的 gRPC 模板并从中创建 Windows 服务?

Art*_*tur 10

这是使用默认模板创建的最小应用程序的示例,并进行了一些修改(请参阅代码注释)

项目文件

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>
    <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Grpc.AspNetCore" Version="2.40.0" />
    <!-- Install additional packages -->
    <PackageReference Include="Grpc.AspNetCore.Server.Reflection" Version="2.40.0" />
    <PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.0" />
  </ItemGroup>

</Project>
Run Code Online (Sandbox Code Playgroud)

程序.cs

using GrpcService1.Services;
using Microsoft.Extensions.Hosting.WindowsServices;

// Use WebApplicationOptions to set the ContentRootPath
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
    Args = args,
    ContentRootPath = WindowsServiceHelpers.IsWindowsService()
        ? AppContext.BaseDirectory
        : default
});

// Set WindowsServiceLifetime
builder.Host.UseWindowsService();

builder.Services.AddGrpc();

// Add reflection services
builder.Services.AddGrpcReflection();

var app = builder.Build();

app.MapGrpcService<GreeterService>();

// Map reflection endpoint
app.MapGrpcReflectionService();

app.Run();
Run Code Online (Sandbox Code Playgroud)

现在在项目文件夹中打开cmd并执行

dotnet publish
Run Code Online (Sandbox Code Playgroud)

publish命令将生成该exe文件(我假设您正在 Windows 计算机上工作,否则您将如何测试 Windows 服务?)。在我的机器上的路径exe

"C:\github\junk\GrpcService1\bin\Debug\net6.0\publish\GrpcService1.exe"
Run Code Online (Sandbox Code Playgroud)

现在以管理员身份打开cmd并运行以下命令

sc.exe create "GrpcService" binpath="C:\github\junk\GrpcService1\bin\Debug\net6.0\publish\GrpcService1.exe"
Run Code Online (Sandbox Code Playgroud)

打开Services并启动GrpcService. 现在安装并运行grpcui 工具

grpcui -plaintext localhost:5000
Run Code Online (Sandbox Code Playgroud)

grpcui 工具将打开 UI,您应该能够在其中看到 Greeter 服务在此输入图像描述

笔记:

  • 我使用了WebApplication.CreateBuilder(new WebApplicationOptions()),因为没有它,服务将无法启动。Windows 事件查看器显示错误:

描述:由于未处理的异常,进程被终止。异常信息:System.NotSupportedException:内容根目录从“C:\Windows\system32”更改为“C:\github\junk\GrpcService1\bin\Debug\net6.0\publish”。不支持使用 WebApplicationBuilder.Host 更改主机配置。请改用 WebApplication.CreateBuilder(WebApplicationOptions)。

在这里找到了解决方案。

  • 默认情况下,应用程序将在端口 上启动5000。如果您想使用其他端口,请--urls在创建服务时添加参数
sc.exe create "GrpcService" binpath="C:\github\junk\GrpcService1\bin\Debug\net6.0\publish\GrpcService1.exe --urls \"http://localhost:6276\""
Run Code Online (Sandbox Code Playgroud)