diff --git a/Makefile.am b/Makefile.am
index 54ef6e80..bce2ace0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -96,7 +96,7 @@ console_bs_SOURCES = \
console/executor_store.cpp \
console/executor_test_reader.cpp \
console/executor_test_writer.cpp \
- console/executor_windows.cpp \
+ console/executor_window.cpp \
console/localize.hpp \
console/main.cpp \
console/stack_trace.cpp \
diff --git a/builds/cmake/CMakeLists.txt b/builds/cmake/CMakeLists.txt
index ef062c6b..9162cbb0 100644
--- a/builds/cmake/CMakeLists.txt
+++ b/builds/cmake/CMakeLists.txt
@@ -334,8 +334,7 @@ if (with-console)
"../../console/executor_store.cpp"
"../../console/executor_test_reader.cpp"
"../../console/executor_test_writer.cpp"
- "../../console/executor_windows.cpp"
- "../../console/libbitcoin.ico"
+ "../../console/executor_window.cpp"
"../../console/localize.hpp"
"../../console/main.cpp"
"../../console/stack_trace.cpp"
diff --git a/builds/msvc/vs2022/bs/bs.vcxproj b/builds/msvc/vs2022/bs/bs.vcxproj
index a33ff0aa..84644c86 100644
--- a/builds/msvc/vs2022/bs/bs.vcxproj
+++ b/builds/msvc/vs2022/bs/bs.vcxproj
@@ -139,7 +139,7 @@
-
+
diff --git a/builds/msvc/vs2022/bs/bs.vcxproj.filters b/builds/msvc/vs2022/bs/bs.vcxproj.filters
index ff4d012d..5da9d976 100644
--- a/builds/msvc/vs2022/bs/bs.vcxproj.filters
+++ b/builds/msvc/vs2022/bs/bs.vcxproj.filters
@@ -81,7 +81,7 @@
src
-
+
src
diff --git a/console/executor.cpp b/console/executor.cpp
index 7b27be3d..0b123d20 100644
--- a/console/executor.cpp
+++ b/console/executor.cpp
@@ -29,6 +29,7 @@ namespace libbitcoin {
namespace server {
using boost::format;
+using namespace system;
using namespace std::placeholders;
// static initializers.
@@ -81,6 +82,34 @@ executor::~executor()
// ----------------------------------------------------------------------------
// static
+#if defined(HAVE_MSC)
+BOOL WINAPI executor::control_handler(DWORD signal)
+{
+ switch (signal)
+ {
+ // Keyboard events. These prevent exit altogether when TRUE returned.
+ // handle_stop(signal) therefore shuts down gracefully/completely.
+ case CTRL_C_EVENT:
+ case CTRL_BREAK_EVENT:
+
+ // A signal that the system sends to all processes attached to a
+ // console when the user closes the console (by clicking Close on the
+ // console window's window menu). Returning TRUE here does not
+ // materially delay exit, so aside from capture this is a noop.
+ case CTRL_CLOSE_EVENT:
+ executor::handle_stop(possible_narrow_sign_cast(signal));
+ return TRUE;
+
+ ////// Only services receive this (*any* user is logging off).
+ ////case CTRL_LOGOFF_EVENT:
+ ////// Only services receive this (all users already logged off).
+ ////case CTRL_SHUTDOWN_EVENT:
+ default:
+ return FALSE;
+ }
+}
+#endif
+
void executor::initialize_stop()
{
poll_for_stopping();
diff --git a/console/executor.hpp b/console/executor.hpp
index f0180b53..6ec47168 100644
--- a/console/executor.hpp
+++ b/console/executor.hpp
@@ -69,6 +69,7 @@ class executor
HWND window_{};
std::thread thread_{};
+ std::promise ready_{};
#endif
// Executor.
diff --git a/console/executor_windows.cpp b/console/executor_window.cpp
similarity index 78%
rename from console/executor_windows.cpp
rename to console/executor_window.cpp
index e61fd2d5..76e6ad3e 100644
--- a/console/executor_windows.cpp
+++ b/console/executor_window.cpp
@@ -26,38 +26,10 @@ namespace server {
// TODO: use RegisterServiceCtrlHandlerEx for service registration.
using namespace system;
-
constexpr auto window_name = L"HiddenShutdownWindow";
constexpr auto window_text = L"Flushing tables...";
constexpr auto window_title = L"Libbitcoin Server";
-// static
-BOOL WINAPI executor::control_handler(DWORD signal)
-{
- switch (signal)
- {
- // Keyboard events. These prevent exit altogether when TRUE returned.
- // handle_stop(signal) therefore shuts down gracefully/completely.
- case CTRL_C_EVENT:
- case CTRL_BREAK_EVENT:
-
- // A signal that the system sends to all processes attached to a
- // console when the user closes the console (by clicking Close on the
- // console window's window menu). Returning TRUE here does not
- // materially delay exit, so aside from capture this is a noop.
- case CTRL_CLOSE_EVENT:
- executor::handle_stop(possible_narrow_sign_cast(signal));
- return TRUE;
-
- ////// Only services receive this (*any* user is logging off).
- ////case CTRL_LOGOFF_EVENT:
- ////// Only services receive this (all users already logged off).
- ////case CTRL_SHUTDOWN_EVENT:
- default:
- return FALSE;
- }
-}
-
// static
LRESULT CALLBACK executor::window_proc(HWND handle, UINT message,
WPARAM wparam, LPARAM lparam)
@@ -120,6 +92,7 @@ void executor::create_hidden_window()
MSG message{};
BOOL result{};
+ ready_.set_value(true);
while (!is_zero(result = ::GetMessageW(&message, NULL, 0, 0)))
{
// fault
@@ -134,6 +107,9 @@ void executor::create_hidden_window()
void executor::destroy_hidden_window()
{
+ // Wait until window is accepting messages, so WM_QUIT isn't missed.
+ ready_.get_future().wait();
+
if (!is_null(window_))
::PostMessageW(window_, WM_QUIT, 0, 0);