Fixed json bom handling when serializing/deserializing json
This commit is contained in:
@@ -82,6 +82,8 @@ Das BizTalk Platform Management Tool unterstützt kontrollierte Wartungsfenster
|
|||||||
|
|
||||||
Bei echten Shutdown- und Restore-Aktionen wird jeder Schritt vor der Ausführung mit Artefakttyp, WMI-Klasse, Schlüsselproperty, Schlüsselwert und Methodenname protokolliert. Die Objektauflösung verwendet eine breite `SELECT * FROM <class>`-Abfrage und filtert danach im Prozess auf den Schlüsselwert. Dadurch können Host-Instance-Namen und andere BizTalk-Namen mit Sonderzeichen keine ungültige WMI-WQL-`WHERE`-Query mehr erzeugen.
|
Bei echten Shutdown- und Restore-Aktionen wird jeder Schritt vor der Ausführung mit Artefakttyp, WMI-Klasse, Schlüsselproperty, Schlüsselwert und Methodenname protokolliert. Die Objektauflösung verwendet eine breite `SELECT * FROM <class>`-Abfrage und filtert danach im Prozess auf den Schlüsselwert. Dadurch können Host-Instance-Namen und andere BizTalk-Namen mit Sonderzeichen keine ungültige WMI-WQL-`WHERE`-Query mehr erzeugen.
|
||||||
|
|
||||||
|
Snapshot- und Plan-JSON-Dateien werden als UTF-8 ohne BOM geschrieben. Beim Laden werden vorhandene Dateien mit UTF-8-BOM oder durch Encoding-Konvertierung sichtbar gewordenem BOM-Marker toleriert.
|
||||||
|
|
||||||
## Status Mapping
|
## Status Mapping
|
||||||
|
|
||||||
- `MSBTS_SendPort.Status`: `1=Bound`, `2=Stopped`, `3=Started`
|
- `MSBTS_SendPort.Status`: `1=Bound`, `2=Stopped`, `3=Started`
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ Log files are retained for the current day plus the previous four days. Older `B
|
|||||||
|
|
||||||
The Operation Log shows the WMI class, key property, key value and method for real shutdown and restore steps. WMI objects are resolved with a broad `SELECT * FROM <class>` query and a client-side key filter so names containing special characters do not break the WMI query parser.
|
The Operation Log shows the WMI class, key property, key value and method for real shutdown and restore steps. WMI objects are resolved with a broad `SELECT * FROM <class>` query and a client-side key filter so names containing special characters do not break the WMI query parser.
|
||||||
|
|
||||||
|
Snapshot and plan JSON files are written as UTF-8 without BOM. Loading is tolerant of existing files that contain a UTF-8 BOM or a visible BOM marker from previous encoding conversions.
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
Open `BizTalkPlatformManagementTool.sln` in Visual Studio on Windows with the .NET Framework 4.6.1 Developer Pack installed, then build the `Release|Any CPU` configuration.
|
Open `BizTalkPlatformManagementTool.sln` in Visual Studio on Windows with the .NET Framework 4.6.1 Developer Pack installed, then build the `Release|Any CPU` configuration.
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
using System.Runtime.Serialization.Json;
|
using System.Runtime.Serialization.Json;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -6,6 +7,8 @@ namespace BizTalkPlatformManagementTool.Services
|
|||||||
{
|
{
|
||||||
public static class JsonFileStore
|
public static class JsonFileStore
|
||||||
{
|
{
|
||||||
|
private static readonly Encoding Utf8NoBom = new UTF8Encoding(false);
|
||||||
|
|
||||||
public static void Save<T>(string path, T value)
|
public static void Save<T>(string path, T value)
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(path)));
|
Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(path)));
|
||||||
@@ -17,8 +20,8 @@ namespace BizTalkPlatformManagementTool.Services
|
|||||||
using (var stream = new MemoryStream())
|
using (var stream = new MemoryStream())
|
||||||
{
|
{
|
||||||
serializer.WriteObject(stream, value);
|
serializer.WriteObject(stream, value);
|
||||||
var json = Encoding.UTF8.GetString(stream.ToArray());
|
var json = Utf8NoBom.GetString(stream.ToArray());
|
||||||
File.WriteAllText(path, json, Encoding.UTF8);
|
File.WriteAllText(path, json, Utf8NoBom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,10 +32,55 @@ namespace BizTalkPlatformManagementTool.Services
|
|||||||
UseSimpleDictionaryFormat = true
|
UseSimpleDictionaryFormat = true
|
||||||
});
|
});
|
||||||
|
|
||||||
using (var stream = File.OpenRead(path))
|
var json = NormalizeJson(File.ReadAllText(path, Encoding.UTF8));
|
||||||
|
using (var stream = new MemoryStream(Utf8NoBom.GetBytes(json)))
|
||||||
{
|
{
|
||||||
return (T)serializer.ReadObject(stream);
|
try
|
||||||
|
{
|
||||||
|
return (T)serializer.ReadObject(stream);
|
||||||
|
}
|
||||||
|
catch (SerializationException ex)
|
||||||
|
{
|
||||||
|
throw new InvalidDataException("Failed to load JSON file '" + path + "'. " + DescribeJsonStart(json), ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string NormalizeJson(string json)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(json))
|
||||||
|
{
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json[0] == '\uFEFF')
|
||||||
|
{
|
||||||
|
json = json.Substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json.StartsWith("\u00EF\u00BB\u00BF"))
|
||||||
|
{
|
||||||
|
json = json.Substring(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string DescribeJsonStart(string json)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(json))
|
||||||
|
{
|
||||||
|
return "The file is empty or contains only whitespace.";
|
||||||
|
}
|
||||||
|
|
||||||
|
var trimmed = json.TrimStart();
|
||||||
|
var first = trimmed.Length == 0 ? '\0' : trimmed[0];
|
||||||
|
if (first != '{' && first != '[')
|
||||||
|
{
|
||||||
|
return "The first JSON character is '" + first + "' instead of '{' or '['.";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "The file starts with valid JSON syntax but could not be deserialized into the expected model.";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user