public void DotWaitAndDotResultAreNeverUsed() { //TODO: We should use Roslyn to do this //What this expression means: //(?<!//.*?) -- Make sure that any await we find is not preceeded on the same line by // //(?s: -- means . will match newlines in this sub-expression. //\\.Wait\\(\\) -- matches .Wait() //(?<!this\\.?)\\.Result(\\.|;|\\s|,) -- matches .Result followed by a ., ;, whitespace, or , which is not prefixed immediately by "this." const string pattern = "(?<!//.*?)(?s:(\\.Wait\\(\\)|(?<!this\\.?)\\.Result(\\.|;|\\s|,)))"; SourceParser sourceParser = new SourceParser(this.sourceLocation, SourceFileType, null, pattern); List <SourceParserResult> results = sourceParser.Parse().ToList(); //There should be no .Result or .Wait() calls outside of the two which are expected below //Remove the two we expect results.Remove(results.First(r => r.File.Contains("UtilitiesInternal.cs"))); results.Remove(results.First(r => r.File.Contains("SynchronousMethodExceptionBehavior.cs"))); foreach (SourceParserResult parserResult in results) { this.testOutputHelper.WriteLine("Found .Wait or .Result in {0} at {1} -- {2}", parserResult.File, parserResult.LineNumber, parserResult.Match); } Assert.Equal(0, results.Count); }
/// <summary> /// Initializes a new instance of the <see cref="StringBasedSourceCode"/> class. /// </summary> /// <param name="project"> /// The project. /// </param> /// <param name="parser"> /// The parser. /// </param> /// <param name="path"> /// The path. /// </param> /// <param name="source"> /// The source. /// </param> public StringBasedSourceCode(CodeProject project, SourceParser parser, string path, string source) : base(project, parser) { this.source = source; this.path = path; // Strip out the name of the file. int index = path.LastIndexOf(@"\", StringComparison.Ordinal); if (-1 == index) { this.name = this.path; } else { this.name = path.Substring(index + 1, path.Length - index - 1); } // Strip out the file extension. index = this.name.LastIndexOf(".", StringComparison.Ordinal); if (-1 == index) { this.fileType = string.Empty; } else { this.fileType = this.name.Substring(index + 1, this.name.Length - index - 1).ToUpperInvariant(); } }
public async Task Parsing() { const string source = "portal2_sp.dem"; var parser = new SourceParser(); var demo = await parser.ParseFromFileAsync(Paths.Demos + source); }
public async Task Net() { const string source = "portal2.dem"; var parser = new SourceParser(new SourceParserOptions() { ReadPackets = true }); var demo = await parser.ParseFromFileAsync(Paths.Demos + source); var dump = new System.Collections.Generic.List <string>(); foreach (var msg in demo.Messages) { if (msg is Packet packet) { dump.Add($"--- tick {msg.Tick} ---"); foreach (var nmsg in packet.NetMessages) { dump.Add($"{nmsg.Code} {nmsg.Name}"); } } } await System.IO.File.WriteAllLinesAsync("logs/dump.txt", dump); }
public void PrintSetails(SourceParser d) { if (CurrentDemoFile == null) { return; } richTextBox1.Text = string.Format("Analyzed source engine demo file:" + "\n" + "----------------------------------------------------------{0}\n", $"\n{$"Demo protocol: {CurrentDemoFile.Info.DemoProtocol}\n"}{$"Net protocol: {CurrentDemoFile.Info.NetProtocol}\n"}{$"Server name: {CurrentDemoFile.Info.ServerName}\n"}{$"Client name: {CurrentDemoFile.Info.ClientName}\n"}{$"Map name: {CurrentDemoFile.Info.MapName}\n"}{$"Game directory: {CurrentDemoFile.Info.GameDirectory}\n"}{$"Length in seconds: {CurrentDemoFile.Info.Seconds}\n"}{$"Tick count: {CurrentDemoFile.Info.TickCount}\n"}{$"Frame count: {CurrentDemoFile.Info.FrameCount}\n"}----------------------------------------------------------"); foreach (var f in CurrentDemoFile.Info.Flags) { switch (f.Name) { case "#SAVE#": richTextBox1.Text += $"#SAVE# flag at Tick: {f.Tick} -> {f.Time}s" + "\n"; HighlightLastLine(richTextBox1, Color.Yellow); break; case "autosave": richTextBox1.Text += $"Autosave at Tick: {f.Tick} -> {f.Time}s" + "\n"; HighlightLastLine(richTextBox1, Color.DarkOrange); break; default: break; } } }
public async Task Discover() { try { const string source = "portal2_cm_coop.dem"; var parser = new SourceParser(); var demo = await parser.ParseFromFileAsync(Paths.Demos + source); Console.WriteLine("Before: " + demo.PlaybackTicks); // Load automatically from assembly #if !DISCOVER_2 await Adjustments.DiscoverAsync(); #else await Adjustments.DiscoverAsync(System.Reflection.Assembly.GetEntryAssembly()); #endif await demo.AdjustAsync(); Console.WriteLine("After: " + demo.PlaybackTicks); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } }
private void fontToolStripMenuItem1_Click(object sender, EventArgs e) { try { using (var fd = new FontDialog()) { if (fd.ShowDialog() == DialogResult.OK) { richTextBox1.Font = fd.Font; } } if (CurrentFile == null || (!File.Exists(CurrentFile) || Path.GetExtension(CurrentFile) != ".dem")) { return; } Stream cfs = File.Open(CurrentFile, FileMode.Open); CurrentDemoFile = new SourceParser(cfs); cfs.Close(); PrintSetails(CurrentDemoFile); toolsToolStripMenuItem.Enabled = true; Log(Path.GetFileName(CurrentFile + " rescanned for font change.")); //Terribble hack for recolor. Log("Font changed"); } catch (Exception ex) { Log(ex.Message); } }
/// <summary> /// Parses a demo file from any engine /// </summary> /// <param name="filename">Path to the file</param> /// <returns></returns> public static CrossParseResult Parse(string filename) { var cpr = new CrossParseResult(); switch (CheckDemoType(filename)) { case Parseresult.GoldSource: cpr.Type = Parseresult.GoldSource; cpr.GsDemoInfo = GoldSourceParser.ReadGoldSourceDemo(filename); break; case Parseresult.UnsupportedFile: cpr.Type = Parseresult.UnsupportedFile; Main.Log("Demotype check resulted in an unsupported file."); break; case Parseresult.Source: cpr.Type = Parseresult.Source; var a = new SourceParser(new MemoryStream(File.ReadAllBytes(filename))); cpr.Sdi = a.Info; if (cpr.Sdi.GameDirectory == "portal") { cpr.Type = Parseresult.Portal; var lp = new L4D2BranchParser(); cpr.L4D2BranchInfo = lp.Parse(filename); } break; case Parseresult.Hlsooe: cpr.Type = Parseresult.Hlsooe; cpr.HlsooeDemoInfo = GoldSourceParser.ParseDemoHlsooe(filename); break; case Parseresult.L4D2Branch: cpr.Type = Parseresult.L4D2Branch; var l = new L4D2BranchParser(); cpr.L4D2BranchInfo = l.Parse(filename); break; default: cpr.Type = Parseresult.UnsupportedFile; Main.Log( "No idea how the f**k did this happen but default happened at switch(CheckDemoType(filename))"); break; } if (cpr.Type == Parseresult.GoldSource) { if (cpr.GsDemoInfo.ParsingErrors.Count > 0) { if (MessageBox.Show(@"Would you like to open the demo doctor?", @"Demo errors detected!", MessageBoxButtons.YesNo) == DialogResult.Yes) { using (var dd = new DemoDoctor(filename)) dd.ShowDialog(); } } } cpr.DisplayData = GetDemoDataTuples(cpr); return(cpr); }
public async Task OldEngine() { const string source = "hl2oe.dem"; var parser = new SourceParser(); var demo = await parser.ParseFromFileAsync(Paths.Demos + source); Console.WriteLine($"Messages: {demo.Messages.Count}"); }
/// <summary> /// Retrieves a <see cref="SourceCode"/> object corresponding to the given path. /// </summary> /// <param name="path"> /// The path to the source code object. /// </param> /// <param name="project"> /// The project which contains the source code object. /// </param> /// <param name="parser"> /// The parser for the source code type. /// </param> /// <param name="context"> /// Optional context. /// </param> /// <returns> /// Returns the source code object. /// </returns> private SourceCode SourceCodeFactory(string path, CodeProject project, SourceParser parser, object context) { Param.Ignore(path, project, parser, context); int index = (int)context; Assert.IsTrue(index >= 0 && index < StaticSource.Sources.Length, "The index is out of range."); return new ObjectBasedSourceCode(project, parser, index); }
/// <summary> /// Initializes a new instance of the <see cref="ObjectBasedSourceCode"/> class. /// </summary> /// <param name="project"> /// The project. /// </param> /// <param name="parser"> /// The parser. /// </param> /// <param name="index"> /// The index. /// </param> public ObjectBasedSourceCode(CodeProject project, SourceParser parser, int index) : base(project, parser) { Param.Ignore(project); Param.Ignore(parser); Param.AssertValueBetween(index, 0, StaticSource.Sources.Length - 1, "Out of range."); this.index = index; }
/// <summary> /// The create. /// </summary> /// <param name="path"> /// The path. /// </param> /// <param name="project"> /// The project. /// </param> /// <param name="parser"> /// The parser. /// </param> /// <param name="context"> /// The context. /// </param> /// <returns> /// A new StringBasedSourceCode object. /// </returns> public SourceCode Create(string path, CodeProject project, SourceParser parser, object context) { StyleCopTrace.In(); string source = (string)context; SourceCode sourceCode = source == null ? (SourceCode) new CodeFile(path, project, parser) : new StringBasedSourceCode(project, parser, path, source); return(StyleCopTrace.Out(sourceCode)); }
/// <summary> /// The create. /// </summary> /// <param name="path"> /// The path. /// </param> /// <param name="project"> /// The project. /// </param> /// <param name="parser"> /// The parser. /// </param> /// <param name="context"> /// The context. /// </param> /// <returns> /// A new StringBasedSourceCode object. /// </returns> public SourceCode Create(string path, CodeProject project, SourceParser parser, object context) { StyleCopTrace.In(); string source = (string)context; StyleCopTrace.Out(); return(new StringBasedSourceCode(project, parser, path, source)); }
/// <summary> /// The create. /// </summary> /// <param name="path"> /// The path. /// </param> /// <param name="project"> /// The project. /// </param> /// <param name="parser"> /// The parser. /// </param> /// <param name="context"> /// The context. /// </param> /// <returns> /// A new StringBasedSourceCode object. /// </returns> public SourceCode Create(string path, CodeProject project, SourceParser parser, object context) { StyleCopTrace.In(); string source = (string)context; SourceCode sourceCode = source == null ? (SourceCode)new CodeFile(path, project, parser) : new StringBasedSourceCode(project, parser, path, source); return StyleCopTrace.Out(sourceCode); }
/// <summary> /// The create. /// </summary> /// <param name="path"> /// The path. /// </param> /// <param name="project"> /// The project. /// </param> /// <param name="parser"> /// The parser. /// </param> /// <param name="context"> /// The context. /// </param> /// <returns> /// A new StringBasedSourceCode object. /// </returns> public SourceCode Create(string path, CodeProject project, SourceParser parser, object context) { StyleCopTrace.In(); string source = (string)context; StyleCopTrace.Out(); return new StringBasedSourceCode(project, parser, path, source); }
public Source(CodeProject project, SourceParser parser, string source, string sourceName) : base(project, parser) { Param.Ignore(project); Param.Ignore(parser); Param.AssertNotNull(source, "source"); Param.AssertNotNull(sourceName, "sourceName"); this.source = source; this.sourceName = sourceName; }
public async Task Portal() { const string source = "portal_steampipe.dem"; var parser = new SourceParser(); var demo = await parser.ParseFromFileAsync(Paths.Demos + source); Console.WriteLine($"Messages: {demo.Messages.Count}"); foreach (var message in demo.Messages.Take(50)) { Console.WriteLine(message); } }
public async Task Portal2() { const string source = "portal2_sp.dem"; var parser = new SourceParser(); var demo = await parser.ParseFromFileAsync(Paths.Demos + source); foreach (var message in demo.Messages) { if (message is UserCmd ucmsg) { Console.WriteLine(message.Tick + ": " + (ucmsg as UserCmd).Cmd.SideMove); } } }
// TODO: Real benchmarking public async Task Timing() { const string source = "portal2_sp.dem"; var watch = new Stopwatch(); var fast = new SourceParser(); var slow = new SourceParser(new SourceParserOptions() { ReadPackets = true, ReadDataTables = true, ReadStringTables = true, ReadUserCmds = true, }); var headeronly = new SourceParser(new SourceParserOptions() { ReadMessages = false }); // Everything watch = Stopwatch.StartNew(); _ = await slow.ParseFromFileAsync(Paths.Demos + source); watch.Stop(); var result2 = watch.Elapsed.TotalMilliseconds; // Default watch = Stopwatch.StartNew(); _ = await fast.ParseFromFileAsync(Paths.Demos + source); watch.Stop(); var result1 = watch.Elapsed.TotalMilliseconds; // Header only watch = Stopwatch.StartNew(); _ = await headeronly.ParseFromFileAsync(Paths.Demos + source); watch.Stop(); var result3 = watch.Elapsed.TotalMilliseconds; Console.WriteLine($"Default: {result1}ms"); Console.WriteLine($"Everything: {result2}ms ({(int)(result2 / result1)} times slower)"); Console.WriteLine($"Header only: {result3}ms ({(int)(result1 / result3)} times faster)"); /* Random Result * Default: 33.0111ms * Everything: 82.6472ms (2 times slower) * Header only: 0.1249ms (264 times faster) */ }
private void rescanFileToolStripMenuItem_Click(object sender, EventArgs e) { if (CurrentFile == null || (!File.Exists(CurrentFile) || Path.GetExtension(CurrentFile) != ".dem")) { return; } Stream cfs = File.Open(CurrentFile, FileMode.Open); CurrentDemoFile = new SourceParser(cfs); cfs.Close(); PrintSetails(CurrentDemoFile); toolsToolStripMenuItem.Enabled = true; Log(Path.GetFileName(CurrentFile + " rescanned.")); }
public async Task Analyze() { const string source = "splice.dem"; var parser = new SourceParser(); var demo = await parser.ParseFromFileAsync(Paths.Export + source); using (var fs = File.Create(Paths.Logs + "test.txt")) using (var sr = new StreamWriter(fs)) { foreach (var msg in demo.Messages) { sr.WriteLine(msg); } } }
static void Main(string[] args) { SystemGeneratedSourceCache.Data = new Dictionary <string, object> { ["a"] = -2, ["b"] = 3 }; var statement = "multiply(sum(a,b), square(3))"; var a = SourceParser.Evaluate(statement); var toAndBack = SourceParser.ToAndBack(statement); Console.WriteLine("{0} = {1}", statement, a); Console.WriteLine("{0} = {1}", statement, toAndBack); }
/// <summary> /// This does an asynchronous demo parse. /// </summary> /// <param name="filepath"></param> /// <returns></returns> /// <summary> /// Parses a demo file from any engine /// </summary> /// <param name="filename">Path to the file</param> /// <returns></returns> public static CrossParseResult Parse(string filename) { var cpr = new CrossParseResult(); switch (CheckDemoType(filename)) { case Parseresult.GoldSource: cpr.Type = Parseresult.GoldSource; cpr.GsDemoInfo = GoldSourceParser.ReadGoldSourceDemo(filename); break; case Parseresult.UnsupportedFile: cpr.Type = Parseresult.UnsupportedFile; //Main.//Log("Demotype check resulted in an unsupported file."); break; case Parseresult.Source: cpr.Type = Parseresult.Source; var a = new SourceParser(new MemoryStream(File.ReadAllBytes(filename))); cpr.Sdi = a.Info; if (cpr.Sdi.GameDirectory == "portal") { cpr.Type = Parseresult.Portal; var lp = new L4D2BranchParser(); cpr.L4D2BranchInfo = lp.Parse(filename); } break; case Parseresult.Hlsooe: cpr.Type = Parseresult.Hlsooe; cpr.HlsooeDemoInfo = GoldSourceParser.ParseDemoHlsooe(filename); break; case Parseresult.L4D2Branch: cpr.Type = Parseresult.L4D2Branch; var l = new L4D2BranchParser(); cpr.L4D2BranchInfo = l.Parse(filename); break; default: cpr.Type = Parseresult.UnsupportedFile; break; } cpr.DisplayData = GetDemoDataTuples(cpr); return(cpr); }
public void ExceptionsThrownDirectlyByObjectModelDontChange() { const string exceptionNameCaptureGroup = "ExceptionName"; string pattern = GetExceptionCaptureRegex(exceptionNameCaptureGroup); SourceParser sourceParser = new SourceParser(this.sourceLocation, SourceFileType, GeneratedProtocolFolder, pattern); List <SourceParserResult> results = sourceParser.Parse().ToList(); //Ensure we've scanned at least some files... const int expectedExceptionCount = 50; this.testOutputHelper.WriteLine("Found {0} \"throw new Exception\" strings", results.Count); Assert.True(results.Count > expectedExceptionCount); HashSet <string> exceptionSet = new HashSet <string>(); foreach (SourceParserResult parserResult in results) { string exceptionName = parserResult.Match.Groups[exceptionNameCaptureGroup].Value; exceptionSet.Add(exceptionName); } this.testOutputHelper.WriteLine("Found {0} types of exception thrown by object model", exceptionSet.Count); this.testOutputHelper.WriteLine("Exceptions:"); this.testOutputHelper.WriteLine("------------------------"); foreach (string exceptionType in exceptionSet) { this.testOutputHelper.WriteLine("{0}", exceptionType); } var expectedExceptions = new HashSet <string> { "ArgumentNullException", "AddTaskCollectionTerminatedException", "BatchClientException", "RunOnceException", "TimeoutException", "ArgumentOutOfRangeException", "InvalidOperationException", "ArgumentException", "FileNotFoundException", "ParallelOperationsException", }; Assert.Equal(expectedExceptions.OrderBy(e => e), exceptionSet.OrderBy(e => e)); }
public Main() { InitializeComponent(); AllowDrop = true; HotkeyTimer.Start(); goldSourceToolsToolStripMenuItem.Enabled = false; toolsToolStripMenuItem.Enabled = false; GlobalHotkeys.RegisterHotKey(Handle, _hotkey.HotkeyID, (int)global::GlobalHotkeys.MOD_ALT, (int)Keys.D); _hotkey.UnregisterGlobalHotKey(); if (File.Exists(LogPath)) { File.Delete(LogPath); } #region OpenedWithFile check var dropFile = (Environment.GetCommandLineArgs().Any(x => Path.GetExtension(x) == ".dem")) ? Environment.GetCommandLineArgs().First(x => Path.GetExtension(x) == ".dem") : null; if (dropFile == null) { toolsToolStripMenuItem.Enabled = false; richTextBox1.Text = "^ Use File->Open to open a correct \".dem\" file!" + "\n" + "No file dropped!"; } else { if (Path.GetExtension(dropFile) == ".dem") { CurrentFile = dropFile; Stream cfs = File.Open(CurrentFile, FileMode.Open); CurrentDemoFile = new SourceParser(cfs); cfs.Close(); PrintSetails(CurrentDemoFile); toolsToolStripMenuItem.Enabled = true; Log(Path.GetFileName(CurrentFile + " opened")); } else { toolsToolStripMenuItem.Enabled = false; richTextBox1.Text = "^ Use File->Open to open a correct \".dem\" file!" + "\n" + "No file dropped!"; } } #endregion }
public async Task <List <ISourceVacancy> > Load() { if (SourceParser == null) { throw new Exception("Не определен адаптер для разбора данных с ресурса."); } if (Url == null) { throw new Exception("Не определен адрес ресурса ресурса."); } var htmlText = await GetSourcHtmlText(); var results = SourceParser.Parse(htmlText); return(await Task.FromResult(results)); }
public async Task Cleanup() { const string source = "portal2_pausing.dem"; var parser = new SourceParser(); var demo = await parser.ParseFromFileAsync(Paths.Demos + source); bool RemovePacket = false; var copy = demo.Messages.ToArray(); demo.Messages.CopyTo(copy); var index = 0; foreach (var msg in copy) { if (msg.Tick > 0) { if (msg is ConsoleCmd console) { if (console.Command == "gameui_activate") { RemovePacket = true; } else if (console.Command == "gameui_hide") { RemovePacket = false; } } else if ((msg is UserCmd) || (msg is Packet)) { if (RemovePacket) { demo.Messages.RemoveAt(index); --index; } } } ++index; } var exporter = new SourceExporter(); await exporter.ExportToFileAsync(Paths.Demos + "portal2_cleanup.dem", demo); }
private void renameDemoToolStripMenuItem_Click(object sender, EventArgs e) { if (CurrentFile == null || !File.Exists(CurrentFile) || Path.GetExtension(CurrentFile) != ".dem") { return; } Stream cfs = File.Open(CurrentFile, FileMode.Open); CurrentDemoFile = new SourceParser(cfs); cfs.Close(); var time = (CurrentDemoFile.Info.Flags.Count(x => x.Name == "#SAVE#") == 0) ? CurrentDemoFile.Info.Seconds.ToString("#,0.000") : CurrentDemoFile.Info.Flags.Last(x => x.Name == "#SAVE#").Time.ToString("#,0.000"); File.Move(CurrentFile, Path.GetDirectoryName(CurrentFile) + "\\" + CurrentDemoFile.Info.MapName.Substring(3, CurrentDemoFile.Info.MapName.Length - 3) + "-" + $"{time}" + "-" + CurrentDemoFile.Info.ClientName + ".dem"); }
public void ExceptionsThrownDirectlyByRestProxyDontChange() { const string exceptionNameCaptureGroup = "ExceptionName"; string pattern = GetExceptionCaptureRegex(exceptionNameCaptureGroup); SourceParser sourceParser = new SourceParser(this.proxySourceLocation, SourceFileType, null, pattern); List <SourceParserResult> results = sourceParser.Parse().ToList(); //Ensure we've scanned at least some files... const int expectedExceptionCount = 100; this.testOutputHelper.WriteLine("Found {0} \"throw new Exception\" strings", results.Count); Assert.True(results.Count > expectedExceptionCount); HashSet <string> exceptionSet = new HashSet <string>(); foreach (SourceParserResult parserResult in results) { string exceptionName = parserResult.Match.Groups[exceptionNameCaptureGroup].Value; exceptionSet.Add(exceptionName); } this.testOutputHelper.WriteLine("Found {0} types of exception thrown by rest proxy", exceptionSet.Count); this.testOutputHelper.WriteLine("Exceptions:"); this.testOutputHelper.WriteLine("------------------------"); foreach (string exceptionType in exceptionSet) { this.testOutputHelper.WriteLine("{0}", exceptionType); } IEnumerable <string> expectedExceptions = new List <string>() { "ArgumentNullException", "ValidationException", "SerializationException" }; Assert.Equal(expectedExceptions, exceptionSet); }
/// <summary> /// Initializes a new instance of the <see cref="StringBasedSourceCode"/> class. /// </summary> /// <param name="project"> /// The project. /// </param> /// <param name="parser"> /// The parser. /// </param> /// <param name="path"> /// The path. /// </param> /// <param name="source"> /// The source. /// </param> public StringBasedSourceCode(CodeProject project, SourceParser parser, string path, string source) : base(project, parser) { this.source = source; this.path = path; // Strip out the name of the file. int index = path.LastIndexOf(@"\", StringComparison.Ordinal); if (-1 == index) { this.name = this.path; } else { this.name = path.Substring(index + 1, path.Length - index - 1); this.folder = path.Substring(0, index); if (this.folder != null) { // Trim the path and convert it to lowercase characters // so that we can do string matches and find other files and // projects under the same path. this.folder = CleanPath(this.folder); } } // Strip out the file extension. index = this.name.LastIndexOf(".", StringComparison.Ordinal); if (-1 == index) { this.fileType = string.Empty; } else { this.fileType = this.name.Substring(index + 1, this.name.Length - index - 1).ToUpperInvariant(); } }
private void openToolStripMenuItem_Click(object sender, EventArgs e) { using (var of = new OpenFileDialog()) { of.Filter = "Demo files | *.dem"; switch (of.ShowDialog()) { case DialogResult.OK: CurrentFile = of.FileName; if (CurrentFile != null && (File.Exists(CurrentFile) && Path.GetExtension(CurrentFile) == ".dem")) { Stream cfs = File.Open(CurrentFile, FileMode.Open); CurrentDemoFile = new SourceParser(cfs); cfs.Close(); PrintSetails(CurrentDemoFile); toolsToolStripMenuItem.Enabled = true; Log(Path.GetFileName(CurrentFile) + " opened!"); } break; } } }
private void Main_DragDrop(object sender, DragEventArgs e) { var dropfiles = (string[])e.Data.GetData(DataFormats.FileDrop); var dropfile = (dropfiles.Any(x => Path.GetExtension(x) == ".dem")) ? dropfiles.First(x => Path.GetExtension(x) == ".dem") : null; if (dropfile != null) { CurrentFile = dropfile; } if (CurrentFile == null || (!File.Exists(CurrentFile) || Path.GetExtension(CurrentFile) != ".dem")) { return; } Stream cfs = File.Open(CurrentFile, FileMode.Open); CurrentDemoFile = new SourceParser(cfs); cfs.Close(); PrintSetails(CurrentDemoFile); toolsToolStripMenuItem.Enabled = true; Log(Path.GetFileName(CurrentFile) + " opened!"); }