sys-cpu 0.5.4-mswin32

Sign up to get free protection for your applications and to get access to all the features.
data/lib/sys/cpu.rb ADDED
@@ -0,0 +1,775 @@
1
+ require 'win32ole'
2
+ require 'socket'
3
+
4
+ module Sys
5
+ class CPUError < StandardError; end
6
+
7
+ class CPU
8
+ VERSION = '0.5.4'
9
+
10
+ fields = %w/
11
+ address_width
12
+ architecture
13
+ availability
14
+ caption
15
+ config_manager_error_code
16
+ config_manager_user_config
17
+ cpu_status
18
+ creation_class_name
19
+ freq
20
+ voltage
21
+ data_width
22
+ description
23
+ device_id
24
+ error_cleared?
25
+ error_description
26
+ ext_clock
27
+ family
28
+ install_date
29
+ l2_cache_size
30
+ l2_cache_speed
31
+ last_error_code
32
+ level
33
+ load_avg
34
+ manufacturer
35
+ max_clock_speed
36
+ name
37
+ other_family_description
38
+ pnp_device_id
39
+ power_management_supported?
40
+ power_management_capabilities
41
+ processor_id
42
+ processor_type
43
+ revision
44
+ role
45
+ socket_designation
46
+ status
47
+ status_info
48
+ stepping
49
+ system_creation_class_name
50
+ system_name
51
+ unique_id
52
+ upgrade_method
53
+ version
54
+ voltage_caps
55
+ /
56
+
57
+ CPUStruct = Struct.new("CPUStruct", *fields)
58
+
59
+ # Returns the +host+ CPU's architecture, or nil if it cannot be
60
+ # determined.
61
+ #
62
+ def self.architecture(host=Socket.gethostname)
63
+ cs = "winmgmts://#{host}/root/cimv2:Win32_Processor='cpu0'"
64
+ begin
65
+ wmi = WIN32OLE.connect(cs)
66
+ rescue WIN32OLERuntimeError => e
67
+ raise CPUError, e
68
+ else
69
+ self.get_cpu_arch(wmi.Architecture)
70
+ end
71
+ end
72
+
73
+ # Returns an integer indicating the speed (i.e. frequency in Mhz) of
74
+ # +cpu_num+ on +host+, or the localhost if no +host+ is specified.
75
+ # If +cpu_num+ +1 is greater than the number of cpu's on your system
76
+ # or this call fails for any other reason, a CPUError is raised.
77
+ #
78
+ def self.freq(cpu_num = 0, host = Socket.gethostname)
79
+ cs = "winmgmts://#{host}/root/cimv2:Win32_Processor='cpu#{cpu_num}'"
80
+ begin
81
+ wmi = WIN32OLE.connect(cs)
82
+ rescue WIN32OLERuntimeError => e
83
+ raise CPUError, e
84
+ else
85
+ return wmi.CurrentClockSpeed
86
+ end
87
+ end
88
+
89
+ # Returns the load capacity for +cpu_num+ on +host+, or the localhost
90
+ # if no host is specified, averaged to the last second. Processor
91
+ # loading refers to the total computing burden for each processor at
92
+ # one time.
93
+ #
94
+ # Note that this attribute is actually the LoadPercentage. I may use
95
+ # one of the Win32_Perf* classes in the future.
96
+ #
97
+ def self.load_avg(cpu_num = 0, host = Socket.gethostname)
98
+ cs = "winmgmts://#{host}/root/cimv2:Win32_Processor='cpu#{cpu_num}'"
99
+ begin
100
+ wmi = WIN32OLE.connect(cs)
101
+ rescue WIN32OLERuntimeError => e
102
+ raise CPUError, e
103
+ else
104
+ return wmi.LoadPercentage
105
+ end
106
+ end
107
+
108
+ # Returns a string indicating the cpu model, e.g. Intel Pentium 4.
109
+ #
110
+ def self.model(host = Socket.gethostname)
111
+ cs = "winmgmts://#{host}/root/cimv2:Win32_Processor='cpu0'"
112
+ begin
113
+ wmi = WIN32OLE.connect(cs)
114
+ rescue WIN32OLERuntimeError => e
115
+ raise CPUError, e
116
+ else
117
+ return wmi.Name
118
+ end
119
+ end
120
+
121
+ # Returns an integer indicating the number of cpu's on the system.
122
+ #--
123
+ # This (oddly) requires a different class.
124
+ #
125
+ def self.num_cpu(host = Socket.gethostname)
126
+ cs = "winmgmts://#{host}/root/cimv2:Win32_ComputerSystem='#{host}'"
127
+ begin
128
+ wmi = WIN32OLE.connect(cs)
129
+ rescue WIN32OLERuntimeError => e
130
+ raise CPUError, e
131
+ else
132
+ return wmi.NumberOfProcessors
133
+ end
134
+ end
135
+
136
+ # Returns a CPUStruct for each CPU on +host+, or the localhost if no
137
+ # +host+ is specified. A CPUStruct contains the following members:
138
+ #
139
+ # * address_width
140
+ # * architecture
141
+ # * availability
142
+ # * caption
143
+ # * config_manager_error_code
144
+ # * config_manager_user_config
145
+ # * cpu_status
146
+ # * creation_class_name
147
+ # * freq
148
+ # * voltage
149
+ # * data_width
150
+ # * description
151
+ # * device_id
152
+ # * error_cleared?
153
+ # * error_description
154
+ # * ext_clock
155
+ # * family
156
+ # * install_date
157
+ # * l2_cache_size
158
+ # * l2_cache_speed
159
+ # * last_error_code
160
+ # * level
161
+ # * load_avg
162
+ # * manufacturer
163
+ # * max_clock_speed
164
+ # * name
165
+ # * other_family_description
166
+ # * pnp_device_id
167
+ # * power_management_supported?
168
+ # * power_management_capabilities
169
+ # * processor_id
170
+ # * processor_type
171
+ # * revision
172
+ # * role
173
+ # * socket_designation
174
+ # * status
175
+ # * status_info
176
+ # * stepping
177
+ # * system_creation_class_name
178
+ # * system_name
179
+ # * unique_id
180
+ # * upgrade_method
181
+ # * version
182
+ # * voltage_caps
183
+ #
184
+ # Note that not all of these members will necessarily be defined.
185
+ #
186
+ def self.processors(host = Socket.gethostname)
187
+ begin
188
+ wmi = WIN32OLE.connect("winmgmts://#{host}/root/cimv2")
189
+ rescue WIN32OLERuntimeError => e
190
+ raise CPUError, e
191
+ else
192
+ wmi.InstancesOf("Win32_Processor").each{ |cpu|
193
+ yield CPUStruct.new(
194
+ cpu.AddressWidth,
195
+ self.get_cpu_arch(cpu.Architecture),
196
+ self.get_availability(cpu.Availability),
197
+ cpu.Caption,
198
+ self.get_cmec(cpu.ConfigManagerErrorCode),
199
+ cpu.ConfigManagerUserConfig,
200
+ get_status(cpu.CpuStatus),
201
+ cpu.CreationClassName,
202
+ cpu.CurrentClockSpeed,
203
+ cpu.CurrentVoltage,
204
+ cpu.DataWidth,
205
+ cpu.Description,
206
+ cpu.DeviceId,
207
+ cpu.ErrorCleared,
208
+ cpu.ErrorDescription,
209
+ cpu.ExtClock,
210
+ self.get_family(cpu.Family),
211
+ cpu.InstallDate,
212
+ cpu.L2CacheSize,
213
+ cpu.L2CacheSpeed,
214
+ cpu.LastErrorCode,
215
+ cpu.Level,
216
+ cpu.LoadPercentage,
217
+ cpu.Manufacturer,
218
+ cpu.MaxClockSpeed,
219
+ cpu.Name,
220
+ cpu.OtherFamilyDescription,
221
+ cpu.PNPDeviceID,
222
+ cpu.PowerManagementSupported,
223
+ cpu.PowerManagementCapabilities,
224
+ cpu.ProcessorId,
225
+ self.get_processor_type(cpu.ProcessorType),
226
+ cpu.Revision,
227
+ cpu.Role,
228
+ cpu.SocketDesignation,
229
+ cpu.Status,
230
+ cpu.StatusInfo,
231
+ cpu.Stepping,
232
+ cpu.SystemCreationClassName,
233
+ cpu.SystemName,
234
+ cpu.UniqueId,
235
+ self.get_upgrade_method(cpu.UpgradeMethod),
236
+ cpu.Version,
237
+ self.get_voltage_caps(cpu.VoltageCaps)
238
+ )
239
+ }
240
+ end
241
+ end
242
+
243
+ # Returns a string indicating the type of processor, e.g. GenuineIntel.
244
+ #
245
+ def self.type(host = Socket.gethostname)
246
+ cs = "winmgmts://#{host}/root/cimv2:Win32_Processor='cpu0'"
247
+ begin
248
+ wmi = WIN32OLE.connect(cs)
249
+ rescue WIN32OLERuntimeError => e
250
+ raise CPUError, e
251
+ else
252
+ return wmi.Manufacturer
253
+ end
254
+ end
255
+
256
+ private
257
+
258
+ # Convert the ConfigManagerErrorCode number to its corresponding string
259
+ # Note that this value returns nil on my system.
260
+ def self.get_cmec(num)
261
+ case
262
+ when 0
263
+ str = "The device is working properly."
264
+ return str
265
+ when 1
266
+ str = "The device is not configured correctly."
267
+ return str
268
+ when 2
269
+ str = "Windows cannot load the driver for the device."
270
+ return str
271
+ when 3
272
+ str = "The driver for the device might be corrupted, or the"
273
+ str << " system may be running low on memory or other"
274
+ str << " resources."
275
+ return str
276
+ when 4
277
+ str = "The device is not working properly. One of the drivers"
278
+ str << " or the registry might be corrupted."
279
+ return str
280
+ when 5
281
+ str = "The driver for this device needs a resource that"
282
+ str << " Windows cannot manage."
283
+ return str
284
+ when 6
285
+ str = "The boot configuration for this device conflicts with"
286
+ str << " other devices."
287
+ return str
288
+ when 7
289
+ str = "Cannot filter."
290
+ return str
291
+ when 8
292
+ str = "The driver loader for the device is missing."
293
+ return str
294
+ when 9
295
+ str = "This device is not working properly because the"
296
+ str << " controlling firmware is reporting the resources"
297
+ str << " for the device incorrectly."
298
+ return str
299
+ when 10
300
+ str = "This device cannot start."
301
+ return str
302
+ when 11
303
+ str = "This device failed."
304
+ return str
305
+ when 12
306
+ str = "This device cannot find enough free resources that"
307
+ str << " it can use."
308
+ return str
309
+ when 13
310
+ str = "Windows cannot verify this device's resources."
311
+ return str
312
+ when 14
313
+ str = "This device cannot work properly until you restart"
314
+ str << " your computer."
315
+ return str
316
+ when 15
317
+ str = "This device is not working properly because there is"
318
+ str << " probably a re-enumeration problem."
319
+ return str
320
+ when 16
321
+ str = "Windows cannot identify all the resources this device "
322
+ str << " uses."
323
+ return str
324
+ when 17
325
+ str = "This device is asking for an unknown resource type."
326
+ return str
327
+ when 18
328
+ str = "Reinstall the drivers for this device."
329
+ return str
330
+ when 19
331
+ str = "Failure using the VXD loader."
332
+ return str
333
+ when 20
334
+ str = "Your registry might be corrupted."
335
+ return str
336
+ when 21
337
+ str = "System failure: try changing the driver for this device."
338
+ str << " If that does not work, see your hardware documentation."
339
+ str << " Windows is removing this device."
340
+ return str
341
+ when 22
342
+ str = "This device is disabled."
343
+ return str
344
+ when 23
345
+ str = "System failure: try changing the driver for this device."
346
+ str << "If that doesn't work, see your hardware documentation."
347
+ return str
348
+ when 24
349
+ str = "This device is not present, not working properly, or"
350
+ str << " does not have all its drivers installed."
351
+ return str
352
+ when 25
353
+ str = "Windows is still setting up this device."
354
+ return str
355
+ when 26
356
+ str = "Windows is still setting up this device."
357
+ return str
358
+ when 27
359
+ str = "This device does not have valid log configuration."
360
+ return str
361
+ when 28
362
+ str = "The drivers for this device are not installed."
363
+ return str
364
+ when 29
365
+ str = "This device is disabled because the firmware of the"
366
+ str << " device did not give it the required resources."
367
+ return str
368
+ when 30
369
+ str = "This device is using an Interrupt Request (IRQ)"
370
+ str << " resource that another device is using."
371
+ return str
372
+ when 31
373
+ str = "This device is not working properly because Windows"
374
+ str << " cannot load the drivers required for this device"
375
+ return str
376
+ else
377
+ return nil
378
+ end
379
+ end
380
+
381
+ # Convert an cpu architecture number to a string
382
+ def self.get_cpu_arch(num)
383
+ case num
384
+ when 0
385
+ return "x86"
386
+ when 1
387
+ return "MIPS"
388
+ when 2
389
+ return "Alpha"
390
+ when 3
391
+ return "PowerPC"
392
+ when 4
393
+ return "IA64"
394
+ else
395
+ return nil
396
+ end
397
+ end
398
+
399
+ # convert an Availability number into a string
400
+ def self.get_availability(num)
401
+ case num
402
+ when 1
403
+ return "Other"
404
+ when 2
405
+ return "Unknown"
406
+ when 3
407
+ return "Running"
408
+ when 4
409
+ return "Warning"
410
+ when 5
411
+ return "In Test"
412
+ when 6
413
+ return "Not Applicable"
414
+ when 7
415
+ return "Power Off"
416
+ when 8
417
+ return "Off Line"
418
+ when 9
419
+ return "Off Duty"
420
+ when 10
421
+ return "Degraded"
422
+ when 11
423
+ return "Not Installed"
424
+ when 12
425
+ return "Install Error"
426
+ when 13
427
+ return "Power Save - Unknown"
428
+ when 14
429
+ return "Power Save - Low Power Mode"
430
+ when 15
431
+ return "Power Save - Standby"
432
+ when 16
433
+ return "Power Cycle"
434
+ when 17
435
+ return "Power Save - Warning"
436
+ when 18
437
+ return "Paused"
438
+ when 19
439
+ return "Not Ready"
440
+ when 20
441
+ return "Not Configured"
442
+ when 21
443
+ return "Quiesced"
444
+ else
445
+ return nil
446
+ end
447
+ end
448
+
449
+ # convert CpuStatus to a string form. Note that values 5 and 6 are
450
+ # skipped because they're reserved.
451
+ def self.get_status(num)
452
+ case num
453
+ when 0
454
+ return "Unknown"
455
+ when 1
456
+ return "Enabled"
457
+ when 2
458
+ return "Disabled by User via BIOS Setup"
459
+ when 3
460
+ return "Disabled By BIOS (POST Error)"
461
+ when 4
462
+ return "Idle"
463
+ when 7
464
+ return "Other"
465
+ else
466
+ return nil
467
+ end
468
+ end
469
+
470
+ # Convert a family number into the equivalent string
471
+ def self.get_family(num)
472
+ case num
473
+ when 1
474
+ return "Other"
475
+ when 2
476
+ return "Unknown"
477
+ when 3
478
+ return "8086"
479
+ when 4
480
+ return "80286"
481
+ when 5
482
+ return "80386"
483
+ when 6
484
+ return "80486"
485
+ when 7
486
+ return "8087"
487
+ when 8
488
+ return "80287"
489
+ when 9
490
+ return "80387"
491
+ when 10
492
+ return "80487"
493
+ when 11
494
+ return "Pentium?"
495
+ when 12
496
+ return "Pentium?"
497
+ when 13
498
+ return "Pentium?"
499
+ when 14
500
+ return "Pentium?"
501
+ when 15
502
+ return "Celeron?"
503
+ when 16
504
+ return "Pentium?"
505
+ when 17
506
+ return "Pentium?"
507
+ when 18
508
+ return "M1"
509
+ when 19
510
+ return "M2"
511
+ when 24
512
+ return "K5"
513
+ when 25
514
+ return "K6"
515
+ when 26
516
+ return "K6-2"
517
+ when 27
518
+ return "K6-3"
519
+ when 28
520
+ return "AMD"
521
+ when 29
522
+ return "AMD?"
523
+ when 30
524
+ return "AMD2900"
525
+ when 31
526
+ return "K6-2+"
527
+ when 32
528
+ return "Power"
529
+ when 33
530
+ return "Power"
531
+ when 34
532
+ return "Power"
533
+ when 35
534
+ return "Power"
535
+ when 36
536
+ return "Power"
537
+ when 37
538
+ return "Power"
539
+ when 38
540
+ return "Power"
541
+ when 39
542
+ return "Power"
543
+ when 48
544
+ return "Alpha"
545
+ when 49
546
+ return "Alpha"
547
+ when 50
548
+ return "Alpha"
549
+ when 51
550
+ return "Alpha"
551
+ when 52
552
+ return "Alpha"
553
+ when 53
554
+ return "Alpha"
555
+ when 54
556
+ return "Alpha"
557
+ when 55
558
+ return "Alpha"
559
+ when 64
560
+ return "MIPS"
561
+ when 65
562
+ return "MIPS"
563
+ when 66
564
+ return "MIPS"
565
+ when 67
566
+ return "MIPS"
567
+ when 68
568
+ return "MIPS"
569
+ when 69
570
+ return "MIPS"
571
+ when 80
572
+ return "SPARC"
573
+ when 81
574
+ return "SuperSPARC"
575
+ when 82
576
+ return "microSPARC"
577
+ when 83
578
+ return "microSPARC"
579
+ when 84
580
+ return "UltraSPARC"
581
+ when 85
582
+ return "UltraSPARC"
583
+ when 86
584
+ return "UltraSPARC"
585
+ when 87
586
+ return "UltraSPARC"
587
+ when 88
588
+ return "UltraSPARC"
589
+ when 96
590
+ return "68040"
591
+ when 97
592
+ return "68xxx"
593
+ when 98
594
+ return "68000"
595
+ when 99
596
+ return "68010"
597
+ when 100
598
+ return "68020"
599
+ when 101
600
+ return "68030"
601
+ when 112
602
+ return "Hobbit"
603
+ when 120
604
+ return "Crusoe?"
605
+ when 121
606
+ return "Crusoe?"
607
+ when 128
608
+ return "Weitek"
609
+ when 130
610
+ return "Itanium?"
611
+ when 144
612
+ return "PA-RISC"
613
+ when 145
614
+ return "PA-RISC"
615
+ when 146
616
+ return "PA-RISC"
617
+ when 147
618
+ return "PA-RISC"
619
+ when 148
620
+ return "PA-RISC"
621
+ when 149
622
+ return "PA-RISC"
623
+ when 150
624
+ return "PA-RISC"
625
+ when 160
626
+ return "V30"
627
+ when 176
628
+ return "Pentium?"
629
+ when 177
630
+ return "Pentium?"
631
+ when 178
632
+ return "Pentium?"
633
+ when 179
634
+ return "Intel?"
635
+ when 180
636
+ return "AS400"
637
+ when 181
638
+ return "Intel?"
639
+ when 182
640
+ return "AMD"
641
+ when 183
642
+ return "AMD"
643
+ when 184
644
+ return "Intel?"
645
+ when 185
646
+ return "AMD"
647
+ when 190
648
+ return "K7"
649
+ when 200
650
+ return "IBM390"
651
+ when 201
652
+ return "G4"
653
+ when 202
654
+ return "G5"
655
+ when 250
656
+ return "i860"
657
+ when 251
658
+ return "i960"
659
+ when 260
660
+ return "SH-3"
661
+ when 261
662
+ return "SH-4"
663
+ when 280
664
+ return "ARM"
665
+ when 281
666
+ return "StrongARM"
667
+ when 300
668
+ return "6x86"
669
+ when 301
670
+ return "MediaGX"
671
+ when 302
672
+ return "MII"
673
+ when 320
674
+ return "WinChip"
675
+ when 350
676
+ return "DSP"
677
+ when 500
678
+ return "Video"
679
+ else
680
+ return nil
681
+ end
682
+ end
683
+
684
+ # Convert power management capabilities number to its equivalent string
685
+ def self.get_pmc(num)
686
+ case num
687
+ when 0
688
+ return "Unknown"
689
+ when 1
690
+ return "Not Supported"
691
+ when 2
692
+ return "Disabled"
693
+ when 3
694
+ return "Enabled"
695
+ when 4
696
+ return "Power Saving Modes Entered Automatically"
697
+ when 5
698
+ return "Power State Settable"
699
+ when 6
700
+ return "Power Cycling Supported"
701
+ when 7
702
+ return "Timed Power On Supported"
703
+ else
704
+ return nil
705
+ end
706
+ end
707
+
708
+ # Convert a processor type into its equivalent string
709
+ def self.get_processor_type(num)
710
+ case num
711
+ when 1
712
+ return "Other"
713
+ when 2
714
+ return "Unknown"
715
+ when 3
716
+ return "Central Processor"
717
+ when 4
718
+ return "Math Processor"
719
+ when 5
720
+ return "DSP Processor"
721
+ when 6
722
+ return "Video Processor"
723
+ else
724
+ return nil
725
+ end
726
+ end
727
+
728
+ # Convert an upgrade method into its equivalent string
729
+ def self.get_upgrade_method(num)
730
+ case num
731
+ when 1
732
+ return "Other"
733
+ when 2
734
+ return "Unknown"
735
+ when 3
736
+ return "Daughter Board"
737
+ when 4
738
+ return "ZIF Socket"
739
+ when 5
740
+ return "Replacement/Piggy Back"
741
+ when 6
742
+ return "None"
743
+ when 7
744
+ return "LIF Socket"
745
+ when 8
746
+ return "Slot 1"
747
+ when 9
748
+ return "Slot 2"
749
+ when 10
750
+ return "370 Pin Socket"
751
+ when 11
752
+ return "Slot A"
753
+ when 12
754
+ return "Slot M"
755
+ else
756
+ return nil
757
+ end
758
+ end
759
+
760
+ # Convert return values to voltage cap values (floats)
761
+ def self.get_voltage_caps(num)
762
+ case num
763
+ when 1
764
+ return 5.0
765
+ when 2
766
+ return 3.3
767
+ when 4
768
+ return 2.9
769
+ else
770
+ return nil
771
+ end
772
+ end
773
+
774
+ end
775
+ end