Upload via GUI (43 Dateien)
This commit is contained in:
+73
-11
@@ -14,7 +14,12 @@ const path = require('path');
|
||||
const { execFile, spawn } = require('child_process');
|
||||
|
||||
const PKG_FAMILY = 'Microsoft.MinecraftUWP_8wekyb3d8bbwe';
|
||||
const APP_ID = PKG_FAMILY + '!App';
|
||||
// Der Teil nach "!" (Application Id) ist NICHT stabil – Microsoft hat ihn
|
||||
// schon mindestens einmal geändert (früher "App", inzwischen "Game").
|
||||
// Deshalb zur Laufzeit über Get-StartApps auflösen statt fest zu verdrahten;
|
||||
// dieser Wert dient nur als letzter Rückfallwert, falls die Auflösung
|
||||
// fehlschlägt (z. B. PowerShell blockiert).
|
||||
const FALLBACK_APP_ID = PKG_FAMILY + '!Game';
|
||||
|
||||
function comMojangDir() {
|
||||
return path.join(process.env.LOCALAPPDATA || '', 'Packages', PKG_FAMILY,
|
||||
@@ -49,30 +54,87 @@ async function detect() {
|
||||
// Start
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
let cachedAppId = null;
|
||||
|
||||
/*
|
||||
* Ermittelt die aktuell gültige AUMID über Get-StartApps – das ist derselbe
|
||||
* Weg, den auch das Startmenü nutzt, und bildet daher immer die Application
|
||||
* Id ab, die Windows gerade tatsächlich zum Starten akzeptiert.
|
||||
*/
|
||||
async function resolveAppId() {
|
||||
if (cachedAppId) return cachedAppId;
|
||||
const out = await runPwsh(
|
||||
`(Get-StartApps | Where-Object { $_.AppID -like '${PKG_FAMILY}*' } `
|
||||
+ `| Select-Object -First 1 -ExpandProperty AppID)`);
|
||||
cachedAppId = out || FALLBACK_APP_ID;
|
||||
return cachedAppId;
|
||||
}
|
||||
|
||||
/*
|
||||
* Startet Bedrock direkt.
|
||||
* Wichtig: Der AppsFolder-Pfad darf NICHT in Anführungszeichen stehen – sonst
|
||||
* öffnet der Explorer nur ein Ordnerfenster. Daher windowsVerbatimArguments.
|
||||
*/
|
||||
function launch() {
|
||||
const target = 'shell:appsFolder\\' + APP_ID;
|
||||
async function launch() {
|
||||
const appId = await resolveAppId();
|
||||
const target = 'shell:appsFolder\\' + appId;
|
||||
// Wichtig: Es darf pro Klick nur EINE Aktivierung tatsächlich lostreten.
|
||||
// Die App-Aktivierung lässt sich nicht abbrechen – wenn wir bei einer
|
||||
// Verzögerung (Xbox-Dienste, Kaltstart) automatisch einen zweiten Weg
|
||||
// probieren, laufen im Zweifel beide an und Bedrock öffnet sich doppelt.
|
||||
// Die anderen Wege dienen daher nur als Rückfall, falls das Spawnen
|
||||
// selbst scheitert (Programm nicht gefunden o. Ä.), nicht als
|
||||
// Reaktion auf einen bloß langsamen Start.
|
||||
const versuche = [
|
||||
// 1) genau der Aufruf, der sich unter Windows als zuverlässig erwiesen hat
|
||||
// 1) explorer direkt, ohne zusätzliche Anführungszeichen – entspricht
|
||||
// exakt dem manuellen "explorer.exe shell:appsFolder\...", der
|
||||
// nachweislich zuverlässig funktioniert
|
||||
['explorer.exe', [target], { windowsVerbatimArguments: true }],
|
||||
// 2) über die Eingabeaufforderung
|
||||
['cmd', ['/c', 'start', '', target], { windowsVerbatimArguments: true }],
|
||||
// 3) Rückfallweg über eine versteckte PowerShell – aus einem
|
||||
// windowless/detached Kindprozess heraus offenbar nicht überall
|
||||
// zuverlässig, daher nur letzter Versuch
|
||||
['powershell', ['-NoProfile', '-WindowStyle', 'Hidden', '-Command',
|
||||
`Start-Process explorer.exe -ArgumentList '${target}'`], {}],
|
||||
// 2) explorer direkt, ohne zusätzliche Anführungszeichen
|
||||
['explorer.exe', [target], { windowsVerbatimArguments: true }],
|
||||
// 3) über die Eingabeaufforderung
|
||||
['cmd', ['/c', 'start', '', target], { windowsVerbatimArguments: true }],
|
||||
];
|
||||
let methode = null;
|
||||
for (const [cmd, args, extra] of versuche) {
|
||||
try {
|
||||
const p = spawn(cmd, args, Object.assign({ detached: true, stdio: 'ignore', windowsHide: true }, extra));
|
||||
p.unref();
|
||||
return { ok: true, method: cmd };
|
||||
} catch { /* nächsten Weg versuchen */ }
|
||||
methode = cmd;
|
||||
break; // nur diesen einen Weg tatsächlich auslösen
|
||||
} catch { /* Spawnen selbst fehlgeschlagen – nächsten Weg versuchen */ }
|
||||
}
|
||||
if (!methode) return { ok: false, message: 'Bedrock konnte nicht gestartet werden.' };
|
||||
// Aktivierung kann dauern (v. a. beim ersten Start nach längerer Pause) –
|
||||
// hier nur zur ehrlichen Rückmeldung abwarten, OHNE bei Zeitüberschreitung
|
||||
// einen weiteren Versuch zu starten (siehe Hinweis oben).
|
||||
const bestaetigt = await waitForBedrockProcess(15000);
|
||||
return { ok: true, method: methode, confirmed: bestaetigt };
|
||||
}
|
||||
|
||||
function isBedrockRunning() {
|
||||
return new Promise((resolve) => {
|
||||
execFile('tasklist', ['/FI', 'IMAGENAME eq Minecraft.Windows.exe', '/FO', 'CSV', '/NH'],
|
||||
{ windowsHide: true, timeout: 5000 },
|
||||
(err, stdout) => resolve(!err && /Minecraft\.Windows\.exe/i.test(String(stdout || ''))));
|
||||
});
|
||||
}
|
||||
|
||||
function warten(ms) {
|
||||
return new Promise((resolve) => { setTimeout(resolve, ms); });
|
||||
}
|
||||
|
||||
async function waitForBedrockProcess(timeoutMs) {
|
||||
const start = Date.now();
|
||||
// sofort prüfen (falls schon ein Fenster lief) und danach im Kurztakt
|
||||
for (;;) {
|
||||
if (await isBedrockRunning()) return true;
|
||||
if (Date.now() - start >= timeoutMs) return false;
|
||||
await warten(500);
|
||||
}
|
||||
return { ok: false, message: 'Bedrock konnte nicht gestartet werden.' };
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user