Improved updater UI
This commit is contained in:
parent
5433bc55f4
commit
185f70182a
@ -9,10 +9,14 @@ set(SOURCE_FILES
|
||||
file.cpp
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
list(APPEND SOURCE_FILES win32/retry_ui.cpp win32/Resource.rc)
|
||||
endif ()
|
||||
|
||||
add_executable(update_installer ${SOURCE_FILES})
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(update_installer kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;Shlwapi.lib)
|
||||
target_link_libraries(update_installer kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;Shlwapi.lib;Rstrtmgr.lib)
|
||||
|
||||
add_custom_command(TARGET update_installer POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E
|
||||
|
@ -3,10 +3,12 @@
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
#include "logger.h"
|
||||
#include "config.h"
|
||||
#include "util.h"
|
||||
#include "file.h"
|
||||
#include "./logger.h"
|
||||
#include "./config.h"
|
||||
#include "./util.h"
|
||||
#include "./file.h"
|
||||
|
||||
#include "./ui.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace log_helper;
|
||||
@ -116,7 +118,7 @@ int main(int argc, char** argv) {
|
||||
{
|
||||
auto admin = is_administrator();
|
||||
logger::info("App executed as admin: %s", admin ? "yes" : "no");
|
||||
if(!admin) {
|
||||
if(!admin && false) {
|
||||
logger::info("Requesting administrator rights");
|
||||
if(!request_administrator(argc, argv)) {
|
||||
execute_callback_fail_exit("permissions", "failed to get administrator permissions");
|
||||
@ -137,20 +139,24 @@ int main(int argc, char** argv) {
|
||||
|
||||
{
|
||||
logger::info("Awaiting the unlocking of all files");
|
||||
await_unlock:
|
||||
auto begin = chrono::system_clock::now();
|
||||
while(true) {
|
||||
bool locked = false;
|
||||
for(shared_ptr<config::LockFile>& file : config::locking_files) {
|
||||
if(file::file_locked(file->filename)) {
|
||||
locked = true;
|
||||
if(chrono::system_clock::now() - chrono::milliseconds(file->timeout) > begin) {
|
||||
if(chrono::system_clock::now() - std::chrono::milliseconds{1000} > begin) { /* we don't use the lock timeout here because we've a new system */
|
||||
auto result = ui::open_file_blocked(file->filename);
|
||||
if(result == ui::FileBlockedResult::PROCESSES_CLOSED)
|
||||
goto await_unlock;
|
||||
logger::fatal(
|
||||
"Failed to lock file %s. Timeout: %d, Time tried: %d",
|
||||
file->filename.c_str(),
|
||||
file->timeout,
|
||||
chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now() - begin).count()
|
||||
);
|
||||
execute_callback_fail_exit(file->error_id, "lock timeout (" + to_string(file->timeout) + ")");
|
||||
execute_callback_fail_exit(file->error_id, "failed to lock file");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,11 @@
|
||||
"callback_file": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
|
||||
"callback_argument_fail": "-EncodedCommand \"QQBkAGQALQBUAHkAcABlACAALQBBAHMAcwBlAG0AYgBsAHkATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVwBpAG4AZABvAHcAcwAuAEYAbwByAG0AcwA7ACAAWwBTAHkAcwB0AGUAbQAuAFcAaQBuAGQAbwB3AHMALgBGAG8AcgBtAHMALgBNAGUAcwBzAGEAZwBlAEIAbwB4AF0AOgA6AFMAaABvAHcAKAAiAFUAcABkAGEAdABlACAAZgBhAGkAbABlAGQAIgAsACIAVQBwAGQAYQB0AGUAcgAiACwAMAApAA==\"",
|
||||
"callback_argument_success": "-EncodedCommand \"QQBkAGQALQBUAHkAcABlACAALQBBAHMAcwBlAG0AYgBsAHkATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVwBpAG4AZABvAHcAcwAuAEYAbwByAG0AcwA7ACAAWwBTAHkAcwB0AGUAbQAuAFcAaQBuAGQAbwB3AHMALgBGAG8AcgBtAHMALgBNAGUAcwBzAGEAZwBlAEIAbwB4AF0AOgA6AFMAaABvAHcAKAAiAFUAcABkAGEAdABlACAAcwB1AGMAYwBlAGUAZABlAGQAIgAsACIAVQBwAGQAYQB0AGUAcgAiACwAMAApAA==\"",
|
||||
"locks": [
|
||||
|
||||
],
|
||||
"locks": [{
|
||||
"filename": "D:\\Program Files\\IDA 7.0\\ida.exe",
|
||||
"timeout": 5000,
|
||||
"error-id": "Hello World error"
|
||||
}],
|
||||
"moves": [
|
||||
{
|
||||
"source": "source/file_new.txt",
|
||||
|
0
native/updater/test/lock_file.txt
Normal file
0
native/updater/test/lock_file.txt
Normal file
@ -355,3 +355,268 @@
|
||||
[2] Update unpacking successfully!
|
||||
[2] executing callback file C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe with success with command line C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -EncodedCommand "QQBkAGQALQBUAHkAcABlACAALQBBAHMAcwBlAG0AYgBsAHkATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVwBpAG4AZABvAHcAcwAuAEYAbwByAG0AcwA7ACAAWwBTAHkAcwB0AGUAbQAuAFcAaQBuAGQAbwB3AHMALgBGAG8AcgBtAHMALgBNAGUAcwBzAGEAZwBlAEIAbwB4AF0AOgA6AFMAaABvAHcAKAAiAFUAcABkAGEAdABlACAAcwB1AGMAYwBlAGUAZABlAGQAIgAsACIAVQBwAGQAYQB0AGUAcgAiACwAMAApAA==" bG9nX2ZpbGU6ZFhCa1lYUmxMbXh2Wnc9PQ==
|
||||
[2] ----------- log ended at 2019-04-16.16:46:25 -----------
|
||||
[523F][2] ----------- log started at 2020-04-22.19:51:40 -----------
|
||||
[523F][2] App executed as admin: no
|
||||
[523F][2] Requesting administrator rights
|
||||
[523F][2] Admin right granted. New updater instance executes the update now.
|
||||
[523F][2] ----------- log ended at 2020-04-22.19:51:43 -----------
|
||||
[3DC4][2] ----------- log started at 2020-04-22.19:51:43 -----------
|
||||
[3DC4][2] App executed as admin: yes
|
||||
[3DC4][2] loading config from file updater\test\dummy_config.json
|
||||
[3DC4][5] failed to load config: failed to get key error-id. error: [json.exception.type_error.305] cannot use operator[] with a string argument with string
|
||||
[3DC4][2] ----------- log ended at 2020-04-22.19:51:43 -----------
|
||||
[39EE][2] ----------- log started at 2020-04-22.19:52:35 -----------
|
||||
[39EE][2] App executed as admin: no
|
||||
[39EE][2] Requesting administrator rights
|
||||
[39EE][2] Admin right granted. New updater instance executes the update now.
|
||||
[39EE][2] ----------- log ended at 2020-04-22.19:52:38 -----------
|
||||
[52B2][2] ----------- log started at 2020-04-22.19:52:38 -----------
|
||||
[52B2][2] App executed as admin: yes
|
||||
[52B2][2] loading config from file updater\test\dummy_config.json
|
||||
[52B2][5] failed to load config: failed to get key error-id. error: [json.exception.type_error.305] cannot use operator[] with a string argument with string
|
||||
[52B2][2] ----------- log ended at 2020-04-22.19:52:38 -----------
|
||||
[35F3][2] ----------- log started at 2020-04-22.19:52:47 -----------
|
||||
[35F3][2] App executed as admin: no
|
||||
[35F3][2] Requesting administrator rights
|
||||
[35F3][2] Admin right granted. New updater instance executes the update now.
|
||||
[35F3][2] ----------- log ended at 2020-04-22.19:52:49 -----------
|
||||
[64D5][2] ----------- log started at 2020-04-22.19:52:49 -----------
|
||||
[64D5][2] App executed as admin: yes
|
||||
[64D5][2] loading config from file updater\test\dummy_config.json
|
||||
[64D5][5] failed to load config: failed to get key error-id. error: [json.exception.type_error.305] cannot use operator[] with a string argument with string
|
||||
[64D5][2] ----------- log ended at 2020-04-22.19:52:49 -----------
|
||||
[65B6][2] ----------- log started at 2020-04-22.19:52:51 -----------
|
||||
[65B6][2] App executed as admin: no
|
||||
[65B6][2] Requesting administrator rights
|
||||
[65B6][5] callback file () is not executable! Ignoring fail callback
|
||||
[65B6][2] ----------- log ended at 2020-04-22.19:52:53 -----------
|
||||
[59A3][2] ----------- log started at 2020-04-22.19:53:00 -----------
|
||||
[59A3][2] App executed as admin: no
|
||||
[59A3][2] loading config from file updater\test\dummy_config.json
|
||||
[59A3][5] failed to load config: failed to get key error-id. error: [json.exception.type_error.305] cannot use operator[] with a string argument with string
|
||||
[59A3][2] ----------- log ended at 2020-04-22.19:53:00 -----------
|
||||
[370F][2] ----------- log started at 2020-04-22.19:53:43 -----------
|
||||
[370F][2] App executed as admin: no
|
||||
[370F][2] loading config from file updater\test\dummy_config.json
|
||||
[370F][5] failed to load config: failed to get key error-id. error: [json.exception.type_error.302] type must be string, but is null
|
||||
[370F][2] ----------- log ended at 2020-04-22.19:53:43 -----------
|
||||
[65DD][2] ----------- log started at 2020-04-22.19:53:45 -----------
|
||||
[65DD][2] App executed as admin: no
|
||||
[65DD][2] loading config from file updater\test\dummy_config.json
|
||||
[65DD][5] failed to load config: failed to get key error-id. error: [json.exception.type_error.302] type must be string, but is null
|
||||
[65DD][2] ----------- log ended at 2020-04-22.19:53:45 -----------
|
||||
[4225][2] ----------- log started at 2020-04-22.19:55:34 -----------
|
||||
[4225][2] App executed as admin: no
|
||||
[4225][2] loading config from file updater\test\dummy_config.json
|
||||
[4225][1] Loaded 1 locking actions and 1 moving actions
|
||||
[4225][2] Awaiting the unlocking of all files
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[4225][5] Failed to lock file lock_file.txt. Timeout: 5000, Time tried: 7941
|
||||
[4225][2] Rollbacking 0 moved files
|
||||
[4225][2] Rollbacking 0 deleted files
|
||||
[4225][2] Rollback done
|
||||
[4225][2] executing callback file C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe with fail command line C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -EncodedCommand "QQBkAGQALQBUAHkAcABlACAALQBBAHMAcwBlAG0AYgBsAHkATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVwBpAG4AZABvAHcAcwAuAEYAbwByAG0AcwA7ACAAWwBTAHkAcwB0AGUAbQAuAFcAaQBuAGQAbwB3AHMALgBGAG8AcgBtAHMALgBNAGUAcwBzAGEAZwBlAEIAbwB4AF0AOgA6AFMAaABvAHcAKAAiAFUAcABkAGEAdABlACAAZgBhAGkAbABlAGQAIgAsACIAVQBwAGQAYQB0AGUAcgAiACwAMAApAA=="bG9nX2ZpbGU6ZFhCa1lYUmxjbHgwWlhOMFhIVndaR0YwWlM1c2IyYz07ZXJyb3JfaWQ6U0dWc2JHOGdWMjl5YkdRZ1pYSnliM0k9O2Vycm9yX21lc3NhZ2U6Ykc5amF5QjBhVzFsYjNWMElDZzFNREF3S1E9PQ==
|
||||
[4225][2] ----------- log ended at 2020-04-22.19:55:50 -----------
|
||||
[3BB5][2] ----------- log started at 2020-04-22.19:56:36 -----------
|
||||
[3BB5][2] App executed as admin: no
|
||||
[3BB5][2] loading config from file updater\test\dummy_config.json
|
||||
[3BB5][1] Loaded 1 locking actions and 1 moving actions
|
||||
[3BB5][2] Awaiting the unlocking of all files
|
||||
[3BB5][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[3BB5][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[3BB5][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[3BB5][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[3BB5][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[3BB5][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[3BB5][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[3BB5][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[3BB5][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[3BB5][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[3BB5][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[3BB5][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[3BB5][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[3BB5][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[3BB5][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[3BB5][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[3BB5][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[3BB5][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[3BB5][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[3BB5][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[3BB5][2] Failed to open file! (The system cannot find the file specified.) (2)
|
||||
[3BB5][5] Failed to lock file lock_file.txt. Timeout: 5000, Time tried: 8660
|
||||
[3BB5][2] Rollbacking 0 moved files
|
||||
[3BB5][2] Rollbacking 0 deleted files
|
||||
[3BB5][2] Rollback done
|
||||
[3BB5][2] executing callback file C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe with fail command line C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -EncodedCommand "QQBkAGQALQBUAHkAcABlACAALQBBAHMAcwBlAG0AYgBsAHkATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVwBpAG4AZABvAHcAcwAuAEYAbwByAG0AcwA7ACAAWwBTAHkAcwB0AGUAbQAuAFcAaQBuAGQAbwB3AHMALgBGAG8AcgBtAHMALgBNAGUAcwBzAGEAZwBlAEIAbwB4AF0AOgA6AFMAaABvAHcAKAAiAFUAcABkAGEAdABlACAAZgBhAGkAbABlAGQAIgAsACIAVQBwAGQAYQB0AGUAcgAiACwAMAApAA=="bG9nX2ZpbGU6ZFhCa1lYUmxjbHgwWlhOMFhIVndaR0YwWlM1c2IyYz07ZXJyb3JfaWQ6U0dWc2JHOGdWMjl5YkdRZ1pYSnliM0k9O2Vycm9yX21lc3NhZ2U6Ykc5amF5QjBhVzFsYjNWMElDZzFNREF3S1E9PQ==
|
||||
[3BB5][2] ----------- log ended at 2020-04-22.19:56:44 -----------
|
||||
[6DF9][2] ----------- log started at 2020-04-22.19:57:03 -----------
|
||||
[6DF9][2] App executed as admin: no
|
||||
[6DF9][2] loading config from file updater\test\dummy_config.json
|
||||
[6DF9][1] Loaded 1 locking actions and 1 moving actions
|
||||
[6DF9][2] Awaiting the unlocking of all files
|
||||
[6DF9][2] All files have been unlocked (0ms required)
|
||||
[6DF9][2] Moving file from source/file_new.txt to target/file.txt
|
||||
[6DF9][5] failed to move file source/file_new.txt to target/file.txt (source file does not exists)
|
||||
[6DF9][2] Rollbacking 0 moved files
|
||||
[6DF9][2] Rollbacking 0 deleted files
|
||||
[6DF9][2] Rollback done
|
||||
[6DF9][2] executing callback file C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe with fail command line C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -EncodedCommand "QQBkAGQALQBUAHkAcABlACAALQBBAHMAcwBlAG0AYgBsAHkATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVwBpAG4AZABvAHcAcwAuAEYAbwByAG0AcwA7ACAAWwBTAHkAcwB0AGUAbQAuAFcAaQBuAGQAbwB3AHMALgBGAG8AcgBtAHMALgBNAGUAcwBzAGEAZwBlAEIAbwB4AF0AOgA6AFMAaABvAHcAKAAiAFUAcABkAGEAdABlACAAZgBhAGkAbABlAGQAIgAsACIAVQBwAGQAYQB0AGUAcgAiACwAMAApAA=="bG9nX2ZpbGU6ZFhCa1lYUmxjbHgwWlhOMFhIVndaR0YwWlM1c2IyYz07ZXJyb3JfaWQ6TURBd01RPT07ZXJyb3JfbWVzc2FnZTpjMjkxY21ObElHWnBiR1VnWkc5bGN5QnViM1FnWlhocGMzUno=
|
||||
[6DF9][2] ----------- log ended at 2020-04-22.19:57:03 -----------
|
||||
[2B0D][2] ----------- log started at 2020-04-22.19:57:18 -----------
|
||||
[2B0D][2] App executed as admin: no
|
||||
[2B0D][2] loading config from file updater\test\dummy_config.json
|
||||
[2B0D][1] Loaded 1 locking actions and 1 moving actions
|
||||
[2B0D][2] Awaiting the unlocking of all files
|
||||
[2B0D][2] All files have been unlocked (0ms required)
|
||||
[2B0D][2] Moving file from source/file_new.txt to target/file.txt
|
||||
[2B0D][5] failed to move file source/file_new.txt to target/file.txt (source file does not exists)
|
||||
[2B0D][2] Rollbacking 0 moved files
|
||||
[2B0D][2] Rollbacking 0 deleted files
|
||||
[2B0D][2] Rollback done
|
||||
[2B0D][2] executing callback file C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe with fail command line C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -EncodedCommand "QQBkAGQALQBUAHkAcABlACAALQBBAHMAcwBlAG0AYgBsAHkATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVwBpAG4AZABvAHcAcwAuAEYAbwByAG0AcwA7ACAAWwBTAHkAcwB0AGUAbQAuAFcAaQBuAGQAbwB3AHMALgBGAG8AcgBtAHMALgBNAGUAcwBzAGEAZwBlAEIAbwB4AF0AOgA6AFMAaABvAHcAKAAiAFUAcABkAGEAdABlACAAZgBhAGkAbABlAGQAIgAsACIAVQBwAGQAYQB0AGUAcgAiACwAMAApAA=="bG9nX2ZpbGU6ZFhCa1lYUmxjbHgwWlhOMFhIVndaR0YwWlM1c2IyYz07ZXJyb3JfaWQ6TURBd01RPT07ZXJyb3JfbWVzc2FnZTpjMjkxY21ObElHWnBiR1VnWkc5bGN5QnViM1FnWlhocGMzUno=
|
||||
[2B0D][2] ----------- log ended at 2020-04-22.19:57:18 -----------
|
||||
[79AD][2] ----------- log started at 2020-04-22.19:57:34 -----------
|
||||
[79AD][2] App executed as admin: no
|
||||
[79AD][2] loading config from file updater\test\dummy_config.json
|
||||
[79AD][1] Loaded 1 locking actions and 1 moving actions
|
||||
[79AD][2] Awaiting the unlocking of all files
|
||||
[79AD][2] All files have been unlocked (0ms required)
|
||||
[79AD][2] Moving file from source/file_new.txt to target/file.txt
|
||||
[79AD][5] failed to move file source/file_new.txt to target/file.txt (source file does not exists)
|
||||
[79AD][2] Rollbacking 0 moved files
|
||||
[79AD][2] Rollbacking 0 deleted files
|
||||
[79AD][2] Rollback done
|
||||
[79AD][2] executing callback file C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe with fail command line C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -EncodedCommand "QQBkAGQALQBUAHkAcABlACAALQBBAHMAcwBlAG0AYgBsAHkATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVwBpAG4AZABvAHcAcwAuAEYAbwByAG0AcwA7ACAAWwBTAHkAcwB0AGUAbQAuAFcAaQBuAGQAbwB3AHMALgBGAG8AcgBtAHMALgBNAGUAcwBzAGEAZwBlAEIAbwB4AF0AOgA6AFMAaABvAHcAKAAiAFUAcABkAGEAdABlACAAZgBhAGkAbABlAGQAIgAsACIAVQBwAGQAYQB0AGUAcgAiACwAMAApAA=="bG9nX2ZpbGU6ZFhCa1lYUmxjbHgwWlhOMFhIVndaR0YwWlM1c2IyYz07ZXJyb3JfaWQ6TURBd01RPT07ZXJyb3JfbWVzc2FnZTpjMjkxY21ObElHWnBiR1VnWkc5bGN5QnViM1FnWlhocGMzUno=
|
||||
[79AD][2] ----------- log ended at 2020-04-22.19:57:34 -----------
|
||||
[5665][2] ----------- log started at 2020-04-22.19:57:35 -----------
|
||||
[5665][2] App executed as admin: no
|
||||
[5665][2] loading config from file updater\test\dummy_config.json
|
||||
[5665][1] Loaded 1 locking actions and 1 moving actions
|
||||
[5665][2] Awaiting the unlocking of all files
|
||||
[5665][2] All files have been unlocked (0ms required)
|
||||
[5665][2] Moving file from source/file_new.txt to target/file.txt
|
||||
[5665][5] failed to move file source/file_new.txt to target/file.txt (source file does not exists)
|
||||
[5665][2] Rollbacking 0 moved files
|
||||
[5665][2] Rollbacking 0 deleted files
|
||||
[5665][2] Rollback done
|
||||
[5665][2] executing callback file C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe with fail command line C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -EncodedCommand "QQBkAGQALQBUAHkAcABlACAALQBBAHMAcwBlAG0AYgBsAHkATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVwBpAG4AZABvAHcAcwAuAEYAbwByAG0AcwA7ACAAWwBTAHkAcwB0AGUAbQAuAFcAaQBuAGQAbwB3AHMALgBGAG8AcgBtAHMALgBNAGUAcwBzAGEAZwBlAEIAbwB4AF0AOgA6AFMAaABvAHcAKAAiAFUAcABkAGEAdABlACAAZgBhAGkAbABlAGQAIgAsACIAVQBwAGQAYQB0AGUAcgAiACwAMAApAA=="bG9nX2ZpbGU6ZFhCa1lYUmxjbHgwWlhOMFhIVndaR0YwWlM1c2IyYz07ZXJyb3JfaWQ6TURBd01RPT07ZXJyb3JfbWVzc2FnZTpjMjkxY21ObElHWnBiR1VnWkc5bGN5QnViM1FnWlhocGMzUno=
|
||||
[5665][2] ----------- log ended at 2020-04-22.19:57:35 -----------
|
||||
[0A74][2] ----------- log started at 2020-04-22.19:57:43 -----------
|
||||
[0A74][2] App executed as admin: no
|
||||
[0A74][2] loading config from file updater\test\dummy_config.json
|
||||
[0A74][1] Loaded 1 locking actions and 1 moving actions
|
||||
[0A74][2] Awaiting the unlocking of all files
|
||||
[0A74][2] All files have been unlocked (0ms required)
|
||||
[0A74][2] Moving file from source/file_new.txt to target/file.txt
|
||||
[0A74][5] failed to move file source/file_new.txt to target/file.txt (source file does not exists)
|
||||
[0A74][2] Rollbacking 0 moved files
|
||||
[0A74][2] Rollbacking 0 deleted files
|
||||
[0A74][2] Rollback done
|
||||
[0A74][2] executing callback file C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe with fail command line C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -EncodedCommand "QQBkAGQALQBUAHkAcABlACAALQBBAHMAcwBlAG0AYgBsAHkATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVwBpAG4AZABvAHcAcwAuAEYAbwByAG0AcwA7ACAAWwBTAHkAcwB0AGUAbQAuAFcAaQBuAGQAbwB3AHMALgBGAG8AcgBtAHMALgBNAGUAcwBzAGEAZwBlAEIAbwB4AF0AOgA6AFMAaABvAHcAKAAiAFUAcABkAGEAdABlACAAZgBhAGkAbABlAGQAIgAsACIAVQBwAGQAYQB0AGUAcgAiACwAMAApAA=="bG9nX2ZpbGU6ZFhCa1lYUmxjbHgwWlhOMFhIVndaR0YwWlM1c2IyYz07ZXJyb3JfaWQ6TURBd01RPT07ZXJyb3JfbWVzc2FnZTpjMjkxY21ObElHWnBiR1VnWkc5bGN5QnViM1FnWlhocGMzUno=
|
||||
[0A74][2] ----------- log ended at 2020-04-22.19:57:43 -----------
|
||||
[4337][2] ----------- log started at 2020-04-22.19:57:44 -----------
|
||||
[4337][2] App executed as admin: no
|
||||
[4337][2] loading config from file updater\test\dummy_config.json
|
||||
[4337][1] Loaded 1 locking actions and 1 moving actions
|
||||
[4337][2] Awaiting the unlocking of all files
|
||||
[4337][2] All files have been unlocked (0ms required)
|
||||
[4337][2] Moving file from source/file_new.txt to target/file.txt
|
||||
[4337][5] failed to move file source/file_new.txt to target/file.txt (source file does not exists)
|
||||
[4337][2] Rollbacking 0 moved files
|
||||
[4337][2] Rollbacking 0 deleted files
|
||||
[4337][2] Rollback done
|
||||
[4337][2] executing callback file C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe with fail command line C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -EncodedCommand "QQBkAGQALQBUAHkAcABlACAALQBBAHMAcwBlAG0AYgBsAHkATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVwBpAG4AZABvAHcAcwAuAEYAbwByAG0AcwA7ACAAWwBTAHkAcwB0AGUAbQAuAFcAaQBuAGQAbwB3AHMALgBGAG8AcgBtAHMALgBNAGUAcwBzAGEAZwBlAEIAbwB4AF0AOgA6AFMAaABvAHcAKAAiAFUAcABkAGEAdABlACAAZgBhAGkAbABlAGQAIgAsACIAVQBwAGQAYQB0AGUAcgAiACwAMAApAA=="bG9nX2ZpbGU6ZFhCa1lYUmxjbHgwWlhOMFhIVndaR0YwWlM1c2IyYz07ZXJyb3JfaWQ6TURBd01RPT07ZXJyb3JfbWVzc2FnZTpjMjkxY21ObElHWnBiR1VnWkc5bGN5QnViM1FnWlhocGMzUno=
|
||||
[4337][2] ----------- log ended at 2020-04-22.19:57:44 -----------
|
||||
[5F3A][2] ----------- log started at 2020-04-22.19:59:41 -----------
|
||||
[5F3A][2] App executed as admin: no
|
||||
[5F3A][2] loading config from file updater\test\dummy_config.json
|
||||
[5F3A][1] Loaded 1 locking actions and 1 moving actions
|
||||
[5F3A][2] Awaiting the unlocking of all files
|
||||
[5F3A][2] All files have been unlocked (0ms required)
|
||||
[5F3A][2] Moving file from source/file_new.txt to target/file.txt
|
||||
[5F3A][5] failed to move file source/file_new.txt to target/file.txt (source file does not exists)
|
||||
[5F3A][2] Rollbacking 0 moved files
|
||||
[5F3A][2] Rollbacking 0 deleted files
|
||||
[5F3A][2] Rollback done
|
||||
[5F3A][2] executing callback file C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe with fail command line C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -EncodedCommand "QQBkAGQALQBUAHkAcABlACAALQBBAHMAcwBlAG0AYgBsAHkATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVwBpAG4AZABvAHcAcwAuAEYAbwByAG0AcwA7ACAAWwBTAHkAcwB0AGUAbQAuAFcAaQBuAGQAbwB3AHMALgBGAG8AcgBtAHMALgBNAGUAcwBzAGEAZwBlAEIAbwB4AF0AOgA6AFMAaABvAHcAKAAiAFUAcABkAGEAdABlACAAZgBhAGkAbABlAGQAIgAsACIAVQBwAGQAYQB0AGUAcgAiACwAMAApAA=="bG9nX2ZpbGU6ZFhCa1lYUmxjbHgwWlhOMFhIVndaR0YwWlM1c2IyYz07ZXJyb3JfaWQ6TURBd01RPT07ZXJyb3JfbWVzc2FnZTpjMjkxY21ObElHWnBiR1VnWkc5bGN5QnViM1FnWlhocGMzUno=
|
||||
[5F3A][2] ----------- log ended at 2020-04-22.19:59:41 -----------
|
||||
[3179][2] ----------- log started at 2020-04-22.19:59:52 -----------
|
||||
[3179][2] App executed as admin: no
|
||||
[3179][2] loading config from file updater\test\dummy_config.json
|
||||
[3179][1] Loaded 1 locking actions and 1 moving actions
|
||||
[3179][2] Awaiting the unlocking of all files
|
||||
[3179][2] All files have been unlocked (0ms required)
|
||||
[3179][2] Moving file from source/file_new.txt to target/file.txt
|
||||
[3179][5] failed to move file source/file_new.txt to target/file.txt (source file does not exists)
|
||||
[3179][2] Rollbacking 0 moved files
|
||||
[3179][2] Rollbacking 0 deleted files
|
||||
[3179][2] Rollback done
|
||||
[3179][2] executing callback file C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe with fail command line C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -EncodedCommand "QQBkAGQALQBUAHkAcABlACAALQBBAHMAcwBlAG0AYgBsAHkATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVwBpAG4AZABvAHcAcwAuAEYAbwByAG0AcwA7ACAAWwBTAHkAcwB0AGUAbQAuAFcAaQBuAGQAbwB3AHMALgBGAG8AcgBtAHMALgBNAGUAcwBzAGEAZwBlAEIAbwB4AF0AOgA6AFMAaABvAHcAKAAiAFUAcABkAGEAdABlACAAZgBhAGkAbABlAGQAIgAsACIAVQBwAGQAYQB0AGUAcgAiACwAMAApAA=="bG9nX2ZpbGU6ZFhCa1lYUmxjbHgwWlhOMFhIVndaR0YwWlM1c2IyYz07ZXJyb3JfaWQ6TURBd01RPT07ZXJyb3JfbWVzc2FnZTpjMjkxY21ObElHWnBiR1VnWkc5bGN5QnViM1FnWlhocGMzUno=
|
||||
[3179][2] ----------- log ended at 2020-04-22.20:00:03 -----------
|
||||
[5E98][2] ----------- log started at 2020-04-22.20:00:53 -----------
|
||||
[5E98][2] App executed as admin: no
|
||||
[5E98][2] loading config from file updater\test\dummy_config.json
|
||||
[5E98][1] Loaded 1 locking actions and 1 moving actions
|
||||
[5E98][2] Awaiting the unlocking of all files
|
||||
[5E98][2] All files have been unlocked (0ms required)
|
||||
[5E98][2] Moving file from source/file_new.txt to target/file.txt
|
||||
[5E98][5] failed to move file source/file_new.txt to target/file.txt (source file does not exists)
|
||||
[5E98][2] Rollbacking 0 moved files
|
||||
[5E98][2] Rollbacking 0 deleted files
|
||||
[5E98][2] Rollback done
|
||||
[5E98][2] executing callback file C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe with fail command line C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -EncodedCommand "QQBkAGQALQBUAHkAcABlACAALQBBAHMAcwBlAG0AYgBsAHkATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVwBpAG4AZABvAHcAcwAuAEYAbwByAG0AcwA7ACAAWwBTAHkAcwB0AGUAbQAuAFcAaQBuAGQAbwB3AHMALgBGAG8AcgBtAHMALgBNAGUAcwBzAGEAZwBlAEIAbwB4AF0AOgA6AFMAaABvAHcAKAAiAFUAcABkAGEAdABlACAAZgBhAGkAbABlAGQAIgAsACIAVQBwAGQAYQB0AGUAcgAiACwAMAApAA=="bG9nX2ZpbGU6ZFhCa1lYUmxjbHgwWlhOMFhIVndaR0YwWlM1c2IyYz07ZXJyb3JfaWQ6TURBd01RPT07ZXJyb3JfbWVzc2FnZTpjMjkxY21ObElHWnBiR1VnWkc5bGN5QnViM1FnWlhocGMzUno=
|
||||
[5E98][2] ----------- log ended at 2020-04-22.20:00:54 -----------
|
||||
[59B2][2] ----------- log started at 2020-04-22.20:00:59 -----------
|
||||
[59B2][2] App executed as admin: no
|
||||
[59B2][2] loading config from file updater\test\dummy_config.json
|
||||
[59B2][1] Loaded 1 locking actions and 1 moving actions
|
||||
[59B2][2] Awaiting the unlocking of all files
|
||||
[59B2][2] All files have been unlocked (0ms required)
|
||||
[59B2][2] Moving file from source/file_new.txt to target/file.txt
|
||||
[59B2][5] failed to move file source/file_new.txt to target/file.txt (source file does not exists)
|
||||
[59B2][2] Rollbacking 0 moved files
|
||||
[59B2][2] Rollbacking 0 deleted files
|
||||
[59B2][2] Rollback done
|
||||
[59B2][2] executing callback file C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe with fail command line C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -EncodedCommand "QQBkAGQALQBUAHkAcABlACAALQBBAHMAcwBlAG0AYgBsAHkATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVwBpAG4AZABvAHcAcwAuAEYAbwByAG0AcwA7ACAAWwBTAHkAcwB0AGUAbQAuAFcAaQBuAGQAbwB3AHMALgBGAG8AcgBtAHMALgBNAGUAcwBzAGEAZwBlAEIAbwB4AF0AOgA6AFMAaABvAHcAKAAiAFUAcABkAGEAdABlACAAZgBhAGkAbABlAGQAIgAsACIAVQBwAGQAYQB0AGUAcgAiACwAMAApAA=="bG9nX2ZpbGU6ZFhCa1lYUmxjbHgwWlhOMFhIVndaR0YwWlM1c2IyYz07ZXJyb3JfaWQ6TURBd01RPT07ZXJyb3JfbWVzc2FnZTpjMjkxY21ObElHWnBiR1VnWkc5bGN5QnViM1FnWlhocGMzUno=
|
||||
[59B2][2] ----------- log ended at 2020-04-22.20:01:11 -----------
|
||||
|
17
native/updater/ui.h
Normal file
17
native/updater/ui.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace ui {
|
||||
enum struct FileBlockedResult {
|
||||
UNSET,
|
||||
PROCESSES_CLOSED,
|
||||
CANCELED,
|
||||
INTERNAL_ERROR
|
||||
};
|
||||
|
||||
#ifdef WIN32
|
||||
extern void init_win32();
|
||||
#endif
|
||||
extern FileBlockedResult open_file_blocked(const std::string&);
|
||||
}
|
1
native/updater/win32/Resource.rc
Normal file
1
native/updater/win32/Resource.rc
Normal file
@ -0,0 +1 @@
|
||||
101 ICON "logo.ico"
|
BIN
native/updater/win32/logo.ico
Normal file
BIN
native/updater/win32/logo.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 116 KiB |
555
native/updater/win32/retry_ui.cpp
Normal file
555
native/updater/win32/retry_ui.cpp
Normal file
@ -0,0 +1,555 @@
|
||||
//
|
||||
// Created by WolverinDEV on 21/04/2020.
|
||||
//
|
||||
|
||||
#include <Windows.h>
|
||||
#include <RestartManager.h>
|
||||
#include <CommCtrl.h>
|
||||
#include <windowsx.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <condition_variable>
|
||||
#include "../ui.h"
|
||||
|
||||
struct BlockingProcess {
|
||||
RM_APP_TYPE type{};
|
||||
std::wstring name{};
|
||||
std::wstring exe_path{};
|
||||
int pid{};
|
||||
};
|
||||
|
||||
bool blocking_processes(std::vector<BlockingProcess>& result, std::wstring& error, const std::wstring& file) {
|
||||
DWORD dwSession{0};
|
||||
WCHAR szSessionKey[CCH_RM_SESSION_KEY + 1] = { 0 };
|
||||
DWORD dwError = RmStartSession(&dwSession, 0, szSessionKey);
|
||||
if(dwError != ERROR_SUCCESS) {
|
||||
error = L"Failed to start rm session (" + std::to_wstring(dwError) + L")";
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
PCWSTR pszFile = file.data();
|
||||
dwError = RmRegisterResources(dwSession, 1, &pszFile, 0, nullptr, 0, nullptr);
|
||||
if(dwError != ERROR_SUCCESS) {
|
||||
error = L"Failed to register resource (" + std::to_wstring(dwError) + L")";
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
DWORD dwReason;
|
||||
UINT i;
|
||||
UINT nProcInfoNeeded;
|
||||
UINT nProcInfo = 10;
|
||||
RM_PROCESS_INFO rgpi[10];
|
||||
dwError = RmGetList(dwSession, &nProcInfoNeeded, &nProcInfo, rgpi, &dwReason);
|
||||
if(dwError != ERROR_SUCCESS) {
|
||||
error = L"Failed to get list from rm (" + std::to_wstring(dwError) + L")";
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
result.reserve(nProcInfo);
|
||||
for (i = 0; i < nProcInfo; i++) {
|
||||
auto& info = result.emplace_back();
|
||||
|
||||
info.type = rgpi[i].ApplicationType;
|
||||
info.name = rgpi[i].strAppName;
|
||||
info.pid = rgpi[i].Process.dwProcessId;
|
||||
info.exe_path = L"unknown";
|
||||
|
||||
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, rgpi[i].Process.dwProcessId);
|
||||
if (hProcess) {
|
||||
FILETIME ftCreate, ftExit, ftKernel, ftUser;
|
||||
if (GetProcessTimes(hProcess, &ftCreate, &ftExit, &ftKernel, &ftUser) && CompareFileTime(&rgpi[i].Process.ProcessStartTime, &ftCreate) == 0) {
|
||||
WCHAR sz[MAX_PATH];
|
||||
DWORD cch{MAX_PATH};
|
||||
if (QueryFullProcessImageNameW(hProcess, 0, sz, &cch) && cch <= MAX_PATH) {
|
||||
info.exe_path = sz;
|
||||
}
|
||||
}
|
||||
CloseHandle(hProcess);
|
||||
}
|
||||
}
|
||||
|
||||
RmEndSession(dwSession);
|
||||
return true;
|
||||
|
||||
error_exit:
|
||||
if(dwSession)
|
||||
RmEndSession(dwSession);
|
||||
return false;
|
||||
}
|
||||
|
||||
#if 0
|
||||
enum LabelDefault { LABEL_MAX };
|
||||
enum BrushDefault { BRUSH_MAX };
|
||||
template <typename Labels = LabelDefault, typename Brush = BrushDefault>
|
||||
class Win32Window {
|
||||
public:
|
||||
template <typename Label>
|
||||
using WithLabels = Win32Window<Label, Brush>;
|
||||
|
||||
template <typename Brush>
|
||||
using WithBrush = Win32Window<Labels, Brush>;
|
||||
|
||||
Win32Window();
|
||||
|
||||
protected:
|
||||
std::array<HWND, Labels::LABEL_MAX> hLabel{};
|
||||
std::array<HBRUSH, Brush::BRUSH_MAX> hBrush{};
|
||||
};
|
||||
|
||||
static void a() {
|
||||
auto window = new Win32Window();
|
||||
}
|
||||
#endif
|
||||
|
||||
class FileInUseWindow {
|
||||
public:
|
||||
static constexpr auto ClassName = "FileInUseWindow";
|
||||
static bool register_class();
|
||||
|
||||
explicit FileInUseWindow(HWND);
|
||||
virtual ~FileInUseWindow();
|
||||
|
||||
bool initialize();
|
||||
void finalize();
|
||||
|
||||
void set_file(const std::wstring&);
|
||||
void update_blocking_info();
|
||||
|
||||
ui::FileBlockedResult result{ui::FileBlockedResult::UNSET};
|
||||
bool deleteOnClose{true};
|
||||
private:
|
||||
static constexpr auto kBackgroundColor = RGB(240, 240, 240);
|
||||
|
||||
static LRESULT CALLBACK window_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
INT_PTR window_proc_color_static(HWND hElement, HDC hDC);
|
||||
INT_PTR window_proc_command(HWND hwnd, DWORD cID);
|
||||
void set_blocking_info(const std::wstring_view&, const std::vector<BlockingProcess>&);
|
||||
|
||||
enum Label {
|
||||
LABEL_FIRST_LINE,
|
||||
LABEL_FILE_NAME,
|
||||
LABEL_SECOND_LINE,
|
||||
LABEL_MAX
|
||||
};
|
||||
|
||||
enum Brush {
|
||||
BRUSH_BACKGROUND,
|
||||
BRUSH_MAX
|
||||
};
|
||||
|
||||
enum Font {
|
||||
FONT_TEXT,
|
||||
FONT_FILE_NAME,
|
||||
FONT_PROCESS_INFO,
|
||||
FONT_MAX
|
||||
};
|
||||
|
||||
enum Tooltip {
|
||||
TOOLTIP_FILE,
|
||||
TOOLTIP_MAX
|
||||
};
|
||||
|
||||
enum Button {
|
||||
BUTTON_CANCEL,
|
||||
BUTTON_CONTINUE,
|
||||
BUTTON_REFRESH,
|
||||
BUTTON_MAX
|
||||
};
|
||||
|
||||
HWND hWindow;
|
||||
|
||||
std::array<HWND, Label::LABEL_MAX> hLabels{};
|
||||
std::array<HWND, Tooltip::TOOLTIP_MAX> hTooltips{};
|
||||
std::array<HWND, Button::BUTTON_MAX> hButton{};
|
||||
HWND hListBox{};
|
||||
|
||||
std::array<HBRUSH, Brush::BRUSH_MAX> hBrush{};
|
||||
std::array<HFONT, Font::FONT_MAX> hFont{};
|
||||
|
||||
std::wstring blocking_file{};
|
||||
bool window_active{false};
|
||||
|
||||
bool update_exit{false};
|
||||
bool force_update{false};
|
||||
std::thread update_thread{};
|
||||
std::condition_variable update_cv{};
|
||||
std::mutex update_mutex{};
|
||||
};
|
||||
|
||||
bool FileInUseWindow::register_class() {
|
||||
WNDCLASS wc = {};
|
||||
wc.lpfnWndProc = FileInUseWindow::window_proc;
|
||||
wc.hInstance = GetModuleHandle(nullptr);
|
||||
wc.lpszClassName = "FileInUseWindow";
|
||||
return RegisterClass(&wc);
|
||||
}
|
||||
|
||||
LRESULT FileInUseWindow::window_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||||
auto window = (FileInUseWindow*) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
switch(uMsg) {
|
||||
case WM_CREATE:
|
||||
window = new FileInUseWindow(hwnd);
|
||||
if(!window->initialize())
|
||||
assert(false);
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) window);
|
||||
/* Certain window data is cached, so changes you make using SetWindowLongPtr will not take effect until you call the SetWindowPos function */
|
||||
SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
|
||||
return 0;
|
||||
case WM_DESTROY:
|
||||
window->finalize();
|
||||
if(window->deleteOnClose)
|
||||
delete window;
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
case WM_CLOSE:
|
||||
if(window->result == ui::FileBlockedResult::UNSET) {
|
||||
if (MessageBoxW(hwnd, L"Do you really want to cancel the update?", L"Are you sure?", MB_OKCANCEL) == IDOK) {
|
||||
window->result = ui::FileBlockedResult::CANCELED;
|
||||
DestroyWindow(hwnd);
|
||||
}
|
||||
} else {
|
||||
DestroyWindow(hwnd);
|
||||
}
|
||||
return 0;
|
||||
case WM_CTLCOLORSTATIC:
|
||||
return window->window_proc_color_static((HWND) lParam, (HDC) wParam);
|
||||
case WM_COMMAND:
|
||||
return window->window_proc_command((HWND) lParam, LOWORD(wParam));
|
||||
case WM_ACTIVATE:
|
||||
if(!window) return 0;
|
||||
if(wParam == WA_INACTIVE) {
|
||||
window->window_active = false;
|
||||
} else if(wParam == WA_ACTIVE) {
|
||||
window->window_active = true;
|
||||
window->force_update = true;
|
||||
window->update_cv.notify_all(); /* update the list */
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return DefWindowProcA(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
HWND CreateToolTip(HWND window, HWND hwnd, PTSTR pszText) {
|
||||
HWND hwndTip = CreateWindowEx(NULL, TOOLTIPS_CLASS, NULL,
|
||||
WS_POPUP | TTS_ALWAYSTIP | TTS_BALLOON,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
hwnd, NULL,
|
||||
(HINSTANCE) GetWindowLongPtr(hwnd, GWLP_WNDPROC), NULL);
|
||||
|
||||
if(!hwndTip) return nullptr;
|
||||
|
||||
// Associate the tooltip with the tool.
|
||||
TOOLINFO toolInfo = { 0 };
|
||||
toolInfo.cbSize = sizeof(toolInfo);
|
||||
toolInfo.uId = 22;
|
||||
toolInfo.hwnd = hwnd;
|
||||
toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
|
||||
toolInfo.lpszText = pszText;
|
||||
SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo);
|
||||
SendMessage(hwndTip, TTM_ACTIVATE, TRUE, 0);
|
||||
|
||||
return hwndTip;
|
||||
}
|
||||
|
||||
HWND CreateAHorizontalScrollBar(HWND hwndParent, int sbHeight)
|
||||
{
|
||||
RECT rect;
|
||||
|
||||
// Get the dimensions of the parent window's client area;
|
||||
if (!GetClientRect(hwndParent, &rect))
|
||||
return NULL;
|
||||
|
||||
// Create the scroll bar.
|
||||
return (CreateWindowExW(
|
||||
0, // no extended styles
|
||||
L"SCROLLBAR", // scroll bar control class
|
||||
nullptr, // no window text
|
||||
WS_CHILD | WS_VISIBLE // window styles
|
||||
| SBS_HORZ, // horizontal scroll bar style
|
||||
rect.left, // horizontal position
|
||||
rect.bottom - sbHeight - 12, // vertical position
|
||||
rect.right, // width of the scroll bar
|
||||
sbHeight, // height of the scroll bar
|
||||
hwndParent, // handle to main window
|
||||
(HMENU) NULL, // no menu
|
||||
(HINSTANCE) GetWindowLongPtr(hwndParent, GWLP_WNDPROC), // instance owning this window
|
||||
(PVOID) NULL // pointer not needed
|
||||
));
|
||||
}
|
||||
|
||||
FileInUseWindow::FileInUseWindow(HWND hwnd) : hWindow{hwnd} {}
|
||||
FileInUseWindow::~FileInUseWindow() = default;
|
||||
|
||||
bool FileInUseWindow::initialize() {
|
||||
::SetWindowLong(this->hWindow, GWL_STYLE, GetWindowLong(this->hWindow, GWL_STYLE) & ~ (WS_SIZEBOX | WS_MINIMIZEBOX | WS_MAXIMIZEBOX));
|
||||
|
||||
this->hBrush[Brush::BRUSH_BACKGROUND] = CreateSolidBrush(kBackgroundColor);
|
||||
this->hFont[Font::FONT_TEXT] = CreateFontW(16, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, L"Arial");
|
||||
this->hFont[Font::FONT_FILE_NAME] = CreateFontW(16, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, L"Consolas");
|
||||
this->hFont[Font::FONT_PROCESS_INFO] = CreateFontW(16, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, L"Consolas");
|
||||
|
||||
SetClassLongPtr(this->hWindow, GCLP_HBRBACKGROUND, (LONG_PTR) this->hBrush[Brush::BRUSH_BACKGROUND]);
|
||||
|
||||
{
|
||||
this->hLabels[Label::LABEL_FIRST_LINE] = CreateWindow(WC_STATIC, "Failed to unlock the following file:",
|
||||
WS_CHILD | WS_VISIBLE | WS_TABSTOP,
|
||||
10, 10, 400, 20,
|
||||
this->hWindow, nullptr,
|
||||
(HINSTANCE) GetWindowLongPtr(this->hWindow, GWLP_WNDPROC), nullptr);
|
||||
|
||||
this->hLabels[Label::LABEL_FILE_NAME] = CreateWindow(WC_STATIC, "<file name here>",
|
||||
WS_CHILD | WS_VISIBLE | WS_TABSTOP,
|
||||
10, 30, 400, 20,
|
||||
this->hWindow, nullptr,
|
||||
(HINSTANCE) GetWindowLongPtr(this->hWindow, GWLP_WNDPROC), nullptr);
|
||||
this->hTooltips[Tooltip::TOOLTIP_FILE] = CreateToolTip(this->hWindow, this->hLabels[Label::LABEL_FILE_NAME], "Hello World"); //FIXME: Tooltip not working...
|
||||
|
||||
this->hLabels[Label::LABEL_SECOND_LINE] = CreateWindow(WC_STATIC, "Please close these processes:",
|
||||
WS_CHILD | WS_VISIBLE | WS_TABSTOP,
|
||||
10, 60, 400, 20,
|
||||
this->hWindow, nullptr,
|
||||
(HINSTANCE) GetWindowLongPtr(this->hWindow, GWLP_WNDPROC), nullptr);
|
||||
|
||||
for(auto& hLabel : this->hLabels)
|
||||
SendMessage(hLabel, WM_SETFONT, (WPARAM) this->hFont[Font::FONT_TEXT], TRUE);
|
||||
SendMessage(this->hLabels[Label::LABEL_FILE_NAME], WM_SETFONT, (WPARAM) this->hFont[Font::FONT_FILE_NAME], TRUE);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
this->hListBox = CreateWindow("ListBox", nullptr, WS_VISIBLE | WS_CHILD | LBS_STANDARD | LBS_NOTIFY | WS_HSCROLL , 10, 80, 565, 200, this->hWindow, nullptr,
|
||||
(HINSTANCE) GetWindowLongPtr(this->hWindow, GWLP_WNDPROC), nullptr);
|
||||
SendMessage(this->hListBox, WM_SETFONT, (WPARAM) this->hFont[Font::FONT_PROCESS_INFO], TRUE);
|
||||
}
|
||||
|
||||
{
|
||||
#if 0
|
||||
this->hButton[Button::BUTTON_CANCEL] = CreateWindowW(
|
||||
WC_BUTTONW, // Predefined class; Unicode assumed
|
||||
L"Cancel", // Button text
|
||||
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // Styles
|
||||
10, // x position
|
||||
280, // y position
|
||||
100, // Button width
|
||||
30, // Button height
|
||||
this->hWindow, // Parent window
|
||||
nullptr, // No menu.
|
||||
(HINSTANCE)GetWindowLongPtr(this->hWindow, GWLP_HINSTANCE),
|
||||
nullptr); // Pointer not needed.
|
||||
#endif
|
||||
|
||||
this->hButton[Button::BUTTON_REFRESH] = CreateWindowW(
|
||||
WC_BUTTONW, // Predefined class; Unicode assumed
|
||||
L"Refresh", // Button text
|
||||
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // Styles
|
||||
10, // x position
|
||||
280, // y position
|
||||
100, // Button width
|
||||
30, // Button height
|
||||
this->hWindow, // Parent window
|
||||
nullptr, // No menu.
|
||||
(HINSTANCE)GetWindowLongPtr(this->hWindow, GWLP_HINSTANCE),
|
||||
nullptr); // Pointer not needed.
|
||||
|
||||
this->hButton[Button::BUTTON_CONTINUE] = CreateWindowW(
|
||||
WC_BUTTONW, // Predefined class; Unicode assumed
|
||||
L"Continue", // Button text
|
||||
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // Styles
|
||||
475, // x position
|
||||
280, // y position
|
||||
100, // Button width
|
||||
30, // Button height
|
||||
this->hWindow, // Parent window
|
||||
nullptr, // No menu.
|
||||
(HINSTANCE)GetWindowLongPtr(this->hWindow, GWLP_HINSTANCE),
|
||||
nullptr); // Pointer not needed.
|
||||
}
|
||||
|
||||
ShowWindow(this->hWindow, SW_SHOWNORMAL);
|
||||
this->window_active = true;
|
||||
|
||||
this->update_thread = std::thread([&]{
|
||||
while(!this->update_exit) {
|
||||
{
|
||||
std::unique_lock update_lock{this->update_mutex};
|
||||
this->update_cv.wait_for(update_lock, std::chrono::milliseconds{1000});
|
||||
if(this->update_exit) return;
|
||||
}
|
||||
if(this->window_active && !this->force_update) continue; /* only auto update in the background */
|
||||
this->force_update = false;
|
||||
|
||||
this->update_blocking_info();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
INT_PTR FileInUseWindow::window_proc_color_static(HWND hElement, HDC hDC) {
|
||||
SetBkColor(hDC, kBackgroundColor);
|
||||
return (INT_PTR) this->hBrush[Brush::BRUSH_BACKGROUND];
|
||||
}
|
||||
|
||||
INT_PTR FileInUseWindow::window_proc_command(HWND hwnd, DWORD cID) {
|
||||
if(hwnd == this->hButton[Button::BUTTON_CANCEL]) {
|
||||
SendMessageA(this->hWindow, WM_CLOSE, (WPARAM) nullptr, (LPARAM) nullptr);
|
||||
} else if(hwnd == this->hButton[Button::BUTTON_REFRESH]) {
|
||||
this->force_update = true;
|
||||
this->update_cv.notify_all();
|
||||
} else if(hwnd == this->hButton[Button::BUTTON_CONTINUE]) {
|
||||
this->result = ui::FileBlockedResult::PROCESSES_CLOSED;
|
||||
SendMessageA(this->hWindow, WM_CLOSE, (WPARAM) nullptr, (LPARAM) nullptr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FileInUseWindow::finalize() {
|
||||
this->update_exit = true;
|
||||
this->update_cv.notify_all();
|
||||
if(this->update_thread.joinable())
|
||||
this->update_thread.join();
|
||||
|
||||
//TODO: Free resources?
|
||||
}
|
||||
|
||||
static inline std::wstring_view app_type_prefix(RM_APP_TYPE type) {
|
||||
switch (type) {
|
||||
case RM_APP_TYPE::RmOtherWindow:
|
||||
return L"Child App : ";
|
||||
case RM_APP_TYPE::RmMainWindow:
|
||||
return L"Application: ";
|
||||
case RM_APP_TYPE::RmConsole:
|
||||
return L"Console App: ";
|
||||
case RM_APP_TYPE::RmService:
|
||||
return L"NT Service : ";
|
||||
case RM_APP_TYPE::RmExplorer:
|
||||
return L"Explorer : ";
|
||||
case RM_APP_TYPE::RmCritical:
|
||||
return L"System : ";
|
||||
default:
|
||||
return L" ";
|
||||
}
|
||||
}
|
||||
|
||||
void FileInUseWindow::set_file(const std::wstring &file) {
|
||||
this->blocking_file = file;
|
||||
this->update_blocking_info();
|
||||
}
|
||||
|
||||
void FileInUseWindow::update_blocking_info() {
|
||||
std::wstring error{};
|
||||
std::vector<BlockingProcess> result_{};
|
||||
if(!blocking_processes(result_, error, this->blocking_file)) {
|
||||
MessageBoxW(this->hWindow, (L"Failed to get file info:\n" + error).c_str(), L"Failed to query file info", MB_OK | MB_ICONERROR);
|
||||
SendMessageA(this->hWindow, WM_CLOSE, (WPARAM) nullptr, (LPARAM) nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
this->set_blocking_info(this->blocking_file, result_);
|
||||
}
|
||||
|
||||
void FileInUseWindow::set_blocking_info(const std::wstring_view &file, const std::vector<BlockingProcess> &processes) {
|
||||
SetWindowTextW(this->hLabels[Label::LABEL_FILE_NAME], file.data());
|
||||
|
||||
std::vector<BlockingProcess> output_processes{};
|
||||
for(const auto& type : {
|
||||
RM_APP_TYPE::RmMainWindow,
|
||||
RM_APP_TYPE::RmConsole,
|
||||
RM_APP_TYPE::RmService,
|
||||
RM_APP_TYPE::RmCritical,
|
||||
RM_APP_TYPE::RmOtherWindow
|
||||
}) {
|
||||
for(const auto& proc : processes) {
|
||||
if(proc.type != type) continue;
|
||||
auto it = std::find_if(output_processes.begin(), output_processes.end(), [&](const BlockingProcess& entry) {
|
||||
return entry.name == proc.name && proc.exe_path == entry.exe_path;
|
||||
});
|
||||
if(it != output_processes.end())
|
||||
continue;
|
||||
output_processes.emplace_back(proc);
|
||||
}
|
||||
}
|
||||
|
||||
HDC hDC = GetDC(NULL);
|
||||
SelectFont(hDC, this->hFont[Font::FONT_PROCESS_INFO]);
|
||||
|
||||
size_t width{0};
|
||||
SendMessage(this->hListBox, LB_RESETCONTENT, 0, 0);
|
||||
for(auto& process : output_processes) {
|
||||
auto message = L" " + std::wstring{app_type_prefix(process.type)} + process.name + L" " + std::to_wstring(process.pid) + L" (" + process.exe_path + L") ";
|
||||
SendMessageW(this->hListBox, LB_ADDSTRING, 0, (LPARAM) message.c_str());
|
||||
|
||||
RECT r = { 0, 0, 0, 0 };
|
||||
DrawTextW(hDC, message.data(), message.length(), &r, DT_CALCRECT);
|
||||
if(r.right - r.left > width)
|
||||
width = r.right - r.left;
|
||||
}
|
||||
|
||||
SendMessage(this->hListBox, LB_SETHORIZONTALEXTENT, (WPARAM) width, 0);
|
||||
ReleaseDC(NULL, hDC);
|
||||
|
||||
EnableWindow(this->hButton[Button::BUTTON_CONTINUE], output_processes.empty());
|
||||
}
|
||||
|
||||
inline std::wstring mbtow(const std::string_view& str) {
|
||||
int length = MultiByteToWideChar(CP_UTF8, 0, str.data(), -1, nullptr, 0);
|
||||
std::wstring result{};
|
||||
result.resize(length + 1);
|
||||
MultiByteToWideChar(CP_UTF8, 0, str.data(), -1, result.data() , length);
|
||||
return result;
|
||||
}
|
||||
|
||||
#define IDR_APP_ICON 101
|
||||
ui::FileBlockedResult ui::open_file_blocked(const std::string& file) {
|
||||
FileInUseWindow::register_class();
|
||||
auto hInstance = GetModuleHandle(nullptr);
|
||||
|
||||
auto hWindow = CreateWindowEx(
|
||||
0, // Optional window styles.
|
||||
FileInUseWindow::ClassName, // Window class
|
||||
"One or more files are still in use", // Window text
|
||||
WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_SYSMENU, // Window style
|
||||
|
||||
// Size and position
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, 600, 360,
|
||||
|
||||
nullptr, // Parent window
|
||||
nullptr, // Menu
|
||||
hInstance, // Instance handle
|
||||
nullptr // Additional application data
|
||||
);
|
||||
if (hWindow == nullptr)
|
||||
return ui::FileBlockedResult::INTERNAL_ERROR;
|
||||
|
||||
auto hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDR_APP_ICON));
|
||||
SendMessage(hWindow, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
|
||||
SendMessage(hWindow, WM_SETICON, ICON_SMALL, (LPARAM) hIcon);
|
||||
DestroyIcon(hIcon);
|
||||
|
||||
auto window = (FileInUseWindow*) GetWindowLongPtr(hWindow, GWLP_USERDATA);
|
||||
window->deleteOnClose = false;
|
||||
|
||||
window->set_file(mbtow(file));
|
||||
|
||||
MSG msg = { };
|
||||
while (GetMessage(&msg, hWindow, 0, 0))
|
||||
{
|
||||
if (msg.message == WM_NULL)
|
||||
break;
|
||||
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
auto result = window->result;
|
||||
delete window;
|
||||
return result;
|
||||
}
|
Loading…
Reference in New Issue
Block a user