1- // COPYRIGHT 2015 by the Open Rails project.
2- //
1+ // COPYRIGHT 2009 - 2023 by the Open Rails project.
2+ //
33// This file is part of Open Rails.
4- //
4+ //
55// Open Rails is free software: you can redistribute it and/or modify
66// it under the terms of the GNU General Public License as published by
77// the Free Software Foundation, either version 3 of the License, or
88// (at your option) any later version.
9- //
9+ //
1010// Open Rails is distributed in the hope that it will be useful,
1111// but WITHOUT ANY WARRANTY; without even the implied warranty of
1212// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1313// GNU General Public License for more details.
14- //
14+ //
1515// You should have received a copy of the GNU General Public License
1616// along with Open Rails. If not, see <http://www.gnu.org/licenses/>.
1717
18- using Microsoft . Win32 ;
1918using System ;
20- using System . Diagnostics ;
2119using System . IO ;
20+ using System . Linq ;
2221using System . Management ;
2322using System . Runtime . InteropServices ;
24- using System . Text ;
25- using System . Windows . Forms ;
26- using Microsoft . Xna . Framework . Graphics ;
23+ using System . Text . RegularExpressions ;
24+ using System . Collections . Generic ;
25+ using System . Globalization ;
2726
2827namespace ORTS . Common
2928{
3029 public static class SystemInfo
3130 {
32- public static void WriteSystemDetails ( TextWriter output )
31+ static readonly Regex NameAndVersionRegex = new Regex ( "^(.*?) +([0-9.]+)$" ) ;
32+ static readonly NativeStructs . MemoryStatusExtended MemoryStatusExtended = new NativeStructs . MemoryStatusExtended ( )
3333 {
34- output . WriteLine ( "Date/time = {0} ({1:u})" , DateTime . Now , DateTime . UtcNow ) ;
35- WriteEnvironment ( output ) ;
36- WriteAvailableRuntimes ( output ) ;
37- output . WriteLine ( "Runtime = {0} ({1}bit)" , Environment . Version , IntPtr . Size * 8 ) ;
38- WriteGraphicsAdapter ( output ) ;
39- }
34+ Size = 64
35+ } ;
4036
41- static void WriteEnvironment ( TextWriter output )
37+ static SystemInfo ( )
4238 {
43- var buffer = new NativeStructs . MemoryStatusExtended { Size = 64 } ;
44- NativeMethods . GlobalMemoryStatusEx ( buffer ) ;
45- try
46- {
47- foreach ( ManagementObject bios in new ManagementClass ( "Win32_BIOS" ) . GetInstances ( ) )
48- {
49- output . WriteLine ( "BIOS = {0} ({1})" , ( string ) bios [ "Description" ] , ( string ) bios [ "Manufacturer" ] ) ;
50- }
51- }
52- catch ( Exception error )
53- {
54- Trace . WriteLine ( error ) ;
55- }
56- try
39+ Application = new Platform
5740 {
58- foreach ( ManagementObject processor in new ManagementClass ( "Win32_Processor" ) . GetInstances ( ) )
59- {
60- output . Write ( "Processor = {0} ({2} threads, {1} cores, {3:F1} GHz)" , ( string ) processor [ "Name" ] , ( uint ) processor [ "NumberOfCores" ] , ( uint ) processor [ "NumberOfLogicalProcessors" ] , ( float ) ( uint ) processor [ "MaxClockSpeed" ] / 1000 ) ;
61- foreach ( ManagementObject cpuCache in processor . GetRelated ( "Win32_CacheMemory" ) )
62- {
63- output . Write ( " ({0} {1:F0} KB)" , ( string ) cpuCache [ "Purpose" ] , ( float ) ( uint ) cpuCache [ "InstalledSize" ] ) ;
64- }
65- output . WriteLine ( ) ;
66- }
67- }
68- catch ( Exception error )
69- {
70- Trace . WriteLine ( error ) ;
71- }
72- output . WriteLine ( "Memory = {0:F1} GB" , ( float ) buffer . TotalPhysical / 1024 / 1024 / 1024 ) ;
73- try
74- {
75- foreach ( ManagementObject display in new ManagementClass ( "Win32_VideoController" ) . GetInstances ( ) )
76- {
77- // ? used as display["AdapterRAM"] may be null on a virtual machine (e.g. VMWare)
78- output . WriteLine ( "Video = {0} ({1:F1} GB RAM){2}" , ( string ) display [ "Description" ] , ( float ? ) ( uint ? ) display [ "AdapterRAM" ] / 1024 / 1024 / 1024 , GetPnPDeviceDrivers ( display ) ) ;
79- }
80- }
81- catch ( Exception error )
82- {
83- Trace . WriteLine ( error ) ;
84- }
85- try
86- {
87- foreach ( var screen in Screen . AllScreens )
88- {
89- output . WriteLine ( "Display = {0} ({3} x {4}, {5}-bit{6}, {1} x {2})" , screen . DeviceName , screen . Bounds . X , screen . Bounds . Y , screen . Bounds . Width , screen . Bounds . Height , screen . BitsPerPixel , screen . Primary ? ", primary" : "" ) ;
90- }
91- }
92- catch ( Exception error )
93- {
94- Trace . WriteLine ( error ) ;
95- }
96- try
97- {
98- foreach ( ManagementObject sound in new ManagementClass ( "Win32_SoundDevice" ) . GetInstances ( ) )
99- {
100- output . WriteLine ( "Sound = {0}{1}" , ( string ) sound [ "Description" ] , GetPnPDeviceDrivers ( sound ) ) ;
101- }
102- }
103- catch ( Exception error )
104- {
105- Trace . WriteLine ( error ) ;
106- }
107- try
108- {
109- foreach ( ManagementObject disk in new ManagementClass ( "Win32_LogicalDisk" ) . GetInstances ( ) )
110- {
111- output . Write ( "Disk = {0} ({1}, {2}" , ( string ) disk [ "Name" ] , ( string ) disk [ "Description" ] , ( string ) disk [ "FileSystem" ] ) ;
112- if ( disk [ "Size" ] != null && disk [ "FreeSpace" ] != null )
113- output . WriteLine ( ", {0:F1} GB, {1:F1} GB free)" , ( float ) ( ulong ) disk [ "Size" ] / 1024 / 1024 / 1024 , ( float ) ( ulong ) disk [ "FreeSpace" ] / 1024 / 1024 / 1024 ) ;
114- else
115- output . WriteLine ( ")" ) ;
116- }
117- }
118- catch ( Exception error )
119- {
120- Trace . WriteLine ( error ) ;
121- }
122- try
41+ Name = System . Windows . Forms . Application . ProductName ,
42+ Version = VersionInfo . VersionOrBuild ,
43+ Architecture = RuntimeInformation . ProcessArchitecture . ToString ( ) ,
44+ } ;
45+
46+ var runtime = NameAndVersionRegex . Match ( RuntimeInformation . FrameworkDescription . Trim ( ) ) ;
47+ Runtime = new Platform
12348 {
124- foreach ( ManagementObject os in new ManagementClass ( "Win32_OperatingSystem" ) . GetInstances ( ) )
125- {
126- output . WriteLine ( "OS = {0} {1} ({2})" , ( string ) os [ "Caption" ] , ( string ) os [ "OSArchitecture" ] , ( string ) os [ "Version" ] ) ;
127- }
128- }
129- catch ( Exception error )
49+ Name = runtime . Groups [ 1 ] . Value ,
50+ Version = runtime . Groups [ 2 ] . Value ,
51+ } ;
52+
53+ // Almost nothing will correctly identify Windows 11 at this point, so we have to use WMI.
54+ var operatingSystem = new ManagementClass ( "Win32_OperatingSystem" ) . GetInstances ( ) . Cast < ManagementObject > ( ) . First ( ) ;
55+ OperatingSystem = new Platform
56+ {
57+ Name = ( string ) operatingSystem [ "Caption" ] ,
58+ Version = ( string ) operatingSystem [ "Version" ] ,
59+ Architecture = RuntimeInformation . OSArchitecture . ToString ( ) ,
60+ Language = CultureInfo . CurrentUICulture . IetfLanguageTag ,
61+ Languages = ( string [ ] ) operatingSystem [ "MUILanguages" ] ,
62+ } ;
63+
64+ NativeMethods . GlobalMemoryStatusEx ( MemoryStatusExtended ) ;
65+ InstalledMemoryMB = ( int ) ( MemoryStatusExtended . TotalPhysical / 1024 / 1024 ) ;
66+
67+ CPUs = new ManagementClass ( "Win32_Processor" ) . GetInstances ( ) . Cast < ManagementObject > ( ) . Select ( processor => new CPU
13068 {
131- Trace . WriteLine ( error ) ;
132- }
133- }
69+ Name = ( string ) processor [ "Name" ] ,
70+ Manufacturer = ( string ) processor [ "Manufacturer" ] ,
71+ ThreadCount = ( uint ) processor [ "ThreadCount" ] ,
72+ MaxClockMHz = ( uint ) processor [ "MaxClockSpeed" ] ,
73+ } ) . ToList ( ) ;
13474
135- static string GetPnPDeviceDrivers ( ManagementObject device )
136- {
137- var output = new StringBuilder ( ) ;
138- foreach ( ManagementObject pnpDevice in device . GetRelated ( "Win32_PnPEntity" ) )
75+ GPUs = new ManagementClass ( "Win32_VideoController" ) . GetInstances ( ) . Cast < ManagementObject > ( ) . Select ( adapter => new GPU
13976 {
140- foreach ( ManagementObject dataFile in pnpDevice . GetRelated ( "CIM_DataFile" ) )
77+ Name = ( string ) adapter [ "Name" ] ,
78+ Manufacturer = ( string ) adapter [ "AdapterCompatibility" ] ,
79+ MemoryMB = ( uint ) adapter [ "AdapterRAM" ] / 1024 / 1024 ,
80+ } ) . ToList ( ) ;
81+
82+ var featureLevels = new uint [ ] {
83+ NativeMethods . D3D_FEATURE_LEVEL_12_2 ,
84+ NativeMethods . D3D_FEATURE_LEVEL_12_1 ,
85+ NativeMethods . D3D_FEATURE_LEVEL_12_0 ,
86+ NativeMethods . D3D_FEATURE_LEVEL_11_1 ,
87+ NativeMethods . D3D_FEATURE_LEVEL_11_0 ,
88+ NativeMethods . D3D_FEATURE_LEVEL_10_1 ,
89+ NativeMethods . D3D_FEATURE_LEVEL_10_0 ,
90+ NativeMethods . D3D_FEATURE_LEVEL_9_3 ,
91+ NativeMethods . D3D_FEATURE_LEVEL_9_2 ,
92+ NativeMethods . D3D_FEATURE_LEVEL_9_1 ,
93+ } ;
94+ foreach ( var featureLevel in featureLevels )
95+ {
96+ var levels = new uint [ ] { featureLevel } ;
97+ try
14198 {
142- output . AppendFormat ( " ({0} {1})" , ( string ) dataFile [ "FileName" ] , ( string ) dataFile [ "Version" ] ) ;
99+ var rv = NativeMethods . D3D11CreateDevice ( IntPtr . Zero , NativeMethods . D3D_DRIVER_TYPE_HARDWARE , IntPtr . Zero , 0 , levels , levels . Length , NativeMethods . D3D11_SDK_VERSION , IntPtr . Zero , out uint level , IntPtr . Zero ) ;
100+ if ( level == featureLevel ) Direct3DFeatureLevels . Add ( string . Format ( "{0}_{1}" , level >> 12 & 0xF , level >> 8 & 0xF ) ) ;
143101 }
102+ catch ( EntryPointNotFoundException ) { }
103+ catch ( DllNotFoundException ) { }
144104 }
145- return output . ToString ( ) ;
146105 }
147106
148- static void WriteAvailableRuntimes ( TextWriter output )
107+ public static readonly Platform Application ;
108+ public static readonly Platform Runtime ;
109+ public static readonly Platform OperatingSystem ;
110+ public static readonly int InstalledMemoryMB ;
111+ public static readonly List < CPU > CPUs ;
112+ public static readonly List < GPU > GPUs ;
113+ public static readonly List < string > Direct3DFeatureLevels = new List < string > ( ) ;
114+
115+ public static void WriteSystemDetails ( TextWriter output )
149116 {
150- output . Write ( "Runtimes =" ) ;
151- try
152- {
153- // This remote access is necessary to ensure we get the correct bitness view of the registry.
154- using ( var frameworksKey = RegistryKey . OpenRemoteBaseKey ( RegistryHive . LocalMachine , "" ) . OpenSubKey ( @"SOFTWARE\Microsoft\NET Framework Setup\NDP" , false ) )
155- {
156- foreach ( var versionKeyName in frameworksKey . GetSubKeyNames ( ) )
157- {
158- if ( ! versionKeyName . StartsWith ( "v" ) )
159- continue ;
160-
161- using ( var versionKey = frameworksKey . OpenSubKey ( versionKeyName ) )
162- {
163- var fullVersion = WriteInstalledRuntimes ( output , versionKeyName , versionKey ) ;
164- if ( fullVersion != "" )
165- continue ;
166-
167- foreach ( var skuKeyName in versionKey . GetSubKeyNames ( ) )
168- {
169- using ( var skuKey = versionKey . OpenSubKey ( skuKeyName ) )
170- {
171- WriteInstalledRuntimes ( output , versionKeyName + " " + skuKeyName , skuKey ) ;
172- }
173- }
174- }
175- }
176- }
177- output . WriteLine ( ) ;
178- }
179- catch ( Exception error )
180- {
181- Trace . WriteLine ( error ) ;
182- }
117+ output . WriteLine ( "Date/time = {0} ({1:u})" ,
118+ DateTime . Now , DateTime . UtcNow ) ;
119+ output . WriteLine ( "Application = {0} {1} ({2})" , Application . Name , Application . Version , Application . Architecture ) ;
120+ output . WriteLine ( "Runtime = {0} {1}" , Runtime . Name , Runtime . Version ) ;
121+ output . WriteLine ( "System = {0} {1} ({2}; {3}; {4})" , OperatingSystem . Name , OperatingSystem . Version , OperatingSystem . Architecture , OperatingSystem . Language , string . Join ( "," , OperatingSystem . Languages ) ) ;
122+ output . WriteLine ( "Memory = {0:N0} MB" , InstalledMemoryMB ) ;
123+ foreach ( var cpu in CPUs ) output . WriteLine ( "CPU = {0} ({1}; {2} threads; {3:N0} MHz)" , cpu . Name , cpu . Manufacturer , cpu . ThreadCount , cpu . MaxClockMHz ) ;
124+ foreach ( var gpu in GPUs ) output . WriteLine ( "GPU = {0} ({1}; {2:N0} MB)" , gpu . Name , gpu . Manufacturer , gpu . MemoryMB ) ;
125+ output . WriteLine ( "Direct3D = {0}" , string . Join ( "," , Direct3DFeatureLevels ) ) ;
183126 }
184127
185- static string WriteInstalledRuntimes ( TextWriter output , string versionKeyName , RegistryKey versionKey )
128+ public struct Platform
186129 {
187- var installed = SafeReadKey ( versionKey , "Install" , - 1 ) ;
188- var fullVersion = SafeReadKey ( versionKey , "Version" , "" ) ;
189- var servicePack = SafeReadKey ( versionKey , "SP" , - 1 ) ;
190-
191- if ( installed == 1 && servicePack != - 1 )
192- {
193- output . Write ( " {0} SP{2} " , versionKeyName . Substring ( 1 ) , fullVersion , servicePack ) ;
194- }
195- else if ( installed == 1 )
196- {
197- output . Write ( " {0} " , versionKeyName . Substring ( 1 ) , fullVersion ) ;
198- }
199- return fullVersion ;
130+ public string Name ;
131+ public string Version ;
132+ public string Architecture ;
133+ public string Language ;
134+ public string [ ] Languages ;
200135 }
201136
202- static void WriteGraphicsAdapter ( TextWriter output )
137+ public struct CPU
203138 {
204- try {
205- foreach ( var adapter in GraphicsAdapter . Adapters )
206- {
207- try
208- {
209- output . WriteLine ( "{0} = {1}" , adapter . DeviceName , adapter . Description ) ;
210- }
211- catch ( Exception ) { }
212- }
213- }
214- catch ( Exception error )
215- {
216- output . WriteLine ( error ) ;
217- }
139+ public string Name ;
140+ public string Manufacturer ;
141+ public uint ThreadCount ;
142+ public uint MaxClockMHz ;
218143 }
219144
220- static T SafeReadKey < T > ( RegistryKey key , string name , T defaultValue )
145+ public struct GPU
221146 {
222- try
223- {
224- return ( T ) key . GetValue ( name , defaultValue ) ;
225- }
226- catch
227- {
228- return defaultValue ;
229- }
147+ public string Name ;
148+ public string Manufacturer ;
149+ public uint MemoryMB ;
230150 }
231151
232152 static class NativeStructs
@@ -250,6 +170,35 @@ static class NativeMethods
250170 {
251171 [ DllImport ( "kernel32.dll" , SetLastError = true ) ]
252172 public static extern bool GlobalMemoryStatusEx ( [ In , Out ] NativeStructs . MemoryStatusExtended buffer ) ;
173+
174+ public const uint D3D11_SDK_VERSION = 7 ;
175+
176+ public const uint D3D_DRIVER_TYPE_HARDWARE = 1 ;
177+
178+ public const uint D3D_FEATURE_LEVEL_9_1 = 0x9100 ;
179+ public const uint D3D_FEATURE_LEVEL_9_2 = 0x9200 ;
180+ public const uint D3D_FEATURE_LEVEL_9_3 = 0x9300 ;
181+ public const uint D3D_FEATURE_LEVEL_10_0 = 0xA000 ;
182+ public const uint D3D_FEATURE_LEVEL_10_1 = 0xA100 ;
183+ public const uint D3D_FEATURE_LEVEL_11_0 = 0xB000 ;
184+ public const uint D3D_FEATURE_LEVEL_11_1 = 0xB100 ;
185+ public const uint D3D_FEATURE_LEVEL_12_0 = 0xC000 ;
186+ public const uint D3D_FEATURE_LEVEL_12_1 = 0xC100 ;
187+ public const uint D3D_FEATURE_LEVEL_12_2 = 0xC200 ;
188+
189+ [ DllImport ( "d3d11.dll" , ExactSpelling = true ) ]
190+ public static extern uint D3D11CreateDevice (
191+ IntPtr adapter ,
192+ uint driverType ,
193+ IntPtr software ,
194+ uint flags ,
195+ [ In ] uint [ ] featureLevels ,
196+ int featureLevelCount ,
197+ uint sdkVersion ,
198+ IntPtr device ,
199+ out uint featureLevel ,
200+ IntPtr immediateContext
201+ ) ;
253202 }
254203 }
255204}
0 commit comments