// Methods to write Binary Serialization Record onto the stream, a record is composed of primitive types internal void WriteSerializationHeader(int topId, int headerId, int minorVersion, int majorVersion) { SerializationHeaderRecord record = new SerializationHeaderRecord(BinaryHeaderEnum.SerializedStreamHeader, topId, headerId, minorVersion, majorVersion); record.Dump(); record.Write(this); }
IRecordObject IRecordTypeHandler.Handle(IAnalyze analyze) { //EOF //感觉是无意义的数据 while (analyze.Reader.BaseStream.Position < analyze.Reader.BaseStream.Length) { if (analyze.Reader.BaseStream.Position == 1) { break; } else { return(null); } } var record = new SerializationHeaderRecord(); record.RootId = analyze.Reader.ReadInt32(); record.HeaderId = analyze.Reader.ReadInt32(); record.MajorVersion = analyze.Reader.ReadInt32(); record.MinorVersion = analyze.Reader.ReadInt32(); return(record); }
/// <summary> /// Attempt to dump a set of classes that can be used to deserialize a .NET binary stream /// </summary> /// <param name="argument">The file to parse</param> /// <param name="classPrefix">Search for classes with the specified prefix (supports multiple)</param> /// <param name="fullScan">Search every possible class structure</param> /// <param name="namespaceToOutput">The namespace to use in the output files</param> /// <param name="outputPath">Where to output the files, if not supplied will create an 'generated' directory in the input directory</param> /// <returns></returns> private static int Main( FileInfo argument, string[] classPrefix, bool fullScan, string namespaceToOutput = "DeserializeClassBuilder", DirectoryInfo outputPath = null ) { if (!fullScan && (classPrefix == null || classPrefix.Length < 1)) { Console.WriteLine("Either --full-scan or --class-prefix must be specified"); return(1); } if (fullScan && classPrefix != null && classPrefix.Length > 0) { Console.WriteLine("You must choose either --full-scan or --class-prefix, not both."); return(1); } try { var outputPathString = outputPath == null ? Path.Combine(Path.GetDirectoryName(argument.FullName), $"{argument.Name}.generated") : outputPath.FullName; if (!Directory.Exists(outputPathString) && !Directory.CreateDirectory(outputPathString).Exists) { Console.WriteLine($"Failed to create output path: \"{argument.FullName}\""); return(1); } using var fileStream = File.OpenRead(argument.FullName); using var reader = new DeserializeReader(fileStream); // Make sure we have a valid header before looking // TODO Improve the structure checking in SerializationHeaderRecord, it currenly only checks the first // byte while checking the type. var header = new SerializationHeaderRecord(reader); // Search through the file for positions to check var positions = FindPositions(fileStream, fullScan, classPrefix); Console.WriteLine( $"Found {positions.Length.ToString("N0", CultureInfo.InvariantCulture)} locations to check in" + $" \"{argument.Name}\"" ); // Store the percent so we only re-render when changed var renderedPercent = 0.0; // Check the found positions for class structures var classes = ScanForClasses(reader, positions, (int currentIndex) => { var percent = Math.Round((double)currentIndex / (double)positions.Length * 100, 0); if (renderedPercent != percent) { Console.Write($"\r({percent}%) "); renderedPercent = percent; } }); // Overwrite the last % line Console.Write($"\r{new string(' ', "(100.00%) ".Length)}\r"); foreach (var structure in classes) { WriteClass(structure, outputPathString, namespaceToOutput); } return(0); } catch (Exception e) when(e is DirectoryNotFoundException || e is FileNotFoundException) { Console.WriteLine($"File not found: \"{argument.FullName}\""); return(1); } catch (DeserializeException e) { Console.WriteLine($"Unexpected file structure: {e.Message}"); return(1); } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception e) #pragma warning restore CA1031 // Do not catch general exception types { Console.WriteLine($"Fatal error: {e.Message}"); #if DEBUG Debugger.Break(); #endif return(1); } }