.NET Core获取程序运行行环境信息与反射的应用

简介: .NET Core获取程序运行行环境信息与反射的应用

RuntimeInformation、Environment


RuntimeInformation 类提供有关 .NET 运行时安装的信息。主要获取平台以及 版本,API较少。


文档地址 https://docs.microsoft.com/zh-cn/dotnet/api/system.runtime.interopservices.runtimeinformation?view=netcore-3.1

Environment 提供有关当前环境和平台的信息以及操作它们的方法。API比较多。

文档地址 https://docs.microsoft.com/zh-cn/dotnet/api/system.environment?view=netcore-3.1


以上两个类已经提供了文档地址,这里不再赘述。

需要注意的是,Windows、Linux 之间有差异,因此有些 API 是无法跨平台的。另外 .NET Core 相对 .NET Framework ,对获取系统资源信息等的 API 十分少。

.NET Core 是无有 API 获取系统 CPU 情况和 内存使用情况,倒是可以获取当前进程的 CPU 和 内存使用情况。

可以查看 stackoverflow 了解。

https://stackoverflow.com/questions/54215334/how-to-measure-cpu-usage-and-memory-for-a-process-in-net-core-linux


获取信息


下面获取的属于进程使用的内存已经使用 CPU 时间。

CPU 时间不像直接获取到的 使用百分比,可以很直观地看到。

CPU 时间地公式如下。


CPU时间 = 执行程序所需的时钟周期数 * 时钟周期时间

CPU 有多核多线程,因此不能按照运行多长时间去计算。同时进程存在休眠、上下文切换等情况。


程序运行了几小时,有可能CPU时间只有几十分钟。

对 CPU 性能计算方法有兴趣,请参考 https://www.cnblogs.com/whuanle/p/12260224.html

对 Linux CPU 使用率计算有兴趣,请查看 https://www.cnblogs.com/aresxin/p/9152127.html

我们在 C# 中使用地代码如下


[Display(Name = "运行信息")]
    public class ApplicationRunInfo
    {
        private double _UsedMem;
        private double _UsedCPUTime;
        public ApplicationRunInfo()
        {
            var proc = Process.GetCurrentProcess();
            var mem = proc.WorkingSet64;
            var cpu = proc.TotalProcessorTime;
            _UsedMem = mem / 1024.0;
            _UsedCPUTime = cpu.TotalMilliseconds;
        }
        [Display(Name = "进程已使用物理内存(kb)")]
        public double UsedMem { get { return _UsedMem; } }
        [Display(Name = "进程已占耗CPU时间(ms)")]
        public double UsedCPUTime { get { return _UsedCPUTime; } }
    }


这里只有两个属性。

我们使用 Display 特性来标记此属性地的含义,方便反射时获取信息。

另外还有两个获取不同类型信息的类如下


[Display(Name = "系统运行平台")]
    public class SystemPlatformInfo
    {
        [Display(Name = "运行框架")]
        public string FrameworkDescription { get { return RuntimeInformation.FrameworkDescription; } }
        [Display(Name = "操作系统")]
        public string OSDescription { get { return RuntimeInformation.OSDescription; } }
        [Display(Name = "操作系统版本")]
        public string OSVersion { get { return Environment.OSVersion.ToString(); } }
        [Display(Name = "平台架构")]
        public string OSArchitecture { get { return RuntimeInformation.OSArchitecture.ToString(); } }
    }
    [Display(Name = "运行环境")]
    public class SystemRunEvnInfo
    {
        [Display(Name = "机器名称")]
        public string MachineName { get { return Environment.MachineName; } }
        [Display(Name = "用户网络域名")]
        public string UserDomainName { get { return Environment.UserDomainName; } }
        [Display(Name = "分区磁盘")]
        public string GetLogicalDrives { get { return string.Join(", ", Environment.GetLogicalDrives()); } }
        [Display(Name = "系统目录")]
        public string SystemDirectory { get { return Environment.SystemDirectory; } }
        [Display(Name = "系统已运行时间(毫秒)")]
        public int TickCount { get { return Environment.TickCount; } }
        [Display(Name = "是否在交互模式中运行")]
        public bool UserInteractive { get { return Environment.UserInteractive; } }
        [Display(Name = "当前关联用户名")]
        public string UserName { get { return Environment.UserName; } }
        [Display(Name = "Web程序核心框架版本")]
        public string Version { get { return Environment.Version.ToString(); } }
        //对Linux无效
        [Display(Name = "磁盘分区")]
        public string SystemDrive { get { return Environment.ExpandEnvironmentVariables("%SystemDrive%"); } }
        //对Linux无效
        [Display(Name = "系统目录")]
        public string SystemRoot { get { return Environment.ExpandEnvironmentVariables("%SystemRoot%"); } }
    }


可能你会觉得,为什么不写成方法,为啥要写得这么奇怪。不急,慢慢看下去~

反射获取信息


我们来定义一个静态类型,作为获取各种信息的入口。


public static class EnvironmentInfo
{
}
}


获取属性值

反射获取属性值的方法,用于获取上述几个类的属性值。


/// <summary>
        /// 获取属性的值
        /// </summary>
        /// <param name="info"></param>
        /// <param name="obj">实例</param>
        /// <returns></returns>
        private static object GetPropertyInfoValue(PropertyInfo info, object obj)
        {
            return info.GetValue(obj);
        }


反射获取特性值

我们使用了特性 [Display(Name = "当前关联用户名")] 来存储别名。

我们要通过反射获取 Dispaly 特性的 Name 属性值。


/// <summary>
        /// 获取 [Display] 特性的属性 Name 的值
        /// </summary>
        /// <param name="attrs"></param>
        /// <returns></returns>
        private static string GetDisplayNameValue(IList<CustomAttributeData> attrs)
        {
            var argument = attrs.FirstOrDefault(x => x.AttributeType.Name == nameof(DisplayAttribute)).NamedArguments;
            return argument.FirstOrDefault(x => x.MemberName == nameof(DisplayAttribute.Name)).TypedValue.Value.ToString();
        }


获取某个属性的值以及别名


我们使用了这样的方式去设置获取一项信息


[Display(Name = "操作系统")]
        public string OSDescription { get { return RuntimeInformation.OSDescription; } }


因此我们要获取到一个类型所有的属性值和属性的特性值。


/// <summary>
        /// 获取某个类型的值以及名称
        /// </summary>
        /// <typeparam name="TInfo"></typeparam>
        /// <param name="info"></param>
        /// <returns></returns>
        private static (string, List<KeyValuePair<string, object>>) GetValues<TInfo>(TInfo info)
        {
            List<KeyValuePair<string, object>> list = new List<KeyValuePair<string, object>>();
            Type type = info.GetType();
            PropertyInfo[] pros = type.GetProperties();
            foreach (var item in pros)
            {
                var name = GetDisplayNameValue(item.GetCustomAttributesData());
                var value = GetPropertyInfoValue(item, info);
                list.Add(new KeyValuePair<string, object>(name, value));
            }
            return
                (GetDisplayNameValue(info.GetType().GetCustomAttributesData()),
                list);
        }


反射获取信息


上面的工具方法定义后,我们来设置不同的方法获取不同的信息。


/// <summary>
        /// 获取程序运行资源信息
        /// </summary>
        /// <returns></returns>
        public static (string, List<KeyValuePair<string, object>>) GetApplicationRunInfo()
        {
            ApplicationRunInfo info = new ApplicationRunInfo();
            return GetValues(info);
        }
        /// <summary>
        /// 获取系统运行平台信息
        /// </summary>
        /// <returns></returns>
        public static (string, List<KeyValuePair<string, object>>) GetSystemPlatformInfo()
        {
            SystemPlatformInfo info = new SystemPlatformInfo();
            return GetValues(info);
        }
        /// <summary>
        /// 获取系统运行环境信息
        /// </summary>
        /// <returns></returns>
        public static (string, List<KeyValuePair<string, object>>) GetSystemRunEvnInfo()
        {
            SystemRunEvnInfo info = new SystemRunEvnInfo();
            return GetValues(info);
        }


还有一个方法获取环境变量的,不需要利用上面的类型-属性来操作,可以直接封装到方法中。


/// <summary>
        /// 获取系统全部环境变量
        /// </summary>
        /// <returns></returns>
        public static (string, List<KeyValuePair<string, object>>) GetEnvironmentVariables()
        {
            List<KeyValuePair<string, object>> list = new List<KeyValuePair<string, object>>();
            IDictionary environmentVariables = Environment.GetEnvironmentVariables();
            foreach (DictionaryEntry de in environmentVariables)
            {
                list.Add(new KeyValuePair<string, object>(de.Key.ToString(), de.Value));
            }
            return ("系统环境变量", list);
        }


使用


我们在 Program 中,这些写就可以输出所有信息了


static void Main(string[] args)
        {
            var a = EnvironmentInfo.GetApplicationRunInfo();
            var b = EnvironmentInfo.GetSystemPlatformInfo();
            var c = EnvironmentInfo.GetSystemRunEvnInfo();
            var d = EnvironmentInfo.GetEnvironmentVariables();
            ConsoleInfo(a.Item1, a.Item2);
            ConsoleInfo(b.Item1, b.Item2);
            ConsoleInfo(c.Item1, c.Item2);
            ConsoleInfo(d.Item1, d.Item2);
            Console.ReadKey();
        }
        public static void ConsoleInfo(string title, List<KeyValuePair<string, object>> list)
        {
            Console.WriteLine("\n***********" + title + "***********");
            foreach (var item in list)
            {
                Console.WriteLine(item.Key + ":" + item.Value);
            }
        }


在 Linux 中显示


微信图片_20220503114225.png


总结


我以上使用了 类-属性 来作为获取功能,这样可以不必写很多方法去调用获取环境信息,属性就是数据。既方便序列化,又方便反射。


同时,如果先拓展信息项,直接添加上去就行,反射直接全部拿到手。

另外有个 Display 特性,专业用来显示信息项的。这样设置,可以为属性灵活设置别名,便于显示信息以及说明。


笔者会继续带来更多反射的使用实例,融入到日常需求中。

相关文章
|
14天前
|
开发框架 .NET 开发者
简化 ASP.NET Core 依赖注入(DI)注册-Scrutor
Scrutor 是一个简化 ASP.NET Core 应用程序中依赖注入(DI)注册过程的开源库,支持自动扫描和注册服务。通过简单的配置,开发者可以轻松地从指定程序集中筛选、注册服务,并设置其生命周期,同时支持服务装饰等高级功能。适用于大型项目,提高代码的可维护性和简洁性。仓库地址:&lt;https://github.com/khellang/Scrutor&gt;
37 5
|
2月前
|
存储 开发框架 JSON
ASP.NET Core OData 9 正式发布
【10月更文挑战第8天】Microsoft 在 2024 年 8 月 30 日宣布推出 ASP.NET Core OData 9,此版本与 .NET 8 的 OData 库保持一致,改进了数据编码以符合 OData 规范,并放弃了对旧版 .NET Framework 的支持,仅支持 .NET 8 及更高版本。新版本引入了更快的 JSON 编写器 `System.Text.UTF8JsonWriter`,优化了内存使用和序列化速度。
|
1月前
|
开发框架 .NET C#
在 ASP.NET Core 中创建 gRPC 客户端和服务器
本文介绍了如何使用 gRPC 框架搭建一个简单的“Hello World”示例。首先创建了一个名为 GrpcDemo 的解决方案,其中包含一个 gRPC 服务端项目 GrpcServer 和一个客户端项目 GrpcClient。服务端通过定义 `greeter.proto` 文件中的服务和消息类型,实现了一个简单的问候服务 `GreeterService`。客户端则通过 gRPC 客户端库连接到服务端并调用其 `SayHello` 方法,展示了 gRPC 在 C# 中的基本使用方法。
41 5
在 ASP.NET Core 中创建 gRPC 客户端和服务器
|
20天前
|
算法 Java 测试技术
Benchmark.NET:让 C# 测试程序性能变得既酷又简单
Benchmark.NET是一款专为 .NET 平台设计的性能基准测试框架,它可以帮助你测量代码的执行时间、内存使用情况等性能指标。它就像是你代码的 "健身教练",帮助你找到瓶颈,优化性能,让你的应用跑得更快、更稳!希望这个小教程能让你在追求高性能的路上越走越远,享受编程带来的无限乐趣!
68 13
|
22天前
|
开发框架 缓存 .NET
GraphQL 与 ASP.NET Core 集成:从入门到精通
本文详细介绍了如何在ASP.NET Core中集成GraphQL,包括安装必要的NuGet包、创建GraphQL Schema、配置GraphQL服务等步骤。同时,文章还探讨了常见问题及其解决方法,如处理复杂查询、错误处理、性能优化和实现认证授权等,旨在帮助开发者构建灵活且高效的API。
24 3
|
1月前
|
开发框架 监控 .NET
【Azure App Service】部署在App Service上的.NET应用内存消耗不能超过2GB的情况分析
x64 dotnet runtime is not installed on the app service by default. Since we had the app service running in x64, it was proxying the request to a 32 bit dotnet process which was throwing an OutOfMemoryException with requests >100MB. It worked on the IaaS servers because we had the x64 runtime install
|
1月前
|
JSON 算法 安全
JWT Bearer 认证在 .NET Core 中的应用
【10月更文挑战第30天】JWT(JSON Web Token)是一种开放标准,用于在各方之间安全传输信息。它由头部、载荷和签名三部分组成,用于在用户和服务器之间传递声明。JWT Bearer 认证是一种基于令牌的认证方式,客户端在请求头中包含 JWT 令牌,服务器验证令牌的有效性后授权用户访问资源。在 .NET Core 中,通过安装 `Microsoft.AspNetCore.Authentication.JwtBearer` 包并配置认证服务,可以实现 JWT Bearer 认证。具体步骤包括安装 NuGet 包、配置认证服务、启用认证中间件、生成 JWT 令牌以及在控制器中使用认证信息
102 2
|
3月前
|
开发框架 监控 前端开发
在 ASP.NET Core Web API 中使用操作筛选器统一处理通用操作
【9月更文挑战第27天】操作筛选器是ASP.NET Core MVC和Web API中的一种过滤器,可在操作方法执行前后运行代码,适用于日志记录、性能监控和验证等场景。通过实现`IActionFilter`接口的`OnActionExecuting`和`OnActionExecuted`方法,可以统一处理日志、验证及异常。创建并注册自定义筛选器类,能提升代码的可维护性和复用性。
|
2月前
|
开发框架 JavaScript 前端开发
一个适用于 ASP.NET Core 的轻量级插件框架
一个适用于 ASP.NET Core 的轻量级插件框架
|
2月前
|
XML 存储 安全
C#开发的程序如何良好的防止反编译被破解?ConfuserEx .NET混淆工具使用介绍
C#开发的程序如何良好的防止反编译被破解?ConfuserEx .NET混淆工具使用介绍
116 0