Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
J
jlib
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
captainwong
jlib
Commits
c9174ca4
Commit
c9174ca4
authored
Nov 06, 2023
by
captainwong
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
update
parent
c024947b
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
1415 additions
and
1410 deletions
+1415
-1410
ErrorCode.h
jlib/qt/ErrorCode.h
+47
-47
QtDebug.h
jlib/qt/QtDebug.h
+50
-50
QtPathHelper.h
jlib/qt/QtPathHelper.h
+181
-181
version.h
jlib/util/version.h
+264
-259
path_helper.h
jlib/win32/path_helper.h
+177
-177
path_op.h
jlib/win32/path_op.h
+123
-123
process.h
jlib/win32/process.h
+435
-435
rect.h
jlib/win32/rect.h
+138
-138
No files found.
jlib/qt/ErrorCode.h
View file @
c9174ca4
#pragma once
#pragma once
#include "qt_global.h"
#include "qt_global.h"
#include <system_error>
#include <system_error>
#include <QString>
#include <QString>
JLIBQT_NAMESPACE_BEGIN
JLIBQT_NAMESPACE_BEGIN
//!
获取错误码文字描述
//!
获取错误码文字描述
inline
QString
ecString
(
const
std
::
error_code
&
ec
)
{
inline
QString
ecString
(
const
std
::
error_code
&
ec
)
{
return
QString
::
fromLocal8Bit
(
ec
.
message
().
data
());
return
QString
::
fromLocal8Bit
(
ec
.
message
().
data
());
}
}
//!
获取错误码文字描述(带有错误目录)
//!
获取错误码文字描述(带有错误目录)
inline
QString
ecStringWithCategory
(
const
std
::
error_code
&
ec
)
{
inline
QString
ecStringWithCategory
(
const
std
::
error_code
&
ec
)
{
return
QString
::
fromLocal8Bit
(
ec
.
category
().
name
())
+
": "
+
QString
::
fromLocal8Bit
(
ec
.
message
().
data
());
return
QString
::
fromLocal8Bit
(
ec
.
category
().
name
())
+
": "
+
QString
::
fromLocal8Bit
(
ec
.
message
().
data
());
}
}
#define BREAK_IF_QUERY_FAILED(ec_type) if (!ok) { \
#define BREAK_IF_QUERY_FAILED(ec_type) if (!ok) { \
ec = ec_type; \
ec
=
ec_type
;
\
MYQCRITICAL << ecStringWithCategory(ec) << "\n" << query.lastError(); \
MYQCRITICAL
<<
ecStringWithCategory
(
ec
)
<<
"
\n
"
<<
query
.
lastError
();
\
break; \
break
;
\
}
}
enum
class
DatabaseErrorCode
{
enum
class
DatabaseErrorCode
{
OpenDbFailed
=
1
,
OpenDbFailed
=
1
,
CreateDbTableFailed
,
CreateDbTableFailed
,
QueryDbFailed
,
QueryDbFailed
,
};
};
JLIBQT_NAMESPACE_END
JLIBQT_NAMESPACE_END
#define ENABLE_ENUM_AS_ERROR_CODE(type) \
#define ENABLE_ENUM_AS_ERROR_CODE(type) \
namespace std { \
namespace
std
{
\
template <> struct is_error_code_enum<type> : true_type {}; \
template
<>
struct
is_error_code_enum
<
type
>
:
true_type
{};
\
std::error_code make_error_code(type); \
std
::
error_code
make_error_code
(
type
);
\
}
}
ENABLE_ENUM_AS_ERROR_CODE
(
JLIBQT_NAMESPACE
DatabaseErrorCode
)
ENABLE_ENUM_AS_ERROR_CODE
(
JLIBQT_NAMESPACE
DatabaseErrorCode
)
std
::
error_code
std
::
make_error_code
(
JLIBQT_NAMESPACE
DatabaseErrorCode
ec
);
std
::
error_code
std
::
make_error_code
(
JLIBQT_NAMESPACE
DatabaseErrorCode
ec
);
jlib/qt/QtDebug.h
View file @
c9174ca4
#pragma once
#pragma once
#include <QDebug>
#include <QDebug>
#include <QDateTime>
#include <QDateTime>
#ifdef _WIN32
#ifdef _WIN32
#include <Windows.h>
#include <Windows.h>
#endif //_WIN32
#endif //_WIN32
#define JLIBQT_QDEBUG_FILE_LINE_STREAM "[" << __FUNCTION__ << __LINE__ << "]: "
#define JLIBQT_QDEBUG_FILE_LINE_STREAM "[" << __FUNCTION__ << __LINE__ << "]: "
#define JLIBQT_QDEBUG_FILE_LINE_VALUE (QString("[") + __FUNCTION__ + " " + QString::number(__LINE__) + "]: ")
#define JLIBQT_QDEBUG_FILE_LINE_VALUE (QString("[") + __FUNCTION__ + " " + QString::number(__LINE__) + "]: ")
#define MYQDEBUG qDebug() << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQDEBUG qDebug() << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQINFO qInfo() << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQINFO qInfo() << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQWARN qWarning() << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQWARN qWarning() << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQCRITICAL qCritical() << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQCRITICAL qCritical() << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQDEBUG_NOQUOTE qDebug().noquote() << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQDEBUG_NOQUOTE qDebug().noquote() << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQINFO_NOQUOTE qInfo().noquote() << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQINFO_NOQUOTE qInfo().noquote() << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQWARN_NOQUOTE qWarning().noquote() << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQWARN_NOQUOTE qWarning().noquote() << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQCRITICAL_NOQUOTE qCritical().noquote() << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQCRITICAL_NOQUOTE qCritical().noquote() << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQDEBUG2 qDebug() << QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss") << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQDEBUG2 qDebug() << QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss") << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQINFO2 qInfo() << QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss") << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQINFO2 qInfo() << QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss") << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQWARN2 qWarning() << QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss") << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQWARN2 qWarning() << QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss") << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQCRITICAL2 qCritical() << QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss") << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQCRITICAL2 qCritical() << QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss") << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQDEBUG2_NOQUOTE qDebug().noquote() << QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss") << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQDEBUG2_NOQUOTE qDebug().noquote() << QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss") << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQINFO2_NOQUOTE qInfo().noquote() << QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss") << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQINFO2_NOQUOTE qInfo().noquote() << QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss") << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQWARN2_NOQUOTE qWarning().noquote() << QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss") << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQWARN2_NOQUOTE qWarning().noquote() << QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss") << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQCRITICAL2_NOQUOTE qCritical().noquote() << QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss") << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQCRITICAL2_NOQUOTE qCritical().noquote() << QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss") << JLIBQT_QDEBUG_FILE_LINE_STREAM
//!
弹窗报告行号开关
//!
弹窗报告行号开关
// #define JLIBQT_SHOW_LINE 0
// #define JLIBQT_SHOW_LINE 0
//!
当行号大于下方定义的值时,弹窗报告行号,否则忽略。可在多个cpp文件分别定义不同的值。
//!
当行号大于下方定义的值时,弹窗报告行号,否则忽略。可在多个cpp文件分别定义不同的值。
// #define JLIBQT_SHOW_MSGBOX_AFTER_LINE 1
// #define JLIBQT_SHOW_MSGBOX_AFTER_LINE 1
#if JLIBQT_SHOW_LINE
#if JLIBQT_SHOW_LINE
#ifdef JLIBQT_SHOW_MSGBOX_AFTER_LINE
#ifdef JLIBQT_SHOW_MSGBOX_AFTER_LINE
#define JLIBQT_SHOW_MSGBOX_LINE_NUMBER if(__LINE__ >= JLIBQT_SHOW_MSGBOX_AFTER_LINE) { MessageBoxW(nullptr, (std::wstring(__FILEW__) + L":" + std::to_wstring(__LINE__)).data(), L"Test", 0); }
#define JLIBQT_SHOW_MSGBOX_LINE_NUMBER if(__LINE__ >= JLIBQT_SHOW_MSGBOX_AFTER_LINE) { MessageBoxW(nullptr, (std::wstring(__FILEW__) + L":" + std::to_wstring(__LINE__)).data(), L"Test", 0); }
#define JLIBQT_SHOW_MSGBOX_LINE_NUMBER_WITH_TITLE(title) if(__LINE__ >= JLIBQT_SHOW_MSGBOX_AFTER_LINE) { MessageBoxW(nullptr, (std::wstring(__FILEW__) + L":" + std::to_wstring(__LINE__)).data(), title, 0); }
#define JLIBQT_SHOW_MSGBOX_LINE_NUMBER_WITH_TITLE(title) if(__LINE__ >= JLIBQT_SHOW_MSGBOX_AFTER_LINE) { MessageBoxW(nullptr, (std::wstring(__FILEW__) + L":" + std::to_wstring(__LINE__)).data(), title, 0); }
#else
#else
#define JLIBQT_SHOW_MSGBOX_LINE_NUMBER { MessageBoxW(nullptr, (std::wstring(__FILEW__) + L":" + std::to_wstring(__LINE__)).data(), L"Test", 0); }
#define JLIBQT_SHOW_MSGBOX_LINE_NUMBER { MessageBoxW(nullptr, (std::wstring(__FILEW__) + L":" + std::to_wstring(__LINE__)).data(), L"Test", 0); }
#define JLIBQT_SHOW_MSGBOX_LINE_NUMBER_WITH_TITLE(title) { MessageBoxW(nullptr, (std::wstring(__FILEW__) + L":" + std::to_wstring(__LINE__)).data(), title, 0); }
#define JLIBQT_SHOW_MSGBOX_LINE_NUMBER_WITH_TITLE(title) { MessageBoxW(nullptr, (std::wstring(__FILEW__) + L":" + std::to_wstring(__LINE__)).data(), title, 0); }
#endif
#endif
#else
#else
#define JLIBQT_SHOW_MSGBOX_LINE_NUMBER
#define JLIBQT_SHOW_MSGBOX_LINE_NUMBER
#define JLIBQT_SHOW_MSGBOX_LINE_NUMBER_WITH_TITLE(title)
#define JLIBQT_SHOW_MSGBOX_LINE_NUMBER_WITH_TITLE(title)
#endif
#endif
jlib/qt/QtPathHelper.h
View file @
c9174ca4
#pragma once
#pragma once
#include "qt_global.h"
#include "qt_global.h"
#include <QDir>
#include <QDir>
#include <QCoreApplication>
#include <QCoreApplication>
#include <QString>
#include <QString>
#include <QDateTime>
#include <QDateTime>
#include <QStandardPaths>
#include <QStandardPaths>
JLIBQT_NAMESPACE_BEGIN
JLIBQT_NAMESPACE_BEGIN
static
const
auto
JLIBQT_FILE_TIME_FORMAT
=
"yyyy-MM-dd_hh-mm-ss"
;
static
const
auto
JLIBQT_FILE_TIME_FORMAT
=
"yyyy-MM-dd_hh-mm-ss"
;
struct
PathHelper
struct
PathHelper
{
{
static
inline
bool
mkpath
(
const
QString
&
path
)
{
static
inline
bool
mkpath
(
const
QString
&
path
)
{
QDir
dir
;
return
dir
.
exists
(
path
)
?
true
:
dir
.
mkpath
(
path
);
QDir
dir
;
return
dir
.
exists
(
path
)
?
true
:
dir
.
mkpath
(
path
);
}
}
static
inline
QString
currentTimeString
()
{
static
inline
QString
currentTimeString
()
{
return
QDateTime
::
currentDateTime
().
toString
(
JLIBQT_FILE_TIME_FORMAT
);
return
QDateTime
::
currentDateTime
().
toString
(
JLIBQT_FILE_TIME_FORMAT
);
}
}
static
inline
QString
getFolder
(
const
QString
&
path
)
{
static
inline
QString
getFolder
(
const
QString
&
path
)
{
QDir
dir
(
path
);
dir
.
cdUp
();
QDir
dir
(
path
);
dir
.
cdUp
();
return
dir
.
absolutePath
();
return
dir
.
absolutePath
();
}
}
virtual
~
PathHelper
()
{}
virtual
~
PathHelper
()
{}
virtual
QString
program
()
const
{
return
programPath_
;
}
virtual
QString
program
()
const
{
return
programPath_
;
}
virtual
QString
exe
()
const
{
return
exePath_
;
}
virtual
QString
exe
()
const
{
return
exePath_
;
}
virtual
QString
bin
()
const
{
return
program
()
+
"/bin"
;
}
virtual
QString
bin
()
const
{
return
program
()
+
"/bin"
;
}
virtual
QString
data
()
const
{
return
program
()
+
"/data"
;
}
virtual
QString
data
()
const
{
return
program
()
+
"/data"
;
}
virtual
QString
log
()
const
{
return
program
()
+
"/log"
;
}
virtual
QString
log
()
const
{
return
program
()
+
"/log"
;
}
virtual
QString
dumps
()
const
{
return
program
()
+
"/dumps"
;
}
virtual
QString
dumps
()
const
{
return
program
()
+
"/dumps"
;
}
virtual
QString
config
()
const
{
return
data
()
+
"/config"
;
}
virtual
QString
config
()
const
{
return
data
()
+
"/config"
;
}
virtual
QString
db
()
const
{
return
data
()
+
"/db"
;
}
virtual
QString
db
()
const
{
return
data
()
+
"/db"
;
}
protected
:
protected
:
// disable constructor
// disable constructor
explicit
PathHelper
()
{}
explicit
PathHelper
()
{}
//!
应用程序安装目录
//!
应用程序安装目录
QString
programPath_
=
{};
QString
programPath_
=
{};
//!
应用程序路径
//!
应用程序路径
QString
exePath_
=
{};
QString
exePath_
=
{};
};
};
struct
AutoSwithToBin
{
struct
AutoSwithToBin
{
AutoSwithToBin
(
PathHelper
*
helper
)
:
helper
(
helper
)
{}
AutoSwithToBin
(
PathHelper
*
helper
)
:
helper
(
helper
)
{}
AutoSwithToBin
(
PathHelper
*
helper
,
const
QString
&
path
)
:
helper
(
helper
)
{
AutoSwithToBin
(
PathHelper
*
helper
,
const
QString
&
path
)
:
helper
(
helper
)
{
QDir
().
setCurrent
(
path
);
QDir
().
setCurrent
(
path
);
}
}
~
AutoSwithToBin
()
{
~
AutoSwithToBin
()
{
if
(
helper
)
{
QDir
().
setCurrent
(
helper
->
bin
());
}
if
(
helper
)
{
QDir
().
setCurrent
(
helper
->
bin
());
}
}
}
PathHelper
*
helper
=
nullptr
;
PathHelper
*
helper
=
nullptr
;
};
};
/*
/*
* @brief
路径辅助类,数据保存在安装目录,程序和dll在bin文件夹
* @brief
路径辅助类,数据保存在安装目录,程序和dll在bin文件夹
* @note
大致结构树为:
* @note
大致结构树为:
* @note |-- program-install-dir
* @note |-- program-install-dir
* @note | |-- bin
* @note | |-- bin
* @note | | |-- program.exe
* @note | | |-- program.exe
* @note | | |-- *.dlls
* @note | | |-- *.dlls
* @note | |-- dumps
* @note | |-- dumps
* @note | |-- log
* @note | |-- log
* @note | |-- data
* @note | |-- data
* @note | |-- config
* @note | |-- config
* @note | |-- db
* @note | |-- db
*/
*/
struct
PathHelperLocal
:
PathHelper
struct
PathHelperLocal
:
PathHelper
{
{
PathHelperLocal
()
:
PathHelper
()
{
PathHelperLocal
()
:
PathHelper
()
{
exePath_
=
QCoreApplication
::
applicationFilePath
();
exePath_
=
QCoreApplication
::
applicationFilePath
();
QDir
dir
(
QCoreApplication
::
applicationDirPath
());
QDir
dir
(
QCoreApplication
::
applicationDirPath
());
dir
.
cdUp
();
programPath_
=
dir
.
absolutePath
();
dir
.
cdUp
();
programPath_
=
dir
.
absolutePath
();
}
}
};
};
/*
/*
* @brief
路径辅助类,数据保存在安装目录,程序和dll也在安装目录
* @brief
路径辅助类,数据保存在安装目录,程序和dll也在安装目录
* @note
大致结构树为:
* @note
大致结构树为:
* @note |-- program-install-dir
* @note |-- program-install-dir
* @note | |-- dumps
* @note | |-- dumps
* @note | |-- log
* @note | |-- log
* @note | |-- data
* @note | |-- data
* @note | | |-- config
* @note | | |-- config
* @note | | |-- db
* @note | | |-- db
* @note | |-- program.exe
* @note | |-- program.exe
* @note | |-- *.dlls
* @note | |-- *.dlls
*/
*/
struct
PathHelperLocalWithoutBin
:
PathHelper
struct
PathHelperLocalWithoutBin
:
PathHelper
{
{
PathHelperLocalWithoutBin
()
:
PathHelper
()
{
PathHelperLocalWithoutBin
()
:
PathHelper
()
{
exePath_
=
QCoreApplication
::
applicationFilePath
();
exePath_
=
QCoreApplication
::
applicationFilePath
();
QDir
dir
(
QCoreApplication
::
applicationDirPath
());
QDir
dir
(
QCoreApplication
::
applicationDirPath
());
programPath_
=
dir
.
absolutePath
();
programPath_
=
dir
.
absolutePath
();
}
}
virtual
QString
bin
()
const
override
{
return
program
();
}
virtual
QString
bin
()
const
override
{
return
program
();
}
};
};
/*
/*
* @brief
路径辅助类,数据保存在其他可写目录,如 C:/Users/[USER]/AppData/Roaming
* @brief
路径辅助类,数据保存在其他可写目录,如 C:/Users/[USER]/AppData/Roaming
* @note program-name
无需设置,Qt会自动设置
* @note program-name
无需设置,Qt会自动设置
* @note
如果在调用此类之前先调用了 QCoreApplication::setOrganizationName("your-organization-name");
* @note
如果在调用此类之前先调用了 QCoreApplication::setOrganizationName("your-organization-name");
* @note
那么program-name在your-organization-name下
* @note
那么program-name在your-organization-name下
* @note
大致结构树为:
* @note
大致结构树为:
* @note |-- program-install-dir
* @note |-- program-install-dir
* @note | |-- bin
* @note | |-- bin
* @note | | |-- program.exe
* @note | | |-- program.exe
* @note | | |-- *.dlls
* @note | | |-- *.dlls
* @note
* @note
* @note |-- writable-dir
* @note |-- writable-dir
* @note | |-- your-organization-name
* @note | |-- your-organization-name
* @note | | |-- program-name
* @note | | |-- program-name
* @note | | |-- log
* @note | | |-- log
* @note | | |-- dumps
* @note | | |-- dumps
* @note | | |-- config
* @note | | |-- config
* @note | | |-- db
* @note | | |-- db
*/
*/
struct
PathHelperDataSeperated
:
PathHelperLocal
struct
PathHelperDataSeperated
:
PathHelperLocal
{
{
PathHelperDataSeperated
(
bool
useTmpAsLogFolder
=
false
)
PathHelperDataSeperated
(
bool
useTmpAsLogFolder
=
false
)
:
PathHelperLocal
(),
useTmpAsLogFolder
(
useTmpAsLogFolder
)
:
PathHelperLocal
(),
useTmpAsLogFolder
(
useTmpAsLogFolder
)
{}
{}
virtual
QString
data
()
const
override
{
virtual
QString
data
()
const
override
{
return
QStandardPaths
::
writableLocation
(
QStandardPaths
::
AppDataLocation
);
return
QStandardPaths
::
writableLocation
(
QStandardPaths
::
AppDataLocation
);
}
}
virtual
QString
log
()
const
override
{
return
useTmpAsLogFolder
?
QStandardPaths
::
writableLocation
(
QStandardPaths
::
TempLocation
)
:
(
data
()
+
"/log"
);
}
virtual
QString
log
()
const
override
{
return
useTmpAsLogFolder
?
QStandardPaths
::
writableLocation
(
QStandardPaths
::
TempLocation
)
:
(
data
()
+
"/log"
);
}
virtual
QString
dumps
()
const
override
{
return
data
()
+
"/dumps"
;
}
virtual
QString
dumps
()
const
override
{
return
data
()
+
"/dumps"
;
}
virtual
QString
config
()
const
override
{
return
data
()
+
"/config"
;
}
virtual
QString
config
()
const
override
{
return
data
()
+
"/config"
;
}
virtual
QString
db
()
const
override
{
return
data
()
+
"/db"
;
}
virtual
QString
db
()
const
override
{
return
data
()
+
"/db"
;
}
protected
:
protected
:
bool
useTmpAsLogFolder
=
false
;
bool
useTmpAsLogFolder
=
false
;
};
};
/*
/*
* @brief
路径辅助类,数据保存在其他可写目录,如 C:/Users/[USER]/AppData/Roaming
* @brief
路径辅助类,数据保存在其他可写目录,如 C:/Users/[USER]/AppData/Roaming
* @note program-name
无需设置,Qt会自动设置
* @note program-name
无需设置,Qt会自动设置
* @note
如果在调用此类之前先调用了 QCoreApplication::setOrganizationName("your-organization-name");
* @note
如果在调用此类之前先调用了 QCoreApplication::setOrganizationName("your-organization-name");
* @note
那么program-name在your-organization-name下
* @note
那么program-name在your-organization-name下
* @note
大致结构树为:
* @note
大致结构树为:
* @note |-- program-install-dir
* @note |-- program-install-dir
* @note | |-- program.exe
* @note | |-- program.exe
* @note | |-- *.dlls
* @note | |-- *.dlls
* @note
* @note
* @note |-- writable-dir
* @note |-- writable-dir
* @note | |-- your-organization-name
* @note | |-- your-organization-name
* @note | | |-- program-name
* @note | | |-- program-name
* @note | | |-- log
* @note | | |-- log
* @note | | |-- dumps
* @note | | |-- dumps
* @note | | |-- config
* @note | | |-- config
* @note | | |-- db
* @note | | |-- db
*/
*/
struct
PathHelperDataSeperatedWithoutBin
:
PathHelperLocalWithoutBin
struct
PathHelperDataSeperatedWithoutBin
:
PathHelperLocalWithoutBin
{
{
PathHelperDataSeperatedWithoutBin
(
bool
useTmpAsLogFolder
=
false
)
PathHelperDataSeperatedWithoutBin
(
bool
useTmpAsLogFolder
=
false
)
:
PathHelperLocalWithoutBin
(),
useTmpAsLogFolder
(
useTmpAsLogFolder
)
:
PathHelperLocalWithoutBin
(),
useTmpAsLogFolder
(
useTmpAsLogFolder
)
{}
{}
virtual
QString
data
()
const
override
{
virtual
QString
data
()
const
override
{
return
QStandardPaths
::
writableLocation
(
QStandardPaths
::
AppDataLocation
);
return
QStandardPaths
::
writableLocation
(
QStandardPaths
::
AppDataLocation
);
}
}
virtual
QString
log
()
const
override
{
return
useTmpAsLogFolder
?
QStandardPaths
::
writableLocation
(
QStandardPaths
::
TempLocation
)
:
(
data
()
+
"/log"
);
}
virtual
QString
log
()
const
override
{
return
useTmpAsLogFolder
?
QStandardPaths
::
writableLocation
(
QStandardPaths
::
TempLocation
)
:
(
data
()
+
"/log"
);
}
virtual
QString
dumps
()
const
override
{
return
data
()
+
"/dumps"
;
}
virtual
QString
dumps
()
const
override
{
return
data
()
+
"/dumps"
;
}
virtual
QString
config
()
const
override
{
return
data
()
+
"/config"
;
}
virtual
QString
config
()
const
override
{
return
data
()
+
"/config"
;
}
virtual
QString
db
()
const
override
{
return
data
()
+
"/db"
;
}
virtual
QString
db
()
const
override
{
return
data
()
+
"/db"
;
}
protected
:
protected
:
bool
useTmpAsLogFolder
=
false
;
bool
useTmpAsLogFolder
=
false
;
};
};
JLIBQT_NAMESPACE_END
JLIBQT_NAMESPACE_END
jlib/util/version.h
View file @
c9174ca4
#
pragma
once
#
pragma
once
#include "../base/config.h"
#include "../base/config.h"
#include <string>
#include <string>
#include <cstdlib>
#include <cstdlib>
#include <sstream>
#include <sstream>
#include <fstream>
#include <fstream>
#include <vector>
#include <vector>
#include <stdint.h>
#include <stdint.h>
namespace
jlib
namespace
jlib
{
{
//! 应用程序版本分支
//! 应用程序版本分支
enum
class
Branch
:
int
{
enum
class
Branch
:
int
{
//! 测试版,一般仅用于测试人员测试
// 开发版,开发人员自测
Test
,
Dev
,
//! 体验版,可以投放给少量用户进行灰度测试
//! 测试版,一般仅用于测试人员测试
Experimental
,
Test
,
//! 正式版
//! 体验版,可以投放给少量用户进行灰度测试
Stable
,
Experimental
,
//! 正式版
BranchCount
,
Stable
,
InvalidBranch
=
0x0FFFFFFF
,
BranchCount
,
};
InvalidBranch
=
0x0FFFFFFF
,
static
constexpr
auto
BranchNameTest
=
"test"
;
};
static
constexpr
auto
BranchNameExperimental
=
"experimental"
;
static
constexpr
auto
BranchNameStable
=
"stable"
;
static
constexpr
auto
BranchNameDev
=
"dev"
;
static
constexpr
auto
BranchNameTest
=
"test"
;
inline
const
char
*
branchName
(
Branch
branch
)
{
static
constexpr
auto
BranchNameExperimental
=
"experimental"
;
switch
(
branch
)
{
static
constexpr
auto
BranchNameStable
=
"stable"
;
case
jlib
:
:
Branch
::
Test
:
return
BranchNameTest
;
case
jlib
:
:
Branch
::
Experimental
:
return
BranchNameExperimental
;
inline
const
char
*
branchName
(
Branch
branch
)
{
case
jlib
:
:
Branch
::
Stable
:
return
BranchNameStable
;
switch
(
branch
)
{
default:
return
"InvalidBranch"
;
case
jlib
:
:
Branch
::
Dev
:
return
BranchNameDev
;
}
case
jlib
:
:
Branch
::
Test
:
return
BranchNameTest
;
}
case
jlib
:
:
Branch
::
Experimental
:
return
BranchNameExperimental
;
case
jlib
:
:
Branch
::
Stable
:
return
BranchNameStable
;
inline
Branch
branchFromString
(
const
std
::
string
&
name
)
{
default:
return
"InvalidBranch"
;
if
(
name
==
BranchNameTest
)
{
return
Branch
::
Test
;
}
}
else
if
(
name
==
BranchNameExperimental
)
{
return
Branch
::
Experimental
;
}
}
else
if
(
name
==
BranchNameStable
)
{
return
Branch
::
Stable
;
}
else
{
return
Branch
::
InvalidBranch
;
}
inline
Branch
branchFromString
(
const
std
::
string
&
name
)
{
}
if
(
name
==
BranchNameDev
)
{
return
Branch
::
Dev
;
}
else
if
(
name
==
BranchNameTest
)
{
return
Branch
::
Test
;
}
//! 应用程序版本号
else
if
(
name
==
BranchNameExperimental
)
{
return
Branch
::
Experimental
;
}
struct
Version
{
else
if
(
name
==
BranchNameStable
)
{
return
Branch
::
Stable
;
}
//! 主版本
else
{
return
Branch
::
InvalidBranch
;
}
uint16_t
major
=
0
;
}
//! 功能更新
uint16_t
minor
=
0
;
//! 应用程序版本号
//! bug 修复
struct
Version
{
uint16_t
revision
=
0
;
//! 主版本
//! 随意,我一般用来表示程序总迭代(编译成功)次数
uint16_t
major
=
0
;
uint16_t
build
=
0
;
//! 功能更新
uint16_t
minor
=
0
;
Version
()
=
default
;
//! bug 修复
Version
(
uint16_t
major
,
uint16_t
minor
,
uint16_t
revision
,
uint16_t
build
)
uint16_t
revision
=
0
;
:
major
(
major
),
minor
(
minor
),
revision
(
revision
),
build
(
build
)
{}
//! 随意,我一般用来表示程序总迭代(编译成功)次数
Version
(
const
std
::
string
&
s
)
{
_fromString
(
s
);
}
uint16_t
build
=
0
;
Version
(
uint64_t
v
)
{
fromUInt64
(
v
);
}
Version
&
fromString
(
const
std
::
string
&
s
)
{
_fromString
(
s
);
return
*
this
;
}
Version
()
=
default
;
Version
&
operator
=
(
const
std
::
string
&
s
)
{
_fromString
(
s
);
return
*
this
;
}
Version
(
uint16_t
major
,
uint16_t
minor
,
uint16_t
revision
,
uint16_t
build
)
Version
&
operator
=
(
uint64_t
v
)
{
fromUInt64
(
v
);
return
*
this
;
}
:
major
(
major
),
minor
(
minor
),
revision
(
revision
),
build
(
build
)
{}
Version
(
const
std
::
string
&
s
)
{
_fromString
(
s
);
}
bool
valid
()
const
{
return
!
(
major
==
0
&&
minor
==
0
&&
revision
==
0
&&
build
==
0
);
}
Version
(
uint64_t
v
)
{
fromUInt64
(
v
);
}
void
reset
()
{
major
=
minor
=
revision
=
build
=
0
;
}
Version
&
fromString
(
const
std
::
string
&
s
)
{
_fromString
(
s
);
return
*
this
;
}
Version
&
operator
=
(
const
std
::
string
&
s
)
{
_fromString
(
s
);
return
*
this
;
}
bool
_fromString
(
const
std
::
string
&
s
)
{
Version
&
operator
=
(
uint64_t
v
)
{
fromUInt64
(
v
);
return
*
this
;
}
if
(
std
::
sscanf
(
s
.
c_str
(),
"%hu.%hu.%hu.%hu"
,
&
major
,
&
minor
,
&
revision
,
&
build
)
!=
4
)
{
reset
();
return
false
;
bool
valid
()
const
{
return
!
(
major
==
0
&&
minor
==
0
&&
revision
==
0
&&
build
==
0
);
}
}
void
reset
()
{
major
=
minor
=
revision
=
build
=
0
;
}
if
(
major
<
0
)
major
=
0
;
if
(
minor
<
0
)
minor
=
0
;
if
(
revision
<
0
)
revision
=
0
;
if
(
build
<
0
)
build
=
0
;
bool
_fromString
(
const
std
::
string
&
s
)
{
return
true
;
if
(
std
::
sscanf
(
s
.
c_str
(),
"%hu.%hu.%hu.%hu"
,
&
major
,
&
minor
,
&
revision
,
&
build
)
!=
4
)
{
}
reset
();
return
false
;
}
std
::
string
toString
()
const
{
if
(
major
<
0
)
major
=
0
;
if
(
minor
<
0
)
minor
=
0
;
return
std
::
to_string
(
major
)
+
"."
+
if
(
revision
<
0
)
revision
=
0
;
if
(
build
<
0
)
build
=
0
;
std
::
to_string
(
minor
)
+
"."
+
return
true
;
std
::
to_string
(
revision
)
+
"."
+
}
std
::
to_string
(
build
);
}
std
::
string
toString
()
const
{
return
std
::
to_string
(
major
)
+
"."
+
void
fromUInt64
(
uint64_t
v
)
{
std
::
to_string
(
minor
)
+
"."
+
major
=
(
v
>>
48
)
&
0xFFFF
;
std
::
to_string
(
revision
)
+
"."
+
minor
=
(
v
>>
32
)
&
0xFFFF
;
std
::
to_string
(
build
);
revision
=
(
v
>>
16
)
&
0xFFFF
;
}
build
=
v
&
0xFFFF
;
}
void
fromUInt64
(
uint64_t
v
)
{
major
=
(
v
>>
48
)
&
0xFFFF
;
uint64_t
toUInt64
()
const
{
minor
=
(
v
>>
32
)
&
0xFFFF
;
return
((
uint64_t
)
major
<<
48
)
|
((
uint64_t
)
minor
<<
32
)
|
((
uint64_t
)
revision
<<
16
)
|
(
uint64_t
)
build
;
revision
=
(
v
>>
16
)
&
0xFFFF
;
}
build
=
v
&
0xFFFF
;
}
//! require cpp17
template
<
typename
T
>
uint64_t
toUInt64
()
const
{
bool
fromFile
(
T
const
&
path
)
{
return
((
uint64_t
)
major
<<
48
)
|
((
uint64_t
)
minor
<<
32
)
|
((
uint64_t
)
revision
<<
16
)
|
(
uint64_t
)
build
;
if
constexpr
(
std
::
is_convertible_v
<
T
,
std
::
string
>
);
}
else
if
constexpr
(
std
::
is_convertible_v
<
T
,
std
::
wstring
>
);
else
{
return
false
;
}
//! require cpp17
std
::
ifstream
in
(
path
);
if
(
!
in
)
return
false
;
template
<
typename
T
>
std
::
stringstream
is
;
is
<<
in
.
rdbuf
();
bool
fromFile
(
T
const
&
path
)
{
Version
file_ver
(
is
.
str
());
if
constexpr
(
std
::
is_convertible_v
<
T
,
std
::
string
>
);
if
(
file_ver
.
valid
())
{
*
this
=
file_ver
;
return
true
;
}
else
if
constexpr
(
std
::
is_convertible_v
<
T
,
std
::
wstring
>
);
return
false
;
else
{
return
false
;
}
}
std
::
ifstream
in
(
path
);
if
(
!
in
)
return
false
;
std
::
stringstream
is
;
is
<<
in
.
rdbuf
();
//! require cpp17
Version
file_ver
(
is
.
str
());
template
<
typename
T
>
if
(
file_ver
.
valid
())
{
*
this
=
file_ver
;
return
true
;
}
bool
toFile
(
T
const
&
path
)
{
return
false
;
if
constexpr
(
std
::
is_convertible_v
<
T
,
std
::
string
>
);
}
else
if
constexpr
(
std
::
is_convertible_v
<
T
,
std
::
wstring
>
);
else
{
return
false
;
}
//! require cpp17
std
::
ofstream
out
(
path
);
if
(
!
out
)
{
return
false
;
}
template
<
typename
T
>
auto
str
=
toString
();
out
.
write
(
str
.
data
(),
str
.
size
());
bool
toFile
(
T
const
&
path
)
{
return
true
;
if
constexpr
(
std
::
is_convertible_v
<
T
,
std
::
string
>
);
}
else
if
constexpr
(
std
::
is_convertible_v
<
T
,
std
::
wstring
>
);
else
{
return
false
;
}
bool
operator
==
(
const
Version
&
ver
)
const
{
std
::
ofstream
out
(
path
);
if
(
!
out
)
{
return
false
;
}
return
toUInt64
()
==
ver
.
toUInt64
();
auto
str
=
toString
();
out
.
write
(
str
.
data
(),
str
.
size
());
}
return
true
;
}
bool
operator
<
(
const
Version
&
ver
)
const
{
return
toUInt64
()
<
ver
.
toUInt64
();
bool
operator
==
(
const
Version
&
ver
)
const
{
}
return
toUInt64
()
==
ver
.
toUInt64
();
}
bool
operator
>
(
const
Version
&
ver
)
const
{
return
toUInt64
()
>
ver
.
toUInt64
();
bool
operator
<
(
const
Version
&
ver
)
const
{
}
return
toUInt64
()
<
ver
.
toUInt64
();
}
bool
operator
<=
(
const
Version
&
ver
)
const
{
return
toUInt64
()
<=
ver
.
toUInt64
();
bool
operator
>
(
const
Version
&
ver
)
const
{
}
return
toUInt64
()
>
ver
.
toUInt64
();
}
bool
operator
>=
(
const
Version
&
ver
)
const
{
return
toUInt64
()
>=
ver
.
toUInt64
();
bool
operator
<=
(
const
Version
&
ver
)
const
{
}
return
toUInt64
()
<=
ver
.
toUInt64
();
};
}
//! 安装包下载链接
bool
operator
>=
(
const
Version
&
ver
)
const
{
struct
DownLoadLink
{
return
toUInt64
()
>=
ver
.
toUInt64
();
std
::
string
host
=
{};
// local, qcloud, aliyun, ...
}
std
::
string
link
=
{};
};
std
::
string
md5
=
{};
};
//! 安装包下载链接
struct
DownLoadLink
{
//! 发布
std
::
string
host
=
{};
// local, qcloud, aliyun, ...
struct
Release
{
std
::
string
link
=
{};
Branch
branch
=
Branch
::
InvalidBranch
;
std
::
string
md5
=
{};
Version
version
=
{};
};
bool
force_update
=
false
;
//! 版本更新说明
//! 发布
std
::
string
change
=
{};
struct
Release
{
std
::
vector
<
DownLoadLink
>
dllinks
=
{};
Branch
branch
=
Branch
::
InvalidBranch
;
Version
version
=
{};
std
::
string
toString
()
const
{
bool
force_update
=
false
;
auto
s
=
std
::
string
(
branchName
(
branch
))
+
" "
+
version
.
toString
()
+
//! 版本更新说明
"
\n
force_update="
+
(
force_update
?
"true"
:
"false"
)
+
std
::
string
change
=
{};
"
\n
change="
+
change
+
std
::
vector
<
DownLoadLink
>
dllinks
=
{};
"
\n
download_links=
\n
"
;
if
(
!
dllinks
.
empty
())
{
std
::
string
toString
()
const
{
for
(
const
auto
&
link
:
dllinks
)
{
s
+=
link
.
host
+
" : link="
+
link
.
link
+
" md5="
+
link
.
md5
+
"
\n
"
;
}
auto
s
=
std
::
string
(
branchName
(
branch
))
+
" "
+
version
.
toString
()
+
}
else
{
s
+=
"empty"
;
}
"
\n
force_update="
+
(
force_update
?
"true"
:
"false"
)
+
return
s
;
"
\n
change="
+
change
+
}
"
\n
download_links=
\n
"
;
if
(
!
dllinks
.
empty
())
{
bool
valid
()
const
{
for
(
const
auto
&
link
:
dllinks
)
{
s
+=
link
.
host
+
" : link="
+
link
.
link
+
" md5="
+
link
.
md5
+
"
\n
"
;
}
return
(
branch
!=
Branch
::
InvalidBranch
)
&&
version
.
valid
()
&&
!
dllinks
.
empty
();
}
else
{
s
+=
"empty"
;
}
}
return
s
;
};
}
//! 最新的发布,包含各个分支的最新版本
bool
valid
()
const
{
struct
LatestRelease
{
return
(
branch
!=
Branch
::
InvalidBranch
)
&&
version
.
valid
()
&&
!
dllinks
.
empty
();
std
::
vector
<
Release
>
releases
=
{};
}
};
std
::
string
toString
()
const
{
std
::
string
str
;
//! 最新的发布,包含各个分支的最新版本
for
(
const
auto
&
r
:
releases
)
{
struct
LatestRelease
{
if
(
r
.
valid
())
{
str
+=
r
.
toString
()
+
"
\n
"
;
}
std
::
vector
<
Release
>
releases
=
{};
}
return
str
;
std
::
string
toString
()
const
{
}
std
::
string
str
;
};
for
(
const
auto
&
r
:
releases
)
{
if
(
r
.
valid
())
{
str
+=
r
.
toString
()
+
"
\n
"
;
}
/*
}
* @brief 从服务器获取最新版本信息,包含各个分支的最新版本
return
str
;
* @param value 为从服务器获取的最新发布信息,以 JSON 表示
}
* @param latestReleases 版本信息
};
* @return count
* @note 示例数据
/*
* @code{.json}
* @brief 从服务器获取最新版本信息,包含各个分支的最新版本
* {
* @param value 为从服务器获取的最新发布信息,以 JSON 表示
* "test": {
* @param latestReleases 版本信息
* "version": "2.2.11.13262",
* @return count
* "force_update": true,
* @note 示例数据
* "release_note": "测试;",
* @code{.json}
* "download_links": {
* {
* "local": {
* "test": {
* "link": "https://your-host.com/download/installer.exe",
* "version": "2.2.11.13262",
* "md5": "06907d59d7a656be62fc93bbf867604b"
* "force_update": true,
* }
* "release_note": "测试;",
* }
* "download_links": {
* },
* "local": {
* "stable": {
* "link": "https://your-host.com/download/installer.exe",
* "version": "2.2.12.13282",
* "md5": "06907d59d7a656be62fc93bbf867604b"
* "force_update": false,
* }
* "release_note": "测试稳定",
* }
* "download_links": {
* },
* "local": {
* "stable": {
* "link": "https://your-host.com/download/installer.exe",
* "version": "2.2.12.13282",
* "md5": "06907d59d7a656be62fc93bbf867604b"
* "force_update": false,
* },
* "release_note": "测试稳定",
* "qcloud": {
* "download_links": {
* "link": "https://xxx.file.myqcloud.com/xxx/installer.exe",
* "local": {
* "md5": "06907d59d7a656be62fc93bbf867604b"
* "link": "https://your-host.com/download/installer.exe",
* }
* "md5": "06907d59d7a656be62fc93bbf867604b"
* }
* },
* }
* "qcloud": {
* }
* "link": "https://xxx.file.myqcloud.com/xxx/installer.exe",
* @endcode
* "md5": "06907d59d7a656be62fc93bbf867604b"
*/
* }
template
<
typename
JsonValue
>
* }
int
resolveLatestRelease
(
const
JsonValue
&
value
,
LatestRelease
&
latestRelease
)
{
* }
int
count
=
0
;
* }
for
(
int
i
=
0
;
i
<
(
int
)
Branch
::
BranchCount
;
i
++
)
{
* @endcode
Branch
branch
=
Branch
(
i
);
*/
if
(
value
.
isMember
(
branchName
(
branch
)))
{
template
<
typename
JsonValue
>
const
auto
&
detail
=
value
[
branchName
(
branch
)];
int
resolveLatestRelease
(
const
JsonValue
&
value
,
LatestRelease
&
latestRelease
)
{
Release
release
;
int
count
=
0
;
release
.
branch
=
branch
;
for
(
int
i
=
0
;
i
<
(
int
)
Branch
::
BranchCount
;
i
++
)
{
release
.
force_update
=
detail
.
isMember
(
"force_update"
)
?
detail
[
"force_update"
].
asBool
()
:
false
;
Branch
branch
=
Branch
(
i
);
release
.
version
=
detail
[
"version"
].
asString
();
if
(
value
.
isMember
(
branchName
(
branch
)))
{
release
.
change
=
detail
[
"release_note"
].
asString
();
const
auto
&
detail
=
value
[
branchName
(
branch
)];
if
(
detail
[
"download_links"
].
isMember
(
"local"
))
{
Release
release
;
DownLoadLink
dl
;
release
.
branch
=
branch
;
dl
.
host
=
"local"
;
release
.
force_update
=
detail
.
isMember
(
"force_update"
)
?
detail
[
"force_update"
].
asBool
()
:
false
;
dl
.
link
=
detail
[
"download_links"
][
"local"
][
"link"
].
asString
();
release
.
version
=
detail
[
"version"
].
asString
();
dl
.
md5
=
detail
[
"download_links"
][
"local"
][
"md5"
].
asString
();
release
.
change
=
detail
[
"release_note"
].
asString
();
release
.
dllinks
.
push_back
(
dl
);
if
(
detail
[
"download_links"
].
isMember
(
"local"
))
{
}
DownLoadLink
dl
;
if
(
detail
[
"download_links"
].
isMember
(
"qcloud"
))
{
dl
.
host
=
"local"
;
DownLoadLink
dl
;
dl
.
link
=
detail
[
"download_links"
][
"local"
][
"link"
].
asString
();
dl
.
host
=
"qcloud"
;
dl
.
md5
=
detail
[
"download_links"
][
"local"
][
"md5"
].
asString
();
dl
.
link
=
detail
[
"download_links"
][
"qcloud"
][
"link"
].
asString
();
release
.
dllinks
.
push_back
(
dl
);
dl
.
md5
=
detail
[
"download_links"
][
"qcloud"
][
"md5"
].
asString
();
}
release
.
dllinks
.
push_back
(
dl
);
if
(
detail
[
"download_links"
].
isMember
(
"qcloud"
))
{
}
DownLoadLink
dl
;
latestRelease
.
releases
.
push_back
(
release
);
dl
.
host
=
"qcloud"
;
count
++
;
dl
.
link
=
detail
[
"download_links"
][
"qcloud"
][
"link"
].
asString
();
}
dl
.
md5
=
detail
[
"download_links"
][
"qcloud"
][
"md5"
].
asString
();
}
release
.
dllinks
.
push_back
(
dl
);
}
return
count
;
latestRelease
.
releases
.
push_back
(
release
);
}
count
++
;
}
}
// end namespace jlib
}
return
count
;
}
}
// end namespace jlib
jlib/win32/path_helper.h
View file @
c9174ca4
#pragma once
#pragma once
#include "../base/config.h"
#include "../base/config.h"
#include <string>
#include <string>
#include "path_op.h"
#include "path_op.h"
#include "../util/chrono_wrapper.h"
#include "../util/chrono_wrapper.h"
namespace
jlib
{
namespace
jlib
{
namespace
win32
{
namespace
win32
{
struct
PathHelper
struct
PathHelper
{
{
static
inline
bool
mkpath
(
const
std
::
string
&
path
)
{
static
inline
bool
mkpath
(
const
std
::
string
&
path
)
{
return
folderExists
(
path
)
?
true
:
createDirectory
(
path
);
return
folderExists
(
path
)
?
true
:
createDirectory
(
path
);
}
}
static
inline
bool
mkpath
(
const
std
::
wstring
&
path
)
{
static
inline
bool
mkpath
(
const
std
::
wstring
&
path
)
{
return
folderExists
(
path
)
?
true
:
createDirectory
(
path
);
return
folderExists
(
path
)
?
true
:
createDirectory
(
path
);
}
}
static
inline
std
::
wstring
currentTimeString
()
{
static
inline
std
::
wstring
currentTimeString
()
{
return
integrateFileName
(
nowToWString
());
return
integrateFileName
(
nowToWString
());
}
}
static
inline
std
::
string
currentTimeStringA
()
{
static
inline
std
::
string
currentTimeStringA
()
{
return
integrateFileName
(
nowToString
());
return
integrateFileName
(
nowToString
());
}
}
virtual
~
PathHelper
()
{}
virtual
~
PathHelper
()
{}
virtual
std
::
string
program
()
const
{
return
programPath_
;
}
virtual
std
::
string
program
()
const
{
return
programPath_
;
}
virtual
std
::
string
exe
()
const
{
return
exePath_
;
}
virtual
std
::
string
exe
()
const
{
return
exePath_
;
}
virtual
std
::
string
bin
()
const
{
return
program
()
+
"
\\
bin"
;
}
virtual
std
::
string
bin
()
const
{
return
program
()
+
"
\\
bin"
;
}
virtual
std
::
string
data
()
const
{
return
program
()
+
"
\\
data"
;
}
virtual
std
::
string
data
()
const
{
return
program
()
+
"
\\
data"
;
}
virtual
std
::
string
log
()
const
{
return
program
()
+
"
\\
log"
;
}
virtual
std
::
string
log
()
const
{
return
program
()
+
"
\\
log"
;
}
virtual
std
::
string
dumps
()
const
{
return
program
()
+
"
\\
dumps"
;
}
virtual
std
::
string
dumps
()
const
{
return
program
()
+
"
\\
dumps"
;
}
virtual
std
::
string
config
()
const
{
return
data
()
+
"
\\
config"
;
}
virtual
std
::
string
config
()
const
{
return
data
()
+
"
\\
config"
;
}
virtual
std
::
string
db
()
const
{
return
data
()
+
"
\\
db"
;
}
virtual
std
::
string
db
()
const
{
return
data
()
+
"
\\
db"
;
}
protected
:
protected
:
// disable constructor
// disable constructor
explicit
PathHelper
()
{}
explicit
PathHelper
()
{}
//!
应用程序安装目录
//!
应用程序安装目录
std
::
string
programPath_
=
{};
std
::
string
programPath_
=
{};
//!
应用程序路径
//!
应用程序路径
std
::
string
exePath_
=
{};
std
::
string
exePath_
=
{};
};
};
struct
AutoSwithToBin
{
struct
AutoSwithToBin
{
AutoSwithToBin
(
PathHelper
*
helper
)
:
helper
(
helper
)
{}
AutoSwithToBin
(
PathHelper
*
helper
)
:
helper
(
helper
)
{}
AutoSwithToBin
(
PathHelper
*
helper
,
const
std
::
string
&
path
)
:
helper
(
helper
)
{
AutoSwithToBin
(
PathHelper
*
helper
,
const
std
::
string
&
path
)
:
helper
(
helper
)
{
::
SetCurrentDirectoryA
(
path
.
c_str
());
::
SetCurrentDirectoryA
(
path
.
c_str
());
}
}
~
AutoSwithToBin
()
{
~
AutoSwithToBin
()
{
if
(
helper
)
{
::
SetCurrentDirectoryA
(
helper
->
bin
().
c_str
());
}
if
(
helper
)
{
::
SetCurrentDirectoryA
(
helper
->
bin
().
c_str
());
}
}
}
PathHelper
*
helper
=
nullptr
;
PathHelper
*
helper
=
nullptr
;
};
};
/*
/*
* @brief
路径辅助类,数据保存在安装目录,程序和dll在bin文件夹
* @brief
路径辅助类,数据保存在安装目录,程序和dll在bin文件夹
* @note
大致结构树为:
* @note
大致结构树为:
* @note |-- program-install-dir
* @note |-- program-install-dir
* @note | |-- bin
* @note | |-- bin
* @note | | |-- program.exe
* @note | | |-- program.exe
* @note | | |-- *.dlls
* @note | | |-- *.dlls
* @note | |-- dumps
* @note | |-- dumps
* @note | |-- log
* @note | |-- log
* @note | |-- data
* @note | |-- data
* @note | |-- config
* @note | |-- config
* @note | |-- db
* @note | |-- db
*/
*/
struct
PathHelperLocal
:
PathHelper
struct
PathHelperLocal
:
PathHelper
{
{
PathHelperLocal
()
:
PathHelper
()
{
PathHelperLocal
()
:
PathHelper
()
{
exePath_
=
getExePathA
();
exePath_
=
getExePathA
();
programPath_
=
getFolder
(
getFolder
(
exePath_
));
programPath_
=
getFolder
(
getFolder
(
exePath_
));
}
}
};
};
/*
/*
* @brief
路径辅助类,数据保存在安装目录,程序和dll也在安装目录
* @brief
路径辅助类,数据保存在安装目录,程序和dll也在安装目录
* @note
大致结构树为:
* @note
大致结构树为:
* @note |-- program-install-dir
* @note |-- program-install-dir
* @note | |-- dumps
* @note | |-- dumps
* @note | |-- log
* @note | |-- log
* @note | |-- data
* @note | |-- data
* @note | | |-- config
* @note | | |-- config
* @note | | |-- db
* @note | | |-- db
* @note | |-- program.exe
* @note | |-- program.exe
* @note | |-- *.dlls
* @note | |-- *.dlls
*/
*/
struct
PathHelperLocalWithoutBin
:
PathHelper
struct
PathHelperLocalWithoutBin
:
PathHelper
{
{
PathHelperLocalWithoutBin
()
:
PathHelper
()
{
PathHelperLocalWithoutBin
()
:
PathHelper
()
{
exePath_
=
getExePathA
();
exePath_
=
getExePathA
();
programPath_
=
getFolder
(
exePath_
);
programPath_
=
getFolder
(
exePath_
);
}
}
virtual
std
::
string
bin
()
const
override
{
return
program
();
}
virtual
std
::
string
bin
()
const
override
{
return
program
();
}
};
};
/*
/*
* @brief
路径辅助类,数据保存在其他可写目录,如 C:/Users/[USER]/AppData/Roaming
* @brief
路径辅助类,数据保存在其他可写目录,如 C:/Users/[USER]/AppData/Roaming
* @note
大致结构树为:
* @note
大致结构树为:
* @note |-- program-install-dir
* @note |-- program-install-dir
* @note | |-- bin
* @note | |-- bin
* @note | | |-- program.exe
* @note | | |-- program.exe
* @note | | |-- *.dlls
* @note | | |-- *.dlls
* @note
* @note
* @note |-- C:/Users/[USER]/AppData/Roaming
* @note |-- C:/Users/[USER]/AppData/Roaming
* @note | |-- program-name
* @note | |-- program-name
* @note | |-- log
* @note | |-- log
* @note | |-- dumps
* @note | |-- dumps
* @note | |-- config
* @note | |-- config
* @note | |-- db
* @note | |-- db
*/
*/
struct
PathHelperDataSeperated
:
PathHelperLocal
struct
PathHelperDataSeperated
:
PathHelperLocal
{
{
PathHelperDataSeperated
(
const
std
::
string
&
appName
,
bool
useTmpAsLogFolder
=
false
)
PathHelperDataSeperated
(
const
std
::
string
&
appName
,
bool
useTmpAsLogFolder
=
false
)
:
PathHelperLocal
(),
appName
(
appName
),
useTmpAsLogFolder
(
useTmpAsLogFolder
)
:
PathHelperLocal
(),
appName
(
appName
),
useTmpAsLogFolder
(
useTmpAsLogFolder
)
{}
{}
virtual
std
::
string
data
()
const
override
{
virtual
std
::
string
data
()
const
override
{
auto
path
=
getAppDataPathA
()
+
"
\\
"
+
appName
;
auto
path
=
getAppDataPathA
()
+
"
\\
"
+
appName
;
mkpath
(
path
);
return
path
;
mkpath
(
path
);
return
path
;
}
}
virtual
std
::
string
log
()
const
override
{
return
useTmpAsLogFolder
?
getTempPathA
()
:
(
data
()
+
"
\\
log"
);
}
virtual
std
::
string
log
()
const
override
{
return
useTmpAsLogFolder
?
getTempPathA
()
:
(
data
()
+
"
\\
log"
);
}
virtual
std
::
string
dumps
()
const
override
{
return
data
()
+
"
\\
dumps"
;
}
virtual
std
::
string
dumps
()
const
override
{
return
data
()
+
"
\\
dumps"
;
}
virtual
std
::
string
config
()
const
override
{
return
data
()
+
"
\\
config"
;
}
virtual
std
::
string
config
()
const
override
{
return
data
()
+
"
\\
config"
;
}
virtual
std
::
string
db
()
const
override
{
return
data
()
+
"
\\
db"
;
}
virtual
std
::
string
db
()
const
override
{
return
data
()
+
"
\\
db"
;
}
protected
:
protected
:
std
::
string
appName
=
{};
std
::
string
appName
=
{};
bool
useTmpAsLogFolder
=
false
;
bool
useTmpAsLogFolder
=
false
;
};
};
/*
/*
* @brief
路径辅助类,数据保存在其他可写目录,如 C:/Users/[USER]/AppData/Roaming
* @brief
路径辅助类,数据保存在其他可写目录,如 C:/Users/[USER]/AppData/Roaming
* @note
大致结构树为:
* @note
大致结构树为:
* @note |-- program-install-dir
* @note |-- program-install-dir
* @note | |-- program.exe
* @note | |-- program.exe
* @note | |-- *.dlls
* @note | |-- *.dlls
* @note
* @note
* @note |-- C:/Users/[USER]/AppData/Roaming
* @note |-- C:/Users/[USER]/AppData/Roaming
* @note | |-- program-name
* @note | |-- program-name
* @note | |-- log
* @note | |-- log
* @note | |-- dumps
* @note | |-- dumps
* @note | |-- config
* @note | |-- config
* @note | |-- db
* @note | |-- db
*/
*/
struct
PathHelperDataSeperatedWithoutBin
:
PathHelperLocalWithoutBin
struct
PathHelperDataSeperatedWithoutBin
:
PathHelperLocalWithoutBin
{
{
PathHelperDataSeperatedWithoutBin
(
const
std
::
string
&
appName
,
bool
useTmpAsLogFolder
=
false
)
PathHelperDataSeperatedWithoutBin
(
const
std
::
string
&
appName
,
bool
useTmpAsLogFolder
=
false
)
:
PathHelperLocalWithoutBin
(),
appName
(
appName
),
useTmpAsLogFolder
(
useTmpAsLogFolder
)
:
PathHelperLocalWithoutBin
(),
appName
(
appName
),
useTmpAsLogFolder
(
useTmpAsLogFolder
)
{}
{}
virtual
std
::
string
data
()
const
override
{
virtual
std
::
string
data
()
const
override
{
auto
path
=
getAppDataPathA
()
+
"
\\
"
+
appName
;
auto
path
=
getAppDataPathA
()
+
"
\\
"
+
appName
;
mkpath
(
path
);
return
path
;
mkpath
(
path
);
return
path
;
}
}
virtual
std
::
string
log
()
const
override
{
return
useTmpAsLogFolder
?
getTempPathA
()
:
(
data
()
+
"
\\
log"
);
}
virtual
std
::
string
log
()
const
override
{
return
useTmpAsLogFolder
?
getTempPathA
()
:
(
data
()
+
"
\\
log"
);
}
virtual
std
::
string
dumps
()
const
override
{
return
data
()
+
"
\\
dumps"
;
}
virtual
std
::
string
dumps
()
const
override
{
return
data
()
+
"
\\
dumps"
;
}
virtual
std
::
string
config
()
const
override
{
return
data
()
+
"
\\
config"
;
}
virtual
std
::
string
config
()
const
override
{
return
data
()
+
"
\\
config"
;
}
virtual
std
::
string
db
()
const
override
{
return
data
()
+
"
\\
db"
;
}
virtual
std
::
string
db
()
const
override
{
return
data
()
+
"
\\
db"
;
}
protected
:
protected
:
std
::
string
appName
=
{};
std
::
string
appName
=
{};
bool
useTmpAsLogFolder
=
false
;
bool
useTmpAsLogFolder
=
false
;
};
};
}
}
}
}
jlib/win32/path_op.h
View file @
c9174ca4
#
pragma
once
#pragma once
#include "../base/config.h"
#include "../base/config.h"
#include <ShlObj.h>
#include <ShlObj.h>
#include <string>
#include <string>
#include <algorithm>
#include <algorithm>
namespace
jlib
{
namespace
jlib
{
namespace
win32
{
namespace
win32
{
inline
std
::
wstring
getExePath
()
{
inline
std
::
wstring
getExePath
()
{
wchar_t
path
[
1024
]
=
{
0
};
::
GetModuleFileNameW
(
nullptr
,
path
,
1024
);
return
path
;
wchar_t
path
[
1024
]
=
{
0
};
::
GetModuleFileNameW
(
nullptr
,
path
,
1024
);
return
path
;
}
}
inline
std
::
string
getExePathA
()
{
inline
std
::
string
getExePathA
()
{
char
path
[
1024
]
=
{
0
};
::
GetModuleFileNameA
(
nullptr
,
path
,
1024
);
return
path
;
char
path
[
1024
]
=
{
0
};
::
GetModuleFileNameA
(
nullptr
,
path
,
1024
);
return
path
;
}
}
inline
std
::
wstring
getFolder
(
const
std
::
wstring
&
path
)
{
inline
std
::
wstring
getFolder
(
const
std
::
wstring
&
path
)
{
auto
pos
=
path
.
find_last_of
(
L"
\\
/"
);
return
pos
!=
path
.
npos
?
path
.
substr
(
0
,
pos
)
:
path
;
auto
pos
=
path
.
find_last_of
(
L"
\\
/"
);
return
pos
!=
path
.
npos
?
path
.
substr
(
0
,
pos
)
:
path
;
}
}
inline
std
::
string
getFolder
(
const
std
::
string
&
path
)
{
inline
std
::
string
getFolder
(
const
std
::
string
&
path
)
{
auto
pos
=
path
.
find_last_of
(
"
\\
/"
);
return
pos
!=
path
.
npos
?
path
.
substr
(
0
,
pos
)
:
path
;
auto
pos
=
path
.
find_last_of
(
"
\\
/"
);
return
pos
!=
path
.
npos
?
path
.
substr
(
0
,
pos
)
:
path
;
}
}
inline
std
::
wstring
getExeFolderPath
()
{
return
getFolder
(
getExePath
());
}
inline
std
::
wstring
getExeFolderPath
()
{
return
getFolder
(
getExePath
());
}
inline
std
::
string
getExeFolderPathA
()
{
return
getFolder
(
getExePathA
());
}
inline
std
::
string
getExeFolderPathA
()
{
return
getFolder
(
getExePathA
());
}
static
constexpr
const
wchar_t
*
DEFAULT_PATH_FILTERW
=
L"
\\
/:*?
\"
<>| "
;
static
constexpr
const
wchar_t
*
DEFAULT_PATH_FILTERW
=
L"
\\
/:*?
\"
<>| "
;
static
constexpr
const
char
*
DEFAULT_PATH_FILTER
=
"
\\
/:*?
\"
<>| "
;
static
constexpr
const
char
*
DEFAULT_PATH_FILTER
=
"
\\
/:*?
\"
<>| "
;
inline
std
::
wstring
integrateFileName
(
const
std
::
wstring
&
name
,
const
std
::
wstring
&
filter
=
DEFAULT_PATH_FILTERW
,
wchar_t
replace_by
=
L'_'
)
{
inline
std
::
wstring
integrateFileName
(
const
std
::
wstring
&
name
,
const
std
::
wstring
&
filter
=
DEFAULT_PATH_FILTERW
,
wchar_t
replace_by
=
L'_'
)
{
auto
ret
=
name
;
for
(
auto
c
:
filter
)
{
std
::
replace
(
ret
.
begin
(),
ret
.
end
(),
c
,
replace_by
);
}
return
ret
;
auto
ret
=
name
;
for
(
auto
c
:
filter
)
{
std
::
replace
(
ret
.
begin
(),
ret
.
end
(),
c
,
replace_by
);
}
return
ret
;
}
}
inline
std
::
string
integrateFileName
(
const
std
::
string
&
name
,
const
std
::
string
&
filter
=
DEFAULT_PATH_FILTER
,
char
replace_by
=
'_'
)
{
inline
std
::
string
integrateFileName
(
const
std
::
string
&
name
,
const
std
::
string
&
filter
=
DEFAULT_PATH_FILTER
,
char
replace_by
=
'_'
)
{
auto
ret
=
name
;
for
(
auto
c
:
filter
)
{
std
::
replace
(
ret
.
begin
(),
ret
.
end
(),
c
,
replace_by
);
}
return
ret
;
auto
ret
=
name
;
for
(
auto
c
:
filter
)
{
std
::
replace
(
ret
.
begin
(),
ret
.
end
(),
c
,
replace_by
);
}
return
ret
;
}
}
inline
std
::
wstring
getSpecialFolder
(
int
csidl
)
{
inline
std
::
wstring
getSpecialFolder
(
int
csidl
)
{
wchar_t
path
[
MAX_PATH
]
=
{
0
};
wchar_t
path
[
MAX_PATH
]
=
{
0
};
return
::
SHGetSpecialFolderPathW
(
nullptr
,
path
,
csidl
,
false
)
?
std
::
wstring
(
path
)
:
std
::
wstring
();
return
::
SHGetSpecialFolderPathW
(
nullptr
,
path
,
csidl
,
false
)
?
std
::
wstring
(
path
)
:
std
::
wstring
();
}
}
inline
std
::
string
getSpecialFolderA
(
int
csidl
)
{
inline
std
::
string
getSpecialFolderA
(
int
csidl
)
{
char
path
[
MAX_PATH
]
=
{
0
};
char
path
[
MAX_PATH
]
=
{
0
};
return
::
SHGetSpecialFolderPathA
(
nullptr
,
path
,
csidl
,
false
)
?
std
::
string
(
path
)
:
std
::
string
();
return
::
SHGetSpecialFolderPathA
(
nullptr
,
path
,
csidl
,
false
)
?
std
::
string
(
path
)
:
std
::
string
();
}
}
/**
/**
* @brief 获取%APPDATA%路径,一般用于存储程序配置文件
* @brief 获取%APPDATA%路径,一般用于存储程序配置文件
* @note 一般xp的结果为: C:\Documents and Setting\[UserName]\Application Data
* @note 一般xp的结果为: C:\Documents and Setting\[UserName]\Application Data
* @note 一般vista及以上的结果为:C:\Users\[UserName]\AppData\Roaming
* @note 一般vista及以上的结果为:C:\Users\[UserName]\AppData\Roaming
*/
*/
inline
std
::
wstring
getAppDataPath
()
{
return
getSpecialFolder
(
CSIDL_APPDATA
);
}
inline
std
::
wstring
getAppDataPath
()
{
return
getSpecialFolder
(
CSIDL_APPDATA
);
}
inline
std
::
string
getAppDataPathA
()
{
return
getSpecialFolderA
(
CSIDL_APPDATA
);
}
inline
std
::
string
getAppDataPathA
()
{
return
getSpecialFolderA
(
CSIDL_APPDATA
);
}
inline
std
::
wstring
getTempPath
()
{
wchar_t
path
[
MAX_PATH
]
=
{
0
};
::
GetTempPathW
(
MAX_PATH
,
path
);
return
path
;
}
inline
std
::
wstring
getTempPath
()
{
wchar_t
path
[
MAX_PATH
]
=
{
0
};
::
GetTempPathW
(
MAX_PATH
,
path
);
return
path
;
}
inline
std
::
string
getTempPathA
()
{
char
path
[
MAX_PATH
]
=
{
0
};
::
GetTempPathA
(
MAX_PATH
,
path
);
return
path
;
}
inline
std
::
string
getTempPathA
()
{
char
path
[
MAX_PATH
]
=
{
0
};
::
GetTempPathA
(
MAX_PATH
,
path
);
return
path
;
}
inline
std
::
wstring
getMyDocumentsPath
()
{
return
getSpecialFolder
(
CSIDL_MYDOCUMENTS
);
}
inline
std
::
wstring
getMyDocumentsPath
()
{
return
getSpecialFolder
(
CSIDL_MYDOCUMENTS
);
}
inline
std
::
string
getMyDocumentsPathA
()
{
return
getSpecialFolderA
(
CSIDL_MYDOCUMENTS
);
}
inline
std
::
string
getMyDocumentsPathA
()
{
return
getSpecialFolderA
(
CSIDL_MYDOCUMENTS
);
}
inline
std
::
wstring
getTempFileName
(
const
std
::
wstring
&
folder
,
const
std
::
wstring
&
pre
)
{
inline
std
::
wstring
getTempFileName
(
const
std
::
wstring
&
folder
,
const
std
::
wstring
&
pre
)
{
wchar_t
path
[
MAX_PATH
]
=
{
0
};
wchar_t
path
[
MAX_PATH
]
=
{
0
};
UINT
ret
=
::
GetTempFileNameW
(
folder
.
c_str
(),
pre
.
c_str
(),
0
,
path
);
UINT
ret
=
::
GetTempFileNameW
(
folder
.
c_str
(),
pre
.
c_str
(),
0
,
path
);
if
(
ret
!=
0
)
{
return
path
;
}
return
std
::
wstring
();
if
(
ret
!=
0
)
{
return
path
;
}
return
std
::
wstring
();
}
}
inline
std
::
string
getTempFileName
(
const
std
::
string
&
folder
,
const
std
::
string
&
pre
)
{
inline
std
::
string
getTempFileName
(
const
std
::
string
&
folder
,
const
std
::
string
&
pre
)
{
char
path
[
MAX_PATH
]
=
{
0
};
char
path
[
MAX_PATH
]
=
{
0
};
UINT
ret
=
::
GetTempFileNameA
(
folder
.
c_str
(),
pre
.
c_str
(),
0
,
path
);
UINT
ret
=
::
GetTempFileNameA
(
folder
.
c_str
(),
pre
.
c_str
(),
0
,
path
);
if
(
ret
!=
0
)
{
return
path
;
}
return
std
::
string
();
if
(
ret
!=
0
)
{
return
path
;
}
return
std
::
string
();
}
}
inline
std
::
wstring
getTempFileName
(
const
std
::
wstring
&
pre
=
L"JLIB"
)
{
inline
std
::
wstring
getTempFileName
(
const
std
::
wstring
&
pre
=
L"JLIB"
)
{
return
getTempFileName
(
getTempPath
(),
pre
);
return
getTempFileName
(
getTempPath
(),
pre
);
}
}
inline
std
::
string
getTempFileNameA
(
const
std
::
string
&
pre
=
"JLIB"
)
{
inline
std
::
string
getTempFileNameA
(
const
std
::
string
&
pre
=
"JLIB"
)
{
return
getTempFileName
(
getTempPathA
(),
pre
);
return
getTempFileName
(
getTempPathA
(),
pre
);
}
}
inline
bool
folderExists
(
const
std
::
wstring
&
folderPath
)
{
inline
bool
folderExists
(
const
std
::
wstring
&
folderPath
)
{
DWORD
dwAttrib
=
::
GetFileAttributesW
(
folderPath
.
data
());
DWORD
dwAttrib
=
::
GetFileAttributesW
(
folderPath
.
data
());
return
(
dwAttrib
!=
INVALID_FILE_ATTRIBUTES
)
&&
(
dwAttrib
&
FILE_ATTRIBUTE_DIRECTORY
);
return
(
dwAttrib
!=
INVALID_FILE_ATTRIBUTES
)
&&
(
dwAttrib
&
FILE_ATTRIBUTE_DIRECTORY
);
}
}
inline
bool
folderExists
(
const
std
::
string
&
folderPath
)
{
inline
bool
folderExists
(
const
std
::
string
&
folderPath
)
{
DWORD
dwAttrib
=
::
GetFileAttributesA
(
folderPath
.
data
());
DWORD
dwAttrib
=
::
GetFileAttributesA
(
folderPath
.
data
());
return
(
dwAttrib
!=
INVALID_FILE_ATTRIBUTES
)
&&
(
dwAttrib
&
FILE_ATTRIBUTE_DIRECTORY
);
return
(
dwAttrib
!=
INVALID_FILE_ATTRIBUTES
)
&&
(
dwAttrib
&
FILE_ATTRIBUTE_DIRECTORY
);
}
}
inline
bool
fileExists
(
const
std
::
wstring
&
filePath
)
{
inline
bool
fileExists
(
const
std
::
wstring
&
filePath
)
{
DWORD
dwAttrib
=
::
GetFileAttributesW
(
filePath
.
data
());
DWORD
dwAttrib
=
::
GetFileAttributesW
(
filePath
.
data
());
return
(
dwAttrib
!=
INVALID_FILE_ATTRIBUTES
)
&&
!
(
dwAttrib
&
FILE_ATTRIBUTE_DIRECTORY
);
return
(
dwAttrib
!=
INVALID_FILE_ATTRIBUTES
)
&&
!
(
dwAttrib
&
FILE_ATTRIBUTE_DIRECTORY
);
}
}
inline
bool
fileExists
(
const
std
::
string
&
filePath
)
{
inline
bool
fileExists
(
const
std
::
string
&
filePath
)
{
DWORD
dwAttrib
=
::
GetFileAttributesA
(
filePath
.
data
());
DWORD
dwAttrib
=
::
GetFileAttributesA
(
filePath
.
data
());
return
(
dwAttrib
!=
INVALID_FILE_ATTRIBUTES
)
&&
!
(
dwAttrib
&
FILE_ATTRIBUTE_DIRECTORY
);
return
(
dwAttrib
!=
INVALID_FILE_ATTRIBUTES
)
&&
!
(
dwAttrib
&
FILE_ATTRIBUTE_DIRECTORY
);
}
}
inline
bool
createDirectory
(
const
std
::
wstring
&
path
)
{
inline
bool
createDirectory
(
const
std
::
wstring
&
path
)
{
return
::
CreateDirectoryW
(
path
.
data
(),
nullptr
)
?
true
:
false
;
return
::
CreateDirectoryW
(
path
.
data
(),
nullptr
)
?
true
:
false
;
}
}
inline
bool
createDirectory
(
const
std
::
string
&
path
)
{
inline
bool
createDirectory
(
const
std
::
string
&
path
)
{
return
::
CreateDirectoryA
(
path
.
data
(),
nullptr
)
?
true
:
false
;
return
::
CreateDirectoryA
(
path
.
data
(),
nullptr
)
?
true
:
false
;
}
}
//! 应用程序典型路径辅助
//! 应用程序典型路径辅助
//struct PathHelper {
//struct PathHelper {
//
//
//
//
//};
//};
}
}
}
}
jlib/win32/process.h
View file @
c9174ca4
#
pragma
once
#pragma once
#include <Windows.h>
#include <Windows.h>
#include <tlhelp32.h>
#include <tlhelp32.h>
#include <string>
#include <string>
#include <vector>
#include <vector>
#include <functional>
#include <functional>
#include <unordered_set>
#include <unordered_set>
#include "lasterror.h"
#include "lasterror.h"
#include "UnicodeTool.h"
#include "UnicodeTool.h"
namespace
jlib
namespace
jlib
{
{
namespace
win32
namespace
win32
{
{
/**
/**
* @brief 启动程序
* @brief 启动程序
* @param path 启动命令
* @param path 启动命令
* @param wait_app_exit 是否阻塞等待程序退出
* @param wait_app_exit 是否阻塞等待程序退出
* @param show 是否显示程序
* @param show 是否显示程序
* @return 启动程序失败返回0xFFFFFFFF;当 wait_app_exit 为真,返回程序的进程返回值;否则返回程序进程ID;
* @return 启动程序失败返回0xFFFFFFFF;当 wait_app_exit 为真,返回程序的进程返回值;否则返回程序进程ID;
*/
*/
inline
DWORD
daemon
(
const
std
::
wstring
&
path
,
bool
wait_app_exit
=
true
,
bool
show
=
true
)
{
inline
DWORD
daemon
(
const
std
::
wstring
&
path
,
bool
wait_app_exit
=
true
,
bool
show
=
true
)
{
STARTUPINFOW
si
=
{
0
};
STARTUPINFOW
si
=
{
0
};
si
.
cb
=
sizeof
(
si
);
si
.
cb
=
sizeof
(
si
);
si
.
dwFlags
|=
STARTF_USESHOWWINDOW
;
si
.
dwFlags
|=
STARTF_USESHOWWINDOW
;
si
.
wShowWindow
=
show
?
SW_SHOW
:
SW_HIDE
;
si
.
wShowWindow
=
show
?
SW_SHOW
:
SW_HIDE
;
PROCESS_INFORMATION
pi
;
PROCESS_INFORMATION
pi
;
DWORD
dwCreationFlags
=
show
?
0
:
CREATE_NO_WINDOW
;
DWORD
dwCreationFlags
=
show
?
0
:
CREATE_NO_WINDOW
;
BOOL
bRet
=
CreateProcessW
(
NULL
,
(
LPWSTR
)(
path
.
c_str
()),
NULL
,
NULL
,
FALSE
,
dwCreationFlags
,
NULL
,
NULL
,
&
si
,
&
pi
);
BOOL
bRet
=
CreateProcessW
(
NULL
,
(
LPWSTR
)(
path
.
c_str
()),
NULL
,
NULL
,
FALSE
,
dwCreationFlags
,
NULL
,
NULL
,
&
si
,
&
pi
);
if
(
bRet
)
{
if
(
bRet
)
{
if
(
wait_app_exit
)
{
if
(
wait_app_exit
)
{
WaitForSingleObject
(
pi
.
hProcess
,
INFINITE
);
WaitForSingleObject
(
pi
.
hProcess
,
INFINITE
);
DWORD
dwExit
;
DWORD
dwExit
;
::
GetExitCodeProcess
(
pi
.
hProcess
,
&
dwExit
);
::
GetExitCodeProcess
(
pi
.
hProcess
,
&
dwExit
);
CloseHandle
(
pi
.
hThread
);
CloseHandle
(
pi
.
hThread
);
CloseHandle
(
pi
.
hProcess
);
CloseHandle
(
pi
.
hProcess
);
return
dwExit
;
return
dwExit
;
}
else
{
}
else
{
return
pi
.
dwProcessId
;
return
pi
.
dwProcessId
;
}
}
}
else
{
}
else
{
auto
msg
=
formatLastError
(
""
);
auto
msg
=
formatLastError
(
""
);
(
void
)
msg
.
length
();
(
void
)
msg
.
length
();
}
}
return
0xFFFFFFFF
;
return
0xFFFFFFFF
;
}
}
/**
/**
* @brief 启动程序
* @brief 启动程序
* @param path 启动命令
* @param path 启动命令
* @param wait_app_exit 是否阻塞等待程序退出
* @param wait_app_exit 是否阻塞等待程序退出
* @param show 是否显示程序
* @param show 是否显示程序
* @return 启动程序失败返回0xFFFFFFFF;当 wait_app_exit 为真,返回程序的进程返回值;否则返回程序进程ID;
* @return 启动程序失败返回0xFFFFFFFF;当 wait_app_exit 为真,返回程序的进程返回值;否则返回程序进程ID;
*/
*/
inline
DWORD
daemon
(
const
std
::
string
&
path
,
bool
wait_app_exit
=
true
,
bool
show
=
true
)
{
inline
DWORD
daemon
(
const
std
::
string
&
path
,
bool
wait_app_exit
=
true
,
bool
show
=
true
)
{
return
daemon
(
win32
::
mbcs_to_utf16
(
path
),
wait_app_exit
,
show
);
return
daemon
(
win32
::
mbcs_to_utf16
(
path
),
wait_app_exit
,
show
);
}
}
/**
/**
* @brief 获取父进程ID
* @brief 获取父进程ID
* @return 成功返回父进程ID,否则返回0
* @return 成功返回父进程ID,否则返回0
*/
*/
inline
DWORD
getppid
()
inline
DWORD
getppid
()
{
{
HANDLE
hSnapshot
;
HANDLE
hSnapshot
;
PROCESSENTRY32W
pe32
;
PROCESSENTRY32W
pe32
;
DWORD
ppid
=
0
,
pid
=
GetCurrentProcessId
();
DWORD
ppid
=
0
,
pid
=
GetCurrentProcessId
();
hSnapshot
=
CreateToolhelp32Snapshot
(
TH32CS_SNAPPROCESS
,
pid
);
hSnapshot
=
CreateToolhelp32Snapshot
(
TH32CS_SNAPPROCESS
,
pid
);
__try
{
__try
{
if
(
hSnapshot
==
INVALID_HANDLE_VALUE
)
__leave
;
if
(
hSnapshot
==
INVALID_HANDLE_VALUE
)
__leave
;
ZeroMemory
(
&
pe32
,
sizeof
(
pe32
));
ZeroMemory
(
&
pe32
,
sizeof
(
pe32
));
pe32
.
dwSize
=
sizeof
(
pe32
);
pe32
.
dwSize
=
sizeof
(
pe32
);
if
(
!
Process32FirstW
(
hSnapshot
,
&
pe32
))
__leave
;
if
(
!
Process32FirstW
(
hSnapshot
,
&
pe32
))
__leave
;
do
{
do
{
if
(
pe32
.
th32ProcessID
==
pid
)
{
if
(
pe32
.
th32ProcessID
==
pid
)
{
ppid
=
pe32
.
th32ParentProcessID
;
ppid
=
pe32
.
th32ParentProcessID
;
break
;
break
;
}
}
}
while
(
Process32NextW
(
hSnapshot
,
&
pe32
));
}
while
(
Process32NextW
(
hSnapshot
,
&
pe32
));
}
__finally
{
}
__finally
{
if
(
hSnapshot
!=
INVALID_HANDLE_VALUE
)
CloseHandle
(
hSnapshot
);
if
(
hSnapshot
!=
INVALID_HANDLE_VALUE
)
CloseHandle
(
hSnapshot
);
}
}
return
ppid
;
return
ppid
;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
// https://docs.microsoft.com/zh-cn/windows/win32/toolhelp/taking-a-snapshot-and-viewing-processes
// https://docs.microsoft.com/zh-cn/windows/win32/toolhelp/taking-a-snapshot-and-viewing-processes
struct
ProcessInfo
{
struct
ProcessInfo
{
struct
ModuleInfo
{
struct
ModuleInfo
{
std
::
wstring
name
;
std
::
wstring
name
;
std
::
wstring
path
;
std
::
wstring
path
;
DWORD
pid
;
DWORD
pid
;
DWORD
base_address
;
DWORD
base_address
;
DWORD
base_size
;
DWORD
base_size
;
};
};
struct
ThreadInfo
{
struct
ThreadInfo
{
DWORD
tid
;
DWORD
tid
;
DWORD
base_priority
;
DWORD
base_priority
;
DWORD
delta_priority
;
DWORD
delta_priority
;
};
};
std
::
wstring
name
;
std
::
wstring
name
;
std
::
wstring
path
;
std
::
wstring
path
;
DWORD
pid
;
DWORD
pid
;
DWORD
ppid
;
DWORD
ppid
;
DWORD
thread_count
;
DWORD
thread_count
;
DWORD
priority_base
;
DWORD
priority_base
;
DWORD
priority_class
;
DWORD
priority_class
;
std
::
vector
<
ModuleInfo
>
modules
;
std
::
vector
<
ModuleInfo
>
modules
;
std
::
vector
<
ThreadInfo
>
threads
;
std
::
vector
<
ThreadInfo
>
threads
;
template
<
typename
JsonValue
>
template
<
typename
JsonValue
>
JsonValue
toJson
()
const
{
JsonValue
toJson
()
const
{
JsonValue
v
;
JsonValue
v
;
v
[
"name"
]
=
utf16_to_mbcs
(
name
);
v
[
"name"
]
=
utf16_to_mbcs
(
name
);
v
[
"path"
]
=
utf16_to_mbcs
(
path
);
v
[
"path"
]
=
utf16_to_mbcs
(
path
);
v
[
"pid"
]
=
(
size_t
)
pid
;
v
[
"pid"
]
=
(
size_t
)
pid
;
v
[
"ppid"
]
=
(
size_t
)
ppid
;
v
[
"ppid"
]
=
(
size_t
)
ppid
;
v
[
"thread_count"
]
=
(
size_t
)
thread_count
;
v
[
"thread_count"
]
=
(
size_t
)
thread_count
;
v
[
"priority_base"
]
=
(
size_t
)
priority_base
;
v
[
"priority_base"
]
=
(
size_t
)
priority_base
;
v
[
"priority_class"
]
=
(
size_t
)
priority_class
;
v
[
"priority_class"
]
=
(
size_t
)
priority_class
;
auto
&
ms
=
v
[
"modules"
];
auto
&
ms
=
v
[
"modules"
];
for
(
const
auto
&
m
:
modules
)
{
for
(
const
auto
&
m
:
modules
)
{
JsonValue
jm
;
JsonValue
jm
;
jm
[
"name"
]
=
utf16_to_mbcs
(
m
.
name
);
jm
[
"name"
]
=
utf16_to_mbcs
(
m
.
name
);
jm
[
"path"
]
=
utf16_to_mbcs
(
m
.
path
);
jm
[
"path"
]
=
utf16_to_mbcs
(
m
.
path
);
jm
[
"pid"
]
=
(
size_t
)
m
.
pid
;
jm
[
"pid"
]
=
(
size_t
)
m
.
pid
;
jm
[
"base_address"
]
=
(
size_t
)
m
.
base_address
;
jm
[
"base_address"
]
=
(
size_t
)
m
.
base_address
;
jm
[
"base_size"
]
=
(
size_t
)
m
.
base_size
;
jm
[
"base_size"
]
=
(
size_t
)
m
.
base_size
;
ms
.
append
(
jm
);
ms
.
append
(
jm
);
}
}
auto
&
ts
=
v
[
"threads"
];
auto
&
ts
=
v
[
"threads"
];
for
(
const
auto
&
t
:
threads
)
{
for
(
const
auto
&
t
:
threads
)
{
JsonValue
jt
;
JsonValue
jt
;
jt
[
"tid"
]
=
(
size_t
)
t
.
tid
;
jt
[
"tid"
]
=
(
size_t
)
t
.
tid
;
jt
[
"base_priority"
]
=
(
size_t
)
t
.
base_priority
;
jt
[
"base_priority"
]
=
(
size_t
)
t
.
base_priority
;
jt
[
"delta_priority"
]
=
(
size_t
)
t
.
delta_priority
;
jt
[
"delta_priority"
]
=
(
size_t
)
t
.
delta_priority
;
ts
.
append
(
jt
);
ts
.
append
(
jt
);
}
}
return
v
;
return
v
;
}
}
};
};
typedef
std
::
vector
<
ProcessInfo
>
ProcessInfos
;
typedef
std
::
vector
<
ProcessInfo
>
ProcessInfos
;
template
<
typename
JsonValue
>
template
<
typename
JsonValue
>
inline
JsonValue
toJson
(
const
ProcessInfos
&
pinfos
)
{
inline
JsonValue
toJson
(
const
ProcessInfos
&
pinfos
)
{
JsonValue
v
;
JsonValue
v
;
for
(
const
auto
&
pinfo
:
pinfos
)
{
for
(
const
auto
&
pinfo
:
pinfos
)
{
v
.
append
(
pinfo
.
toJson
<
JsonValue
>
());
v
.
append
(
pinfo
.
toJson
<
JsonValue
>
());
}
}
return
v
;
return
v
;
}
}
typedef
std
::
function
<
void
(
const
std
::
wstring
&
)
>
ErrorOutputFunc
;
typedef
std
::
function
<
void
(
const
std
::
wstring
&
)
>
ErrorOutputFunc
;
inline
void
dummyErrorOutputFunc
(
const
std
::
wstring
&
msg
)
{
inline
void
dummyErrorOutputFunc
(
const
std
::
wstring
&
msg
)
{
printf
(
"%ls
\n
"
,
msg
.
data
());
printf
(
"%ls
\n
"
,
msg
.
data
());
}
}
inline
void
outputLastErrorHelper
(
const
std
::
wstring
&
msg
,
ErrorOutputFunc
func
=
nullptr
)
{
inline
void
outputLastErrorHelper
(
const
std
::
wstring
&
msg
,
ErrorOutputFunc
func
=
nullptr
)
{
if
(
!
func
)
{
return
;
}
if
(
!
func
)
{
return
;
}
func
(
formatLastError
(
msg
));
func
(
formatLastError
(
msg
));
}
}
inline
std
::
vector
<
ProcessInfo
::
ModuleInfo
>
getProcessModules
(
DWORD
dwPID
,
ErrorOutputFunc
output
=
dummyErrorOutputFunc
)
inline
std
::
vector
<
ProcessInfo
::
ModuleInfo
>
getProcessModules
(
DWORD
dwPID
,
ErrorOutputFunc
output
=
dummyErrorOutputFunc
)
{
{
std
::
vector
<
ProcessInfo
::
ModuleInfo
>
modules
=
{};
std
::
vector
<
ProcessInfo
::
ModuleInfo
>
modules
=
{};
HANDLE
hModuleSnap
=
INVALID_HANDLE_VALUE
;
HANDLE
hModuleSnap
=
INVALID_HANDLE_VALUE
;
MODULEENTRY32
me32
;
MODULEENTRY32
me32
;
// Take a snapshot of all modules in the specified process.
// Take a snapshot of all modules in the specified process.
hModuleSnap
=
CreateToolhelp32Snapshot
(
TH32CS_SNAPMODULE
,
dwPID
);
hModuleSnap
=
CreateToolhelp32Snapshot
(
TH32CS_SNAPMODULE
,
dwPID
);
if
(
hModuleSnap
==
INVALID_HANDLE_VALUE
)
{
if
(
hModuleSnap
==
INVALID_HANDLE_VALUE
)
{
outputLastErrorHelper
((
L"CreateToolhelp32Snapshot (of modules)"
),
output
);
outputLastErrorHelper
((
L"CreateToolhelp32Snapshot (of modules)"
),
output
);
return
(
modules
);
return
(
modules
);
}
}
// Set the size of the structure before using it.
// Set the size of the structure before using it.
me32
.
dwSize
=
sizeof
(
MODULEENTRY32
);
me32
.
dwSize
=
sizeof
(
MODULEENTRY32
);
// Retrieve information about the first module,
// Retrieve information about the first module,
// and exit if unsuccessful
// and exit if unsuccessful
if
(
!
Module32First
(
hModuleSnap
,
&
me32
))
{
if
(
!
Module32First
(
hModuleSnap
,
&
me32
))
{
outputLastErrorHelper
((
L"Module32First"
),
output
);
// show cause of failure
outputLastErrorHelper
((
L"Module32First"
),
output
);
// show cause of failure
CloseHandle
(
hModuleSnap
);
// clean the snapshot object
CloseHandle
(
hModuleSnap
);
// clean the snapshot object
return
(
modules
);
return
(
modules
);
}
}
// Now walk the module list of the process,
// Now walk the module list of the process,
// and display information about each module
// and display information about each module
do
{
do
{
ProcessInfo
::
ModuleInfo
info
;
ProcessInfo
::
ModuleInfo
info
;
info
.
name
=
me32
.
szModule
;
info
.
name
=
me32
.
szModule
;
info
.
path
=
me32
.
szExePath
;
info
.
path
=
me32
.
szExePath
;
info
.
pid
=
me32
.
th32ProcessID
;
info
.
pid
=
me32
.
th32ProcessID
;
info
.
base_address
=
(
DWORD
)
me32
.
modBaseAddr
;
info
.
base_address
=
(
DWORD
)
me32
.
modBaseAddr
;
info
.
base_size
=
me32
.
modBaseSize
;
info
.
base_size
=
me32
.
modBaseSize
;
modules
.
emplace_back
(
info
);
modules
.
emplace_back
(
info
);
}
while
(
Module32Next
(
hModuleSnap
,
&
me32
));
}
while
(
Module32Next
(
hModuleSnap
,
&
me32
));
CloseHandle
(
hModuleSnap
);
CloseHandle
(
hModuleSnap
);
return
(
modules
);
return
(
modules
);
}
}
inline
std
::
vector
<
ProcessInfo
::
ThreadInfo
>
getProcessThreads
(
DWORD
dwOwnerPID
,
ErrorOutputFunc
output
=
dummyErrorOutputFunc
)
inline
std
::
vector
<
ProcessInfo
::
ThreadInfo
>
getProcessThreads
(
DWORD
dwOwnerPID
,
ErrorOutputFunc
output
=
dummyErrorOutputFunc
)
{
{
std
::
vector
<
ProcessInfo
::
ThreadInfo
>
threads
=
{};
std
::
vector
<
ProcessInfo
::
ThreadInfo
>
threads
=
{};
HANDLE
hThreadSnap
=
INVALID_HANDLE_VALUE
;
HANDLE
hThreadSnap
=
INVALID_HANDLE_VALUE
;
THREADENTRY32
te32
;
THREADENTRY32
te32
;
// Take a snapshot of all running threads
// Take a snapshot of all running threads
hThreadSnap
=
CreateToolhelp32Snapshot
(
TH32CS_SNAPTHREAD
,
dwOwnerPID
);
hThreadSnap
=
CreateToolhelp32Snapshot
(
TH32CS_SNAPTHREAD
,
dwOwnerPID
);
if
(
hThreadSnap
==
INVALID_HANDLE_VALUE
)
if
(
hThreadSnap
==
INVALID_HANDLE_VALUE
)
return
(
threads
);
return
(
threads
);
// Fill in the size of the structure before using it.
// Fill in the size of the structure before using it.
te32
.
dwSize
=
sizeof
(
THREADENTRY32
);
te32
.
dwSize
=
sizeof
(
THREADENTRY32
);
// Retrieve information about the first thread,
// Retrieve information about the first thread,
// and exit if unsuccessful
// and exit if unsuccessful
if
(
!
Thread32First
(
hThreadSnap
,
&
te32
))
{
if
(
!
Thread32First
(
hThreadSnap
,
&
te32
))
{
outputLastErrorHelper
((
L"Thread32First"
),
output
);
// show cause of failure
outputLastErrorHelper
((
L"Thread32First"
),
output
);
// show cause of failure
CloseHandle
(
hThreadSnap
);
// clean the snapshot object
CloseHandle
(
hThreadSnap
);
// clean the snapshot object
return
(
threads
);
return
(
threads
);
}
}
// Now walk the thread list of the system,
// Now walk the thread list of the system,
// and display information about each thread
// and display information about each thread
// associated with the specified process
// associated with the specified process
do
{
do
{
if
(
te32
.
th32OwnerProcessID
==
dwOwnerPID
)
{
if
(
te32
.
th32OwnerProcessID
==
dwOwnerPID
)
{
ProcessInfo
::
ThreadInfo
tinfo
;
ProcessInfo
::
ThreadInfo
tinfo
;
tinfo
.
tid
=
te32
.
th32ThreadID
;
tinfo
.
tid
=
te32
.
th32ThreadID
;
tinfo
.
base_priority
=
te32
.
tpBasePri
;
tinfo
.
base_priority
=
te32
.
tpBasePri
;
tinfo
.
delta_priority
=
te32
.
tpDeltaPri
;
tinfo
.
delta_priority
=
te32
.
tpDeltaPri
;
threads
.
emplace_back
(
tinfo
);
threads
.
emplace_back
(
tinfo
);
}
}
}
while
(
Thread32Next
(
hThreadSnap
,
&
te32
));
}
while
(
Thread32Next
(
hThreadSnap
,
&
te32
));
CloseHandle
(
hThreadSnap
);
CloseHandle
(
hThreadSnap
);
return
(
threads
);
return
(
threads
);
}
}
static
const
wchar_t
*
PROCESS_FILTER
[]
=
{
static
const
wchar_t
*
PROCESS_FILTER
[]
=
{
L"[System Process]"
,
L"[System Process]"
,
L"ApplicationFrameHost.exe"
,
L"ApplicationFrameHost.exe"
,
L"AppVShNotify.exe"
,
L"AppVShNotify.exe"
,
L"audiodg.exe"
,
L"audiodg.exe"
,
L"backgroundTaskHost.exe"
,
L"backgroundTaskHost.exe"
,
L"ChsIME.exe"
,
L"ChsIME.exe"
,
L"CompPkgSrv.exe"
,
L"CompPkgSrv.exe"
,
L"conhost.exe"
,
L"conhost.exe"
,
L"csrss.exe"
,
L"csrss.exe"
,
L"ctfmon.exe"
,
L"ctfmon.exe"
,
L"dasHost.exe"
,
L"dasHost.exe"
,
L"dllhost.exe"
,
L"dllhost.exe"
,
L"dwm.exe"
,
L"dwm.exe"
,
L"fontdrvhost.exe"
,
L"fontdrvhost.exe"
,
L"GameBarFTServer.exe"
,
L"GameBarFTServer.exe"
,
L"LockApp.exe"
,
L"LockApp.exe"
,
L"LogonUI.exe"
,
L"LogonUI.exe"
,
L"lsass.exe"
,
L"lsass.exe"
,
L"lsm.exe"
,
L"lsm.exe"
,
L"Memory Compression"
,
L"Memory Compression"
,
L"Microsoft.Photos.exe"
,
L"Microsoft.Photos.exe"
,
L"msdtc.exe"
,
L"msdtc.exe"
,
L"mstsc.exe"
,
L"mstsc.exe"
,
L"pacjsworker.exe"
,
L"pacjsworker.exe"
,
L"PresentationFontCache.exe"
,
L"PresentationFontCache.exe"
,
L"rdpclip.exe"
,
L"rdpclip.exe"
,
L"Registry"
,
L"Registry"
,
L"RemindersServer.exe"
,
L"RemindersServer.exe"
,
L"rundll32.exe"
,
L"rundll32.exe"
,
L"RuntimeBroker.exe"
,
L"RuntimeBroker.exe"
,
L"schtasks.exe"
,
L"schtasks.exe"
,
L"SearchFilterHost.exe"
,
L"SearchFilterHost.exe"
,
L"SearchIndexer.exe"
,
L"SearchIndexer.exe"
,
L"SearchProtocolHost.exe"
,
L"SearchProtocolHost.exe"
,
L"SearchUI.exe"
,
L"SearchUI.exe"
,
L"SecurityHealthService.exe"
,
L"SecurityHealthService.exe"
,
L"SecurityHealthSystray.exe"
,
L"SecurityHealthSystray.exe"
,
L"services.exe"
,
L"services.exe"
,
L"SettingSyncHost.exe"
,
L"SettingSyncHost.exe"
,
L"ShellExperienceHost.exe"
,
L"ShellExperienceHost.exe"
,
L"sihost.exe"
,
L"sihost.exe"
,
L"SkypeApp.exe"
,
L"SkypeApp.exe"
,
L"SkypeBackgroundHost.exe"
,
L"SkypeBackgroundHost.exe"
,
L"SkypeBridge.exe"
,
L"SkypeBridge.exe"
,
L"smartscreen.exe"
,
L"smartscreen.exe"
,
L"smss.exe"
,
L"smss.exe"
,
L"SgrmBroker.exe"
,
L"SgrmBroker.exe"
,
L"spoolsv.exe"
,
L"spoolsv.exe"
,
L"StartMenuExperienceHost.exe"
,
L"StartMenuExperienceHost.exe"
,
L"svchost.exe"
,
L"svchost.exe"
,
L"System"
,
L"System"
,
L"SystemSettingsBroker.exe"
,
L"SystemSettingsBroker.exe"
,
L"TabTip.exe"
,
L"TabTip.exe"
,
L"taskhost.exe"
,
L"taskhost.exe"
,
L"taskhostw.exe"
,
L"taskhostw.exe"
,
L"TiWorker.exe"
,
L"TiWorker.exe"
,
L"TrustedInstaller.exe"
,
L"TrustedInstaller.exe"
,
L"Video.UI.exe"
,
L"Video.UI.exe"
,
L"WindowsInternal.ComposableShell.Experiences.TextInput.InputApp.exe"
,
L"WindowsInternal.ComposableShell.Experiences.TextInput.InputApp.exe"
,
L"wininit.exe"
,
L"wininit.exe"
,
L"winlogon.exe"
,
L"winlogon.exe"
,
L"WinStore.App.exe"
,
L"WinStore.App.exe"
,
L"WmiPrvSE.exe"
,
L"WmiPrvSE.exe"
,
L"wmpnetwk.exe"
,
L"wmpnetwk.exe"
,
L"WUDFHost.exe"
,
L"WUDFHost.exe"
,
L"YourPhone.exe"
,
L"YourPhone.exe"
,
};
};
inline
ProcessInfos
getProcessesInfo
(
ErrorOutputFunc
output
=
dummyErrorOutputFunc
,
bool
withModules
=
false
,
bool
withThreads
=
false
,
const
wchar_t
**
filter
=
PROCESS_FILTER
,
size_t
filter_count
=
_countof
(
PROCESS_FILTER
))
inline
ProcessInfos
getProcessesInfo
(
ErrorOutputFunc
output
=
dummyErrorOutputFunc
,
bool
withModules
=
false
,
bool
withThreads
=
false
,
const
wchar_t
**
filter
=
PROCESS_FILTER
,
size_t
filter_count
=
_countof
(
PROCESS_FILTER
))
{
{
// pre-process filter
// pre-process filter
std
::
unordered_set
<
std
::
wstring
>
filterset
;
std
::
unordered_set
<
std
::
wstring
>
filterset
;
for
(
size_t
i
=
0
;
i
<
filter_count
;
i
++
)
{
for
(
size_t
i
=
0
;
i
<
filter_count
;
i
++
)
{
filterset
.
insert
(
filter
[
i
]);
filterset
.
insert
(
filter
[
i
]);
}
}
HANDLE
hProcessSnap
;
HANDLE
hProcessSnap
;
HANDLE
hProcess
;
HANDLE
hProcess
;
PROCESSENTRY32
pe32
;
PROCESSENTRY32
pe32
;
DWORD
dwPriorityClass
;
DWORD
dwPriorityClass
;
ProcessInfos
pinfos
=
{};
ProcessInfos
pinfos
=
{};
// Take a snapshot of all processes in the system.
// Take a snapshot of all processes in the system.
hProcessSnap
=
CreateToolhelp32Snapshot
(
TH32CS_SNAPPROCESS
,
0
);
hProcessSnap
=
CreateToolhelp32Snapshot
(
TH32CS_SNAPPROCESS
,
0
);
if
(
hProcessSnap
==
INVALID_HANDLE_VALUE
)
{
if
(
hProcessSnap
==
INVALID_HANDLE_VALUE
)
{
outputLastErrorHelper
(
L"CreateToolhelp32Snapshot (of processes)"
,
output
);
outputLastErrorHelper
(
L"CreateToolhelp32Snapshot (of processes)"
,
output
);
return
(
pinfos
);
return
(
pinfos
);
}
}
// Set the size of the structure before using it.
// Set the size of the structure before using it.
pe32
.
dwSize
=
sizeof
(
PROCESSENTRY32
);
pe32
.
dwSize
=
sizeof
(
PROCESSENTRY32
);
// Retrieve information about the first process,
// Retrieve information about the first process,
// and exit if unsuccessful
// and exit if unsuccessful
if
(
!
Process32First
(
hProcessSnap
,
&
pe32
))
{
if
(
!
Process32First
(
hProcessSnap
,
&
pe32
))
{
outputLastErrorHelper
((
L"Process32First"
),
output
);
// show cause of failure
outputLastErrorHelper
((
L"Process32First"
),
output
);
// show cause of failure
CloseHandle
(
hProcessSnap
);
// clean the snapshot object
CloseHandle
(
hProcessSnap
);
// clean the snapshot object
return
(
pinfos
);
return
(
pinfos
);
}
}
// Now walk the snapshot of processes, and
// Now walk the snapshot of processes, and
// display information about each process in turn
// display information about each process in turn
do
{
do
{
if
(
filterset
.
find
(
pe32
.
szExeFile
)
!=
filterset
.
end
())
{
continue
;
}
if
(
filterset
.
find
(
pe32
.
szExeFile
)
!=
filterset
.
end
())
{
continue
;
}
ProcessInfo
pinfo
=
{};
ProcessInfo
pinfo
=
{};
pinfo
.
name
=
pe32
.
szExeFile
;
pinfo
.
name
=
pe32
.
szExeFile
;
// Retrieve the priority class.
// Retrieve the priority class.
dwPriorityClass
=
0
;
dwPriorityClass
=
0
;
hProcess
=
OpenProcess
(
PROCESS_ALL_ACCESS
,
FALSE
,
pe32
.
th32ProcessID
);
hProcess
=
OpenProcess
(
PROCESS_ALL_ACCESS
,
FALSE
,
pe32
.
th32ProcessID
);
if
(
hProcess
==
NULL
)
if
(
hProcess
==
NULL
)
outputLastErrorHelper
((
L"OpenProcess"
),
output
);
outputLastErrorHelper
((
L"OpenProcess"
),
output
);
else
{
else
{
dwPriorityClass
=
GetPriorityClass
(
hProcess
);
dwPriorityClass
=
GetPriorityClass
(
hProcess
);
if
(
!
dwPriorityClass
)
if
(
!
dwPriorityClass
)
outputLastErrorHelper
((
L"GetPriorityClass"
),
output
);
outputLastErrorHelper
((
L"GetPriorityClass"
),
output
);
}
}
pinfo
.
pid
=
pe32
.
th32ProcessID
;
pinfo
.
pid
=
pe32
.
th32ProcessID
;
pinfo
.
ppid
=
pe32
.
th32ParentProcessID
;
pinfo
.
ppid
=
pe32
.
th32ParentProcessID
;
pinfo
.
thread_count
=
pe32
.
cntThreads
;
pinfo
.
thread_count
=
pe32
.
cntThreads
;
pinfo
.
priority_base
=
pe32
.
pcPriClassBase
;
pinfo
.
priority_base
=
pe32
.
pcPriClassBase
;
if
(
dwPriorityClass
)
{
if
(
dwPriorityClass
)
{
pinfo
.
priority_class
=
dwPriorityClass
;
pinfo
.
priority_class
=
dwPriorityClass
;
}
}
// List the modules and threads associated with this process
// List the modules and threads associated with this process
pinfo
.
modules
=
getProcessModules
(
pe32
.
th32ProcessID
,
output
);
pinfo
.
modules
=
getProcessModules
(
pe32
.
th32ProcessID
,
output
);
// try to get process exe path
// try to get process exe path
if
(
!
pinfo
.
modules
.
empty
())
{
if
(
!
pinfo
.
modules
.
empty
())
{
pinfo
.
path
=
pinfo
.
modules
.
front
().
path
;
pinfo
.
path
=
pinfo
.
modules
.
front
().
path
;
}
}
if
(
!
withModules
)
{
if
(
!
withModules
)
{
pinfo
.
modules
.
clear
();
pinfo
.
modules
.
clear
();
}
}
if
(
withThreads
)
{
if
(
withThreads
)
{
pinfo
.
threads
=
getProcessThreads
(
pe32
.
th32ProcessID
,
output
);
pinfo
.
threads
=
getProcessThreads
(
pe32
.
th32ProcessID
,
output
);
}
}
// try to get process exe path again
// try to get process exe path again
if
(
pinfo
.
path
.
empty
())
{
if
(
pinfo
.
path
.
empty
())
{
if
(
!
hProcess
)
{
if
(
!
hProcess
)
{
hProcess
=
OpenProcess
(
PROCESS_QUERY_LIMITED_INFORMATION
,
FALSE
,
pe32
.
th32ProcessID
);
hProcess
=
OpenProcess
(
PROCESS_QUERY_LIMITED_INFORMATION
,
FALSE
,
pe32
.
th32ProcessID
);
}
}
if
(
hProcess
)
{
if
(
hProcess
)
{
wchar_t
path
[
4096
];
DWORD
len
=
4096
;
wchar_t
path
[
4096
];
DWORD
len
=
4096
;
if
(
QueryFullProcessImageNameW
(
hProcess
,
0
,
path
,
&
len
))
{
if
(
QueryFullProcessImageNameW
(
hProcess
,
0
,
path
,
&
len
))
{
pinfo
.
path
=
path
;
pinfo
.
path
=
path
;
}
else
{
}
else
{
outputLastErrorHelper
(
L"QueryFullProcessImageNameW"
,
output
);
outputLastErrorHelper
(
L"QueryFullProcessImageNameW"
,
output
);
}
}
}
else
{
}
else
{
outputLastErrorHelper
(
L"OpenProcess"
,
output
);
outputLastErrorHelper
(
L"OpenProcess"
,
output
);
}
}
}
}
pinfos
.
emplace_back
(
pinfo
);
pinfos
.
emplace_back
(
pinfo
);
if
(
hProcess
){
CloseHandle
(
hProcess
);
}
if
(
hProcess
){
CloseHandle
(
hProcess
);
}
}
while
(
Process32Next
(
hProcessSnap
,
&
pe32
));
}
while
(
Process32Next
(
hProcessSnap
,
&
pe32
));
CloseHandle
(
hProcessSnap
);
CloseHandle
(
hProcessSnap
);
return
(
pinfos
);
return
(
pinfos
);
}
}
}
// namespace win32
}
// namespace win32
}
// namespace jlib
}
// namespace jlib
jlib/win32/rect.h
View file @
c9174ca4
#
pragma
once
#pragma once
#include <Windows.h>
#include <Windows.h>
#include <vector>
#include <vector>
namespace
jlib
namespace
jlib
{
{
namespace
win32
namespace
win32
{
{
inline
long
width
(
::
LPCRECT
rc
)
{
inline
long
width
(
::
LPCRECT
rc
)
{
return
rc
->
right
-
rc
->
left
;
return
rc
->
right
-
rc
->
left
;
}
}
inline
long
height
(
::
LPCRECT
rc
)
{
inline
long
height
(
::
LPCRECT
rc
)
{
return
rc
->
bottom
-
rc
->
top
;
return
rc
->
bottom
-
rc
->
top
;
}
}
inline
void
deflateRect
(
::
LPRECT
rc
,
int
l
,
int
t
,
int
r
,
int
b
)
{
inline
void
deflateRect
(
::
LPRECT
rc
,
int
l
,
int
t
,
int
r
,
int
b
)
{
rc
->
left
+=
l
;
rc
->
left
+=
l
;
rc
->
top
+=
t
;
rc
->
top
+=
t
;
rc
->
right
-=
r
;
rc
->
right
-=
r
;
rc
->
bottom
-=
b
;
rc
->
bottom
-=
b
;
}
}
inline
void
inflateRect
(
::
LPRECT
rc
,
int
l
,
int
t
,
int
r
,
int
b
)
{
inline
void
inflateRect
(
::
LPRECT
rc
,
int
l
,
int
t
,
int
r
,
int
b
)
{
rc
->
left
-=
l
;
rc
->
left
-=
l
;
rc
->
top
-=
t
;
rc
->
top
-=
t
;
rc
->
right
+=
r
;
rc
->
right
+=
r
;
rc
->
bottom
+=
b
;
rc
->
bottom
+=
b
;
}
}
//! 将矩形平均分割成 n 份,间距 2*gap, n 必须是平方数 x^2, x={1,2,3...}
//! 将矩形平均分割成 n 份,间距 2*gap, n 必须是平方数 x^2, x={1,2,3...}
inline
std
::
vector
<::
RECT
>
splitRect
(
::
LPCRECT
rc
,
int
n
,
int
gap
=
50
)
{
inline
std
::
vector
<::
RECT
>
splitRect
(
::
LPCRECT
rc
,
int
n
,
int
gap
=
50
)
{
std
::
vector
<::
RECT
>
v
;
std
::
vector
<::
RECT
>
v
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
v
.
push_back
(
*
rc
);
v
.
push_back
(
*
rc
);
}
}
double
l
=
sqrt
(
n
);
double
l
=
sqrt
(
n
);
int
line
=
int
(
l
);
int
line
=
int
(
l
);
int
col_step
=
(
int
)(
width
(
rc
)
/
line
);
int
col_step
=
(
int
)(
width
(
rc
)
/
line
);
int
row_step
=
(
int
)(
height
(
rc
)
/
line
);
int
row_step
=
(
int
)(
height
(
rc
)
/
line
);
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
v
[
i
].
left
=
rc
->
left
+
(
i
%
line
)
*
col_step
;
v
[
i
].
left
=
rc
->
left
+
(
i
%
line
)
*
col_step
;
v
[
i
].
right
=
v
[
i
].
left
+
col_step
;
v
[
i
].
right
=
v
[
i
].
left
+
col_step
;
v
[
i
].
top
=
rc
->
top
+
(
i
/
line
)
*
row_step
;
v
[
i
].
top
=
rc
->
top
+
(
i
/
line
)
*
row_step
;
v
[
i
].
bottom
=
v
[
i
].
top
+
row_step
;
v
[
i
].
bottom
=
v
[
i
].
top
+
row_step
;
deflateRect
(
&
v
[
i
],
gap
,
gap
,
gap
,
gap
);
deflateRect
(
&
v
[
i
],
gap
,
gap
,
gap
,
gap
);
}
}
return
v
;
return
v
;
};
};
//! 将矩形水平平均分割为 n 份矩形, 当 hgap == -1 时,分割出的矩形与源矩形保持比例
//! 将矩形水平平均分割为 n 份矩形, 当 hgap == -1 时,分割出的矩形与源矩形保持比例
inline
std
::
vector
<::
RECT
>
split_rect_horizontal
(
::
LPCRECT
rc
,
int
n
,
int
wgap
=
50
,
int
hgap
=
-
1
)
{
inline
std
::
vector
<::
RECT
>
split_rect_horizontal
(
::
LPCRECT
rc
,
int
n
,
int
wgap
=
50
,
int
hgap
=
-
1
)
{
std
::
vector
<::
RECT
>
v
;
std
::
vector
<::
RECT
>
v
;
int
w
=
(
width
(
rc
)
-
(
n
+
1
)
*
wgap
)
/
n
;
int
w
=
(
width
(
rc
)
-
(
n
+
1
)
*
wgap
)
/
n
;
if
(
hgap
==
-
1
)
{
if
(
hgap
==
-
1
)
{
double
ratio
=
(
rc
->
right
-
rc
->
left
)
*
1
.
0
/
(
rc
->
bottom
-
rc
->
top
);
double
ratio
=
(
rc
->
right
-
rc
->
left
)
*
1
.
0
/
(
rc
->
bottom
-
rc
->
top
);
int
h
=
static_cast
<
int
>
(
w
/
ratio
);
int
h
=
static_cast
<
int
>
(
w
/
ratio
);
hgap
=
(
height
(
rc
)
-
h
)
/
2
;
hgap
=
(
height
(
rc
)
-
h
)
/
2
;
}
}
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
::
RECT
r
=
*
rc
;
::
RECT
r
=
*
rc
;
r
.
left
+=
i
*
w
+
(
i
+
1
)
*
wgap
;
r
.
left
+=
i
*
w
+
(
i
+
1
)
*
wgap
;
r
.
right
=
r
.
left
+
w
;
r
.
right
=
r
.
left
+
w
;
r
.
top
=
rc
->
top
+
hgap
;
r
.
top
=
rc
->
top
+
hgap
;
r
.
bottom
=
rc
->
bottom
-
hgap
;
r
.
bottom
=
rc
->
bottom
-
hgap
;
v
.
push_back
(
r
);
v
.
push_back
(
r
);
}
}
return
v
;
return
v
;
}
}
/**
/**
* @brief 从矩形内获取六边形顶点
* @brief 从矩形内获取六边形顶点
* @param rc 矩形
* @param rc 矩形
* @param spliter 六边形的边长是矩形边长的 1/spliter
* @param spliter 六边形的边长是矩形边长的 1/spliter
* @note rc's width / spliter = (rc's width - hexagon's side length) / 2
* @note rc's width / spliter = (rc's width - hexagon's side length) / 2
* @return 六边形的六个顶点坐标,从上边左侧点顺时针排列
* @return 六边形的六个顶点坐标,从上边左侧点顺时针排列
*/
*/
inline
std
::
vector
<::
POINT
>
getHexagonVertexesFromRect
(
::
LPCRECT
rc
,
float
spliter
=
3
.
0
)
{
inline
std
::
vector
<::
POINT
>
getHexagonVertexesFromRect
(
::
LPCRECT
rc
,
float
spliter
=
3
.
0
)
{
if
(
!
rc
)
{
return
std
::
vector
<::
POINT
>
();
}
if
(
!
rc
)
{
return
std
::
vector
<::
POINT
>
();
}
if
(
spliter
==
0
.
0
)
{
spliter
=
3
.
0
;
}
if
(
spliter
==
0
.
0
)
{
spliter
=
3
.
0
;
}
std
::
vector
<::
POINT
>
v
;
std
::
vector
<::
POINT
>
v
;
auto
w
=
rc
->
right
-
rc
->
left
;
auto
w
=
rc
->
right
-
rc
->
left
;
auto
h
=
rc
->
bottom
-
rc
->
top
;
auto
h
=
rc
->
bottom
-
rc
->
top
;
auto
ww
=
static_cast
<
int
>
(
w
/
spliter
);
auto
ww
=
static_cast
<
int
>
(
w
/
spliter
);
auto
hh
=
static_cast
<
int
>
(
h
/
spliter
);
auto
hh
=
static_cast
<
int
>
(
h
/
spliter
);
::
POINT
pt
;
::
POINT
pt
;
pt
.
x
=
rc
->
left
;
pt
.
x
=
rc
->
left
;
pt
.
y
=
rc
->
top
+
hh
;
pt
.
y
=
rc
->
top
+
hh
;
v
.
push_back
(
pt
);
v
.
push_back
(
pt
);
pt
.
x
=
rc
->
left
+
ww
;
pt
.
x
=
rc
->
left
+
ww
;
pt
.
y
=
rc
->
top
;
pt
.
y
=
rc
->
top
;
v
.
push_back
(
pt
);
v
.
push_back
(
pt
);
pt
.
x
=
rc
->
right
-
ww
;
pt
.
x
=
rc
->
right
-
ww
;
v
.
push_back
(
pt
);
v
.
push_back
(
pt
);
pt
.
x
=
rc
->
right
;
pt
.
x
=
rc
->
right
;
pt
.
y
=
rc
->
top
+
hh
;
pt
.
y
=
rc
->
top
+
hh
;
v
.
push_back
(
pt
);
v
.
push_back
(
pt
);
pt
.
y
=
rc
->
bottom
-
hh
;
pt
.
y
=
rc
->
bottom
-
hh
;
v
.
push_back
(
pt
);
v
.
push_back
(
pt
);
pt
.
x
=
rc
->
right
-
ww
;
pt
.
x
=
rc
->
right
-
ww
;
pt
.
y
=
rc
->
bottom
;
pt
.
y
=
rc
->
bottom
;
v
.
push_back
(
pt
);
v
.
push_back
(
pt
);
pt
.
x
=
rc
->
left
+
ww
;
pt
.
x
=
rc
->
left
+
ww
;
v
.
push_back
(
pt
);
v
.
push_back
(
pt
);
pt
.
x
=
rc
->
left
;
pt
.
x
=
rc
->
left
;
pt
.
y
=
rc
->
bottom
-
hh
;
pt
.
y
=
rc
->
bottom
-
hh
;
v
.
push_back
(
pt
);
v
.
push_back
(
pt
);
return
v
;
return
v
;
}
}
}
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment