diff --git a/PresentMon/CommandLine.cpp b/PresentMon/CommandLine.cpp index 74583a83..e7483c68 100644 --- a/PresentMon/CommandLine.cpp +++ b/PresentMon/CommandLine.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2017,2019-2022 Intel Corporation +// Copyright (C) 2017,2019-2023 Intel Corporation // SPDX-License-Identifier: MIT #include @@ -244,7 +244,7 @@ bool ParseValue(char** argv, int argc, int* i, char const** value) return true; } -bool ParseValue(char** argv, int argc, int* i, std::vector* value) +bool ParseValue(char** argv, int argc, int* i, std::vector* value) { char const* v = nullptr; if (!ParseValue(argv, argc, i, &v)) return false; @@ -554,19 +554,19 @@ bool ParseCommandLine(int argc, char** argv) " output, and recording arguments.\n"); } - // Prune any directory and ".exe" off of the provided process names. This - // is primarily because the ProcessStart event typically has a full path - // including "\\Device\\..." and ProcessStop event sometimes is missing - // part of the extension. + // Convert the provided process names into a canonical form used for comparison. + // The comparison is not case-sensitive, and does not include any directory nor + // extension. + // + // This is because the different paths for obtaining process information return + // different image name strings. e.g., the ProcessStart event typically has a + // full path including "\\Device\\..." and ProcessStop event sometimes is + // missing part of the extension. for (auto& name : args->mTargetProcessNames) { - auto pr = GetProcessNameComparisonRange(name, strlen(name)); - name += pr.first; - ((char*) name)[pr.second] = '\0'; + CanonicalizeProcessName(&name); } for (auto& name : args->mExcludeProcessNames) { - auto pr = GetProcessNameComparisonRange(name, strlen(name)); - name += pr.first; - ((char*) name)[pr.second] = '\0'; + CanonicalizeProcessName(&name); } return true; diff --git a/PresentMon/OutputThread.cpp b/PresentMon/OutputThread.cpp index fa86fdd3..6b23ff4e 100644 --- a/PresentMon/OutputThread.cpp +++ b/PresentMon/OutputThread.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2019-2022 Intel Corporation +// Copyright (C) 2019-2023 Intel Corporation // SPDX-License-Identifier: MIT #include "PresentMon.hpp" @@ -91,40 +91,35 @@ static void UpdateRecordingToggles(size_t nextIndex) static std::unordered_map gProcesses; static uint32_t gTargetProcessCount = 0; -std::pair GetProcessNameComparisonRange(char const* name, size_t length) +// Removes any directory and extension, and converts the remaining name to +// lower case. +void CanonicalizeProcessName(std::string* name) { - std::pair pr(0, length); - - if (pr.second >= 4 && _stricmp(name + pr.second - 4, ".exe") == 0) { - pr.second -= 4; - } - for (size_t i = pr.second; i--; ) { - if (name[i] == '/' || name[i] == '\\') { - pr.first = i + 1; - break; - } + size_t i = name->find_last_of("./\\"); + if (i != std::string::npos && (*name)[i] == '.') { + name->resize(i); + i = name->find_last_of("/\\"); } - pr.second = pr.second - pr.first; - return pr; + *name = name->substr(i + 1); + + std::transform(name->begin(), name->end(), name->begin(), + [](unsigned char c) { return (unsigned char) ::tolower((int) c); }); } static bool IsTargetProcess(uint32_t processId, std::string const& processName) { auto const& args = GetCommandLineArgs(); - char const* compareName = nullptr; - size_t compareLength = 0; + std::string compareName; if (args.mExcludeProcessNames.size() + args.mTargetProcessNames.size() > 0) { - compareName = processName.c_str(); - auto pr = GetProcessNameComparisonRange(compareName, processName.size()); - compareName += pr.first; - compareLength = pr.second; + compareName = processName; + CanonicalizeProcessName(&compareName); } // -exclude for (auto excludeProcessName : args.mExcludeProcessNames) { - if (_strnicmp(excludeProcessName, compareName, compareLength) == 0) { + if (excludeProcessName == compareName) { return false; } } @@ -141,7 +136,7 @@ static bool IsTargetProcess(uint32_t processId, std::string const& processName) // -process_name for (auto targetProcessName : args.mTargetProcessNames) { - if (_strnicmp(targetProcessName, compareName, compareLength) == 0) { + if (targetProcessName == compareName) { return true; } } diff --git a/PresentMon/PresentMon.hpp b/PresentMon/PresentMon.hpp index d762a6d8..aae2a86c 100644 --- a/PresentMon/PresentMon.hpp +++ b/PresentMon/PresentMon.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2017,2019-2022 Intel Corporation +// Copyright (C) 2017,2019-2023 Intel Corporation // SPDX-License-Identifier: MIT #pragma once @@ -42,8 +42,8 @@ enum class ConsoleOutput { }; struct CommandLineArgs { - std::vector mTargetProcessNames; - std::vector mExcludeProcessNames; + std::vector mTargetProcessNames; + std::vector mExcludeProcessNames; const char *mOutputCsvFileName; const char *mEtlFileName; const char *mSessionName; @@ -137,7 +137,7 @@ void ExitMainThread(); void StartOutputThread(); void StopOutputThread(); void SetOutputRecordingState(bool record); -std::pair GetProcessNameComparisonRange(char const* name, size_t length); +void CanonicalizeProcessName(std::string* path); // Privilege.cpp: bool InPerfLogUsersGroup(); diff --git a/Tools/run_tests.cmd b/Tools/run_tests.cmd index 22b2a650..300c397f 100644 --- a/Tools/run_tests.cmd +++ b/Tools/run_tests.cmd @@ -152,6 +152,8 @@ if %do_realtime_tests% EQU 1 ( call :realtime_multicsv_test + call :realtime_exclude_test + echo. ) @@ -380,3 +382,42 @@ exit /b 0 exit /b 0 +:: ----------------------------------------------------------------------------- +:realtime_exclude_test + call :start_target_app /width=320 /height=240 + if %errorlevel% NEQ 0 ( + echo error: realtime PresentBench tests cannot run with a process named PresentBench.exe already running + set /a errorcount=%errorcount%+1 + exit /b 0 + ) + + set saw_excluded=0 + set saw_nonexcluded=0 + for /f "tokens=1 delims=," %%a in ('"%pmdir%\build\%test_config%\PresentMon-%version%-x64.exe" -exclude presentbench -output_stdout -timed 2 -terminate_after_timed 2^>NUL') do ( + if "%%a" EQU "PresentBench.exe" ( + set saw_excluded=1 + ) + ) + for /f "tokens=1 delims=," %%a in ('"%pmdir%\build\%test_config%\PresentMon-%version%-x64.exe" -exclude presentbench2 -output_stdout -timed 2 -terminate_after_timed 2^>NUL') do ( + if "%%a" EQU "PresentBench.exe" ( + set saw_nonexcluded=1 + ) + ) + + call :stop_target_app + + if %saw_nonexcluded% EQU 0 ( + echo error: -exclude PresentBench2 did not record any presents + set /a errorcount=%errorcount%+1 + exit /b 0 + ) + if %saw_excluded% EQU 1 ( + echo error: -exclude PresentBench recorded presents + set /a errorcount=%errorcount%+1 + exit /b 0 + ) + + echo. -exclude presentbench + echo. -exclude presentbench2 + exit /b 0 +