如何从远程机器获取系统信息并本地展示?远程Windows服务实现咨询
实现远程Windows服务监控方案的分步指南
看起来你已经迈出了关键的第一步,接下来我们一步步把这个监控服务搭起来——核心思路是在远程机器部署一个轻量的Windows服务(托管数据采集API),本地通过HTTP调用获取监控数据,这样既不会干扰远程进程,又能安全高效地拿到你需要的系统信息。
一、重构数据采集逻辑(确保无干扰)
你已经能获取本地磁盘信息,现在扩展到CPU和进程,核心原则是只读采集,绝对不操作远程进程:
1. 磁盘空间采集(复用你的代码,优化为可复用方法)
using System.IO; using System.Linq; public static class SystemMonitor { public static List<DriveInfo> GetDiskInfo() { // 只获取就绪的固定磁盘,过滤光驱、网络驱动器这类无关设备 return DriveInfo.GetDrives() .Where(d => d.DriveType == DriveType.Fixed && d.IsReady) .ToList(); } }
2. CPU使用率采集
注意:PerformanceCounter第一次调用会返回0,需要先刷新一次,避免频繁创建实例造成性能开销:
using System.Diagnostics; using System.Threading; private static readonly PerformanceCounter _cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total"); public static float GetCpuUsage() { // 第一次调用初始化计数器 _cpuCounter.NextValue(); Thread.Sleep(1000); // 等待1秒获取准确值,可根据需求调整间隔 return _cpuCounter.NextValue(); }
3. 运行中进程采集
只读取进程的基础属性,绝对不调用Kill()、Start()等操作方法:
public static List<ProcessInfo> GetRunningProcesses() { return Process.GetProcesses() .Select(p => new ProcessInfo { ProcessName = p.ProcessName, Id = p.Id, MemoryUsage = p.WorkingSet64 / 1024 / 1024, // 转换为MB单位 StartTime = p.StartTime }) .ToList(); } // 定义DTO传递进程信息,避免直接序列化Process对象带来的问题 public class ProcessInfo { public string ProcessName { get; set; } public int Id { get; set; } public double MemoryUsage { get; set; } public DateTime StartTime { get; set; } }
二、将采集逻辑封装为可远程调用的服务(推荐用ASP.NET Core Web API托管Windows服务)
现在.NET Core/.NET 6+做Windows服务非常便捷,而且Web API的HTTP调用对本地客户端友好,不需要复杂的配置:
1. 创建ASP.NET Core Web API项目
选择「ASP.NET Core Web API」模板,然后修改项目文件,添加Windows服务支持:
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>net6.0-windows</TargetFramework> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> <OutputType>Exe</OutputType> <!-- 必须设置为Exe才能作为Windows服务运行 --> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.1" /> </ItemGroup> </Project>
2. 配置Program.cs,启用Windows服务托管
var builder = WebApplication.CreateBuilder(args); // 添加Windows服务托管支持,设置服务名称 builder.Host.UseWindowsService(options => { options.ServiceName = "RemoteSystemMonitorService"; }); // 添加控制器支持 builder.Services.AddControllers(); var app = builder.Build(); // 配置API路由 app.MapControllers(); // 监听所有IP的5000端口,方便远程访问 app.Run("http://0.0.0.0:5000");
3. 创建监控API控制器
using Microsoft.AspNetCore.Mvc; using System.Linq; [ApiController] [Route("api/monitor")] public class MonitorController : ControllerBase { [HttpGet("disk")] public IActionResult GetDiskInfo() { var disks = SystemMonitor.GetDiskInfo(); return Ok(disks.Select(d => new { DriveName = d.Name, TotalSpaceGB = d.TotalSize / 1024 / 1024 / 1024, FreeSpaceGB = d.AvailableFreeSpace / 1024 / 1024 / 1024, UsedSpaceGB = (d.TotalSize - d.AvailableFreeSpace) / 1024 / 1024 / 1024 })); } [HttpGet("cpu")] public IActionResult GetCpuUsage() { var cpuUsage = SystemMonitor.GetCpuUsage(); return Ok(new { UsagePercent = cpuUsage }); } [HttpGet("processes")] public IActionResult GetProcesses() { var processes = SystemMonitor.GetRunningProcesses(); return Ok(processes); } }
三、部署远程Windows服务
- 发布项目:在Visual Studio中右键项目→发布,选择「文件夹」作为发布目标,生成可执行文件。
- 安装服务:以管理员身份打开命令提示符,运行以下命令(替换为你的发布路径):
sc create RemoteSystemMonitorService binPath="C:\你的发布路径\RemoteSystemMonitorService.exe" start=autostart=auto表示开机自动启动服务- 推荐使用
LocalService账户运行服务(权限足够读取系统信息,安全性更高):sc config RemoteSystemMonitorService obj="NT AUTHORITY\LocalService"
- 启动服务:
sc start RemoteSystemMonitorService - 防火墙配置:在远程机器上开放5000端口(或你指定的端口),允许入站HTTP请求。
四、本地客户端调用远程服务
用HttpClient简单调用即可,示例代码如下:
using System.Net.Http.Json; public class RemoteMonitorClient { private readonly HttpClient _httpClient; public RemoteMonitorClient(string remoteIp) { _httpClient = new HttpClient { BaseAddress = new Uri($"http://{remoteIp}:5000/api/monitor/") }; } public async Task<List<DiskInfo>> GetDiskInfoAsync() { return await _httpClient.GetFromJsonAsync<List<DiskInfo>>("disk"); } public async Task<CpuInfo> GetCpuUsageAsync() { return await _httpClient.GetFromJsonAsync<CpuInfo>("cpu"); } public async Task<List<ProcessInfo>> GetProcessesAsync() { return await _httpClient.GetFromJsonAsync<List<ProcessInfo>>("processes"); } } // 对应API返回的DTO类 public class DiskInfo { public string DriveName { get; set; } public double TotalSpaceGB { get; set; } public double FreeSpaceGB { get; set; } public double UsedSpaceGB { get; set; } } public class CpuInfo { public float UsagePercent { get; set; } }
关键注意事项
- 权限控制:远程服务尽量使用
LocalService或NetworkService账户,避免使用管理员账户,降低安全风险。 - 性能优化:CPU采集不要过于频繁(比如10秒一次),进程采集可以缓存结果,避免每秒遍历所有进程。
- 无干扰保证:所有采集逻辑都只读取系统/进程的属性,绝对不调用任何修改或操作进程的方法,完全不会影响远程机器的运行进程。
内容的提问来源于stack exchange,提问作者Shah
相关产品推荐
相关产品推荐

