1 // Copyright 2001-2019 Crytek GmbH / Crytek Group. All rights reserved.
4 using System
.Collections
.Generic
;
7 using System
.Net
.NetworkInformation
;
8 using System
.Runtime
.InteropServices
;
10 using Microsoft
.VisualStudio
;
11 using Microsoft
.VisualStudio
.OLE
.Interop
;
12 using Microsoft
.VisualStudio
.Shell
.Interop
;
13 using Mono
.Debugging
.Soft
;
14 using Mono
.Debugging
.VisualStudio
;
16 namespace CryEngine
.Debugger
.Mono
18 internal class CryEngineDebuggableConfig
: IVsDebuggableProjectCfg
, IVsProjectFlavorCfg
, IVsProjectCfgDebugTargetSelection
20 private const string DebugTargetGuidString
= "6E87CFAD-6C05-4adf-9CD7-3B7943875B7C";
22 private static readonly uint[] DebugTargetCommandIds
= new uint[] { 0x02001, 0x02002, 0x02003 }
;
23 private static readonly string[] DebugTargetNames
= new string[] { "Debug GameLauncher", "Debug Sandbox", "Debug Server" }
;
24 private static readonly Guid DebugTargetGuid
= new Guid(DebugTargetGuidString
);
26 private static LauncherType _launcherType
= LauncherType
.GameLauncher
;
27 private static IVsDebugTargetSelectionService _debugService
;
29 private IVsProjectFlavorCfg _baseProjectCfg
;
30 private Project _baseProject
;
32 public CryEngineDebuggableConfig(IVsProjectFlavorCfg pBaseProjectCfg
, Project project
)
34 _baseProject
= project
;
35 _baseProjectCfg
= pBaseProjectCfg
;
40 if (_baseProjectCfg
!= null)
42 _baseProjectCfg
.Close();
43 _baseProjectCfg
= null;
46 return VSConstants
.S_OK
;
49 private int GetAvailablePort()
51 const int startPort
= 17615;
52 const int stopPort
= 18000;
53 var random
= new Random(DateTime
.Now
.Millisecond
);
55 IPGlobalProperties ipGlobalProperties
= IPGlobalProperties
.GetIPGlobalProperties();
56 TcpConnectionInformation
[] tcpConnInfoArray
= ipGlobalProperties
.GetActiveTcpConnections();
58 var busyPorts
= tcpConnInfoArray
.Select(t
=> t
.LocalEndPoint
.Port
).Where(v
=> v
>= startPort
&& v
<= stopPort
).ToArray();
60 var firstAvailableRandomPort
= Enumerable
.Range(startPort
, stopPort
- startPort
).OrderBy(v
=> random
.Next()).FirstOrDefault(p
=> !busyPorts
.Contains(p
));
62 return firstAvailableRandomPort
;
66 /// Called when the application is run with debugging support. Otherwise it will just launch.
68 /// <param name="grfLaunch"></param>
69 /// <returns></returns>
70 public int DebugLaunch(uint grfLaunch
)
72 var port
= NetworkHelper
.GetAvailablePort(17615, 18000);
74 var startArgs
= new SoftDebuggerConnectArgs("CRYENGINE", IPAddress
.Loopback
, port
)
76 MaxConnectionAttempts
= 10
79 var startInfo
= new CryEngineStartInfo(startArgs
, null, _baseProject
, CryEngineProjectData
.GetProjectData(_baseProject
), _launcherType
);
80 var session
= new CryEngineDebuggerSession();
82 IDebugLauncher debugLauncher
= new CryEngineDebugLauncher();
83 var progress
= new Progress
<string>();
84 progress
.ProgressChanged
+= OnProgressChanged
;
85 var launcher
= new MonoDebuggerLauncher(progress
, debugLauncher
);
87 launcher
.StartSession(startInfo
, session
);
89 return VSConstants
.S_OK
;
92 private void OnProgressChanged(object sender
, string e
)
94 OutputHandler
.LogMessage(string.Format("[MonoInternal] {0}", e
));
97 public int QueryDebugLaunch(uint grfLaunch
, out int pfCanLaunch
)
100 return VSConstants
.S_OK
;
103 public int get_CfgType(ref Guid iidCfg
, out IntPtr ppCfg
)
109 if (iidCfg
== typeof(IVsDebuggableProjectCfg
).GUID
)
110 ppCfg
= Marshal
.GetComInterfaceForObject(this, typeof(IVsDebuggableProjectCfg
));
111 else if ((ppCfg
== IntPtr
.Zero
) && (this._baseProjectCfg
!= null))
112 return this._baseProjectCfg
.get_CfgType(ref iidCfg
, out ppCfg
);
114 catch (InvalidCastException
)
118 return VSConstants
.S_OK
;
121 public int EnumOutputs(out IVsEnumOutputs ppIVsEnumOutputs
)
123 throw new NotImplementedException();
126 public int get_BuildableProjectCfg(out IVsBuildableProjectCfg ppIVsBuildableProjectCfg
)
128 throw new NotImplementedException();
131 public int get_CanonicalName(out string pbstrCanonicalName
)
133 throw new NotImplementedException();
136 public int get_DisplayName(out string pbstrDisplayName
)
138 throw new NotImplementedException();
141 public int get_IsDebugOnly(out int pfIsDebugOnly
)
143 throw new NotImplementedException();
146 public int get_IsPackaged(out int pfIsPackaged
)
148 throw new NotImplementedException();
151 public int get_IsReleaseOnly(out int pfIsReleaseOnly
)
153 throw new NotImplementedException();
156 public int get_IsSpecifyingOutputSupported(out int pfIsSpecifyingOutputSupported
)
158 throw new NotImplementedException();
161 public int get_Platform(out Guid pguidPlatform
)
163 throw new NotImplementedException();
166 public int get_ProjectCfgProvider(out IVsProjectCfgProvider ppIVsProjectCfgProvider
)
168 throw new NotImplementedException();
171 public int get_RootURL(out string pbstrRootURL
)
173 throw new NotImplementedException();
176 public int get_TargetCodePage(out uint puiTargetCodePage
)
178 throw new NotImplementedException();
181 public int get_UpdateSequenceNumber(ULARGE_INTEGER
[] puliUSN
)
183 throw new NotImplementedException();
186 public int OpenOutput(string szOutputCanonicalName
, out IVsOutput ppIVsOutput
)
188 throw new NotImplementedException();
191 public bool HasDebugTargets(IVsDebugTargetSelectionService pDebugTargetSelectionService
, out Array pbstrSupportedTargetCommandIDs
)
193 _debugService
= pDebugTargetSelectionService
;
195 var targets
= new string[DebugTargetCommandIds
.Length
];
196 for (int i
= 0; i
< DebugTargetCommandIds
.Length
; ++i
)
198 var commandId
= DebugTargetCommandIds
[i
];
199 targets
[i
] = string.Join(":", DebugTargetGuid
, commandId
);
202 pbstrSupportedTargetCommandIDs
= targets
;
206 public Array
GetDebugTargetListOfType(Guid guidDebugTargetType
, uint debugTargetTypeId
)
208 if(guidDebugTargetType
!= DebugTargetGuid
)
210 return new string[0];
213 for (int i
= 0; i
< DebugTargetCommandIds
.Length
; ++i
)
215 if(debugTargetTypeId
== DebugTargetCommandIds
[i
])
217 return new string[] { DebugTargetNames[i] }
;
221 return new string[0];
224 public void GetCurrentDebugTarget(out Guid pguidDebugTargetType
, out uint pDebugTargetTypeId
, out string pbstrCurrentDebugTarget
)
226 pguidDebugTargetType
= DebugTargetGuid
;
227 pDebugTargetTypeId
= DebugTargetCommandIds
[(int)_launcherType
];
228 pbstrCurrentDebugTarget
= DebugTargetNames
[(int)_launcherType
];
231 public void SetCurrentDebugTarget(Guid guidDebugTargetType
, uint debugTargetTypeId
, string bstrCurrentDebugTarget
)
233 if (guidDebugTargetType
!= DebugTargetGuid
)
238 for (int i
= 0; i
< DebugTargetCommandIds
.Length
; ++i
)
240 if(debugTargetTypeId
== DebugTargetCommandIds
[i
])
242 _launcherType
= (LauncherType
)i
;
243 _debugService
?.UpdateDebugTargets();
249 public static void SetCurrentLauncherTarget(LauncherType launcherType
)
251 _launcherType
= launcherType
;
252 _debugService
?.UpdateDebugTargets();