Skip to content
This repository was archived by the owner on Jan 16, 2019. It is now read-only.

Commit 631cf28

Browse files
committed
Added no window option and fixed a few bugs
1 parent 6392360 commit 631cf28

File tree

8 files changed

+249
-118
lines changed

8 files changed

+249
-118
lines changed

SampSharp.VisualStudio/DebugEngine/Guids.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,10 @@ public static class Guids
5555
/// The filter all locals and arguments GUID.
5656
/// </summary>
5757
public static Guid FilterAllLocalsPlusArgs = new Guid("939729a8-4cb0-4647-9831-7ff465240d5f");
58+
59+
/// <summary>
60+
/// The server window GUID.
61+
/// </summary>
62+
public static Guid ServerWindow = new Guid("e7aa0b93-e5ff-4a46-80be-7a535fff2a53");
5863
}
5964
}

SampSharp.VisualStudio/DebugEngine/MonoEngine.cs

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ public MonoEngine()
3232
public MonoCallback Callback { get; private set; }
3333
public DebuggedProgram Program { get; }
3434

35+
public IVsOutputWindowPane OutputWindow => _outputWindow;
36+
3537
#region Implementation of IDebugSymbolSettings100
3638

3739
/// <summary>
@@ -102,24 +104,7 @@ public string GetLocationInfo(IDebugDocumentPosition2 docPosition, out TEXT_POSI
102104

103105
return documentName;
104106
}
105-
106-
/// <summary>
107-
/// Logs a message to the debugger, console and output window.
108-
/// </summary>
109-
/// <param name="message"></param>
110-
public void Log(string message)
111-
{
112-
Debug.WriteLine(message);
113-
Console.WriteLine(message);
114-
_outputWindow.OutputString(message + "\r\n");
115-
}
116107

117-
public void Log(VsLogSeverity severity, string project, string file,
118-
string consoleMessage, int lineNumber = 0, int column = 0)
119-
{
120-
_outputWindow.Log(severity, project, file, consoleMessage, lineNumber, column);
121-
}
122-
123108
private void OnStartDebuggingFailed(Exception exception)
124109
{
125110
if (exception is OperationCanceledException)
@@ -153,14 +138,14 @@ public int CreatePendingBreakpoint(IDebugBreakpointRequest2 request,
153138
try
154139
{
155140
pendingBreakpoint = Program.CreatePendingBreakpoint(request);
141+
142+
return S_OK;
156143
}
157144
catch
158145
{
159146
pendingBreakpoint = null;
160147
return E_FAIL;
161148
}
162-
163-
return E_FAIL;
164149
}
165150

166151
/// <summary>
@@ -653,7 +638,15 @@ public int LaunchSuspended(string server, IDebugPort2 port, string exe, string a
653638
Callback = new MonoCallback(callback, this);
654639
try
655640
{
656-
Program.LaunchSuspended(port, args, options, exe, directory, out process);
641+
var opt = options.Split(new[] { "|split|" }, StringSplitOptions.None);
642+
643+
if (opt.Length != 2)
644+
throw new Exception("Invalid launch options");
645+
646+
bool noWindow;
647+
bool.TryParse(opt[1], out noWindow);
648+
649+
Program.LaunchSuspended(port, opt[0], noWindow, exe, directory, out process);
657650

658651
return S_OK;
659652
}

SampSharp.VisualStudio/Debugger/DebuggedProgram.cs

Lines changed: 72 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
using System.Linq;
55
using System.Net;
66
using System.Threading;
7-
using System.Threading.Tasks;
87
using Microsoft.VisualStudio.Debugger.Interop;
8+
using Microsoft.VisualStudio.Shell;
9+
using Microsoft.VisualStudio.Shell.Interop;
910
using Mono.Debugging.Client;
1011
using Mono.Debugging.Soft;
1112
using SampSharp.VisualStudio.DebugEngine;
@@ -14,19 +15,19 @@
1415
using SampSharp.VisualStudio.ProgramProperties;
1516
using SampSharp.VisualStudio.Projects;
1617
using SampSharp.VisualStudio.Utils;
18+
using Task = System.Threading.Tasks.Task;
1719

1820
namespace 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
{

SampSharp.VisualStudio/Debugger/DebuggerAddress.cs

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Linq;
33
using System.Net;
44
using System.Net.NetworkInformation;
5+
using System.Net.Sockets;
56

67
namespace SampSharp.VisualStudio.Debugger
78
{
@@ -31,31 +32,18 @@ public override string ToString()
3132
return $"{Ip}:{Port}";
3233
}
3334

34-
public bool IsAvailable()
35+
public static DebuggerAddress GetAvailable()
3536
{
36-
var ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
37-
var tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();
38-
39-
return tcpConnInfoArray.All(tcpi => tcpi.LocalEndPoint.Port != Port);
37+
return new DebuggerAddress(LocalIp, (ushort) FreeTcpPort());
4038
}
4139

42-
public DebuggerAddress GetNextAvailable()
40+
private static int FreeTcpPort()
4341
{
44-
if (!Ip.Equals(LocalIp))
45-
return null;
46-
47-
int port = Port;
48-
port++;
49-
50-
if (port > ushort.MaxValue)
51-
return null;
52-
53-
var addr = new DebuggerAddress(LocalIp, (ushort) port);
54-
55-
while (addr != null && !addr.IsAvailable())
56-
addr = addr.GetNextAvailable();
57-
58-
return addr;
42+
var l = new TcpListener(IPAddress.Loopback, 0);
43+
l.Start();
44+
var port = ((IPEndPoint) l.LocalEndpoint).Port;
45+
l.Stop();
46+
return port;
5947
}
6048

6149
public static bool TryParse(string s, out DebuggerAddress result)

SampSharp.VisualStudio/ProgramProperties/SampSharpPropertiesView.Designer.cs

Lines changed: 30 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

SampSharp.VisualStudio/ProgramProperties/SampSharpPropertiesView.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ protected override PropertyControlTable PropertyControlTable
5252
// Add two Property Name / Control KeyValuePairs.
5353
_propertyControlTable.Add(SampSharpPropertyPage.MonoDirectory, monoLocationTextBox);
5454
_propertyControlTable.Add(SampSharpPropertyPage.GameMode, gameModeTextBox);
55+
_propertyControlTable.Add(SampSharpPropertyPage.NoWindow, noWindowCheckbox);
5556
}
5657
return _propertyControlTable;
5758
}

0 commit comments

Comments
 (0)