Windows 服务中获取本机的 IP 地址,核心是通过System.Net.NetworkInformation和System.Net命名空间下的 API,区分IPv4/IPv6 、内网 / 公网 、排除回环地址(127.0.0.1),下面是完整的 IP 获取方法,并集成到之前的服务代码中,确保获取的 IP 地址准确且实用。
一、核心 IP 获取方法
先封装通用的 IP 获取工具类,支持获取所有有效 IPv4 地址、首选 IPv4 地址(常用)、公网 IP(需联网),你可根据需求选择使用
cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
/// <summary>
/// IP地址获取工具类
/// </summary>
public static class IpHelper
{
/// <summary>
/// 获取本机所有有效IPv4地址(排除回环地址、虚拟网卡)
/// </summary>
/// <returns>IPv4地址列表</returns>
public static List<string> GetAllValidIPv4Addresses()
{
var ipList = new List<string>();
try
{
// 获取所有网络接口
foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
{
// 过滤:仅保留启用的、非回环、非隧道的物理/无线网卡
if (ni.OperationalStatus != OperationalStatus.Up ||
ni.NetworkInterfaceType == NetworkInterfaceType.Loopback ||
ni.NetworkInterfaceType == NetworkInterfaceType.Tunnel)
{
continue;
}
// 获取该网卡的IP地址信息
foreach (UnicastIPAddressInformation ipInfo in ni.GetIPProperties().UnicastAddresses)
{
// 仅保留IPv4地址,排除回环地址(127.0.0.1)
if (ipInfo.Address.AddressFamily == AddressFamily.InterNetwork &&
!IPAddress.IsLoopback(ipInfo.Address))
{
ipList.Add(ipInfo.Address.ToString());
}
}
}
}
catch (Exception ex)
{
throw new Exception("获取IPv4地址失败:" + ex.Message);
}
return ipList.Distinct().ToList(); // 去重
}
/// <summary>
/// 获取本机首选IPv4地址(第一个有效IPv4)
/// </summary>
/// <returns>首选IPv4地址,无则返回空</returns>
public static string GetPrimaryIPv4Address()
{
var allIps = GetAllValidIPv4Addresses();
return allIps.Count > 0 ? allIps[0] : string.Empty;
}
/// <summary>
/// 获取公网IP地址(需联网,调用第三方接口)
/// 注意:服务运行账户需有外网访问权限
/// </summary>
/// <returns>公网IP,获取失败则返回空</returns>
public static string GetPublicIPAddress()
{
try
{
// 调用免费的公网IP查询接口(备选:https://api.ipify.org、https://icanhazip.com)
using (var client = new WebClient())
{
client.Timeout = 5000; // 设置5秒超时
string publicIp = client.DownloadString("https://ifconfig.me/ip").Trim();
// 验证是否为合法IPv4
if (IPAddress.TryParse(publicIp, out IPAddress ip) && ip.AddressFamily == AddressFamily.InterNetwork)
{
return publicIp;
}
}
}
catch (Exception)
{
// 捕获超时/网络异常,返回空即可
}
return string.Empty;
}
}
二、集成到 Windows 服务中
将 IP 获取逻辑添加到之前的服务代码中,比如在服务启动时记录 IP 地址,或在定时任务中使用 IP 信息
cs
using System;
using System.ServiceProcess;
using System.Timers;
using System.Threading.Tasks;
using System.Threading;
namespace MultiTimerMultiTaskService
{
public partial class MultiTimerMultiTaskService : ServiceBase
{
private Timer _timerTask1;
private Timer _timerTask2;
public MultiTimerMultiTaskService()
{
InitializeComponent();
InitTimers();
}
private void InitTimers()
{
// 定时器1:每10秒执行,演示获取IP并记录
_timerTask1 = new Timer
{
Interval = 10 * 1000,
AutoReset = true,
Enabled = false
};
_timerTask1.Elapsed += TimerTask1_Elapsed;
_timerTask2 = new Timer
{
Interval = 30 * 1000,
AutoReset = true,
Enabled = false
};
_timerTask2.Elapsed += TimerTask2_Elapsed;
}
protected override void OnStart(string[] args)
{
try
{
WriteLog("多定时器多任务服务开始启动...");
// 服务启动时获取并记录IP地址
WriteLog("=== 本机网络信息 ===");
string primaryIp = IpHelper.GetPrimaryIPv4Address();
WriteLog($"首选内网IPv4:{ (string.IsNullOrEmpty(primaryIp) ? "未获取到" : primaryIp) }");
var allIps = IpHelper.GetAllValidIPv4Addresses();
WriteLog($"所有内网IPv4:{ (allIps.Count > 0 ? string.Join(",", allIps) : "未获取到") }");
string publicIp = IpHelper.GetPublicIPAddress();
WriteLog($"公网IPv4:{ (string.IsNullOrEmpty(publicIp) ? "未获取到(请检查网络)" : publicIp) }\n");
// 立即执行任务
ExecuteTask1Logic();
ExecuteTask2Logic();
// 启动定时器
_timerTask1.Enabled = true;
_timerTask2.Enabled = true;
WriteLog("服务启动完成,定时器已运行");
}
catch (Exception ex)
{
WriteLog($"服务启动失败:{ex.Message}");
this.Stop();
}
}
protected override void OnStop()
{
// 原有停止逻辑...
try
{
if (_timerTask1 != null)
{
_timerTask1.Enabled = false;
_timerTask1.Elapsed -= TimerTask1_Elapsed;
_timerTask1.Dispose();
_timerTask1 = null;
}
if (_timerTask2 != null)
{
_timerTask2.Enabled = false;
_timerTask2.Elapsed -= TimerTask2_Elapsed;
_timerTask2.Dispose();
_timerTask2 = null;
}
WriteLog("多定时器多任务服务已停止,所有资源已释放");
}
catch (Exception ex)
{
WriteLog($"服务停止失败:{ex.Message}");
}
}
// 定时器1任务:演示定时获取IP
private void TimerTask1_Elapsed(object sender, ElapsedEventArgs e)
{
var timer = (Timer)sender;
timer.Enabled = false;
try
{
ExecuteTask1Logic();
}
catch (Exception ex)
{
WriteLog($"定时器1执行异常:{ex.Message}");
}
finally
{
timer.Enabled = true;
}
}
private void ExecuteTask1Logic()
{
WriteLog("===== 定时器1任务执行(获取IP) =====");
// 定时任务中获取IP并使用
string currentIp = IpHelper.GetPrimaryIPv4Address();
WriteLog($"当前首选内网IP:{currentIp}");
// 此处可添加业务逻辑(比如用IP标识服务实例、上报IP等)
WriteLog("===== 定时器1任务执行完成 =====\n");
}
private void TimerTask2_Elapsed(object sender, ElapsedEventArgs e)
{
var timer = (Timer)sender;
timer.Enabled = false;
try
{
ExecuteTask2Logic();
}
catch (Exception ex)
{
WriteLog($"定时器2执行异常:{ex.Message}");
}
finally
{
timer.Enabled = true;
}
}
private void ExecuteTask2Logic()
{
// 原有定时器2逻辑...
WriteLog("===== 执行定时器2任务(立即/定时触发) =====");
var taskList = new[]
{
Task.Factory.StartNew(() => ExecuteSubTask("定时器2-子任务1(报表生成)", 3000)),
Task.Factory.StartNew(() => ExecuteSubTask("定时器2-子任务2(邮件发送)", 2500))
};
Task.WaitAll(taskList);
WriteLog("===== 定时器2任务执行完成 =====\n");
}
private void ExecuteSubTask(string taskName, int executeTimeMs)
{
try
{
WriteLog($"{taskName} 开始执行(线程ID:{Thread.CurrentThread.ManagedThreadId})");
Thread.Sleep(executeTimeMs);
WriteLog($"{taskName} 执行完成");
}
catch (Exception ex)
{
WriteLog($"{taskName} 执行失败:{ex.Message}(线程ID:{Thread.CurrentThread.ManagedThreadId})");
}
}
private void WriteLog(string content)
{
string logPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
if (!System.IO.Directory.Exists(logPath))
{
System.IO.Directory.CreateDirectory(logPath);
}
string logFile = $"ServiceLog_{DateTime.Now:yyyy-MM-dd}.txt";
string fullPath = System.IO.Path.Combine(logPath, logFile);
using (var sw = new System.IO.StreamWriter(fullPath, true, System.Text.Encoding.UTF8))
{
sw.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} | {content}");
}
}
}
}