NutJS (3:1)


NutJS – auch als nutjs.dev bekannt – ist eine leistungsstarke Desktop-Automatisierungs-Software für Node.js. Entwickelt von Simon Hofmann aus Rain (Niederbayern), um die Automatisierung von Abläufen auf dem Desktop zu erleichtern, bietet dir NutJS eine einfache und zugängliche Schnittstelle für die Skripterstellung. Mit Funktionen wie Tastatureingaben, Mausbewegungen und Bilderkennung ermöglicht dir NutJS die nahtlose Automatisierung von Desktop-Anwendungen für verschiedene Anwendungsfälle.


Anmerkung: In diesem Beitrag nutze ich die informelle Anrede „du“ und gleichzeitig das generische Maskulinum. Dies dient dazu, eine persönliche Atmosphäre zu schaffen, die den Austausch und das Lernen ansprechender macht. Gleichzeitig erleichtert es den Lesefluss. Dennoch gilt natürlich allen mein höchster Respekt.


Einleitung

Für wen ist dieser Artikel?

Dieser Blog-Beitrag richtet sich an dich, wenn du dich für Desktop-Automatisierung interessierst, egal ob du dich schon länger damit beschäftigst, oder nur einmal hereinschnuppern möchtest. Für das allgemeine Verständnis ist es wichtig, dass du zumindest über Grundkenntnisse in JavaScript/TypeScript und Node.js verfügst. Außerdem gehe ich davon aus, dass Node.js bei dir auch installiert ist.
WICHTIG: Das (kostenlose) NutJS wird maximal bis Node.js-Version 18 LTS unterstützt!


Kosten und Lizenzen

Um NutJS auszuprobieren, gibt es eine kostenlose Lizenz, die du direkt mit npm installieren kannst. Die enthaltenen Funktionalitäten sind bereits sehr mächtig, kommen allerdings auch an Grenzen, wenn du etwas mehr möchtest. Du hast dann die Möglichkeit, ab 40 Dollar monatlich eine entsprechende Lizenz zu erwerben. Je nach Anwendungsgebiet kannst du zwischen dem sogenannten Solo-Plan, für die private Nutzung, und dem Team-Plan, für die kommerzielle Nutzung, wählen. Falls dein Anwendungsgebiet nicht in die Lizenzbedingungen passt, kannst du dich mit dem Entwickler in Verbindung setzen und einen Custom-Plan vereinbaren. Ich selbst habe NutJS mit dem sog. Free-Plan ausprobiert. Folglich werde ich in diesem Tutorial nur auf die kostenlosen Features detailiert eingehen. Gerne darfst du auf der Entwicklerseite auch entdecken, was die kostenpflichtigen Lizenzen beinhalten. Ich werde auch nicht auf alle Funktionalitäten eingehen, das würde den Rahmen dieses Beitrags sprengen. Ich werde dir stattdessen mit trivialen Beispielen einen ersten Einblick geben.


Erste Schritte

Installation

Zuerst richtest du dir ein Node.js-Projekt ein, indem du an geeigneter Stelle einen Ordner – ich nenne ihn hier nutjs-demo – anlegst und diesen mit dem Befehl

C:\Users\Robert\nutjs-demo>npm init

initialisierst. Dann konfigurierst du die entsprechenden Standard-Module, je nachdem, ob du mit JavaScript oder TypeScript arbeitest. NutJS kannst du mit beidem verwenden – ich selbst arbeite mit TypeScript. Das Grundpaket mit den Core-Funktionalitäten installierst du mit

C:\Users\Robert\nutjs-demo>npm install @nut-tree/nut-js

und die Funktionen für die Bilderkennung mit

C:\Users\Robert\nutjs-demo>npm install @nut-tree/template-matcher

It works on my machine(?)

Aus eigener Erfahrung kann ich sagen, dass die Installation nicht so „einfach“ ist, wie der Entwickler angibt. Ich hatte bei der Verwendung des Template Matchers diverse Fehlermeldungen. Nach einiger Recherche durfte ich erst einmal die zum September 2023 aktuellste Node.js-Version 20 auf 18 LTS downgraden. Dann durfte ich mich Stück für Stück voranarbeiten, und diverse Pakete in meinem Node.js-Projekt manuell nachinstallieren. Solltest du auch möglichweise Schwierigkeiten bei der Installation oder bei der Verwendung haben, stelle ich dir hier ein GitHub-Template zur Verfügung. Lad es dir gerne herunter und pass es deinen Bedürfnissen an. Das sollte die initialen Fehlermeldungen reduzieren oder vielleicht sogar komplett eliminieren.

It works on my machine NOT


Los geht’s!

Der Umgang mit NutJS ist im Prinzip sehr einfach, da die Core-Funktionen überschaubar sind, und die Funktionsaufrufe ziemlich intuitiv sind. Das hier sind die Hauptobjekte, die man aus der Bibliothek @nut-tree/nut-js importieren kann:

  • clipboard (für die Zwischenablage)
  • keyboard (für Tastatureingaben)
  • mouse (für Mauseingaben)
  • screen (für Bildschirmabfragen)
  • jestMatchers (Erweiterung für expect des Jest-Frameworks)

Zwischenablage

Da die Zwischenablage der kostenlosen NutJS-Version auf reinen Text beschränkt ist, verzichte ich hier auf ein Beispiel, weil das meiner Meinung nach nicht sonderlich spannend ist. Falls dich das Feature dennoch interessiert, kannst du es dir gerne auf der Entwicklerseite ansehen. Die beiden Methoden lauten:

  • clipboard.getContent() holt den aktuellen Text der Windows-Zwischenablage.
  • clipboard.setContent() kopiert einen beliebigen Text in die Windows-Zwischenablage.

Tastatureingaben simulieren

Lass uns anfangen, ein paar einfache Tastatureingaben zu simulieren. Das keyboard-Objekt stellt dabei die folgenden Funktionalitäten zur Verfügung:

keyboard.config
keyboard.pressKey()
keyboard.releaseKey()
keyboard.type()
  • config enthält verschiedene Properties, um die Tastaturfunktionen einzustellen (siehe Konfiguration von NutJS-Komponenten).
  • Mit pressKey werden Tastendrücke simuliert. Dabei gelten die Tasten solange als heruntergedrückt, bis man die gleiche Taste mit releaseKey wieder freigibt. Also das Code-Pendant zum echten „drück eine Taste“ und „lass die Taste wieder los“.
  • Mit type kannst du das Eingeben ganzer Strings bzw. Texte simulieren, so wie du sie auch selbst mit der Tastatur eintippen würdest. Beim Ausprobieren habe ich herausgefunden. dass man auch einzelne Tasten kurz antippen kann, damit man nicht jedesmal pressKey und releaseKey extra aufrufen muss. Ich werde es in den Beispielen zu Demonstrationszwecken trotzdem tun.

Kommen wir nun zum eigentlichen Beispiel. Wir wollen mithilfe von NutJS den Windows-Editor (notepad.exe) aufrufen, darin den Text „Hallo, Welt.“ eingeben und die Datei unter dem Namen „hallo_welt.txt“ speichern. Hier erstmal der Code:

01: import { keyboard, Key, sleep } from "@nut-tree/nut-js";
02:
03: async(() => {
04: 	await keyboard.pressKey(Key.LeftWin, Key.R);
05: 	await keyboard.releaseKey(Key.LeftWin, Key.R);
06: 	await keyboard.type("notepad.exe\n");
07: 	await sleep(100);
08: 	await keyboard.type("Hallo, Welt.\n");
09: 	await keyboard.pressKey(Key.LeftControl, Key.S);
10: 	await keyboard.releaseKey(Key.LeftControl, Key.S);
11: 	await keyboard.type("hallo_welt.txt\n");
12: 	await sleep(100);
13: 	await keyboard.pressKey(Key.LeftAlt, Key.F4);
14: 	await keyboard.release(Key.LeftAlt, Key.F4);
15: })();
  • In Zeile 1 importiere ich nicht nur die keyboard-Klasse für die Tastatureingaben, sondern auch den Enum Key, der alle Tasten der Tastatur als Namen beinhält, und die Funktion sleep, die ich weiter unten für eine kurze Pause benötige.
  • Vielleicht ist dir bereits aufgefallen, dass hier in den Zeilen 4 bis 14 vor jeder Anweisung await steht. Das liegt daran, dass alle NutJS-Funktionen asynchron ablaufen. Deswegen benötige ich für den Aufruf des Skripts auch einen async-Block, wie ich ihn mit den Zeilen 3 und 15 eingeschlossen habe, der dann durch das abschließende () gleich aufgerufen wird.
  • In den Zeilen 4 und 5 lasse ich die Tastenkombination <WINDOWS><R> drücken, die den Ausführen-Dialog von Windows auruft:
    Run-Dialogue
  • Dort trage ich mithilfe der type-Methode (Zeile 6) den Dateinamen des Windows-Editors ein. Das abschließende \n am Ende, was bei einer Textausgabe normalerweise einen Zeilenumbruch ausführt, simuliert hier den Druck auf die <ENTER>– bzw. <RETURN>-Taste.
  • In Zeile 7 warte ich 100 Milliskeunden lang, also eine zehntel Sekunde, bis das Programm geladen ist. Diese Angabe ist möglichweise nicht ganz so intuitiv. Vielleicht ist der ein oder andere der Meinung, dass solch eine Zahl standardmäßig für Sekunden oder Millisekunden steht, der andere bevorzugt möglichweise eine Bezeichnung in der Art Duration.ofMilliseconds() (siehe unten). Für NutJS nehmen wir das jetzt einfach so hin. Hier geht es lediglich darum, dass eine Anwendung, je nach Größe immer einen Moment benötigt, bis sie geladen ist.
  • In Zeile 8 gebe ich also den Text „Hallo, Welt.“ ein mit einem abschließenden Zeilenumbruch.
  • In den Zeile 9 und 10 drücke ich die Tastenkombination <CTRL><S> bzw. <STRG><S>, was in den meisten Programmen für „Speichern“ steht. Da unsere Datei noch keinen Namen hat, wird hier der „Speichern-Als“-Dialog angezeigt.
  • In Zeile 11 gebe ich der Datei also den Namen „hallo_welt.txt“ und bestätige auch hier meine Eingabe wie in Zeile 6 durch die Escape-Sequenz \n. Ich hätte hier auch einen Pfad wählen können, ich wollte das Beispiel jedoch so einfach wie möglich halten.
  • In Zeile 12 warte ich wieder eine zehntel Sekunde, bis die Datei gespeichert wurde.
  • In den Zeile 13 und 14 beende ich den Editor mithilfe der Tastenkombination <ALT><F4>.

Anmerkung: Ich habe hier die Tasten LeftWin, LeftControl und LeftAlt verwendet. Bei den ersten beiden, und bei der <SHIFT>-Taste, ist es i.d.R. egal, ob man die linke oder die rechte drückt. Bei der <ALT>-Taste ist das nicht so. Die linke ist die „normale“ <ALT>-Taste, und die rechte ist die Taste <ALT GR>.

Die kostenpflichtige Erweiterung der Tastatursimulation beinhaltet sogar eine komplette Unicode-Unterstützung und kann somit bspw. auch Emojis tippen.


Intuitive Zeitangaben

Falls du die Wartezeit bei sleep etwas leserlicher haben möchtest, stelle ich dir hier den Code meines Scripts Duration.ts zur Verfügung.

export function ofMilliseconds(milliseconds: number): number {
	return milliseconds;
}

export function ofSeconds(seconds: number): number {
	return seconds * ofMilliseconds(1000);
}
export function ofMinutes(minutes: number): number {
	return minutes * ofSeconds(60);
}

export function ofHours(hours: number): number {
	return hours * ofMinutes(60);
}

export function ofDays(days: number): number {
	return days * ofHours(24);
}

export function ofWeeks(weeks: number): number {
	return weeks * ofDays(7);
}

export function ofYears(years: number): number {
	return years * ofDays(365);
}

export function ofLeapYears(years: number): number {
	return years * ofDays(366);
}

Mauseingaben simulieren

Auch den Mauscursor kannst du mit NutJS bewegen. Im unteren Beispiel verwende ich auch Bildschirmabfrage-Funktionen. Diese sind weiter unten noch einmal beschrieben. Für die Mausfunktionen benötigst du das mouse-Objekt und ggf. entsprechene Richtungsfunktionen. Die Mausfunktionalitäten lauten wie folgt:

mouse.config
mouse.move()
mouse.getPosition()
mouse.setPosition()
mouse.click(), mouse.doubleClick(), mouse.leftClick(), mouse.rightClick()
mouse.pressButton(), mouse.releaseButton()
mouse.drag()
mouse.scrollDown(), mouse.scrollLeft(), mouse.scrollRight(), mouse.scrollUp()
down(), left(), right(), up()
straightTo()
  • config enthält verschiedene Properties, um die Mausfunktionen einzustellen (siehe Konfiguration von NutJS-Komponenten).
  • move bewegt den Mauscursor in eine bestimmte Richtung oder an einen bestimmten Punkt. Je nach konfigurierter Zeigergeschwindigkeit kannst du dabei zusehen, wie sich der Cursor bewegt.
  • getPosition holt die aktuelle Position des Mauscursors.
  • setPosition setzt den Mauscursor unmittelbar an einen bestimmten Punkt auf dem Bildschirm.
  • click, doubleClick, leftClick und rightClick simulieren entsprechende Mausklicks.
  • pressButton und releaseButton simulieren, ähnlich wie beim keyboard-Objekt das Drücken oder Loslassen einer Maustaste.
  • drag zieht das Objekt, auf das der Cursor gerade zeigt, entlang der angegebenen Punkte, die als Point-Array angegeben werden.
  • scrollDown, scrollLeft, scrollRight und scrollUp simulieren eine Scrollbewegung in die entsprechende Richtung.
  • down, left, right und up geben an, wohin der Mauscursor bewegt werden soll.
  • straighTo bewegt bei der Verwendung von move den Mauscursor, ähnlich wie setPosition, zu einer bestimmen Position.

Kommen wir zum Beispiel:

01: import { down, left, mouse, Point, right, screen, up } from "@nut-tree/nut-js";
02:
03: async(() => {
04: 	const width = await screen.width();
05: 	const height = await screen.height();
06: 	const halfWidth = Math.floor(width / 2);
07: 	const halfHeight = Math.floor(height / 2);
08: 	await mouse.setPosition(new Point(halfWidth, halfHeight));
09: 	await mouse.move(right(100));
10: 	await mouse.move(down(100));
11: 	await mouse.move(left(100));
12: 	await mouse.move(up(100));
13: })();
  • In Zeile 1 importiere ich also das mouse– und das screen-Objekt, dann die Richtungsfunktionen und den Datentyp Point, der später noch einmal genauer beschrieben wird.
  • Desweiteren haben wir hier wieder mehrere await-Anweisungen. Ich habe ja bereits erwähnt, dass die NutJS-Funktionen asynchron sind.
  • In den Zeilen 4 und 5 hole ich mir mithilfe des screen-Objekts die aktuelle Bildschirmauflösung in Pixeln.
  • In den Zeilen 6 und 7 berechne ich mir dann schlicht und einfach die Bildschirmmitte.
  • In Zeile 8 setze ich mit der setPosition-Methode den Cursor dorthin. Dazu definiere ich vorher mit new Point() ein Punkt-Objekt, das die Bildschirmmitte darstellt.
  • In den Zeilen 9 bis 12 beschreibe ich zu Demozwecken eine Art „Vierecksbewegung“ (100 Pixel).

Bildschirmabfragen

Nun wollen wir uns ‚mal ein bisschen auf dem Bildschirm umschauen. Um Bilder oder Bildausschnitte abzugleichen, benötigst du zusätzlich die Bibliothek @nut-tree/template-matcher. Die Verwendungsweise sieht du um unteren Beispiel. Das screen-Objekt enthält folgende Funktionalitäten:

screen.config
screen.height(), screen.width()
screen.find(), screen.findAll()
screen.highlight()
screen.waitFor()
screen.capture(), screen.captureRegion()
screen.grab(), screen.grabRegion()
  • config enthält verschiedene Properties, um die Bildschirmfunktionen einzustellen (siehe Konfiguration von NutJS-Komponenten).
  • width und height bestimmen die Bildschirmauflösung (Breite und Höhe) in Pixeln.
  • find und findAll suchen Bildausschnitte am Bildschirm. Es wird der erste bzw. es werden alle gefundenen zurückgegeben.
  • highlight markiert einen bestimmten Bildschirmausschnitt.
  • waitFor wartet, bis ein bestimmter Bildschirmausschnitt am Bildschirm sichtbar ist.
  • capture und captureRegion machen einen Screenshot (komplett oder Bereich) und speichern ihn in eine Datei.
  • grab und grabRegion machen einen Screenshot und liefern das Ergebnis als Objekt vom Typ Image (Bild) zurück.

Beim laden und speichern von Bildern unterstützt NutJS die beiden Bildformate JPEG und PNG. Ob die bezahlten Lizenzen eventuell mehr Formate unterstützen, konnte ich der Dokumentation nicht entnehmen. Doch für die meisten Anwendungsfälle sollten diese beiden Formate genügen. Widmen wir uns einem einfachen Beispiel, wie eine solche Bildschirmabfrage aussehen kann. Ich will einen Bildausschnit laden und ihn am Bildschirm finden lassen.

01: import { loadImage, screen } from "@nut-tree/nut-js";
02: import "@nut-tree/template-matcher";
03: 
04: async(() => {
05: 	screen.config.autoHighlight = true;
06: 	screen.config.confidence = 0.8;
07: 	const width = await screen.width();
08: 	const height = await screen.height();
09: 	const image = await loadImage("./example.png");
10: 	const position = await screen.find(image);
11: })();
  • In Zeile 1 importiere ich die Funktion loadImage und das screen-Objekt.
  • Die Syntax von Zeile 2 ist hier sehr wichtig. Das Modul template-matcher wird im Prinzip direkt ausgeführt, weswegen hier weder Funktionen noch Objekte stehen, und auch kein from. Solltest du anstelle der import-Anweisung die require-Funktion verwenden, ist die Syntax ähnlich. Du lässt einfach die Zuweisung weg, und schreibst direkt require("@nut-tree/template-matcher");.
  • In Zeile 4 wird wieder der bekannte async-Block eingeleitet.
  • In Zeile 5 möchte ich, dass der gefundene Bildausschnitt am Bildschirm automatisch markiert wird.
  • In Zeile 6 lege ich fest, wie ähnlich der Bildausschnitt dem tatsächlich gefundenen sein muss. Darauf gehe ich bei der Konfiguration noch genauer ein.
  • Die Zeilen 7 und 8 haben für das Beispiel keine konkrete Funktion, sondern zeigen lediglich noch einmal, wie man die aktuelle Bildschirmauflösung ermittelt.
  • In Zeile 9 lade ich eine potenzielle Datei mit dem zu suchenden Bildschirmausschnitt. Wenn du das Beispiel selbst ausprobieren möchtest, empfehle ich dir, einen Screenshot zu machen und davon einen beliebigen Ausschnitt in einer beliebigen Bilddatei abzuspeichern. Dann gibst du diesen Dateinamen als Argument in der Funktion loadImage an.
  • In Zeile 10 ermittle ich dann die Position (als Datentyp Point) des gefundenen Ausschnitts.

Konfiguration von NutJS-Komponenten

In diesem Abschnitt will ich die Konfiguration der einzelnen Komponenten innerhalb des Codes aufzeigen, nicht die Einstellungen in einer JSON-Datei. Jedes der oben genannten Objekte hat eine eigene config-Propery. Dabei kann bei den Objekten folgendes insgesamt eingestellt werden:

  • keyboard.config.autoDelayMs: Gibt an, wie viele Millisekunden automatisch zwischen zwei Tastatureingaben gewartet werden soll.
  • mouse.config.autoDelayMs: Gibt an, wie viele Millisekunden automatisch zwischen zwei Mausklicks gewartet werden soll.
  • mouse.config.mouseSpeed: Gibt die Geschwindigkeit des Mauscursors in Pixel/Sekunde an.
  • screen.config.autoHighlight: Gibt an, ob Suchergebnisse auf dem Bildschirm markiert werden sollen (bzw. ob sie kurz aufleuchten sollen).
  • screen.config.confidence: Ähnlichkeit, mit der zwei Bilder übereinstimmen müssen. Laut Dokumentation ist hier die Ähnlichkeit in Prozent anzugeben. Ich finde das etwas irreführend, da ich beim Ausprobieren festgestellt habe, dass die Prozentzahl als Kommazahl gemeint ist. Das heißt bspw. für eine 80%ige Übereinstimmung gibt man 0.8 an. Sollen die Bilder genau übereinstimmen, gibt man 1 an.
  • screen.config.highlightDurationMs: Gibt an, wie lange (in Millisekunden) gefundene Elemente markiert werden sollen.
  • screen.config.highlightOpacity: Deckungskraft der Markierung. 0 ist unsichtbar, 0.5 steht für 50%, 1 ist komplett deckend.
  • screen.config.resourceDirectory: Gibt das Standardverzeichnis an, von dem Bilder mit relativem Pfad aus geladen oder gespeichert werden sollen.

Weitere Funktionalitäten in NutJs

Vielleicht sind dir neben den verwendeten Komponenten (clipboard, keyboard, mouse und screen) auch ein paar weitere Datentypen, Funktionen usw. aufgefallen. Ich will dir hier die wichtigsten aufzählen:

  • Button: Enum, der die drei üblichen Maustasten als Namen (LEFT, MIDDLE und RIGHT) enthält.
  • down: Funktion, um den Mauscursor nach unten zu bewegen.
  • fetchFromUrl: Lädt ein Bild mit einer angegebenen URL. Dadurch kann man Bilder aus dem Netz laden. Die Bildadresse kann als string oder als URL angegeben werden.
  • FileType: entält die Enum-Konstanten JPG und PNG.
  • getActiveWindow: Holt das aktuell fokussierte Fenster.
  • getWindows: Liefert eine Liste mit allen geöffneten Anwendungen und Prozessen.
  • Image: Datentyp für ein Bild mit weiteren Eigenschaften wie Auflösung (Breite und Höhe), Bits/Pixel, Farbkanäle, Farbmodus, usw.
  • isPoint: Prüft, ob ein Objekt vom Datentyp Point ist.
  • jestMatchers: Damit kann man expect im die Matcher toBeAt, toBeIn und toShow erweitern.
  • Key: Hierbei handelt es sich um einen Enum, der alle Tasten einer üblichen Tastatur als Namen enthält.
  • left: Funktion, um den Mauscursor nach links zu bewegen.
  • loadImage: Lädt ein Bild im JPEG- oder PNG-Format von der Festplatte.
  • Point: Datentyp für einen beliebigen Punkt (x-/y-Koordinate) auf dem Bildschirm.
  • Region: Datentyp für einen rechteckigen Bereich; enthält die linke, oberen Koordinate und die Ausdehnung (Breite/Höhe); wird u.a. von Window verwendet.
  • RGBA: Datentyp für eine Farbe mit Rot-, Grün-, Blau- und Alpha-Kanal.
  • right: Funktion, um den Mauscursor nach rechts zu bewegen.
  • saveImage: Speichert ein Bild im JPEG- oder PNG-Format auf die Festplatte.
  • sleep: Wartet mit der weiteren Ausführung für die angegebene Anzahl an Millisekunden.
  • straightTo: Funktion, um den Mauscursor zu einem bestimmten Punkt hinzubewegen.
  • toBeAt: Jest-Matcher, um zu prüfen, ob sich der Mauscursor an einem bestmmten Punkt befindet.
  • toBeIn: Jest-Matcher, um zu prüfen, ob sich der Mauscursor in einem bestimmten Bereich befindet.
  • toShow: Jest-Matcher, um zu prüfen, ob ein bestimmtes Bild oder ein bestimmter Bildausschnitt am Bildschirm sichtbar ist.
  • up: Funktion, um den Mauscursor nach oben zu bewegen.
  • URL: Datentyp, der von fetchFromUrl verwendet wird.
  • Window: Fensterdatentyp; enthält den Namen des Fensters und seine Region, also wo sich das Fenster genau am Bildschim befindet. Wird u.a. von getActiveWindow und getWindows verwendet.

Und noch mehr Funktionalitäten in NutJs

Ich selbst habe nur die kostenlose NutJS-Lizenz ausprobiert. Wenn du dich dafür entscheiden solltest, dir die kostenpflichtige Lizenz zu holen, stehen dir noch mehr Funktionen zur Verfügung. Du hast dann Zugriff auf folgende Bibliotheken:

  • @nut-tree/bolt: Damit kannst du die Funktionalitäten für Bildschirm, Maus, Tastatur und Zwischenablage erweitern. Um das jeweilgie Objekt zu erweitern, rufst du die entsprechende useBolt-Funktion auf. Um bspw. die Tastatur zu erweitern lautet die Funktion useBoltKeyboard. Diese hat dann volle Unicode unterstützung. Das Window-Objekt bietet u.a. auch einen Fenster-Finder an.
  • @nut-tree/nl-matcher: Enthält bessere Bilderkennungsfunktionen als der Template-Matcher, u.a. sogar Gesichtserkennung. Außerdem gibt es hierfür einen Long-Term-Support.
  • @nut-tree/plugin-ocr: Bietet Funktionalitäten zur Texterkennung. Auch auf dem Bildschirm kann dort Text erkannt werden, um bspw. Menüs leichter auffinden zu können.

Zusamenfassung

Die einzige, kleine Schwäche, die ich entdeckt habe, ist beim Ablauf eines Skripts, auch wenn man bspw. gerade einen Test laufen lässt, dass man nicht „hineinfunken“ darf. Das heißt, man sollte währenddessen keine Taste drücken und auch die Maus in Ruhe lassen. Da ein PC üblicherweise nur eine einzige Tastatur und nur eine einzige Maus hat, kann auch NutJS nur diese beiden einzigen ansteuern. Insgesamt kann ich jedoch sagen, dass NutJS im Bezug auf Desktop-Automatisierung Potenzial hat. Nur die kostenlosen Features stoßen schnell an ihre Grenzen, und es gibt auch leider keine Möglichkeit, die Pro-Features für einen kleinen Zeitraum kostenlos zu testen, wie man es von anderer kommerzieller Software kennt. Mit der bezahlten Lizenz kann man sicher noch mehr herausholen. Wenn du bis hierhin gelesen hast, danke ich dir für deine Aufmerksamkeit. Und wenn du zusätzlich auch auf den Geschmack gekommen bist, wünsche dir viel Spaß beim Ausprobieren. Lass deiner Kreativität freien Lauf! Bei Fragen und Anregungen freue ich mich auf einen Kommentar von dir, und bin selbstverständlich auch offen für konstruktive Kritik.


Quellenangaben


0 Kommentare

Hinterlasse einen Kommentar

An der Diskussion beteiligen?
Hinterlasse uns deinen Kommentar!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert