Add archived Siemens software

This commit is contained in:
2026-08-26 12:46:05 +03:00
parent aa7dbcf33d
commit 9990eed34c
125 changed files with 1227 additions and 19 deletions
+24 -1
View File
@@ -80,6 +80,9 @@ public static class ScreenshotWindowApi {
[DllImport("user32.dll")]
public static extern bool PostMessage(IntPtr hWnd, uint message, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
public static extern bool PrintWindow(IntPtr hWnd, IntPtr hdc, uint flags);
}
"@
@@ -434,7 +437,27 @@ try {
$screenshotPath = Join-Path $OutputDirectory "$Name.png"
$borderInset = 2
if ($ScreenshotTool.Length -gt 0 -and (Test-Path -LiteralPath $ScreenshotTool)) {
if ($ScreenshotTool -eq "printwindow") {
$bitmap = [System.Drawing.Bitmap]::new($window.Width, $window.Height, [System.Drawing.Imaging.PixelFormat]::Format32bppArgb)
try {
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
$deviceContext = $graphics.GetHdc()
try {
if (-not [ScreenshotWindowApi]::PrintWindow($window.Handle, $deviceContext, 2)) {
throw "PrintWindow failed for window '$($window.Title)'."
}
}
finally {
$graphics.ReleaseHdc($deviceContext)
$graphics.Dispose()
}
$bitmap.Save($screenshotPath, [System.Drawing.Imaging.ImageFormat]::Png)
}
finally {
$bitmap.Dispose()
}
}
elseif ($ScreenshotTool.Length -gt 0 -and (Test-Path -LiteralPath $ScreenshotTool)) {
$screenshotToolName = [System.IO.Path]::GetFileName($ScreenshotTool)
if ($screenshotToolName -ieq "winapp.exe") {
$winappExitCode = 1
+12 -1
View File
@@ -38,6 +38,9 @@ function Get-CandidateScore {
if ($stem -eq $slugName) {
$score += 100
}
if ($ProgramSlug -eq "qpst" -and $File.BaseName -eq "QPSTConfig") {
$score += 200
}
foreach ($token in ($ProgramSlug -split '[-_]')) {
if ($token.Length -ge 3 -and $stem.Contains((Get-NormalizedName $token))) {
$score += 15
@@ -138,7 +141,15 @@ try {
exit 1
}
$winapp = "C:\codex\winapp\winapp.exe"
$screenshotTool = if (Test-Path -LiteralPath $winapp) {
$builtInCapturePrograms = @("u10-u15-update-software")
$printWindowCapturePrograms = @("jadmaker")
$screenshotTool = if ($builtInCapturePrograms -contains $Slug) {
""
}
elseif ($printWindowCapturePrograms -contains $Slug) {
"printwindow"
}
elseif (Test-Path -LiteralPath $winapp) {
$winapp
}
else {
+86 -16
View File
@@ -55,7 +55,10 @@ type Options = {
host: string;
importDirectory?: string;
limit?: number;
program?: string;
programs: Set<string>;
sshConfig?: string;
sshControl?: string;
sshPort?: number;
replace: boolean;
waitSeconds: number;
write: boolean;
@@ -86,13 +89,16 @@ const initialKeys = new Map([
"ENTER,TEXT=C:\\codex\\catalog-screenshots\\work\\brew-graphicpatch-creator\\brewrc.exe,ENTER",
],
["brew-apploader", "CLOSE-SMALL,CLOSE-SMALL"],
["cl50-dinghy-downloader", "ENTER"],
["efs-explorer-lite", "ENTER"],
["flash-imager", "ENTER"],
["flex-table-edit", "ENTER"],
["gagin", "CLOSE-SMALL,CLOSE-SMALL"],
["freia", "SELECT-TITLE=Engine"],
["initmap", "CLOSE-LARGEST"],
["mobilechat", "ALT+N"],
["s65-key-definer", "ENTER"],
["s80-user-download-tool", "ENTER"],
["siemens-screenshot", "ENTER"],
]);
@@ -102,8 +108,12 @@ function usage(): void {
Capture one screenshot for each Windows program.
--host HOST Windows SSH host (default: win)
--ssh-config PATH use an alternate OpenSSH configuration file
--ssh-control PATH
use an existing OpenSSH control socket
--ssh-port PORT connect to a specific SSH port
--import DIR import reviewed SLUG.png files without connecting to Windows
--program SLUG process one program directory
--program SLUG process a program directory; may be repeated
--limit COUNT stop after COUNT programs
--replace recapture only existing img/SLUG.png screenshots
--wait SECONDS wait for a program window (default: 8)
@@ -116,7 +126,10 @@ function parseArguments(args: string[]): Options {
let host = "win";
let importDirectory: string | undefined;
let limit: number | undefined;
let program: string | undefined;
const programs = new Set<string>();
let sshConfig: string | undefined;
let sshControl: string | undefined;
let sshPort: number | undefined;
let replace = false;
let waitSeconds = 8;
let write = false;
@@ -125,12 +138,18 @@ function parseArguments(args: string[]): Options {
const argument = args[index];
if (argument === "--host") {
host = args[++index] ?? "";
} else if (argument === "--ssh-config") {
sshConfig = path.resolve(args[++index] ?? "");
} else if (argument === "--ssh-control") {
sshControl = path.resolve(args[++index] ?? "");
} else if (argument === "--ssh-port") {
sshPort = Number(args[++index]);
} else if (argument === "--import") {
importDirectory = path.resolve(args[++index] ?? "");
} else if (argument === "--limit") {
limit = Number(args[++index]);
} else if (argument === "--program") {
program = args[++index];
programs.add(args[++index] ?? "");
} else if (argument === "--replace") {
replace = true;
} else if (argument === "--wait") {
@@ -159,19 +178,48 @@ function parseArguments(args: string[]): Options {
if (!Number.isInteger(waitSeconds) || waitSeconds < 1 || waitSeconds > 60) {
throw new Error("--wait must be an integer between 1 and 60");
}
if (programs.has("")) {
throw new Error("--program must not be empty");
}
if (sshPort !== undefined && (!Number.isInteger(sshPort) || sshPort < 1 || sshPort > 65535)) {
throw new Error("--ssh-port must be an integer between 1 and 65535");
}
return {
catalogDirectory: path.resolve(targets[0] ?? "catalog"),
host,
importDirectory,
limit,
program,
programs,
sshConfig,
sshControl,
sshPort,
replace,
waitSeconds,
write,
};
}
function sshArguments(options: Options, remoteCommand: string): string[] {
return [
...(options.sshConfig !== undefined ? ["-F", options.sshConfig] : []),
...(options.sshControl !== undefined ? ["-S", options.sshControl] : []),
...(options.sshPort !== undefined ? ["-p", String(options.sshPort)] : []),
options.host,
remoteCommand,
];
}
function scpArguments(options: Options, sources: string[], destination: string): string[] {
return [
...(options.sshConfig !== undefined ? ["-F", options.sshConfig] : []),
...(options.sshControl !== undefined ? ["-o", `ControlPath=${options.sshControl}`] : []),
...(options.sshPort !== undefined ? ["-P", String(options.sshPort)] : []),
...sources,
destination,
];
}
async function run(command: string, args: string[], allowFailure = false): Promise<string> {
return await new Promise((resolve, reject) => {
const child = spawn(command, args, { stdio: ["ignore", "pipe", "pipe"] });
@@ -239,7 +287,7 @@ async function collectPrograms(options: Options): Promise<{ programs: Program[];
if (programsWithoutStandaloneGui.has(slug)) {
continue;
}
if (options.program !== undefined && slug !== options.program) {
if (options.programs.size > 0 && !options.programs.has(slug)) {
continue;
}
if (typeof metadata.name !== "string" || metadata.name.length === 0) {
@@ -308,18 +356,30 @@ function failureReason(result: RemoteResult, program: Program): { reason: string
if (failedTitle !== undefined) {
return { reason: "Error window", details: failedTitle };
}
const setupTitle = program.slug === "java-midlet-installer" ? undefined : titles.find((title) => installerTitle.test(title));
const programsWithSetupInMainWindowTitle = new Set([
"ifwd-flashtool-e2",
"java-midlet-installer",
"kp500-flashing-tool",
]);
const setupTitle = programsWithSetupInMainWindowTitle.has(program.slug)
? undefined
: titles.find((title) => installerTitle.test(title));
if (setupTitle !== undefined) {
return { reason: "Installer opened", details: setupTitle };
}
return undefined;
}
async function addScreenshot(program: Program, screenshotPath: string, replace: boolean): Promise<void> {
async function addScreenshot(
options: Options,
program: Program,
screenshotPath: string,
replace: boolean,
): Promise<void> {
const imageDirectory = path.join(program.directory, "img");
const imagePath = path.join(imageDirectory, `${program.slug}.png`);
await mkdir(imageDirectory, { recursive: true });
await run("scp", [`${screenshotPath}`, imagePath]);
await run("scp", scpArguments(options, [screenshotPath], imagePath));
if (replace) {
return;
@@ -380,18 +440,23 @@ async function main(): Promise<void> {
}
let captured = 0;
const tools = ["screenshotApp.ps1", "runScreenshotTask.ps1", "screenshotArchive.ps1"];
await run("ssh", [
options.host,
await run("ssh", sshArguments(options,
`powershell -NoProfile -Command "New-Item -ItemType Directory -Force -Path '${remoteRoot}\\input','${remoteRoot}\\results' | Out-Null"`,
]);
await run("scp", tools.map((file) => path.resolve("tools", file)).concat(`${options.host}:${remoteScpRoot}/`));
));
await run(
"scp",
scpArguments(options, tools.map((file) => path.resolve("tools", file)), `${options.host}:${remoteScpRoot}/`),
);
console.log(`Programs to process: ${programs.length}`);
for (const [index, program] of programs.entries()) {
const prefix = `[${index + 1}/${programs.length}] ${program.name}`;
const remoteArchive = `${remoteRoot}\\input\\${program.slug}.zip`;
try {
await run("scp", [program.archive, `${options.host}:${remoteScpRoot}/input/${program.slug}.zip`]);
await run(
"scp",
scpArguments(options, [program.archive], `${options.host}:${remoteScpRoot}/input/${program.slug}.zip`),
);
const remoteCommand = [
"powershell",
"-NoProfile",
@@ -403,7 +468,7 @@ async function main(): Promise<void> {
`-WaitSeconds ${options.waitSeconds}`,
...(initialKeys.has(program.slug) ? [`-InitialKeys ${initialKeys.get(program.slug)}`] : []),
].join(" ");
const output = await run("ssh", [options.host, remoteCommand], true);
const output = await run("ssh", sshArguments(options, remoteCommand), true);
const result = parseRemoteResult(output);
const failure = failureReason(result, program);
if (failure !== undefined) {
@@ -417,7 +482,12 @@ async function main(): Promise<void> {
}
if (options.write) {
await addScreenshot(program, `${options.host}:${remoteScpRoot}/results/${program.slug}.png`, options.replace);
await addScreenshot(
options,
program,
`${options.host}:${remoteScpRoot}/results/${program.slug}.png`,
options.replace,
);
}
captured += 1;
console.log(`${prefix}: ${options.write ? "saved" : "captured"} (${result.title ?? result.selected ?? "window"})`);