void CSettings::OnBnClickedSelectPerfCounters() { std::vector<std::wstring> counters; PDH_BROWSE_DLG_CONFIG config = {}; CallbackArg arg = {}; const size_t arbitrary_magic_buffer_size = 10000; arg.counter_names.resize(arbitrary_magic_buffer_size); arg.config = &config; arg.counters = &counters; config.bSingleCounterPerDialog = false; config.bIncludeCostlyObjects = false; config.bIncludeInstanceIndex = true; // I get crashes deep inside pdhui.dll if I set this to false and select // something (All Instances) that results in a wildcard. WTF? config.bWildCardInstances = true; config.bDisableMachineSelection = true; // /analyze warns that this const_cast is not needed, but when compiling with // /Zc:strictStrings it absolutely is. The type of szDialogBoxCaption needs to // be changed for this to work cleanly. config.szDialogBoxCaption = const_cast<wchar_t*>(L"Select performance counters"); config.hWndOwner = *this; config.pCallBack = &CounterCallBack; config.dwCallBackArg = reinterpret_cast<DWORD_PTR>(&arg); config.dwDefaultDetailLevel = PERF_DETAIL_EXPERT; config.szReturnPathBuffer = arg.counter_names.data(); config.cchReturnPathLength = static_cast<DWORD>(arg.counter_names.size()); // Need some way to initialize the dialog with the previous settings? const PDH_STATUS status = PdhBrowseCounters(&config); if (status == ERROR_SUCCESS || status == PDH_DIALOG_CANCELLED) { std::wstring counters_string; for (auto& counter : counters) { counters_string += counter; counters_string += ';'; // I hope that is a valid separator. } // Trim the trailing ';' if (!counters_string.empty()) counters_string.resize(counters_string.size() - 1); SetDlgItemTextW(IDC_PERFORMANCECOUNTERS, counters_string.c_str()); } }
long __cdecl _tmain(int argc, TCHAR **argv) { HQUERY hQuery; HCOUNTER hCounter; PDH_STATUS pdhStatus; PDH_FMT_COUNTERVALUE fmtValue; DWORD ctrType; SYSTEMTIME stSampleTime; PDH_BROWSE_DLG_CONFIG BrowseDlgData; CHAR szPathBuffer[PDH_MAX_COUNTER_PATH]; // Create a query. pdhStatus = PdhOpenQuery(NULL, NULL, &hQuery); if (ERROR_SUCCESS != pdhStatus) { _tprintf(TEXT("PdhOpenQuery failed with %ld.\n"), pdhStatus); goto cleanup; } ZeroMemory(&szPathBuffer, sizeof(szPathBuffer)); // Initialize the browser dialog window settings. ZeroMemory(&BrowseDlgData, sizeof(PDH_BROWSE_DLG_CONFIG)); BrowseDlgData.bIncludeInstanceIndex = FALSE; BrowseDlgData.bSingleCounterPerAdd = TRUE; BrowseDlgData.bSingleCounterPerDialog = TRUE; BrowseDlgData.bLocalCountersOnly = FALSE; BrowseDlgData.bWildCardInstances = TRUE; BrowseDlgData.bHideDetailBox = TRUE; BrowseDlgData.bInitializePath = FALSE; BrowseDlgData.bDisableMachineSelection = FALSE; BrowseDlgData.bIncludeCostlyObjects = FALSE; BrowseDlgData.bShowObjectBrowser = FALSE; BrowseDlgData.hWndOwner = NULL; BrowseDlgData.szReturnPathBuffer = szPathBuffer; BrowseDlgData.cchReturnPathLength = sizeof(szPathBuffer); BrowseDlgData.pCallBack = NULL; BrowseDlgData.dwCallBackArg = 0; BrowseDlgData.CallBackStatus = ERROR_SUCCESS; BrowseDlgData.dwDefaultDetailLevel = PERF_DETAIL_WIZARD; BrowseDlgData.szDialogBoxCaption = "Select a counter to monitor."; // Display the counter browser window. The dialog is configured // to return a single selection from the counter list. // DWORD sized = PDH_MAX_COUNTER_PATH; // pdhStatus = PdhLookupPerfNameByIndex(NULL,2,szPathBuffer,&sized); pdhStatus = PdhBrowseCounters (&BrowseDlgData); if (ERROR_SUCCESS != pdhStatus) { if (PDH_DIALOG_CANCELLED != pdhStatus) { _tprintf(TEXT("PdhBrowseCounters failed with %ld.\n"), pdhStatus); } goto cleanup; } // Add the selected counter to the query. pdhStatus = PdhAddCounter (hQuery, szPathBuffer, 0, &hCounter); if (ERROR_SUCCESS != pdhStatus) { _tprintf(TEXT("PdhBrowseCounters failed with %ld.\n"), pdhStatus); goto cleanup; } // Most counters require two sample values to display a formatted value. // PDH stores the current sample value and the previously collected // sample value. This call retrieves the first value that will be used // by PdhGetFormattedCounterValue in the first iteration of the loop // Note that this value is lost if the counter does not require two // values to compute a displayable value. // pdhStatus = PdhCollectQueryData (hQuery); // if (ERROR_SUCCESS != pdhStatus) // { // _tprintf(TEXT("PdhCollectQueryData failed with %ld.\n"), pdhStatus); // goto cleanup; // } // Print counter values until a key is pressed. while (!_kbhit()) { // Wait one interval. Sleep(SAMPLE_INTERVAL_MS); // Get the sample time. GetLocalTime (&stSampleTime); // Get the current data value. pdhStatus = PdhCollectQueryData (hQuery); // Print the time stamp for the sample. _tprintf ( TEXT("\n\"%2.2d/%2.2d/%4.4d %2.2d:%2.2d:%2.2d.%3.3d\""), stSampleTime.wMonth, stSampleTime.wDay, stSampleTime.wYear, stSampleTime.wHour, stSampleTime.wMinute, stSampleTime.wSecond, stSampleTime.wMilliseconds); // Compute a displayable value for the counter. pdhStatus = PdhGetFormattedCounterValue (hCounter, PDH_FMT_DOUBLE, &ctrType, &fmtValue); if (pdhStatus == ERROR_SUCCESS) { _tprintf (TEXT(",\"%.20g\""), fmtValue.doubleValue); } else { _tprintf(TEXT("\nPdhGetFormattedCounterValue failed with %ld.\n"), pdhStatus); // goto cleanup; } } cleanup: // Close the query. if (hQuery) PdhCloseQuery (hQuery); system ("pause"); return pdhStatus; }
static INT_PTR CALLBACK OptionsDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PPH_PERFMON_CONTEXT context = NULL; if (uMsg == WM_INITDIALOG) { context = (PPH_PERFMON_CONTEXT)PhAllocate(sizeof(PH_PERFMON_CONTEXT)); memset(context, 0, sizeof(PH_PERFMON_CONTEXT)); SetProp(hwndDlg, L"Context", (HANDLE)context); } else { context = (PPH_PERFMON_CONTEXT)GetProp(hwndDlg, L"Context"); if (uMsg == WM_NCDESTROY) { PPH_STRING string; ClearCounterList(CountersList); CopyCounterList(CountersList, context->CountersListEdited); PhDereferenceObject(context->CountersListEdited); string = SaveCounterList(CountersList); PhSetStringSetting2(SETTING_NAME_PERFMON_LIST, &string->sr); PhDereferenceObject(string); RemoveProp(hwndDlg, L"Context"); PhFree(context); } } if (context == NULL) return FALSE; switch (uMsg) { case WM_INITDIALOG: { context->CountersListEdited = PhCreateList(2); context->ListViewHandle = GetDlgItem(hwndDlg, IDC_PERFCOUNTER_LISTVIEW); PhSetListViewStyle(context->ListViewHandle, FALSE, TRUE); PhSetControlTheme(context->ListViewHandle, L"explorer"); PhAddListViewColumn(context->ListViewHandle, 0, 0, 0, LVCFMT_LEFT, 420, L"Counter"); PhSetExtendedListView(context->ListViewHandle); ClearCounterList(context->CountersListEdited); CopyCounterList(context->CountersListEdited, CountersList); LoadCountersToListView(context, context->CountersListEdited); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDC_ADD_BUTTON: { PDH_STATUS counterStatus = 0; PPH_STRING counterPathString = NULL; PPH_STRING counterWildCardString = NULL; PDH_BROWSE_DLG_CONFIG browseConfig = { 0 }; WCHAR counterPathBuffer[PDH_MAX_COUNTER_PATH] = L""; browseConfig.bIncludeInstanceIndex = FALSE; browseConfig.bSingleCounterPerAdd = FALSE;// Fix empty CounterPathBuffer browseConfig.bSingleCounterPerDialog = TRUE; browseConfig.bLocalCountersOnly = FALSE; browseConfig.bWildCardInstances = TRUE; // Seems to cause a lot of crashes browseConfig.bHideDetailBox = TRUE; browseConfig.bInitializePath = FALSE; browseConfig.bDisableMachineSelection = FALSE; browseConfig.bIncludeCostlyObjects = FALSE; browseConfig.bShowObjectBrowser = FALSE; browseConfig.hWndOwner = hwndDlg; browseConfig.szReturnPathBuffer = counterPathBuffer; browseConfig.cchReturnPathLength = PDH_MAX_COUNTER_PATH; browseConfig.CallBackStatus = ERROR_SUCCESS; browseConfig.dwDefaultDetailLevel = PERF_DETAIL_WIZARD; browseConfig.szDialogBoxCaption = L"Select a counter to monitor."; __try { // Display the counter browser window. if ((counterStatus = PdhBrowseCounters(&browseConfig)) != ERROR_SUCCESS) { if (counterStatus != PDH_DIALOG_CANCELLED) { PhShowError(hwndDlg, L"PdhBrowseCounters failed with status 0x%x.", counterStatus); } __leave; } else if (wcslen(counterPathBuffer) == 0) { // This gets called when pressing the X on the BrowseCounters dialog. __leave; } counterPathString = PhCreateString(counterPathBuffer); // Check if we need to expand any wildcards... if (PhFindCharInString(counterPathString, 0, '*') != -1) { ULONG counterWildCardLength = 0; // Query WildCard buffer length... PdhExpandWildCardPath( NULL, counterPathString->Buffer, NULL, &counterWildCardLength, 0 ); counterWildCardString = PhCreateStringEx(NULL, counterWildCardLength * sizeof(WCHAR)); if ((counterStatus = PdhExpandWildCardPath( NULL, counterPathString->Buffer, counterWildCardString->Buffer, &counterWildCardLength, 0 )) == ERROR_SUCCESS) { PH_STRINGREF part; PH_STRINGREF remaining = counterWildCardString->sr; while (remaining.Length != 0) { // Split the results if (!PhSplitStringRefAtChar(&remaining, '\0', &part, &remaining)) break; if (remaining.Length == 0) break; if ((counterStatus = PdhValidatePath(part.Buffer)) != ERROR_SUCCESS) { PhShowError(hwndDlg, L"PdhValidatePath failed with status 0x%x.", counterStatus); __leave; } AddCounterToListView(context, part.Buffer); } } else { PhShowError(hwndDlg, L"PdhExpandWildCardPath failed with status 0x%x.", counterStatus); } } else { if ((counterStatus = PdhValidatePath(counterPathString->Buffer)) != ERROR_SUCCESS) { PhShowError(hwndDlg, L"PdhValidatePath failed with status 0x%x.", counterStatus); __leave; } AddCounterToListView(context, counterPathString->Buffer); } } __finally { if (counterWildCardString) PhDereferenceObject(counterWildCardString); if (counterPathString) PhDereferenceObject(counterPathString); } } break; case IDC_REMOVE_BUTTON: { INT itemIndex; // Get the first selected item itemIndex = ListView_GetNextItem(context->ListViewHandle, -1, LVNI_SELECTED); while (itemIndex != -1) { PPH_PERFMON_ENTRY entry; if (PhGetListViewItemParam(context->ListViewHandle, itemIndex, (PPVOID)&entry)) { ULONG index = PhFindItemList(context->CountersListEdited, entry); if (index != -1) { PhRemoveItemList(context->CountersListEdited, index); PhRemoveListViewItem(context->ListViewHandle, itemIndex); FreeCounterEntry(entry); } } // Get the next selected item itemIndex = ListView_GetNextItem(context->ListViewHandle, -1, LVNI_SELECTED); } } break; case IDCANCEL: EndDialog(hwndDlg, IDCANCEL); break; case IDOK: EndDialog(hwndDlg, IDOK); break; } } break; } return FALSE; }