mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 09:46:54 +02:00
[File Locksmith] Add CLI support (#44047)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request This pull request introduces a new command-line interface (CLI) project for the File Locksmith module, enabling users to interact with File Locksmith functionality directly from the command line. The changes include project and build configuration, CLI implementation, and supporting code to integrate with the existing FileLocksmith library. ## Commands and Options | Command / Option | Alias | Description | | :--- | :--- | :--- | | `<path>` | N/A | **Required**. One or more file or directory paths to check. You can specify multiple paths separated by spaces. | | `--kill` | N/A | Terminates (kills) all processes that are currently locking the specified files. | | `--json` | N/A | Outputs the results in structured **JSON** format instead of human-readable text. Useful for automation and scripts. | | `--wait` | N/A | **Blocks execution** and waits until the specified files are released. The command will not exit until the files are unlocked. | | `--help` | N/A | Displays the help message with usage instructions. | ## Usage Examples ### 1. Basic check (Human-readable output) Check which processes are locking a specific file: ```powershell FileLocksmithCLI.exe "C:\Users\Docs\report.docx" ``` ### 2. Check multiple files and output JSON Check multiple files and get the output in JSON format for parsing: ```powershell FileLocksmithCLI.exe --json "C:\File1.txt" "C:\Folder\File2.dll" ``` ### 3. Wait for a file to be unlocked Block script execution until a file is released (useful in build scripts): ```powershell FileLocksmithCLI.exe --wait "C:\bin\output.exe" ``` ### 4. Force unlock a file Kill all processes that are locking a specific file: ```powershell FileLocksmithCLI.exe --kill "C:\LockedFile.dat" ``` <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [ ] Closes: #xxx <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Signed-off-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com>
This commit is contained in:
@@ -117,6 +117,7 @@
|
|||||||
"WinUI3Apps\\PowerToys.FileLocksmithUI.dll",
|
"WinUI3Apps\\PowerToys.FileLocksmithUI.dll",
|
||||||
"WinUI3Apps\\PowerToys.FileLocksmithContextMenu.dll",
|
"WinUI3Apps\\PowerToys.FileLocksmithContextMenu.dll",
|
||||||
"FileLocksmithContextMenuPackage.msix",
|
"FileLocksmithContextMenuPackage.msix",
|
||||||
|
"FileLocksmithCLI.exe",
|
||||||
|
|
||||||
"WinUI3Apps\\Peek.Common.dll",
|
"WinUI3Apps\\Peek.Common.dll",
|
||||||
"WinUI3Apps\\Peek.FilePreviewer.dll",
|
"WinUI3Apps\\Peek.FilePreviewer.dll",
|
||||||
|
|||||||
@@ -420,6 +420,7 @@
|
|||||||
</Project>
|
</Project>
|
||||||
</Folder>
|
</Folder>
|
||||||
<Folder Name="/modules/FileLocksmith/">
|
<Folder Name="/modules/FileLocksmith/">
|
||||||
|
<Project Path="src/modules/FileLocksmith/FileLocksmithCLI/FileLocksmithCLI.vcxproj" Id="49D456D3-F485-45AF-8875-45B44F193DDC" />
|
||||||
<Project Path="src/modules/FileLocksmith/FileLocksmithContextMenu/FileLocksmithContextMenu.vcxproj" Id="799a50d8-de89-4ed1-8ff8-ad5a9ed8c0ca" />
|
<Project Path="src/modules/FileLocksmith/FileLocksmithContextMenu/FileLocksmithContextMenu.vcxproj" Id="799a50d8-de89-4ed1-8ff8-ad5a9ed8c0ca" />
|
||||||
<Project Path="src/modules/FileLocksmith/FileLocksmithExt/FileLocksmithExt.vcxproj" Id="57175ec7-92a5-4c1e-8244-e3fbca2a81de" />
|
<Project Path="src/modules/FileLocksmith/FileLocksmithExt/FileLocksmithExt.vcxproj" Id="57175ec7-92a5-4c1e-8244-e3fbca2a81de" />
|
||||||
<Project Path="src/modules/FileLocksmith/FileLocksmithLib/FileLocksmithLib.vcxproj" Id="9d52fd25-ef90-4f9a-a015-91efc5daf54f" />
|
<Project Path="src/modules/FileLocksmith/FileLocksmithLib/FileLocksmithLib.vcxproj" Id="9d52fd25-ef90-4f9a-a015-91efc5daf54f" />
|
||||||
@@ -429,6 +430,9 @@
|
|||||||
<Platform Solution="*|x64" Project="x64" />
|
<Platform Solution="*|x64" Project="x64" />
|
||||||
</Project>
|
</Project>
|
||||||
</Folder>
|
</Folder>
|
||||||
|
<Folder Name="/modules/FileLocksmith/Tests/">
|
||||||
|
<Project Path="src/modules/FileLocksmith/FileLocksmithCLI/tests/FileLocksmithCLIUnitTests.vcxproj" Id="A1B2C3D4-E5F6-7890-1234-567890ABCDEF" />
|
||||||
|
</Folder>
|
||||||
<Folder Name="/modules/Hosts/">
|
<Folder Name="/modules/Hosts/">
|
||||||
<Project Path="src/modules/Hosts/Hosts/Hosts.csproj">
|
<Project Path="src/modules/Hosts/Hosts/Hosts.csproj">
|
||||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||||
|
|||||||
248
src/modules/FileLocksmith/FileLocksmithCLI/CLILogic.cpp
Normal file
248
src/modules/FileLocksmith/FileLocksmithCLI/CLILogic.cpp
Normal file
@@ -0,0 +1,248 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "CLILogic.h"
|
||||||
|
#include <common/utils/json.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <chrono>
|
||||||
|
#include "resource.h"
|
||||||
|
#include <common/logger/logger.h>
|
||||||
|
#include <common/utils/logger_helper.h>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
DWORD_PTR ToDwordPtr(T val)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_pointer_v<T>)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<DWORD_PTR>(val);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return static_cast<DWORD_PTR>(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
std::wstring FormatString(IStringProvider& strings, UINT id, Args... args)
|
||||||
|
{
|
||||||
|
std::wstring format = strings.GetString(id);
|
||||||
|
if (format.empty()) return L"";
|
||||||
|
|
||||||
|
DWORD_PTR arguments[] = { ToDwordPtr(args)..., 0 };
|
||||||
|
|
||||||
|
LPWSTR buffer = nullptr;
|
||||||
|
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
||||||
|
format.c_str(),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
reinterpret_cast<LPWSTR>(&buffer),
|
||||||
|
0,
|
||||||
|
reinterpret_cast<va_list*>(arguments));
|
||||||
|
|
||||||
|
if (buffer)
|
||||||
|
{
|
||||||
|
std::wstring result(buffer);
|
||||||
|
LocalFree(buffer);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return L"";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring get_usage(IStringProvider& strings)
|
||||||
|
{
|
||||||
|
return strings.GetString(IDS_USAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring get_json(const std::vector<ProcessResult>& results)
|
||||||
|
{
|
||||||
|
json::JsonObject root;
|
||||||
|
json::JsonArray processes;
|
||||||
|
|
||||||
|
for (const auto& result : results)
|
||||||
|
{
|
||||||
|
json::JsonObject process;
|
||||||
|
process.SetNamedValue(L"pid", json::JsonValue::CreateNumberValue(result.pid));
|
||||||
|
process.SetNamedValue(L"name", json::JsonValue::CreateStringValue(result.name));
|
||||||
|
process.SetNamedValue(L"user", json::JsonValue::CreateStringValue(result.user));
|
||||||
|
|
||||||
|
json::JsonArray files;
|
||||||
|
for (const auto& file : result.files)
|
||||||
|
{
|
||||||
|
files.Append(json::JsonValue::CreateStringValue(file));
|
||||||
|
}
|
||||||
|
process.SetNamedValue(L"files", files);
|
||||||
|
|
||||||
|
processes.Append(process);
|
||||||
|
}
|
||||||
|
|
||||||
|
root.SetNamedValue(L"processes", processes);
|
||||||
|
return root.Stringify().c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring get_text(const std::vector<ProcessResult>& results, IStringProvider& strings)
|
||||||
|
{
|
||||||
|
std::wstringstream ss;
|
||||||
|
if (results.empty())
|
||||||
|
{
|
||||||
|
ss << strings.GetString(IDS_NO_PROCESSES);
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
ss << strings.GetString(IDS_HEADER);
|
||||||
|
for (const auto& result : results)
|
||||||
|
{
|
||||||
|
ss << result.pid << L"\t"
|
||||||
|
<< result.user << L"\t"
|
||||||
|
<< result.name << std::endl;
|
||||||
|
}
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring kill_processes(const std::vector<ProcessResult>& results, IProcessTerminator& terminator, IStringProvider& strings)
|
||||||
|
{
|
||||||
|
std::wstringstream ss;
|
||||||
|
for (const auto& result : results)
|
||||||
|
{
|
||||||
|
if (terminator.terminate(result.pid))
|
||||||
|
{
|
||||||
|
ss << FormatString(strings, IDS_TERMINATED, result.pid, result.name.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ss << FormatString(strings, IDS_FAILED_TERMINATE, result.pid, result.name.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandResult run_command(int argc, wchar_t* argv[], IProcessFinder& finder, IProcessTerminator& terminator, IStringProvider& strings)
|
||||||
|
{
|
||||||
|
Logger::info("Parsing arguments");
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
Logger::warn("No arguments provided");
|
||||||
|
return { 1, get_usage(strings) };
|
||||||
|
}
|
||||||
|
|
||||||
|
bool json_output = false;
|
||||||
|
bool kill = false;
|
||||||
|
bool wait = false;
|
||||||
|
int timeout_ms = -1;
|
||||||
|
std::vector<std::wstring> paths;
|
||||||
|
|
||||||
|
for (int i = 1; i < argc; ++i)
|
||||||
|
{
|
||||||
|
std::wstring arg = argv[i];
|
||||||
|
if (arg == L"--json")
|
||||||
|
{
|
||||||
|
json_output = true;
|
||||||
|
}
|
||||||
|
else if (arg == L"--kill")
|
||||||
|
{
|
||||||
|
kill = true;
|
||||||
|
}
|
||||||
|
else if (arg == L"--wait")
|
||||||
|
{
|
||||||
|
wait = true;
|
||||||
|
}
|
||||||
|
else if (arg == L"--timeout")
|
||||||
|
{
|
||||||
|
if (i + 1 < argc)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
timeout_ms = std::stoi(argv[++i]);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
Logger::error("Invalid timeout value");
|
||||||
|
return { 1, strings.GetString(IDS_ERROR_INVALID_TIMEOUT) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger::error("Timeout argument missing");
|
||||||
|
return { 1, strings.GetString(IDS_ERROR_TIMEOUT_ARG) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (arg == L"--help")
|
||||||
|
{
|
||||||
|
return { 0, get_usage(strings) };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
paths.push_back(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (paths.empty())
|
||||||
|
{
|
||||||
|
Logger::error("No paths specified");
|
||||||
|
return { 1, strings.GetString(IDS_ERROR_NO_PATHS) };
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::info("Processing {} paths", paths.size());
|
||||||
|
|
||||||
|
if (wait)
|
||||||
|
{
|
||||||
|
std::wstringstream ss;
|
||||||
|
if (json_output)
|
||||||
|
{
|
||||||
|
Logger::warn("Wait is incompatible with JSON output");
|
||||||
|
ss << strings.GetString(IDS_WARN_JSON_WAIT);
|
||||||
|
json_output = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ss << strings.GetString(IDS_WAITING);
|
||||||
|
auto start_time = std::chrono::steady_clock::now();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
auto results = finder.find(paths);
|
||||||
|
if (results.empty())
|
||||||
|
{
|
||||||
|
Logger::info("Files unlocked");
|
||||||
|
ss << strings.GetString(IDS_UNLOCKED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeout_ms >= 0)
|
||||||
|
{
|
||||||
|
auto current_time = std::chrono::steady_clock::now();
|
||||||
|
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();
|
||||||
|
if (elapsed > timeout_ms)
|
||||||
|
{
|
||||||
|
Logger::warn("Timeout waiting for files to be unlocked");
|
||||||
|
ss << strings.GetString(IDS_TIMEOUT);
|
||||||
|
return { 1, ss.str() };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Sleep(200);
|
||||||
|
}
|
||||||
|
return { 0, ss.str() };
|
||||||
|
}
|
||||||
|
|
||||||
|
auto results = finder.find(paths);
|
||||||
|
Logger::info("Found {} processes locking the files", results.size());
|
||||||
|
std::wstringstream output_ss;
|
||||||
|
|
||||||
|
if (kill)
|
||||||
|
{
|
||||||
|
Logger::info("Killing processes");
|
||||||
|
output_ss << kill_processes(results, terminator, strings);
|
||||||
|
// Re-check after killing
|
||||||
|
results = finder.find(paths);
|
||||||
|
Logger::info("Remaining processes: {}", results.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json_output)
|
||||||
|
{
|
||||||
|
output_ss << get_json(results) << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
output_ss << get_text(results, strings);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { 0, output_ss.str() };
|
||||||
|
}
|
||||||
31
src/modules/FileLocksmith/FileLocksmithCLI/CLILogic.h
Normal file
31
src/modules/FileLocksmith/FileLocksmithCLI/CLILogic.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include "FileLocksmithLib/FileLocksmith.h"
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
struct CommandResult
|
||||||
|
{
|
||||||
|
int exit_code;
|
||||||
|
std::wstring output;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IProcessFinder
|
||||||
|
{
|
||||||
|
virtual std::vector<ProcessResult> find(const std::vector<std::wstring>& paths) = 0;
|
||||||
|
virtual ~IProcessFinder() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IProcessTerminator
|
||||||
|
{
|
||||||
|
virtual bool terminate(DWORD pid) = 0;
|
||||||
|
virtual ~IProcessTerminator() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IStringProvider
|
||||||
|
{
|
||||||
|
virtual std::wstring GetString(UINT id) = 0;
|
||||||
|
virtual ~IStringProvider() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
CommandResult run_command(int argc, wchar_t* argv[], IProcessFinder& finder, IProcessTerminator& terminator, IStringProvider& strings);
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#include "resource.h"
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
STRINGTABLE
|
||||||
|
BEGIN
|
||||||
|
IDS_USAGE "Usage: FileLocksmithCLI.exe [options] <path1> [path2] ...\nOptions:\n --kill Kill processes locking the files\n --json Output results in JSON format\n --wait Wait for files to be unlocked\n --timeout Timeout in milliseconds for --wait\n --help Show this help message\n"
|
||||||
|
IDS_NO_PROCESSES "No processes found locking the file(s).\n"
|
||||||
|
IDS_HEADER "PID\tUser\tProcess\n"
|
||||||
|
IDS_TERMINATED "Terminated process %1!d! (%2)\n"
|
||||||
|
IDS_FAILED_TERMINATE "Failed to terminate process %1!d! (%2)\n"
|
||||||
|
IDS_FAILED_OPEN "Failed to open process %1!d! (%2)\n"
|
||||||
|
IDS_ERROR_NO_PATHS "Error: No paths specified.\n"
|
||||||
|
IDS_WARN_JSON_WAIT "Warning: --wait is incompatible with --json. Ignoring --json.\n"
|
||||||
|
IDS_WAITING "Waiting for files to be unlocked...\n"
|
||||||
|
IDS_UNLOCKED "Files unlocked.\n"
|
||||||
|
IDS_TIMEOUT "Timeout waiting for files to be unlocked.\n"
|
||||||
|
IDS_ERROR_INVALID_TIMEOUT "Error: Invalid timeout value.\n"
|
||||||
|
IDS_ERROR_TIMEOUT_ARG "Error: --timeout requires an argument.\n"
|
||||||
|
END
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>17.0</VCProjectVersion>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<ProjectGuid>{49D456D3-F485-45AF-8875-45B44F193DDC}</ProjectGuid>
|
||||||
|
<RootNamespace>FileLocksmithCLI</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
|
<ProjectName>FileLocksmithCLI</ProjectName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<Import Project="..\..\..\..\deps\spdlog.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutDir>..\..\..\..\$(Platform)\$(Configuration)</OutDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>false</ConformanceMode>
|
||||||
|
<AdditionalIncludeDirectories>$(ProjectDir)..;$(ProjectDir)..\..\..;$(ProjectDir)..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
|
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>shlwapi.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>false</ConformanceMode>
|
||||||
|
<AdditionalIncludeDirectories>$(ProjectDir)..;$(ProjectDir)..\..\..;$(ProjectDir)..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
|
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>shlwapi.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="CLILogic.cpp" />
|
||||||
|
<ClCompile Include="main.cpp" />
|
||||||
|
<ClCompile Include="pch.cpp">
|
||||||
|
<PrecompiledHeader Condition="'$(UsePrecompiledHeaders)' != 'false'">Create</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="CLILogic.h" />
|
||||||
|
<ClInclude Include="pch.h" />
|
||||||
|
<ClInclude Include="resource.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="FileLocksmithCLI.rc" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\FileLocksmithLib\FileLocksmithLib.vcxproj">
|
||||||
|
<Project>{9d52fd25-ef90-4f9a-a015-91efc5daf54f}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\..\..\common\logger\logger.vcxproj">
|
||||||
|
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\..\..\common\SettingsAPI\SettingsAPI.vcxproj">
|
||||||
|
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\..\..\common\version\version.vcxproj">
|
||||||
|
<Project>{1248566c-272a-43c0-88d6-e6675d569a09}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||||
|
</ImportGroup>
|
||||||
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||||
|
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="CLILogic.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="main.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="pch.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="CLILogic.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="pch.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="resource.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
71
src/modules/FileLocksmith/FileLocksmithCLI/main.cpp
Normal file
71
src/modules/FileLocksmith/FileLocksmithCLI/main.cpp
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "CLILogic.h"
|
||||||
|
#include "FileLocksmithLib/FileLocksmith.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include "resource.h"
|
||||||
|
#include <common/logger/logger.h>
|
||||||
|
#include <common/utils/logger_helper.h>
|
||||||
|
|
||||||
|
struct RealProcessFinder : IProcessFinder
|
||||||
|
{
|
||||||
|
std::vector<ProcessResult> find(const std::vector<std::wstring>& paths) override
|
||||||
|
{
|
||||||
|
return find_processes_recursive(paths);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RealProcessTerminator : IProcessTerminator
|
||||||
|
{
|
||||||
|
bool terminate(DWORD pid) override
|
||||||
|
{
|
||||||
|
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
|
||||||
|
if (hProcess)
|
||||||
|
{
|
||||||
|
bool result = TerminateProcess(hProcess, 0);
|
||||||
|
CloseHandle(hProcess);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RealStringProvider : IStringProvider
|
||||||
|
{
|
||||||
|
std::wstring GetString(UINT id) override
|
||||||
|
{
|
||||||
|
wchar_t buffer[4096];
|
||||||
|
int len = LoadStringW(GetModuleHandle(NULL), id, buffer, ARRAYSIZE(buffer));
|
||||||
|
if (len > 0)
|
||||||
|
{
|
||||||
|
return std::wstring(buffer, len);
|
||||||
|
}
|
||||||
|
return L"";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef UNIT_TEST
|
||||||
|
int wmain(int argc, wchar_t* argv[])
|
||||||
|
{
|
||||||
|
winrt::init_apartment();
|
||||||
|
LoggerHelpers::init_logger(L"FileLocksmithCLI", L"", LogSettings::fileLocksmithLoggerName);
|
||||||
|
Logger::info("FileLocksmithCLI started");
|
||||||
|
|
||||||
|
RealProcessFinder finder;
|
||||||
|
RealProcessTerminator terminator;
|
||||||
|
RealStringProvider strings;
|
||||||
|
|
||||||
|
auto result = run_command(argc, argv, finder, terminator, strings);
|
||||||
|
|
||||||
|
if (result.exit_code != 0)
|
||||||
|
{
|
||||||
|
Logger::error("Command failed with exit code {}", result.exit_code);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger::info("Command succeeded");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wcout << result.output;
|
||||||
|
return result.exit_code;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
|
||||||
|
</packages>
|
||||||
1
src/modules/FileLocksmith/FileLocksmithCLI/pch.cpp
Normal file
1
src/modules/FileLocksmith/FileLocksmithCLI/pch.cpp
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#include "pch.h"
|
||||||
22
src/modules/FileLocksmith/FileLocksmithCLI/pch.h
Normal file
22
src/modules/FileLocksmith/FileLocksmithCLI/pch.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef PCH_H
|
||||||
|
#define PCH_H
|
||||||
|
|
||||||
|
#define NOMINMAX
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <winternl.h>
|
||||||
|
#include <Psapi.h>
|
||||||
|
#include <shellapi.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <winrt/base.h>
|
||||||
|
|
||||||
|
#endif // PCH_H
|
||||||
16
src/modules/FileLocksmith/FileLocksmithCLI/resource.h
Normal file
16
src/modules/FileLocksmith/FileLocksmithCLI/resource.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// resource.h
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define IDS_USAGE 101
|
||||||
|
#define IDS_NO_PROCESSES 102
|
||||||
|
#define IDS_HEADER 103
|
||||||
|
#define IDS_TERMINATED 104
|
||||||
|
#define IDS_FAILED_TERMINATE 105
|
||||||
|
#define IDS_FAILED_OPEN 106
|
||||||
|
#define IDS_ERROR_NO_PATHS 107
|
||||||
|
#define IDS_WARN_JSON_WAIT 108
|
||||||
|
#define IDS_WAITING 109
|
||||||
|
#define IDS_UNLOCKED 110
|
||||||
|
#define IDS_TIMEOUT 111
|
||||||
|
#define IDS_ERROR_INVALID_TIMEOUT 112
|
||||||
|
#define IDS_ERROR_TIMEOUT_ARG 113
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "CppUnitTest.h"
|
||||||
|
#include "../CLILogic.h"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||||
|
|
||||||
|
namespace FileLocksmithCLIUnitTests
|
||||||
|
{
|
||||||
|
struct MockProcessFinder : IProcessFinder
|
||||||
|
{
|
||||||
|
std::vector<ProcessResult> results;
|
||||||
|
std::vector<ProcessResult> find(const std::vector<std::wstring>& paths) override
|
||||||
|
{
|
||||||
|
(void)paths;
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MockProcessTerminator : IProcessTerminator
|
||||||
|
{
|
||||||
|
bool shouldSucceed = true;
|
||||||
|
std::vector<DWORD> terminatedPids;
|
||||||
|
bool terminate(DWORD pid) override
|
||||||
|
{
|
||||||
|
terminatedPids.push_back(pid);
|
||||||
|
return shouldSucceed;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MockStringProvider : IStringProvider
|
||||||
|
{
|
||||||
|
std::map<UINT, std::wstring> strings;
|
||||||
|
std::wstring GetString(UINT id) override
|
||||||
|
{
|
||||||
|
if (strings.count(id)) return strings[id];
|
||||||
|
return L"String_" + std::to_wstring(id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_CLASS(CLITests)
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
TEST_METHOD(TestNoArgs)
|
||||||
|
{
|
||||||
|
MockProcessFinder finder;
|
||||||
|
MockProcessTerminator terminator;
|
||||||
|
MockStringProvider strings;
|
||||||
|
|
||||||
|
wchar_t* argv[] = { (wchar_t*)L"exe" };
|
||||||
|
auto result = run_command(1, argv, finder, terminator, strings);
|
||||||
|
|
||||||
|
Assert::AreEqual(1, result.exit_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(TestHelp)
|
||||||
|
{
|
||||||
|
MockProcessFinder finder;
|
||||||
|
MockProcessTerminator terminator;
|
||||||
|
MockStringProvider strings;
|
||||||
|
|
||||||
|
wchar_t* argv[] = { (wchar_t*)L"exe", (wchar_t*)L"--help" };
|
||||||
|
auto result = run_command(2, argv, finder, terminator, strings);
|
||||||
|
|
||||||
|
Assert::AreEqual(0, result.exit_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(TestFindProcesses)
|
||||||
|
{
|
||||||
|
MockProcessFinder finder;
|
||||||
|
finder.results = { { L"process", 123, L"user", { L"file1" } } };
|
||||||
|
MockProcessTerminator terminator;
|
||||||
|
MockStringProvider strings;
|
||||||
|
|
||||||
|
wchar_t* argv[] = { (wchar_t*)L"exe", (wchar_t*)L"file1" };
|
||||||
|
auto result = run_command(2, argv, finder, terminator, strings);
|
||||||
|
|
||||||
|
Assert::AreEqual(0, result.exit_code);
|
||||||
|
Assert::IsTrue(result.output.find(L"123") != std::wstring::npos);
|
||||||
|
Assert::IsTrue(result.output.find(L"process") != std::wstring::npos);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(TestJsonOutput)
|
||||||
|
{
|
||||||
|
MockProcessFinder finder;
|
||||||
|
finder.results = { { L"process", 123, L"user", { L"file1" } } };
|
||||||
|
MockProcessTerminator terminator;
|
||||||
|
MockStringProvider strings;
|
||||||
|
|
||||||
|
wchar_t* argv[] = { (wchar_t*)L"exe", (wchar_t*)L"file1", (wchar_t*)L"--json" };
|
||||||
|
auto result = run_command(3, argv, finder, terminator, strings);
|
||||||
|
|
||||||
|
Microsoft::VisualStudio::CppUnitTestFramework::Logger::WriteMessage(result.output.c_str());
|
||||||
|
|
||||||
|
Assert::AreEqual(0, result.exit_code);
|
||||||
|
Assert::IsTrue(result.output.find(L"\"pid\"") != std::wstring::npos);
|
||||||
|
Assert::IsTrue(result.output.find(L"123") != std::wstring::npos);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(TestKill)
|
||||||
|
{
|
||||||
|
MockProcessFinder finder;
|
||||||
|
finder.results = { { L"process", 123, L"user", { L"file1" } } };
|
||||||
|
MockProcessTerminator terminator;
|
||||||
|
MockStringProvider strings;
|
||||||
|
|
||||||
|
wchar_t* argv[] = { (wchar_t*)L"exe", (wchar_t*)L"file1", (wchar_t*)L"--kill" };
|
||||||
|
auto result = run_command(3, argv, finder, terminator, strings);
|
||||||
|
|
||||||
|
Assert::AreEqual(0, result.exit_code);
|
||||||
|
Assert::AreEqual((size_t)1, terminator.terminatedPids.size());
|
||||||
|
Assert::AreEqual((DWORD)123, terminator.terminatedPids[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(TestTimeout)
|
||||||
|
{
|
||||||
|
MockProcessFinder finder;
|
||||||
|
// Always return results so it waits
|
||||||
|
finder.results = { { L"process", 123, L"user", { L"file1" } } };
|
||||||
|
MockProcessTerminator terminator;
|
||||||
|
MockStringProvider strings;
|
||||||
|
|
||||||
|
wchar_t* argv[] = { (wchar_t*)L"exe", (wchar_t*)L"file1", (wchar_t*)L"--wait", (wchar_t*)L"--timeout", (wchar_t*)L"100" };
|
||||||
|
auto result = run_command(5, argv, finder, terminator, strings);
|
||||||
|
|
||||||
|
Assert::AreEqual(1, result.exit_code);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="..\..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{A1B2C3D4-E5F6-7890-1234-567890ABCDEF}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>FileLocksmithCLIUnitTests</RootNamespace>
|
||||||
|
<ProjectName>FileLocksmithCLI.UnitTests</ProjectName>
|
||||||
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<Import Project="..\..\..\..\..\deps\spdlog.props" />
|
||||||
|
<PropertyGroup Label="Configuration">
|
||||||
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutDir>..\..\..\..\..\$(Platform)\$(Configuration)\tests\FileLocksmithCLI\</OutDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup>
|
||||||
|
<ClCompile>
|
||||||
|
<AdditionalIncludeDirectories>..\;..\..\;..\..\..\..\;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;UNIT_TEST;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<UseFullPaths>true</UseFullPaths>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
|
<DisableSpecificWarnings>26466;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
<AdditionalDependencies>shlwapi.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="pch.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="pch.cpp">
|
||||||
|
<PrecompiledHeader Condition="'$(UsePrecompiledHeaders)' != 'false'">Create</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="FileLocksmithCLITests.cpp" />
|
||||||
|
<ClCompile Include="..\CLILogic.cpp">
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\FileLocksmithLib\FileLocksmithLib.vcxproj">
|
||||||
|
<Project>{9d52fd25-ef90-4f9a-a015-91efc5daf54f}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\..\..\..\common\logger\logger.vcxproj">
|
||||||
|
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\..\..\..\common\SettingsAPI\SettingsAPI.vcxproj">
|
||||||
|
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\..\..\..\common\version\version.vcxproj">
|
||||||
|
<Project>{1248566c-272a-43c0-88d6-e6675d569a09}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
<Import Project="..\..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||||
|
</ImportGroup>
|
||||||
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Error Condition="!Exists('..\..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||||
|
<Error Condition="!Exists('..\..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
|
||||||
|
</packages>
|
||||||
1
src/modules/FileLocksmith/FileLocksmithCLI/tests/pch.cpp
Normal file
1
src/modules/FileLocksmith/FileLocksmithCLI/tests/pch.cpp
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#include "pch.h"
|
||||||
9
src/modules/FileLocksmith/FileLocksmithCLI/tests/pch.h
Normal file
9
src/modules/FileLocksmith/FileLocksmithCLI/tests/pch.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <winrt/base.h>
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <shellapi.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include "CppUnitTest.h"
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ProcessResult.h"
|
||||||
|
|
||||||
|
// Second version, checks handles towards files and all subfiles and folders of given dirs, if any.
|
||||||
|
std::vector<ProcessResult> find_processes_recursive(const std::vector<std::wstring>& paths);
|
||||||
|
|
||||||
|
// Gives the full path of the executable, given the process id
|
||||||
|
std::wstring pid_to_full_path(DWORD pid);
|
||||||
@@ -34,9 +34,9 @@
|
|||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;FILELOCKSMITH_LIB_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>../../..;../..;</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\FileLocksmithLibInterop;../../..;../..;</AdditionalIncludeDirectories>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>
|
<SubSystem>
|
||||||
@@ -50,9 +50,9 @@
|
|||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;FILELOCKSMITH_LIB_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>../../..;../..;</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\FileLocksmithLibInterop;../../..;../..;</AdditionalIncludeDirectories>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>
|
<SubSystem>
|
||||||
@@ -68,13 +68,15 @@
|
|||||||
<ClInclude Include="Settings.h" />
|
<ClInclude Include="Settings.h" />
|
||||||
<ClInclude Include="Trace.h" />
|
<ClInclude Include="Trace.h" />
|
||||||
<ClInclude Include="framework.h" />
|
<ClInclude Include="framework.h" />
|
||||||
<ClInclude Include="pch.h" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="IPC.cpp" />
|
<ClCompile Include="IPC.cpp" />
|
||||||
<ClCompile Include="Settings.cpp" />
|
<ClCompile Include="Settings.cpp" />
|
||||||
<ClCompile Include="Trace.cpp" />
|
<ClCompile Include="Trace.cpp" />
|
||||||
<ClCompile Include="FileLocksmithLib.cpp" />
|
<ClCompile Include="FileLocksmithLib.cpp" />
|
||||||
|
<ClCompile Include="..\FileLocksmithLibInterop\FileLocksmith.cpp" />
|
||||||
|
<ClCompile Include="..\FileLocksmithLibInterop\NtdllBase.cpp" />
|
||||||
|
<ClCompile Include="..\FileLocksmithLibInterop\NtdllExtensions.cpp" />
|
||||||
<ClCompile Include="pch.cpp">
|
<ClCompile Include="pch.cpp">
|
||||||
<PrecompiledHeader Condition="'$(UsePrecompiledHeaders)' != 'false'">Create</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(UsePrecompiledHeaders)' != 'false'">Create</PrecompiledHeader>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|||||||
@@ -38,6 +38,15 @@
|
|||||||
<ClCompile Include="FileLocksmithLib.cpp">
|
<ClCompile Include="FileLocksmithLib.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="FileLocksmith.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="NtdllBase.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="NtdllExtensions.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="pch.cpp">
|
<ClCompile Include="pch.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|||||||
12
src/modules/FileLocksmith/FileLocksmithLib/ProcessResult.h
Normal file
12
src/modules/FileLocksmith/FileLocksmithLib/ProcessResult.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
struct ProcessResult
|
||||||
|
{
|
||||||
|
std::wstring name;
|
||||||
|
DWORD pid;
|
||||||
|
std::wstring user;
|
||||||
|
std::vector<std::wstring> files;
|
||||||
|
};
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "Constants.h"
|
#include "Constants.h"
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
#include <common/utils/json.h>
|
#include <common/utils/json.h>
|
||||||
#include <common/SettingsAPI/settings_helpers.h>
|
#include <common/SettingsAPI/settings_helpers.h>
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
// pch.h: This is a precompiled header file.
|
|
||||||
// Files listed below are compiled only once, improving build performance for future builds.
|
|
||||||
// This also affects IntelliSense performance, including code completion and many code browsing features.
|
|
||||||
// However, files listed here are ALL re-compiled if any one of them is updated between builds.
|
|
||||||
// Do not add files here that you will be updating frequently as this negates the performance advantage.
|
|
||||||
|
|
||||||
#ifndef PCH_H
|
|
||||||
#define PCH_H
|
|
||||||
|
|
||||||
// add headers that you want to pre-compile here
|
|
||||||
#include "framework.h"
|
|
||||||
|
|
||||||
#endif //PCH_H
|
|
||||||
@@ -18,4 +18,6 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
#ifndef FILELOCKSMITH_LIB_STATIC
|
||||||
#include <winrt/PowerToys.Interop.h>
|
#include <winrt/PowerToys.Interop.h>
|
||||||
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user