+class wxExecuteModule : public wxModule
+{
+public:
+ virtual bool OnInit() { return true; }
+ virtual void OnExit()
+ {
+ if ( gs_heventShutdown )
+ {
+ // stop any threads waiting for the termination of asynchronously
+ // running processes
+ if ( !::SetEvent(gs_heventShutdown) )
+ {
+ wxLogDebug(wxT("Failed to set shutdown event in wxExecuteModule"));
+ }
+
+ ::CloseHandle(gs_heventShutdown);
+ gs_heventShutdown = NULL;
+
+ // now wait until they terminate
+ if ( !gs_asyncThreads.empty() )
+ {
+ const size_t numThreads = gs_asyncThreads.size();
+
+ if ( ::WaitForMultipleObjects
+ (
+ numThreads,
+ &gs_asyncThreads[0],
+ TRUE, // wait for all of them to become signalled
+ 3000 // long but finite value
+ ) == WAIT_TIMEOUT )
+ {
+ wxLogDebug(wxT("Failed to stop all wxExecute monitor threads"));
+ }
+
+ for ( size_t n = 0; n < numThreads; n++ )
+ {
+ ::CloseHandle(gs_asyncThreads[n]);
+ }
+
+ gs_asyncThreads.clear();
+ }
+ }
+
+ if ( gs_classForHiddenWindow )
+ {
+ if ( !::UnregisterClass(wxMSWEXEC_WNDCLASSNAME, wxGetInstance()) )
+ {
+ wxLogLastError(wxT("UnregisterClass(wxExecClass)"));
+ }
+
+ gs_classForHiddenWindow = NULL;
+ }
+ }
+
+private:
+ DECLARE_DYNAMIC_CLASS(wxExecuteModule)
+};
+
+IMPLEMENT_DYNAMIC_CLASS(wxExecuteModule, wxModule)
+
+#if wxUSE_STREAMS && !defined(__WXWINCE__)