win32-pdh 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/win32/pdh/constants.rb +2 -0
- data/lib/win32/pdh/counter.rb +41 -6
- data/lib/win32/pdh/query.rb +24 -8
- data/lib/win32/pdh.rb +19 -4
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d9f57c2db43f6412bceab31740be7f3131752334ff5b9c5f1f41f634519477bd
|
4
|
+
data.tar.gz: 74ea0ab008113496543dc001d947cbe93b3751eef9fb65be219887eb88921b36
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3b569a0bf0cfe35093c065cb527dc521fc503ff40dc882e35afdbfa8ec4036da16cf5cd7ef7003609406a640f77ae97ca93367119b2105a1b890212493a7edbd
|
7
|
+
data.tar.gz: 14e6def409243a45b3e3a51dbf544f9e5df224cbb32252bd9c13920702ccd05f6029e690932eb07618f970977579b694c58cb7539a78f111ccf7482ed2a85077
|
data/lib/win32/pdh/constants.rb
CHANGED
@@ -104,6 +104,7 @@ module Win32
|
|
104
104
|
PERF_DETAIL_WIZARD = 400
|
105
105
|
ERROR_SUCCESS = 0x00000000
|
106
106
|
|
107
|
+
# Value-to-name map, for reverse lookup.
|
107
108
|
NAMES = {
|
108
109
|
0x00000000 => 'PDH_CSTATUS_VALID_DATA'.freeze,
|
109
110
|
0x00000001 => 'PDH_CSTATUS_NEW_DATA'.freeze,
|
@@ -193,6 +194,7 @@ module Win32
|
|
193
194
|
0xC0000BFE => 'PDH_QUERY_PERF_DATA_TIMEOUT'.freeze,
|
194
195
|
}.freeze
|
195
196
|
|
197
|
+
# Value-to-message hash, for generating messages.
|
196
198
|
MESSAGES = {
|
197
199
|
0x00000000 => 'The returned data is valid.'.freeze,
|
198
200
|
0x00000001 => 'The return data value is valid and different from the last sample.'.freeze,
|
data/lib/win32/pdh/counter.rb
CHANGED
@@ -5,7 +5,12 @@ require 'win32/pdh/constants'
|
|
5
5
|
|
6
6
|
module Win32
|
7
7
|
module Pdh
|
8
|
+
##
|
9
|
+
# Class representing an individual counter.
|
10
|
+
#
|
11
|
+
# This won't usually be created directly, but built using Query#add_counter.
|
8
12
|
class Counter
|
13
|
+
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa373041(v=vs.85).aspx
|
9
14
|
class PDH_COUNTER_PATH_ELEMENTS < FFI::Struct
|
10
15
|
layout(
|
11
16
|
:szMachineName, :pointer,
|
@@ -16,6 +21,7 @@ module Win32
|
|
16
21
|
:szCounterName, :pointer,
|
17
22
|
)
|
18
23
|
end
|
24
|
+
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa373038(v=vs.85).aspx
|
19
25
|
class PDH_COUNTER_INFO < FFI::Struct
|
20
26
|
layout(
|
21
27
|
:dwLength, :uint,
|
@@ -33,6 +39,7 @@ module Win32
|
|
33
39
|
)
|
34
40
|
end
|
35
41
|
|
42
|
+
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa373050(v=vs.85).aspx
|
36
43
|
class PDH_FMT_COUNTERVALUE_VALUE < FFI::Union
|
37
44
|
layout(
|
38
45
|
:longValue, :int32,
|
@@ -43,6 +50,7 @@ module Win32
|
|
43
50
|
)
|
44
51
|
end
|
45
52
|
|
53
|
+
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa373050(v=vs.85).aspx
|
46
54
|
class PDH_FMT_COUNTERVALUE < FFI::Struct
|
47
55
|
layout(
|
48
56
|
:CStatus, :uint32,
|
@@ -52,6 +60,9 @@ module Win32
|
|
52
60
|
|
53
61
|
attr_accessor :type, :version, :status, :scale, :default_scale, :full_path, :machine_name, :object_name, :instance_name, :instance_index, :counter_name, :explain_text
|
54
62
|
|
63
|
+
##
|
64
|
+
# Initializes the counter from a query and a path. This usually won't be
|
65
|
+
# called directly, but generated from Query#add_counter
|
55
66
|
def initialize(query:, path:)
|
56
67
|
path = (path + "\0").encode('UTF-16LE')
|
57
68
|
handle_pointer = FFI::MemoryPointer.new(:pointer)
|
@@ -66,6 +77,16 @@ module Win32
|
|
66
77
|
load_info
|
67
78
|
end
|
68
79
|
|
80
|
+
##
|
81
|
+
# Remove the counter from its Query.
|
82
|
+
#
|
83
|
+
# This isn't necessary as a part of general cleanup, as closing a Query
|
84
|
+
# will also clean up all counters. This is necessary if you are doing
|
85
|
+
# long-term management that may need counters added and removed while
|
86
|
+
# running. So if you're using a Query as a one-off and it is being closed
|
87
|
+
# after use, don't bother with this. If you are keeping a single query
|
88
|
+
# open long-term, make sure you use this when necessary, otherwise you
|
89
|
+
# will leak memory.
|
69
90
|
def remove
|
70
91
|
# Only allow removing once
|
71
92
|
unless @handle.nil?
|
@@ -105,12 +126,20 @@ module Win32
|
|
105
126
|
Pdh.check_status @status
|
106
127
|
end
|
107
128
|
|
108
|
-
|
109
|
-
@status == Constants::ERROR_SUCCESS
|
110
|
-
end
|
129
|
+
private :load_info
|
111
130
|
|
131
|
+
##
|
112
132
|
# Get the PDH_FMT_COUNTERVALUE_VALUE given the format, checking status and
|
113
|
-
# raising an exception if necessary
|
133
|
+
# raising an exception if necessary.
|
134
|
+
#
|
135
|
+
# Usually, you won't use this directly; you'd use #get_double, #get_long,
|
136
|
+
# or #get_large to get the formatted value without any hassle.
|
137
|
+
#
|
138
|
+
# Will raise a PdhError if the value is bad (if you've only run
|
139
|
+
# Query#collect_query_data once, but this counter requires a history to
|
140
|
+
# calculate a rate, this will raise an exception. Be careful, and
|
141
|
+
# probably wrap all calls to this in an exception block that takes into
|
142
|
+
# account the possibility of a counter failing to get a value)
|
114
143
|
def get(format)
|
115
144
|
value = PDH_FMT_COUNTERVALUE.new
|
116
145
|
status = PdhFFI.PdhGetFormattedCounterValue(
|
@@ -125,19 +154,25 @@ module Win32
|
|
125
154
|
end
|
126
155
|
|
127
156
|
##
|
128
|
-
# Get value as a double
|
157
|
+
# Get value as a double.
|
158
|
+
#
|
159
|
+
# This uses #get, so read the notes in there about exception raising.
|
129
160
|
def get_double
|
130
161
|
get(Constants::PDH_FMT_DOUBLE)[:doubleValue]
|
131
162
|
end
|
132
163
|
|
133
164
|
##
|
134
|
-
# Get value as a 64-bit integer
|
165
|
+
# Get value as a 64-bit integer.
|
166
|
+
#
|
167
|
+
# This uses #get, so read the notes in there about exception raising.
|
135
168
|
def get_large
|
136
169
|
get(Constants::PDH_FMT_LARGE)[:largeValue]
|
137
170
|
end
|
138
171
|
|
139
172
|
##
|
140
173
|
# Get value as a 32-bit integer
|
174
|
+
#
|
175
|
+
# This uses #get, so read the notes in there about exception raising.
|
141
176
|
def get_long
|
142
177
|
get(Constants::PDH_FMT_LONG)[:longValue]
|
143
178
|
end
|
data/lib/win32/pdh/query.rb
CHANGED
@@ -3,6 +3,8 @@ require 'win32/pdh/counter'
|
|
3
3
|
|
4
4
|
module Win32
|
5
5
|
module Pdh
|
6
|
+
##
|
7
|
+
# Class representing a Query, and holding a query handle.
|
6
8
|
class Query
|
7
9
|
def initialize(source=nil)
|
8
10
|
source =
|
@@ -13,7 +15,7 @@ module Win32
|
|
13
15
|
end
|
14
16
|
handle_pointer = FFI::MemoryPointer.new(:pointer)
|
15
17
|
status = PdhFFI.PdhOpenQueryW(source, FFI::Pointer::NULL, handle_pointer)
|
16
|
-
|
18
|
+
Pdh.check_status status
|
17
19
|
@handle = handle_pointer.read_pointer
|
18
20
|
end
|
19
21
|
|
@@ -21,18 +23,20 @@ module Win32
|
|
21
23
|
# Only allow closing once
|
22
24
|
unless @handle.nil?
|
23
25
|
status = PdhFFI.PdhCloseQuery(@handle)
|
24
|
-
|
26
|
+
Pdh.check_status status
|
25
27
|
@handle = nil
|
26
28
|
end
|
27
29
|
end
|
28
30
|
|
29
31
|
##
|
30
|
-
# Simple query opening function.
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
32
|
+
# Simple query opening function.
|
33
|
+
#
|
34
|
+
# Uses the OpenQuery function and gets a query, passes it into the block,
|
35
|
+
# and then closes it afterward. If no block is given, it just returns the
|
36
|
+
# query, and you are responsible for closing it. The GC will not close
|
37
|
+
# this for you, so you can easily leak resources. It's strongly
|
38
|
+
# recommended to use the block style if at all possible to ensure resource
|
39
|
+
# cleanup.
|
36
40
|
def self.open(source=nil)
|
37
41
|
query = new source
|
38
42
|
if block_given?
|
@@ -46,12 +50,18 @@ module Win32
|
|
46
50
|
end
|
47
51
|
end
|
48
52
|
|
53
|
+
##
|
54
|
+
# Simple wrapper around PdhIsRealTimeQuery.
|
55
|
+
#
|
56
|
+
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa372646(v=vs.85).aspx
|
49
57
|
def real_time?
|
50
58
|
PdhFFI.PdhIsRealTimeQuery(@handle) == :true
|
51
59
|
end
|
52
60
|
|
53
61
|
##
|
54
62
|
# Adds a counter to this query and return it as a Counter object.
|
63
|
+
#
|
64
|
+
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa372204(v=vs.85).aspx
|
55
65
|
def add_counter(path)
|
56
66
|
Counter.new(
|
57
67
|
query: @handle,
|
@@ -59,6 +69,12 @@ module Win32
|
|
59
69
|
)
|
60
70
|
end
|
61
71
|
|
72
|
+
##
|
73
|
+
# Calls PdhCollectQueryData. This is necessary to load counters with data
|
74
|
+
# before retreiving it.
|
75
|
+
#
|
76
|
+
# Some counters may need this called twice before they can retreive the
|
77
|
+
# data. CPU counters are obvious examples.
|
62
78
|
def collect_query_data
|
63
79
|
status = PdhFFI.PdhCollectQueryData(@handle)
|
64
80
|
Pdh.check_status status
|
data/lib/win32/pdh.rb
CHANGED
@@ -4,6 +4,9 @@ require 'ffi'
|
|
4
4
|
|
5
5
|
module Win32
|
6
6
|
module Pdh
|
7
|
+
##
|
8
|
+
# Simple error subclass. Currently, this is what type all exceptions
|
9
|
+
# directly raised by this library are.
|
7
10
|
class PdhError < StandardError
|
8
11
|
def initialize(status)
|
9
12
|
super("PDH error #{Constants::NAMES[status]}: #{Constants::MESSAGES[status]}")
|
@@ -36,6 +39,8 @@ module Win32
|
|
36
39
|
array.pack('n*').force_encoding('UTF-16BE').encode('UTF-8')
|
37
40
|
end
|
38
41
|
|
42
|
+
##
|
43
|
+
# Container namespace for all Pdh functions.
|
39
44
|
module PdhFFI
|
40
45
|
extend FFI::Library
|
41
46
|
ffi_lib 'Pdh.dll'
|
@@ -69,12 +74,14 @@ module Win32
|
|
69
74
|
|
70
75
|
##
|
71
76
|
# Uses PdhEnumObjects to enumerate objects at the given target. Returns the
|
72
|
-
# objects as
|
77
|
+
# objects as an array of strings.
|
78
|
+
#
|
79
|
+
# PdhEnumObjects: https://msdn.microsoft.com/en-us/library/windows/desktop/aa372600(v=vs.85).aspx
|
73
80
|
#
|
74
81
|
# Params:
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
82
|
+
# source:: The same as szDataSource
|
83
|
+
# machine:: The same as szMachineName
|
84
|
+
# detail:: Alias for dwDetailLevel, as a symbol. May be :novice, :advanced, :expert, or :wizard. Defaults to :novice.
|
78
85
|
def self.enum_objects(source: nil, machine: nil, detail: :novice)
|
79
86
|
source =
|
80
87
|
if source.nil?
|
@@ -125,11 +132,15 @@ module Win32
|
|
125
132
|
string.split("\0")
|
126
133
|
end
|
127
134
|
|
135
|
+
##
|
136
|
+
# Structure of instances and counters, for ::enum_object_items
|
128
137
|
ItemEnum = Struct.new('ItemEnum', :instances, :counters)
|
129
138
|
|
130
139
|
##
|
131
140
|
# Enumerates an object's counter and instance names. Returns an ItemEnum
|
132
141
|
# with the results.
|
142
|
+
#
|
143
|
+
# Uses PdhEnumObjectItems: https://msdn.microsoft.com/en-us/library/windows/desktop/aa372595(v=vs.85).aspx
|
133
144
|
def self.enum_object_items(object:, source: nil, machine: nil, detail: :novice)
|
134
145
|
object = (object + "\0").encode('UTF-16LE')
|
135
146
|
source =
|
@@ -194,6 +205,10 @@ module Win32
|
|
194
205
|
|
195
206
|
##
|
196
207
|
# Expands a wildcard path into all matching counter paths.
|
208
|
+
#
|
209
|
+
# Returns a frozen array of frozen strings.
|
210
|
+
#
|
211
|
+
# Uses PdhExpandWildCardPath: https://msdn.microsoft.com/en-us/library/windows/desktop/aa372606(v=vs.85).aspx
|
197
212
|
def self.expand_wildcards(path:, source: nil, expand_counters: true, expand_instances: true)
|
198
213
|
path = (path + "\0").encode('UTF-16LE')
|
199
214
|
source =
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: win32-pdh
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Taylor C. Richberger
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-04-
|
11
|
+
date: 2018-04-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|