30
30
import com .sun .jna .Native ;
31
31
import com .sun .jna .platform .win32 .WinDef .DWORD ;
32
32
import com .sun .jna .platform .win32 .WinDef .DWORDByReference ;
33
+ import java .util .Collections ;
33
34
34
35
/**
35
36
* Pdh utility API.
@@ -61,16 +62,23 @@ public abstract class PdhUtil {
61
62
public static String PdhLookupPerfNameByIndex (String szMachineName , int dwNameIndex ) {
62
63
// Call once to get required buffer size
63
64
DWORDByReference pcchNameBufferSize = new DWORDByReference (new DWORD (0 ));
64
- Pdh .INSTANCE .PdhLookupPerfNameByIndex (szMachineName , dwNameIndex , null , pcchNameBufferSize );
65
-
65
+ int result = Pdh .INSTANCE .PdhLookupPerfNameByIndex (szMachineName , dwNameIndex , null , pcchNameBufferSize );
66
+ if (result != WinError .ERROR_SUCCESS && result != Pdh .PDH_MORE_DATA ) {
67
+ throw new PdhException (result );
68
+ }
69
+
66
70
// Can't allocate 0 memory
67
71
if (pcchNameBufferSize .getValue ().intValue () < 1 ) {
68
72
return "" ;
69
73
}
70
74
// Allocate buffer and call again
71
75
Memory mem = new Memory (pcchNameBufferSize .getValue ().intValue () * CHAR_TO_BYTES );
72
- Pdh .INSTANCE .PdhLookupPerfNameByIndex (szMachineName , dwNameIndex , mem , pcchNameBufferSize );
76
+ result = Pdh .INSTANCE .PdhLookupPerfNameByIndex (szMachineName , dwNameIndex , mem , pcchNameBufferSize );
73
77
78
+ if (result != WinError .ERROR_SUCCESS ) {
79
+ throw new PdhException (result );
80
+ }
81
+
74
82
// Convert buffer to Java String
75
83
if (CHAR_TO_BYTES == 1 ) {
76
84
return mem .getString (0 );
@@ -113,9 +121,8 @@ public static int PdhLookupPerfIndexByEnglishName(String szNameBuffer) {
113
121
114
122
/**
115
123
* Utility method to call Pdh's PdhEnumObjectItems that allocates the
116
- * required memory for the mszCounterList parameter based on the type
117
- * mapping used, calls to PdhEnumObjectItems, and returns the received lists
118
- * of strings.
124
+ * required memory for the lists parameters based on the type mapping used,
125
+ * calls to PdhEnumObjectItems, and returns the received lists of strings.
119
126
*
120
127
* @param szDataSource
121
128
* String that specifies the name of the log file used to
@@ -137,113 +144,135 @@ public static int PdhLookupPerfIndexByEnglishName(String szNameBuffer) {
137
144
* returned.
138
145
* @return Returns a List of Strings of the counters for the object.
139
146
*/
140
- public static List < String > PdhEnumObjectItemCounters (String szDataSource , String szMachineName , String szObjectName ,
147
+ public static PdhEnumObjectItems PdhEnumObjectItems (String szDataSource , String szMachineName , String szObjectName ,
141
148
int dwDetailLevel ) {
142
149
List <String > counters = new ArrayList <String >();
150
+ List <String > instances = new ArrayList <String >();
143
151
144
152
// Call once to get string lengths
145
153
DWORDByReference pcchCounterListLength = new DWORDByReference (new DWORD (0 ));
146
154
DWORDByReference pcchInstanceListLength = new DWORDByReference (new DWORD (0 ));
147
- Pdh .INSTANCE .PdhEnumObjectItems (szDataSource , szMachineName , szObjectName , null , pcchCounterListLength , null ,
155
+ int result = Pdh .INSTANCE .PdhEnumObjectItems (szDataSource , szMachineName , szObjectName , null , pcchCounterListLength , null ,
148
156
pcchInstanceListLength , dwDetailLevel , 0 );
157
+ if (result != WinError .ERROR_SUCCESS && result != Pdh .PDH_MORE_DATA ) {
158
+ throw new PdhException (result );
159
+ }
149
160
150
- // Can't allocate 0 memory if no counters
151
- if (pcchCounterListLength .getValue ().intValue () < 1 ) {
152
- return counters ;
161
+ Memory mszCounterList = null ;
162
+ Memory mszInstanceList = null ;
163
+
164
+ if (pcchCounterListLength .getValue ().intValue () > 0 ) {
165
+ mszCounterList = new Memory (pcchCounterListLength .getValue ().intValue () * CHAR_TO_BYTES );
166
+ }
167
+
168
+ if (pcchInstanceListLength .getValue ().intValue () > 0 ) {
169
+ mszInstanceList = new Memory (pcchInstanceListLength .getValue ().intValue () * CHAR_TO_BYTES );
170
+ }
171
+
172
+ result = Pdh .INSTANCE .PdhEnumObjectItems (szDataSource , szMachineName , szObjectName , mszCounterList ,
173
+ pcchCounterListLength , mszInstanceList , pcchInstanceListLength , dwDetailLevel , 0 );
174
+
175
+ if (result != WinError .ERROR_SUCCESS ) {
176
+ throw new PdhException (result );
153
177
}
154
- // Allocate memory and call again to populate strings
155
- Memory mszCounterList = new Memory (pcchCounterListLength .getValue ().intValue () * CHAR_TO_BYTES );
156
- // Don't need the instances
157
- pcchInstanceListLength .getValue ().setValue (0 );
158
- Pdh .INSTANCE .PdhEnumObjectItems (szDataSource , szMachineName , szObjectName , mszCounterList ,
159
- pcchCounterListLength , null , pcchInstanceListLength , dwDetailLevel , 0 );
160
178
161
179
// Fetch counters
162
- int offset = 0 ;
163
- while (offset < mszCounterList .size ()) {
164
- String s = null ;
165
- if (CHAR_TO_BYTES == 1 ) {
166
- s = mszCounterList .getString (offset );
167
- } else {
168
- s = mszCounterList .getWideString (offset );
180
+ if (mszCounterList != null ) {
181
+ int offset = 0 ;
182
+ while (offset < mszCounterList .size ()) {
183
+ String s = null ;
184
+ if (CHAR_TO_BYTES == 1 ) {
185
+ s = mszCounterList .getString (offset );
186
+ } else {
187
+ s = mszCounterList .getWideString (offset );
188
+ }
189
+ // list ends with double null
190
+ if (s .isEmpty ()) {
191
+ break ;
192
+ }
193
+ counters .add (s );
194
+ // Increment for string + null terminator
195
+ offset += (s .length () + 1 ) * CHAR_TO_BYTES ;
169
196
}
170
- // list ends with double null
171
- if (s .isEmpty ()) {
172
- break ;
197
+ }
198
+
199
+ if (mszInstanceList != null ) {
200
+ int offset = 0 ;
201
+ while (offset < mszInstanceList .size ()) {
202
+ String s = null ;
203
+ if (CHAR_TO_BYTES == 1 ) {
204
+ s = mszInstanceList .getString (offset );
205
+ } else {
206
+ s = mszInstanceList .getWideString (offset );
207
+ }
208
+ // list ends with double null
209
+ if (s .isEmpty ()) {
210
+ break ;
211
+ }
212
+ instances .add (s );
213
+ // Increment for string + null terminator
214
+ offset += (s .length () + 1 ) * CHAR_TO_BYTES ;
173
215
}
174
- counters .add (s );
175
- // Increment for string + null terminator
176
- offset += (s .length () + 1 ) * CHAR_TO_BYTES ;
177
216
}
178
217
179
- return counters ;
218
+ return new PdhEnumObjectItems ( counters , instances ) ;
180
219
}
181
220
221
+
182
222
/**
183
- * Utility method to call Pdh's PdhEnumObjectItems that allocates the
184
- * required memory for the mszInstanceList parameters based on the type
185
- * mapping used, calls to PdhEnumObjectItems, and returns the received lists
186
- * of strings.
187
- *
188
- * @param szDataSource
189
- * String that specifies the name of the log file used to
190
- * enumerate the counter and instance names. If NULL, the
191
- * function uses the computer specified in the szMachineName
192
- * parameter to enumerate the names.
193
- * @param szMachineName
194
- * String that specifies the name of the computer that contains
195
- * the counter and instance names that you want to enumerate.
196
- * Include the leading slashes in the computer name, for example,
197
- * \\computername. If the szDataSource parameter is NULL, you can
198
- * set szMachineName to NULL to specify the local computer.
199
- * @param szObjectName
200
- * String that specifies the name of the object whose counter and
201
- * instance names you want to enumerate.
202
- * @param dwDetailLevel
203
- * Detail level of the performance items to return. All items
204
- * that are of the specified detail level or less will be
205
- * returned.
206
- * @return Returns a Lists of Strings of the instances of the object.
223
+ * Holder Object for PdhEnumObjectsItems. The embedded lists are modifiable
224
+ * lists and can be accessed through the {@link #getCounters()} and
225
+ * {@link #getInstances()} accessors.
207
226
*/
208
- public static List < String > PdhEnumObjectItemInstances ( String szDataSource , String szMachineName ,
209
- String szObjectName , int dwDetailLevel ) {
210
- List <String > instances = new ArrayList < String >() ;
227
+ public static class PdhEnumObjectItems {
228
+ private final List < String > counters ;
229
+ private final List <String > instances ;
211
230
212
- // Call once to get string lengths
213
- DWORDByReference pcchCounterListLength = new DWORDByReference (new DWORD (0 ));
214
- DWORDByReference pcchInstanceListLength = new DWORDByReference (new DWORD (0 ));
215
- Pdh .INSTANCE .PdhEnumObjectItems (szDataSource , szMachineName , szObjectName , null , pcchCounterListLength , null ,
216
- pcchInstanceListLength , dwDetailLevel , 0 );
231
+ public PdhEnumObjectItems (List <String > counters , List <String > instances ) {
232
+ this .counters = copyAndEmptyListForNullList (counters );
233
+ this .instances = copyAndEmptyListForNullList (instances );
234
+ }
235
+
236
+ /**
237
+ * @return the embedded counters list, all calls to this function receive
238
+ * the same list and thus share modifications
239
+ */
240
+ public List <String > getCounters () {
241
+ return counters ;
242
+ }
217
243
218
- // Can't allocate 0 memory if no instances
219
- if (pcchInstanceListLength .getValue ().intValue () < 1 ) {
244
+ /**
245
+ * @return the embedded instances list, all calls to this function receive
246
+ * the same list and thus share modifications
247
+ */
248
+ public List <String > getInstances () {
220
249
return instances ;
221
250
}
222
- // Allocate memory and call again to populate strings
223
- Memory mszInstanceList = new Memory (pcchInstanceListLength .getValue ().intValue () * CHAR_TO_BYTES );
224
- // Don't need the counters
225
- pcchCounterListLength .getValue ().setValue (0 );
226
- Pdh .INSTANCE .PdhEnumObjectItems (szDataSource , szMachineName , szObjectName , null , pcchCounterListLength ,
227
- mszInstanceList , pcchInstanceListLength , dwDetailLevel , 0 );
228
-
229
- // Fetch instances
230
- int offset = 0 ;
231
- while (offset < mszInstanceList .size ()) {
232
- String s = null ;
233
- if (CHAR_TO_BYTES == 1 ) {
234
- s = mszInstanceList .getString (offset );
251
+
252
+ private List <String > copyAndEmptyListForNullList (List <String > inputList ) {
253
+ if (inputList == null ) {
254
+ return new ArrayList <String >();
235
255
} else {
236
- s = mszInstanceList .getWideString (offset );
237
- }
238
- // list ends with double null
239
- if (s .isEmpty ()) {
240
- break ;
256
+ return new ArrayList <String >(inputList );
241
257
}
242
- instances .add (s );
243
- // Increment for string + null terminator
244
- offset += (s .length () + 1 ) * CHAR_TO_BYTES ;
245
258
}
246
259
247
- return instances ;
260
+ @ Override
261
+ public String toString () {
262
+ return "PdhEnumObjectItems{" + "counters=" + counters + ", instances=" + instances + '}' ;
263
+ }
264
+ }
265
+
266
+ public static final class PdhException extends RuntimeException {
267
+ private final int errorCode ;
268
+
269
+ public PdhException (int errorCode ) {
270
+ super (String .format ("Pdh call failed with error code 0x%08X" , errorCode ));
271
+ this .errorCode = errorCode ;
272
+ }
273
+
274
+ public int getErrorCode () {
275
+ return errorCode ;
276
+ }
248
277
}
249
278
}
0 commit comments