Generator aus der Anwendung starten
Liefern Sie bpnext-gen mit Ihrem Installer aus, startet Ihre Anwendung den Generator als eigenen
Prozess. Ein vollständiger Lauf dauert je nach Instanz 5 bis 10 Minuten. Mit --json meldet der
Generator Schritt, Fortschritt und aktuellen Datensatz maschinenlesbar, sodass Sie den Stand in
Ihrer eigenen Oberfläche anzeigen können.
Zugangsdaten übergeben
Kennwort und Client-Secret gehören nicht auf die Kommandozeile, dort sind sie in der Prozessliste
und in Setup-Logs sichtbar. --credentials-from liest die Werte stattdessen aus einer Datei oder
von der Standardeingabe.
Das Format ist ein key=value je Zeile. Die Schlüssel entsprechen den Parametern ohne führendes
--, Zeilen mit # am Anfang und Leerzeilen werden übergangen:
# Zugangsdaten für bpnext-gen
user=BENUTZER
password=KENNWORT
mandant=1
endpoint=https://<host>/microtech/erp/<tenant>/graphql/v1
client-id=<client-id>
client-secret=<client-secret>
Neben den Zugangsdaten sind alle Parameter mit Wert erlaubt, etwa out, license oder
models-dll.
Aus einer Datei:
bpnext-gen generate --credentials-from C:\ProgramData\MeineAnwendung\zugang.txt
Von der Standardeingabe, angegeben als -:
Get-Content .\zugang.txt | bpnext-gen generate --credentials-from -
Der Generator liest die Standardeingabe bis zum Ende. Eine startende Anwendung schreibt die Zeilen also hinein und schließt den Strom danach, so landen die Werte weder in einer Datei noch in der Prozessliste. Das Beispiel unten zeigt das.
Liegt ein Wert mehrfach vor, gilt: Argument vor Datei vor Umgebungsvariable.
Fortschritt mit --json
Mit --json schreibt der Generator auf stdout ausschließlich JSON, ein Objekt je Zeile, in UTF-8.
Farben, Fortschrittsbalken und Rückfragen entfallen. --json schließt --non-interactive ein:
Fehlt ein Wert, endet der Lauf mit Exit-Code 6, statt auf eine Eingabe zu warten.
{"type":"start","version":"0.30.2","verb":"generate","ts":"2026-09-27T10:00:00+00:00","elapsedMs":50}
{"type":"step","stage":"com.schemas","message":"Erzeuge Schemas für 319 DataSets...","elapsedMs":1200}
{"type":"progress","stage":"com.schemas","current":12,"total":319,"item":"Artikel","elapsedMs":4100}
{"type":"log","level":"warn","message":"...","elapsedMs":4200}
{"type":"result","exitCode":0,"com":{"assembly":"C:\\...\\BpNexT.NET.Models.dll","dataSets":319,"sourceFiles":4383},"graphQl":{"assembly":"C:\\...\\BpNexT.NET.Models.GraphQL.dll","tables":135,"sourceFiles":1888,"typesInferred":true},"elapsedMs":412000}
Jedes Ereignis trägt type und elapsedMs, die Millisekunden seit Prozessstart.
type |
Felder | Bedeutung |
|---|---|---|
start |
version, verb, ts |
erste Zeile eines Laufs |
step |
stage, message |
ein neuer Abschnitt beginnt |
progress |
stage, current, total, item |
ein Element des laufenden Abschnitts ist erreicht |
log |
level, message, bei --verbose auch exception |
Meldung; level ist debug, info, success, warn oder error |
result |
exitCode, error, com, graphQl |
letzte Zeile, auch bei Fehlern |
message ist für Menschen gedacht und kann sich ändern. Werten Sie Abschnitte über stage aus:
stage |
Abschnitt |
|---|---|
license |
Lizenz prüfen |
com.login |
Anmeldung an microtech ERP |
com.schemas |
Schemas je DataSet lesen, mit Fortschritt |
com.models |
Modelle erzeugen, mit Fortschritt |
com.compile |
COM-Modelle übersetzen |
graphql.introspect |
Schema vom GraphQL-Endpunkt lesen |
graphql.models |
Modelle je Tabelle erzeugen, mit Fortschritt |
graphql.compile |
GraphQL-Modelle übersetzen |
check.com, check.graphql |
Prüfungen von bpnext-gen check |
progress kommt für jedes Element, bei com.models also mehrere tausend Mal. Drosseln Sie die
Anzeige in Ihrer Oberfläche, nicht das Lesen: ein nicht gelesener Ausgabestrom hält den Generator
an.
result fehlt nur, wenn der Prozess hart abbricht. Maßgeblich bleibt der Exit-Code des Prozesses,
com und graphQl fehlen für Stufen, die nicht gelaufen sind. Ist der Exit-Code 5, liegen die
COM-Modelle trotzdem vollständig vor.
Beispiel
var startInfo = new ProcessStartInfo
{
FileName = Path.Combine(AppContext.BaseDirectory, "bpnext-gen.exe"),
ArgumentList = { "generate", "--json", "--credentials-from", "-" },
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
StandardOutputEncoding = Encoding.UTF8,
UseShellExecute = false,
CreateNoWindow = true
};
using var process = Process.Start(startInfo)!;
await process.StandardInput.WriteLineAsync($"user={benutzer}");
await process.StandardInput.WriteLineAsync($"password={kennwort}");
await process.StandardInput.WriteLineAsync($"mandant={mandant}");
await process.StandardInput.WriteLineAsync($"endpoint={endpunkt}");
await process.StandardInput.WriteLineAsync($"client-id={clientId}");
await process.StandardInput.WriteLineAsync($"client-secret={clientSecret}");
process.StandardInput.Close();
var stderr = process.StandardError.ReadToEndAsync();
while (await process.StandardOutput.ReadLineAsync() is { } line)
{
using var ev = JsonDocument.Parse(line);
var root = ev.RootElement;
switch (root.GetProperty("type").GetString())
{
case "step":
ZeigeAbschnitt(root.GetProperty("stage").GetString(), root.GetProperty("message").GetString());
break;
case "progress":
ZeigeFortschritt(
root.GetProperty("current").GetInt32(),
root.GetProperty("total").GetInt32(),
root.GetProperty("item").GetString());
break;
case "result" when root.TryGetProperty("error", out var error):
ZeigeFehler(error.GetString());
break;
}
}
await process.WaitForExitAsync();
await stderr;
var exitCode = process.ExitCode;
stderr wird mitgelesen, damit ein voller Fehlerstrom den Prozess nicht blockiert. Im JSON-Betrieb bleibt er leer, solange der Generator nicht unerwartet abbricht.