Skip to content

Commit dd15b2f

Browse files
committed
feat: 添加简单的xml解析代码[只能解析2层],来自TrafficMonitor拷贝的简单逻辑
1 parent 3a54f58 commit dd15b2f

4 files changed

Lines changed: 260 additions & 4 deletions

File tree

simple_xml.cpp

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
//
2+
// Created by kms on 2025/9/11.
3+
//
4+
5+
#include "simple_xml.h"
6+
7+
BOOL HasUtf8Bom(const std::string_view str)
8+
{
9+
return str.size() >= 3 &&
10+
static_cast<unsigned char>(str[0]) == 0xEF &&
11+
static_cast<unsigned char>(str[1]) == 0xBB &&
12+
static_cast<unsigned char>(str[2]) == 0xBF;
13+
}
14+
15+
std::wstring UTF82UTF16(const std::string& str)
16+
{
17+
if (str.empty())
18+
{
19+
return L"";
20+
}
21+
22+
auto size_needed = MultiByteToWideChar(CP_UTF8, 0, str.data(), str.size(), nullptr, 0);
23+
24+
if (size_needed <= 0)
25+
{
26+
return L"";
27+
}
28+
29+
std::wstring ret(size_needed, 0);
30+
MultiByteToWideChar(CP_UTF8, 0, str.data(), str.size(), ret.data(), size_needed);
31+
return ret;
32+
}
33+
34+
35+
CSimpleXML::CSimpleXML(const wstring& xml_path)
36+
{
37+
std::ifstream file_stream(xml_path, std::ios::binary);
38+
39+
if (!file_stream.is_open())
40+
{
41+
return;
42+
}
43+
44+
//读取文件内容
45+
46+
std::stringstream buffer;
47+
buffer << file_stream.rdbuf();
48+
std::string xml_str = buffer.str();
49+
50+
// UTF-8 BOM(EF BB BF → -17, -69, -65)
51+
if (HasUtf8Bom(xml_str))
52+
{
53+
xml_str.erase(0, 3);
54+
}
55+
56+
// 默认全按照UTF8处理
57+
this->m_xml_content = UTF82UTF16(xml_str);
58+
}
59+
60+
std::wstring CSimpleXML::GetNode(LPCWSTR node, LPCWSTR parent) const
61+
{
62+
wstring node_content = _GetNode(parent, this->m_xml_content);
63+
return _GetNode(node, node_content);
64+
}
65+
66+
std::wstring CSimpleXML::GetNode(LPCWSTR node) const
67+
{
68+
return _GetNode(node, this->m_xml_content);
69+
}
70+
71+
std::wstring CSimpleXML::_GetNode(LPCWSTR node, const wstring& content)
72+
{
73+
std::wstring node_start{L'<'};
74+
std::wstring node_end{L'<'};
75+
node_start += node;
76+
node_start += L'>';
77+
node_end += L'/';
78+
node_end += node;
79+
node_end += L'>';
80+
81+
size_t index_start, index_end;
82+
83+
index_start = content.find(node_start);
84+
index_end = content.find(node_end);
85+
if (index_start == wstring::npos || index_end == wstring::npos)
86+
return wstring();
87+
88+
auto result = content.substr(index_start + node_start.size(), index_end - index_start - node_start.size());
89+
return result;
90+
}

simple_xml.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//
2+
// Created by kms on 2025/9/11.
3+
//
4+
5+
#include <fstream>
6+
#include <sstream>
7+
8+
using std::wstring;
9+
10+
class CSimpleXML
11+
{
12+
public:
13+
CSimpleXML(const wstring& xml_path);
14+
CSimpleXML() = default;
15+
~CSimpleXML() = default;
16+
17+
void LoadXMLContentDirect(const wstring& xml_content) { m_xml_content = xml_content; }
18+
19+
wstring GetNode(const wchar_t* node, const wchar_t* parent) const;
20+
wstring GetNode(const wchar_t* node) const;
21+
22+
static wstring _GetNode(const wchar_t* node, const wstring& content);
23+
24+
protected:
25+
wstring m_xml_content;
26+
27+
};

task_sched.cpp

Lines changed: 140 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,28 @@ BOOL TryInvoke(F&& func, LPCWSTR msg)
2525
#define ErrThrow(msg) \
2626
do { TryInvoke([&] { return E_FAIL; }, msg); return FALSE; } while (0);
2727

28+
29+
std::wstring defaultTaskName()
30+
{
31+
// 获取所需缓冲区大小
32+
const auto required_size = GetEnvironmentVariableW(L"USERNAME", nullptr, 0);
33+
if (required_size == 0) {
34+
return L"timer-devourer-unknown";
35+
}
36+
37+
std::wstring username(required_size, L'\0');
38+
39+
const auto copied = GetEnvironmentVariableW(L"USERNAME", username.data(), required_size);
40+
if (copied == 0 || copied >= required_size) {
41+
return L"timer-devourer-unknown";
42+
}
43+
44+
// 调整大小(copied 是实际字符数)
45+
username.resize(copied);
46+
47+
return L"timer-devourer-" + username;
48+
}
49+
2850
/**
2951
*
3052
* @return BOOL
@@ -34,7 +56,7 @@ BOOL CreateStartupTask()
3456
// 错误位标志
3557
auto hr = S_OK;
3658

37-
std::wstring task_name;
59+
std::wstring task_name = defaultTaskName();
3860

3961
std::wstring username_domain;
4062
username_domain.resize(USERNAME_DOMAIN_LEN);
@@ -68,12 +90,12 @@ BOOL CreateStartupTask()
6890
ErrThrow(L"环境变量:USERDOMAIN获取失败");
6991
}
7092

93+
username.resize(username_len);
94+
username_domain.resize(userdomain_len);
95+
7196
username_domain += L"\\";
7297
username_domain += username;
7398

74-
task_name += L"timer-";
75-
task_name += username;
76-
7799
TryStep(com_scope.init(), L"COM组件:初始化错误");
78100

79101

@@ -226,3 +248,117 @@ BOOL CreateStartupTask()
226248

227249
return SUCCEEDED(hr);
228250
}
251+
252+
253+
BOOL DeleteStartupTask()
254+
{
255+
HRESULT hr = S_OK;
256+
257+
WCHAR username[USERNAME_LEN];
258+
std::wstring task_name = defaultTaskName();
259+
260+
COMScope com_scope;
261+
COMPtr<ITaskService> p_service(nullptr);
262+
COMPtr<ITaskFolder> p_task_folder(nullptr);
263+
264+
265+
TryStep(com_scope.init(), L"COM组件:初始化错误");
266+
267+
TryStep(CoCreateInstance(
268+
__uuidof(TaskScheduler),
269+
nullptr,
270+
CLSCTX_INPROC_SERVER,
271+
__uuidof(ITaskService),
272+
reinterpret_cast<void**>(p_service.AsOutPtr()))
273+
, L"COM组件TaskScheduler:创建失败");
274+
TryStep(hr , L"COM组件:创建ITaskService失败");
275+
276+
hr = p_service->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
277+
TryStep(hr, L"COM组件:连接ITaskService失败");
278+
279+
hr = p_service->GetFolder(_bstr_t(TASK_SCHED_FOLDER), p_task_folder.AsOutPtr());
280+
if (FAILED(hr))
281+
{
282+
// 断言文件夹不存在,不需要删除任务
283+
return TRUE;
284+
}
285+
286+
{
287+
COMPtr<IRegisteredTask> p_exist_reg_task(nullptr);
288+
hr = p_task_folder->GetTask(_bstr_t(task_name.c_str()), p_exist_reg_task.AsOutPtr());
289+
if (SUCCEEDED(hr))
290+
{
291+
hr = p_task_folder->DeleteTask(_bstr_t(task_name.c_str()), 0);
292+
}
293+
}
294+
295+
return (SUCCEEDED(hr));
296+
}
297+
298+
299+
BOOL IsActiveStartupTask(std::wstring* path)
300+
{
301+
HRESULT hr = S_OK;
302+
303+
std::wstring wstrTaskName = defaultTaskName();
304+
305+
COMScope com_scope;
306+
COMPtr<ITaskService> p_service(nullptr);
307+
COMPtr<ITaskFolder> p_task_folder(nullptr);
308+
309+
BOOL command_path_match = FALSE;
310+
311+
TryStep(com_scope.init(), L"COM组件:初始化错误");
312+
TryStep(CoCreateInstance(
313+
__uuidof(TaskScheduler),
314+
nullptr,
315+
CLSCTX_INPROC_SERVER,
316+
__uuidof(ITaskService),
317+
p_service.AsOutVoidPtr())
318+
, L"COM组件TaskScheduler:创建失败");
319+
320+
// Connect to the task service.
321+
hr = p_service->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
322+
TryStep(hr, L"COM组件:连接ITaskService失败");
323+
324+
// ------------------------------------------------------
325+
// Get the TrafficMonitor task folder.
326+
hr = p_service->GetFolder(_bstr_t(TASK_SCHED_FOLDER), p_task_folder.AsOutPtr());
327+
TryStep(hr, L"COM组件:获取ITaskFolder失败");
328+
329+
// ------------------------------------------------------
330+
// If the task exists, disable.
331+
{
332+
COMPtr<IRegisteredTask> p_exist_reg_task(nullptr);
333+
hr = p_task_folder->GetTask(_bstr_t(wstrTaskName.c_str()), p_exist_reg_task.AsOutPtr());
334+
if (SUCCEEDED(hr))
335+
{
336+
VARIANT_BOOL is_enabled;
337+
hr = p_exist_reg_task->get_Enabled(&is_enabled);
338+
//判断已存在的任务计划命令的exe文件路径是否为当前exe的路径
339+
CComBSTR xml_buff{};
340+
p_exist_reg_task->get_Xml(&xml_buff);
341+
CSimpleXML xml;
342+
xml.LoadXMLContentDirect(std::wstring(xml_buff));
343+
// 获得配置中的执行路径
344+
std::wstring command_path = xml.GetNode(L"Command", L"Exec");
345+
if (path != nullptr)
346+
{
347+
*path = command_path;
348+
}
349+
// 获得当前exe的路径
350+
std::wstring exec_path;
351+
exec_path.resize(MAX_PATH);
352+
GetModuleFileName(NULL, exec_path.data(), MAX_PATH);
353+
command_path_match = (command_path == exec_path);
354+
SysFreeString(xml_buff);
355+
if (SUCCEEDED(hr))
356+
{
357+
// Got the value. Return it.
358+
hr = (is_enabled == VARIANT_TRUE) ? S_OK : E_FAIL; // Fake success or fail to return the value.
359+
}
360+
}
361+
}
362+
363+
return (SUCCEEDED(hr) && command_path_match);
364+
}

task_sched.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <comdef.h>
88
#include <Lmcons.h>
99
#include <type_traits>
10+
#include "simple_xml.h"
1011

1112

1213
constexpr auto ENV_USERNAME = L"USERNAME";
@@ -25,6 +26,8 @@ namespace TaskSched
2526

2627

2728
/**
29+
* //--------------------- 后面发现官方有自动包装的CComPtr,努力全部木大
30+
*
2831
* 自动包装COM对象指针,生命周期结束自动调用Release
2932
* 要求T必须能调用Release方法,且T必须是IUnknown的子类
3033
*

0 commit comments

Comments
 (0)