44using System . Linq ;
55using System . Net ;
66using System . Threading ;
7- using System . Threading . Tasks ;
87using Microsoft . VisualStudio . Debugger . Interop ;
8+ using Microsoft . VisualStudio . Shell ;
9+ using Microsoft . VisualStudio . Shell . Interop ;
910using Mono . Debugging . Client ;
1011using Mono . Debugging . Soft ;
1112using SampSharp . VisualStudio . DebugEngine ;
1415using SampSharp . VisualStudio . ProgramProperties ;
1516using SampSharp . VisualStudio . Projects ;
1617using SampSharp . VisualStudio . Utils ;
18+ using Task = System . Threading . Tasks . Task ;
1719
1820namespace SampSharp . VisualStudio . Debugger
1921{
2022 public class DebuggedProgram : IDisposable
2123 {
22- private const int DefaultDebuggerPort = 6438 ;
2324 private readonly MonoBreakpointManager _breakpointManager ;
2425 private readonly MonoEngine _engine ;
2526 private readonly MonoThreadManager _threadManager ;
2627 private AD_PROCESS_ID _processId ;
27-
2828 private Guid _programId ;
2929 private AutoResetEvent _waiter ;
30+ private IVsOutputWindowPane _serverPane ;
3031
3132 public DebuggedProgram ( MonoEngine engine , MonoBreakpointManager breakpointManager ,
3233 MonoThreadManager threadManager )
@@ -107,7 +108,12 @@ public void Break()
107108 Session . Stop ( ) ;
108109 }
109110
110- public void LaunchSuspended ( IDebugPort2 port , string args , string gameMode , string exe , string directory , out IDebugProcess2 process )
111+ private void Log ( string message )
112+ {
113+ _serverPane ? . Log ( message ) ;
114+ }
115+
116+ public void LaunchSuspended ( IDebugPort2 port , string gameMode , bool noWindow , string exe , string directory , out IDebugProcess2 process )
111117 {
112118 _waiter = new AutoResetEvent ( false ) ;
113119
@@ -121,18 +127,63 @@ public void LaunchSuspended(IDebugPort2 port, string args, string gameMode, stri
121127 // Run the server.
122128 Task . Run ( ( ) =>
123129 {
124- Process . Start ( new ProcessStartInfo
130+ if ( noWindow )
125131 {
126- FileName = Path . Combine ( ServerPath , "samp-server.exe" ) ,
127- WorkingDirectory = ServerPath ,
128- UseShellExecute = false ,
129- EnvironmentVariables =
132+ IVsOutputWindow outWindow = Package . GetGlobalService ( typeof ( SVsOutputWindow ) ) as IVsOutputWindow ;
133+
134+ Guid wndGuid = Guids . ServerWindow ;
135+ outWindow . CreatePane ( ref wndGuid , "SA-MP Server" , 1 , 1 ) ;
136+
137+ outWindow . GetPane ( ref wndGuid , out _serverPane ) ;
138+ _serverPane . Clear ( ) ;
139+ Log ( "Starting SA-MP server..." ) ;
140+ _serverPane . Activate ( ) ;
141+
142+
143+ var startInfo = new ProcessStartInfo
130144 {
131- [ "debugger_address" ] = DebuggerAddress . ToString ( ) ,
132- [ "gamemode" ] = $ "{ Path . GetFileNameWithoutExtension ( exe ) } :{ gameMode } "
133- }
134- } ) ;
135-
145+ FileName = Path . Combine ( ServerPath , "samp-server.exe" ) ,
146+ WorkingDirectory = ServerPath ,
147+ UseShellExecute = false ,
148+ CreateNoWindow = true ,
149+ RedirectStandardError = true ,
150+ RedirectStandardOutput = true ,
151+ EnvironmentVariables =
152+ {
153+ [ "debugger_address" ] = DebuggerAddress . ToString ( ) ,
154+ [ "gamemode" ] = $ "{ Path . GetFileNameWithoutExtension ( exe ) } :{ gameMode } "
155+ }
156+ } ;
157+
158+ var server = new Process { StartInfo = startInfo } ;
159+ server . OutputDataReceived += ( sender , args ) =>
160+ {
161+ if ( args . Data != null )
162+ Log ( $ "{ args . Data . Replace ( "\r " , "" ) } ") ;
163+ } ;
164+ server . ErrorDataReceived += ( sender , args ) =>
165+ {
166+ if ( ! string . IsNullOrWhiteSpace ( args . Data ) )
167+ Log ( $ "ERROR: { args . Data } ") ;
168+ } ;
169+ server . Start ( ) ;
170+ server . BeginOutputReadLine ( ) ;
171+ server . BeginErrorReadLine ( ) ;
172+ }
173+ else
174+ {
175+ Process . Start ( new ProcessStartInfo
176+ {
177+ FileName = Path . Combine ( ServerPath , "samp-server.exe" ) ,
178+ WorkingDirectory = ServerPath ,
179+ UseShellExecute = false ,
180+ EnvironmentVariables =
181+ {
182+ [ "debugger_address" ] = DebuggerAddress . ToString ( ) ,
183+ [ "gamemode" ] = $ "{ Path . GetFileNameWithoutExtension ( exe ) } :{ gameMode } "
184+ }
185+ } ) ;
186+ }
136187 // Trigger that the app is now running for whomever might be waiting for that signal
137188 _waiter . Set ( ) ;
138189 } ) ;
@@ -276,15 +327,10 @@ private void ComputeServerDirectory(string path)
276327
277328 private void ComputeAvailableDebuggerAddress ( )
278329 {
279- var address = new DebuggerAddress ( DefaultDebuggerPort ) ;
280-
281- if ( ! address . IsAvailable ( ) )
282- address = address . GetNextAvailable ( ) ;
330+ var address = DebuggerAddress . GetAvailable ( ) ;
283331
284332 if ( address == null )
285- {
286333 throw new DebuggerInitializeException ( "Debugger port is unavailable." ) ;
287- }
288334
289335 DebuggerAddress = address ;
290336 }
@@ -298,34 +344,20 @@ private void CreateDebuggerSession()
298344 _threadManager . Add ( activeThread , new MonoThread ( _engine , activeThread ) ) ;
299345 } ;
300346
301- Session . ExceptionHandler = exception => true ;
302- Session . TargetExited +=
303- ( sender , x ) =>
304- {
305- _engine . Callback . Send ( new SampSharpDestroyEvent ( ( uint ? ) x . ExitCode ?? 0 ) , SampSharpDestroyEvent . Iid , null ) ;
306- } ;
307- Session . TargetUnhandledException += ( sender , x ) =>
308- {
309- _engine . Log ( "Unhandled exception!" + x ) ;
310- } ; // todo
311- Session . TargetExceptionThrown += ( sender , e ) =>
347+ Session . ExceptionHandler = e =>
312348 {
313- _engine . Log ( "Exception: " + e ) ;
349+ Log ( $ "DEBUGGER ERROR: { e } ") ;
350+ return true ;
314351 } ;
315- Session . LogWriter = ( stderr , text ) => { } ;
316- Session . OutputWriter = ( stderr , text ) => { } ;
317352 Session . TargetThreadStarted +=
318353 ( sender , x ) => { _threadManager . Add ( x . Thread , new MonoThread ( _engine , x . Thread ) ) ; } ;
319354 Session . TargetThreadStopped += ( sender , x ) => { _threadManager . Remove ( x . Thread ) ; } ;
320- Session . TargetStopped += ( sender , x ) => { } ;
321- Session . TargetStarted += ( sender , x ) => { } ;
322- Session . TargetSignaled += ( sender , x ) => { } ;
323- Session . TargetInterrupted += ( sender , x ) => { } ;
324- Session . TargetExceptionThrown += ( sender , x ) =>
355+ Session . TargetExited += ( sender , x ) => _engine . Callback . Send ( new SampSharpDestroyEvent ( ( uint ? ) x . ExitCode ?? 0 ) , SampSharpDestroyEvent . Iid , null ) ;
356+ Session . TargetExceptionThrown += ( sender , args ) =>
325357 {
326358 _engine . Callback . Send (
327359 new MonoBreakpointEvent ( new MonoBoundBreakpointsEnumerator ( new IDebugBoundBreakpoint2 [ 0 ] ) ) ,
328- MonoStepCompleteEvent . Iid , _threadManager [ x . Thread ] ) ;
360+ MonoStepCompleteEvent . Iid , _threadManager [ args . Thread ] ) ;
329361 } ;
330362 Session . TargetHitBreakpoint += ( sender , x ) =>
331363 {
0 commit comments