236 lines
7.7 KiB
C#
236 lines
7.7 KiB
C#
using Intel.Management.Wsman;
|
|
using System.Security;
|
|
|
|
namespace AmtScanner.Api.Services;
|
|
|
|
public interface IAmtPowerService
|
|
{
|
|
Task<PowerStateResult> GetPowerStateAsync(string ipAddress, string username, string password, List<int> openPorts);
|
|
Task<PowerActionResult> ChangePowerStateAsync(string ipAddress, string username, string password, List<int> openPorts, PowerAction action);
|
|
}
|
|
|
|
public enum PowerAction
|
|
{
|
|
PowerOn = 2,
|
|
PowerCycle = 5, // 重启(硬重启)
|
|
PowerOff = 8, // 关机(硬关机)
|
|
Reset = 10, // 重置
|
|
GracefulOff = 12, // 优雅关机
|
|
GracefulReset = 14 // 优雅重启
|
|
}
|
|
|
|
public class PowerStateResult
|
|
{
|
|
public bool Success { get; set; }
|
|
public int PowerState { get; set; }
|
|
public string PowerStateText { get; set; } = string.Empty;
|
|
public string? Error { get; set; }
|
|
}
|
|
|
|
public class PowerActionResult
|
|
{
|
|
public bool Success { get; set; }
|
|
public string Message { get; set; } = string.Empty;
|
|
public string? Error { get; set; }
|
|
}
|
|
|
|
public class AmtPowerService : IAmtPowerService
|
|
{
|
|
private readonly ILogger<AmtPowerService> _logger;
|
|
|
|
public AmtPowerService(ILogger<AmtPowerService> logger)
|
|
{
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task<PowerStateResult> GetPowerStateAsync(
|
|
string ipAddress,
|
|
string username,
|
|
string password,
|
|
List<int> openPorts)
|
|
{
|
|
var result = new PowerStateResult();
|
|
|
|
try
|
|
{
|
|
var connection = CreateConnection(ipAddress, username, password, openPorts);
|
|
|
|
await Task.Run(() =>
|
|
{
|
|
// 使用 SDK 中的方式查询电源状态
|
|
var computerSysRef = connection.NewReference("SELECT * FROM CIM_ComputerSystem WHERE Name='ManagedSystem'");
|
|
var associatedPowerMgmtRef = connection.NewReference("CIM_AssociatedPowerManagementService");
|
|
associatedPowerMgmtRef.AddSelector("UserOfService", computerSysRef);
|
|
|
|
foreach (IWsmanItem item in associatedPowerMgmtRef.Enumerate(
|
|
"http://schemas.dmtf.org/wbem/wsman/1/wsman/SelectorFilter", null))
|
|
{
|
|
if (item.Object.GetProperty("ServiceProvided").IsA("CIM_PowerManagementService"))
|
|
{
|
|
var powerState = Convert.ToInt32(item.Object.GetProperty("PowerState").ToString());
|
|
result.PowerState = powerState;
|
|
result.PowerStateText = GetPowerStateText(powerState);
|
|
result.Success = true;
|
|
break;
|
|
}
|
|
}
|
|
});
|
|
|
|
if (!result.Success)
|
|
{
|
|
result.Error = "无法获取电源状态";
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "获取电源状态失败: {Ip}", ipAddress);
|
|
result.Error = ex.Message;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<PowerActionResult> ChangePowerStateAsync(
|
|
string ipAddress,
|
|
string username,
|
|
string password,
|
|
List<int> openPorts,
|
|
PowerAction action)
|
|
{
|
|
var result = new PowerActionResult();
|
|
|
|
try
|
|
{
|
|
_logger.LogInformation("执行电源操作: {Action} on {Ip}", action, ipAddress);
|
|
|
|
var connection = CreateConnection(ipAddress, username, password, openPorts);
|
|
|
|
await Task.Run(() =>
|
|
{
|
|
// 获取电源管理服务
|
|
var powerManagementRef = connection.NewReference(
|
|
"SELECT * FROM CIM_PowerManagementService WHERE Name='Intel(r) AMT Power Management Service'");
|
|
|
|
// 创建输入参数
|
|
var inputObject = powerManagementRef.CreateMethodInput("RequestPowerStateChange");
|
|
inputObject.SetProperty("PowerState", ((int)action).ToString());
|
|
|
|
// 设置目标计算机系统
|
|
var computerSystemRef = connection.NewReference(
|
|
"SELECT * FROM CIM_ComputerSystem WHERE Name='ManagedSystem'");
|
|
inputObject.SetProperty("ManagedElement", computerSystemRef);
|
|
|
|
// 调用方法
|
|
var outputObject = powerManagementRef.InvokeMethod(inputObject);
|
|
var returnValue = outputObject.GetProperty("ReturnValue");
|
|
|
|
var returnCode = Convert.ToUInt32(returnValue.ToString());
|
|
|
|
if (returnCode == 0)
|
|
{
|
|
result.Success = true;
|
|
result.Message = GetActionSuccessMessage(action);
|
|
}
|
|
else if (returnCode == 2)
|
|
{
|
|
result.Success = false;
|
|
result.Error = "操作不允许:当前系统状态不支持此操作";
|
|
}
|
|
else
|
|
{
|
|
result.Success = false;
|
|
result.Error = $"操作失败,错误代码: {returnCode}";
|
|
}
|
|
});
|
|
|
|
_logger.LogInformation("电源操作完成: {Action} on {Ip}, Success: {Success}",
|
|
action, ipAddress, result.Success);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "电源操作失败: {Action} on {Ip}", action, ipAddress);
|
|
result.Error = ex.Message;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private WsmanConnection CreateConnection(string ipAddress, string username, string password, List<int> openPorts)
|
|
{
|
|
string protocol;
|
|
int port;
|
|
|
|
if (openPorts.Contains(16992))
|
|
{
|
|
protocol = "http";
|
|
port = 16992;
|
|
}
|
|
else if (openPorts.Contains(16993))
|
|
{
|
|
protocol = "https";
|
|
port = 16993;
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("没有找到可用的AMT端口");
|
|
}
|
|
|
|
var securePassword = new SecureString();
|
|
foreach (char c in password)
|
|
{
|
|
securePassword.AppendChar(c);
|
|
}
|
|
securePassword.MakeReadOnly();
|
|
|
|
var connection = new WsmanConnection();
|
|
connection.Address = $"{protocol}://{ipAddress}:{port}/wsman";
|
|
connection.SetCredentials(username, securePassword);
|
|
|
|
if (protocol == "https")
|
|
{
|
|
connection.Options.ServerCertificateValidationCallback = (certificate, sslPolicyErrors) =>
|
|
{
|
|
if (certificate.Subject.Equals(certificate.Issuer))
|
|
return true;
|
|
if (sslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
|
|
return true;
|
|
return false;
|
|
};
|
|
}
|
|
|
|
return connection;
|
|
}
|
|
|
|
private string GetPowerStateText(int powerState)
|
|
{
|
|
return powerState switch
|
|
{
|
|
2 => "开机",
|
|
3 => "轻度睡眠",
|
|
4 => "深度睡眠",
|
|
5 => "电源循环(软)",
|
|
6 => "硬关机",
|
|
7 => "休眠",
|
|
8 => "软关机",
|
|
9 => "电源循环(硬)",
|
|
10 => "主总线重置",
|
|
11 => "诊断中断",
|
|
_ => $"未知状态 ({powerState})"
|
|
};
|
|
}
|
|
|
|
private string GetActionSuccessMessage(PowerAction action)
|
|
{
|
|
return action switch
|
|
{
|
|
PowerAction.PowerOn => "开机命令已发送",
|
|
PowerAction.PowerCycle => "重启命令已发送",
|
|
PowerAction.PowerOff => "关机命令已发送",
|
|
PowerAction.Reset => "重置命令已发送",
|
|
PowerAction.GracefulOff => "优雅关机命令已发送",
|
|
PowerAction.GracefulReset => "优雅重启命令已发送",
|
|
_ => "电源操作命令已发送"
|
|
};
|
|
}
|
|
}
|