winExec.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platformWin32/platformWin32.h"
  23. #include "console/console.h"
  24. #include "console/simBase.h"
  25. #include "core/strings/unicode.h"
  26. #include "platform/threads/thread.h"
  27. #include "platform/threads/mutex.h"
  28. #include "core/util/safeDelete.h"
  29. #include "util/tempAlloc.h"
  30. //-----------------------------------------------------------------------------
  31. // Thread for executing in
  32. //-----------------------------------------------------------------------------
  33. class ExecuteThread : public Thread
  34. {
  35. // [tom, 12/14/2006] mProcess is only used in the constructor before the thread
  36. // is started and in the thread itself so we should be OK without a mutex.
  37. HANDLE mProcess;
  38. public:
  39. ExecuteThread(const char *executable, const char *args = NULL, const char *directory = NULL);
  40. virtual void run(void *arg = 0);
  41. };
  42. //-----------------------------------------------------------------------------
  43. // Event for cleanup
  44. //-----------------------------------------------------------------------------
  45. class ExecuteCleanupEvent : public SimEvent
  46. {
  47. ExecuteThread *mThread;
  48. bool mOK;
  49. public:
  50. ExecuteCleanupEvent(ExecuteThread *thread, bool ok)
  51. {
  52. mThread = thread;
  53. mOK = ok;
  54. }
  55. virtual void process(SimObject *object)
  56. {
  57. if( Con::isFunction( "onExecuteDone" ) )
  58. Con::executef( "onExecuteDone", Con::getIntArg( mOK ) );
  59. SAFE_DELETE(mThread);
  60. }
  61. };
  62. //-----------------------------------------------------------------------------
  63. ExecuteThread::ExecuteThread(const char *executable, const char *args /* = NULL */, const char *directory /* = NULL */) : Thread(0, NULL, false)
  64. {
  65. SHELLEXECUTEINFO shl;
  66. dMemset(&shl, 0, sizeof(shl));
  67. shl.cbSize = sizeof(shl);
  68. shl.fMask = SEE_MASK_NOCLOSEPROCESS;
  69. char exeBuf[1024];
  70. Platform::makeFullPathName(executable, exeBuf, sizeof(exeBuf));
  71. TempAlloc< TCHAR > dirBuf( ( directory ? dStrlen( directory ) : 0 ) + 1 );
  72. dirBuf[ dirBuf.size - 1 ] = 0;
  73. #ifdef UNICODE
  74. WCHAR exe[ 1024 ];
  75. convertUTF8toUTF16( exeBuf, exe, sizeof( exe ) / sizeof( exe[ 0 ] ) );
  76. TempAlloc< WCHAR > argsBuf( ( args ? dStrlen( args ) : 0 ) + 1 );
  77. argsBuf[ argsBuf.size - 1 ] = 0;
  78. if( args )
  79. convertUTF8toUTF16( args, argsBuf, argsBuf.size );
  80. if( directory )
  81. convertUTF8toUTF16( directory, dirBuf, dirBuf.size );
  82. #else
  83. char* exe = exeBuf;
  84. char* argsBuf = args;
  85. if( directory )
  86. dStrpcy( dirBuf, directory );
  87. #endif
  88. backslash( exe );
  89. backslash( dirBuf );
  90. shl.lpVerb = TEXT( "open" );
  91. shl.lpFile = exe;
  92. shl.lpParameters = argsBuf;
  93. shl.lpDirectory = dirBuf;
  94. shl.nShow = SW_SHOWNORMAL;
  95. if(ShellExecuteEx(&shl) && shl.hProcess)
  96. {
  97. mProcess = shl.hProcess;
  98. start();
  99. }
  100. }
  101. void ExecuteThread::run(void *arg /* = 0 */)
  102. {
  103. if(mProcess == NULL)
  104. return;
  105. DWORD wait = WAIT_OBJECT_0 - 1; // i.e., not WAIT_OBJECT_0
  106. while(! checkForStop() && (wait = WaitForSingleObject(mProcess, 200)) != WAIT_OBJECT_0) ;
  107. Sim::postEvent(Sim::getRootGroup(), new ExecuteCleanupEvent(this, wait == WAIT_OBJECT_0), -1);
  108. }
  109. //-----------------------------------------------------------------------------
  110. // Console Functions
  111. //-----------------------------------------------------------------------------
  112. ConsoleFunction(shellExecute, bool, 2, 4, "(string executable, string args, string directory)"
  113. "@brief Launches an outside executable or batch file\n\n"
  114. "@param executable Name of the executable or batch file\n"
  115. "@param args Optional list of arguments, in string format, to pass to the executable\n"
  116. "@param directory Optional string containing path to output or shell\n"
  117. "@ingroup Platform")
  118. {
  119. ExecuteThread *et = new ExecuteThread(argv[1], argc > 2 ? argv[2] : NULL, argc > 3 ? argv[3] : NULL);
  120. if(! et->isAlive())
  121. {
  122. delete et;
  123. return false;
  124. }
  125. return true;
  126. }
  127. void Platform::openFolder(const char* path )
  128. {
  129. char filePath[1024];
  130. Platform::makeFullPathName(path, filePath, sizeof(filePath));
  131. #ifdef UNICODE
  132. WCHAR p[ 1024 ];
  133. convertUTF8toUTF16( filePath, p, sizeof( p ) / sizeof( p[ 0 ] ) );
  134. #else
  135. char* p = filePath;
  136. #endif
  137. backslash( p );
  138. ::ShellExecute( NULL,TEXT("explore"),p, NULL, NULL, SW_SHOWNORMAL);
  139. }
  140. void Platform::openFile(const char* path )
  141. {
  142. char filePath[1024];
  143. Platform::makeFullPathName(path, filePath, sizeof(filePath));
  144. #ifdef UNICODE
  145. WCHAR p[ 1024 ];
  146. convertUTF8toUTF16( filePath, p, sizeof( p ) / sizeof( p[ 0 ] ) );
  147. #else
  148. char* p = filePath;
  149. #endif
  150. backslash( p );
  151. ::ShellExecute( NULL,TEXT("open"),p, NULL, NULL, SW_SHOWNORMAL);
  152. }