66
77#include " stdafx.h"
88
9+ #if defined (_WIN32)
10+ #define _CRT_SECURE_NO_WARNINGS
11+ #define WINDOWS_LEAN_AND_MEAN
12+ #include < windows.h>
13+ #endif
14+
915#include < stdarg.h>
1016#if (_MSVC_LANG >= 201703L || __cplusplus >= 201703L)
1117#include < algorithm>
@@ -87,8 +93,12 @@ class ktxApp {
8793 virtual int main (int argc, _TCHAR* argv[]) = 0;
8894 virtual void usage () {
8995 cerr <<
90- " -h, --help Print this usage message and exit.\n "
91- " -v, --version Print the version number of this program and exit.\n " ;
96+ " -h, --help Print this usage message and exit.\n "
97+ " -v, --version Print the version number of this program and exit.\n "
98+ #if defined(_WIN32) && defined(DEBUG)
99+ " --ld Launch Visual Studio deugger at start up.\n "
100+ #endif
101+ ;
92102 };
93103
94104 protected:
@@ -97,8 +107,9 @@ class ktxApp {
97107 _tstring outfile;
98108 int test;
99109 int warn;
110+ int launchDebugger;
100111
101- commandOptions () : test(false ), warn(1 ) { }
112+ commandOptions () : test(false ), warn(1 ), launchDebugger( 0 ) { }
102113 };
103114
104115 ktxApp (std::string& version, std::string& defaultVersion,
@@ -259,7 +270,7 @@ class ktxApp {
259270 listName.erase (0 , relativize ? 2 : 1 );
260271
261272 FILE *lf = nullptr ;
262- #ifdef _WIN32
273+ #if defined( _WIN32)
263274 _tfopen_s (&lf, listName.c_str (), " r" );
264275#else
265276 lf = _tfopen (listName.c_str (), " r" );
@@ -352,6 +363,10 @@ class ktxApp {
352363 }
353364 }
354365 }
366+ #if defined(_WIN32) && defined(DEBUG)
367+ if (options.launchDebugger )
368+ launchDebugger ();
369+ #endif
355370 }
356371
357372 virtual bool processOption (argparser& parser, int opt) = 0;
@@ -366,6 +381,47 @@ class ktxApp {
366381 cerr << endl;
367382 }
368383
384+ #if defined(_WIN32) && defined(DEBUG)
385+ // For use when debugging stdin with Visual Studio which does not have a
386+ // "wait for executable to be launched" choice in its debugger settings.
387+ bool launchDebugger ()
388+ {
389+ // Get System directory, typically c:\windows\system32
390+ std::wstring systemDir (MAX_PATH + 1 , ' \0 ' );
391+ UINT nChars = GetSystemDirectoryW (&systemDir[0 ],
392+ static_cast <UINT>(systemDir.length ()));
393+ if (nChars == 0 ) return false ; // failed to get system directory
394+ systemDir.resize (nChars);
395+
396+ // Get process ID and create the command line
397+ DWORD pid = GetCurrentProcessId ();
398+ std::wostringstream s;
399+ s << systemDir << L" \\ vsjitdebugger.exe -p " << pid;
400+ std::wstring cmdLine = s.str ();
401+
402+ // Start debugger process
403+ STARTUPINFOW si;
404+ ZeroMemory (&si, sizeof (si));
405+ si.cb = sizeof (si);
406+
407+ PROCESS_INFORMATION pi;
408+ ZeroMemory (&pi, sizeof (pi));
409+
410+ if (!CreateProcessW (NULL , &cmdLine[0 ], NULL , NULL , FALSE , 0 , NULL , NULL , &si, &pi)) return false ;
411+
412+ // Close debugger process handles to eliminate resource leak
413+ CloseHandle (pi.hThread );
414+ CloseHandle (pi.hProcess );
415+
416+ // Wait for the debugger to attach
417+ while (!IsDebuggerPresent ()) Sleep (100 );
418+
419+ // Stop execution so the debugger can take over
420+ DebugBreak ();
421+ return true ;
422+ }
423+ #endif
424+
369425 _tstring name;
370426 _tstring& version;
371427 _tstring& defaultVersion;
@@ -378,6 +434,9 @@ class ktxApp {
378434 { " help" , argparser::option::no_argument, NULL , ' h' },
379435 { " version" , argparser::option::no_argument, NULL , ' v' },
380436 { " test" , argparser::option::no_argument, &options.test , 1 },
437+ #if defined(_WIN32) && defined(DEBUG)
438+ { " ld" , argparser::option::no_argument, &options.launchDebugger , 1 },
439+ #endif
381440 // -NSDocumentRevisionsDebugMode YES is appended to the end
382441 // of the command by Xcode when debugging and "Allow debugging when
383442 // using document Versions Browser" is checked in the scheme. It
0 commit comments