windows-interact
v1.3.1
Published
NPM Library of various tools for interacting with and automating Windows
Downloads
18
Maintainers
Readme
windows-interact
This library is a collection of tools for interacting with and automating Windows. It is designed to simplify and enhance existing tools while providing access to powerful new features.
With windows-interact
, NodeJS gains the following functionality:
- Control over audio devices
- Shutdown, Restart, Lock, Sleep, or start Screen Saver
- Send Toast notifications or Tray Balloons
- Mixin replacements for the browser's alert(), confirm(), and prompt()
- Native Windows File Picker
- Take screenshots
- Asynchronous Text to speech
- Play audio files in the background
- Manipulate windows (Maximize, Minimize, etc.)
- Manage a list of registered apps (with lots of extra features)
- Manage processes
- Enhanced logging and error throwing
- VERY Advanced PowerShell session manager
- More advanced than node-powershell, with automatic output collection and seperation, and the ability to run multiple command in succession by passing in array.
The current released version is 1.3.1. See the release notes if this version number differs from below
Patch 1.3.1:
- Fixed Win.PowerShell.newCommand rejecting empty 2nd and 3rd parameters
New in version (1.3.0):
- New display methods, including:
- Get/Set resolution
- Set projection mode
- Added
Win.get.user.idleTime()
to check the idle time of the user (last keyboard or mouse input) - Added detection for audio transmitted through both input and output (
Win.get.audioDevices.output.transmitting
,Win.get.audioDevices.input.transmitting
).
What's changed:
Added
stackTrace
as a verbosity option. From now on, most internal methods that use PowerShell will start hiding their large and irrelevant error stack trace unless this option is enabledWin.log()
now parses Javascript objects properly (Similar to console.log. Formatting and color is coming soon)App Manager:
- Added verbosity options
- onLaunch and onKill now return the name of the relevant application
Fixed bugs with
Win.alert()
andWin.confirm()
and now uses the same PowerShell Session under the hood to prevent excessive process spawningFixed a bug where Window Titles in
Win.appManager.registeredApps
would all be the same as the first appFixed an error associated with the AudioDeviceCmdlets module that appeared when installing windows-interact
Fixed
Win.notify()
andWin.filePicker()
(These were broken in the last release, so sorry!)Cleanup up miscellaneous internal code
Known issues:
Win.PowerShell()
:- Using
Start-Sleep
with any value greater than 800ms will cause some very odd issues with the internals ofWin.PowerShell()
. This is because 800ms is the extra time that each command is manually seperated to better discern output. This will be fixed in the future, but for now, avoid usingStart-Sleep
if possible
- Using
What's next:
Win.PowerShell()
is going to be optimized as much as possible and ran through with a fine tooth comb over the next few months.- There will be a lot of refactoring coming soon, this project is getting massive and its time to split it up a little.
- Better documentation / An official, actually navigateable website.
- Most or all methods will be converted to Promises instead of callbacks
- Planning on removing dependency on requestify, perhaps building my own wrapper for nodes' native request methods with zero dependencies
Got ideas? Something you want windows-interact to include? Fantastic, contact me on twitter @Arlodottxt with your suggestions or open a new Issue on Github
Installation
Install the npm package by running npm install windows-interact
in your project folder
Then, in your js file, require
the package.
const Win = require('windows-interact');
Windows-Interact also relies moderately on nircmd. This is included in the package but untested on another machine, so if you start having troubles, try installing it to your machine.
Documentation
Win.set
Used to set various things within Windows, as well as set preferences for windows-interact
Set Global user preferences for Windows Interact
Win.set.preferences({
// Default text to speech voice to use (For Win.speak)
TTSVoice: 'Microsoft David Desktop',
// Inverval at which the app manager gets the status of registered apps. Leaving unset defaults the interval to 5000
appManagerRefreshInterval: 2500,
// Log options
log: {
// File to save log and error history
outputFile: Win.path`C:\Users\User\node-server\log.txt`,
// Show or hide timestamp in log (For Win.log & Win.error)
showTime: true,
// Default message to speak when an error occurs (For Win.error)
spokenErrorMessage: 'Something is wrong with your node server. Details are in the log',
// Control verbosity of parts of windows-interact
verbose: {
// Show preformatted log when requests are made
requestTo: true,
// Be verbose while managing PowerShell sessions
PowerShell: true,
appManager: true
}
}
});
Display
Set the resolution of the primary display
Win.set.display.resolution(width, height, callback) => : void
Win.set.display.resolution(1920, 1080, () => {
console.log('Done');
});
Set the projection mode
// Accepted values are "primary", "secondary", "extend" or "duplicate"
Win.set.display.projectionMode(mode);
Audio Devices
Input
Set the volume of the current input device
Win.set.audioDevices.input.volume('50');
Set the mute state of the current input device
Win.set.audioDevices.input.mute();
Set the default input device in Windows
Win.set.audioDevices.input.default('Headset Earphone');
Output
Set the volume of the current output device
Win.set.audioDevices.output.volume('50');
Set the mute state of the current output device
Win.set.audioDevices.output.mute();
Set the default output device in Windows
Win.set.audioDevices.output.default('Headset Earphone');
Win.get
Used to get the status of various things within Windows
User
Get the Idle time of the current user
Win.get.user.idleTime(callback) => : Promise
// Log the Idle time
Win.get.lastInput()
.then(console.log); // : [hours, minutes, seconds]
Display
Get the current display resolution
Win.get.display.resolution(callback) => : void
Win.get.display.resolution(result => {
console.log(result) // : { height: '1920', width: '1080' }
});
Audio Devices
Input
Get the volume of the current input device
Win.get.audioDevices.input.volume(function(result) {
console.log(result); // Volume level of the current default device
});
Get the mute state of the current input device
Win.get.audioDevices.input.mute(function(result) {
console.log(result); // Mute state of the current default device
});
Get the default input device in Windows
Win.get.audioDevices.input.default(function(result) {
console.log(result); // Name of the current default input device
});
Get the audio transmission state of the default input device (Microphone detection)
Win.get.audioDevices.input.transmitting(callback => : boolean);
Win.get.audioDevices.input.transmitting((result) => {
console.log(result); // Whether or not there is audio being transmitted through the default input
});
Output
Get the volume of the current output device
Win.get.audioDevices.output.volume(function(result) {
console.log(result); // Volume level of the current default device
});
Get the mute state of the current output device
Win.get.audioDevices.output.mute(function(result) {
console.log(result); // Mute state of the current default device
});
Get the default output device in Windows
Win.get.audioDevices.output.default(function(result) {
console.log(result); // Name of the current default output device
});
Get the audio transmission state of the default output device
Win.get.audioDevices.output.transmitting(callback => : boolean);
Win.get.audioDevices.output.transmitting((result) => {
console.log(result); // Whether or not there is audio being transmitted through the default output device
});
Win.log()
Win.log(message, {background: 'color', color: 'color'}); => : void
An alternative to console.log
. It pushes the output of the log to the console and can record each entry in a .txt file, while providing simple colour options for the text
Available colours for background and text are:
- Red
- Green
- Yellow
- Blue
- Magenta
- Cyan
- Black
You can set the default log file location with Win.set.preferences
, like so:
Win.set.preferences({
log: {
// File to save log and error history (For Win.log)
outputFile: Win.path`C:\Users\User\node-server\log.txt`,
// Show or hide timestamp in log (For Win.log & Win.error)
showTime: true,
// Control verbosity of parts of windows-interact
verbose: {
// Show preformatted log when requests are made
requestTo: true,
// Be verbose while managing PowerShell sessions
PowerShell: true,
appManager: true
}
}
});
Usage:
// Log information to the console and .txt file
Win.log('Logged information');
// Log information to the console and .txt file, with colored background and text, and don't show the timestamp (even if enabled in preferences)
Win.log('Logged ', 'information', {background: 'color', color: 'color', showTime: false});
Win.log.speak(phrase, voice, speed, options);
// Log information to the console and .txt file, and also Win.speak() it
Win.log.speak('Testing');
// Log information to the console and .txt file, Win.speak() it with a specific voice, at half speed, with a black background and a blue text colour
Win.log.speak('Testing', 'Microsoft David Desktop', 0.5, {background: 'black', colour: 'blue'})
Win.error()
An alternative to throw new Error()
or console.error
. It will push the output of the log to the console (in a red colour) with a stack trace, and record each entry in the specified log file
You can set some default options with Win.set.preferences
, like so:
Win.set.preferences({
log: {
// Default message to speak when an error occurs
spokenErrorMessage: 'Something is wrong with your node server. Details are in the log',
// File to save log and error history (For Win.log)
outputFile: Win.path`C:\Users\User\node-server\log.txt`,
// Show or hide timestamp in log (For Win.log & Win.error)
showTime: true
}
});
Usage:
// Log an error to the console and default .txt file (if set)
Win.error('Error information');
// Log an error to the console, but don't speak the set spokenErrorMessage
Win.error('Error information', {silent: true});
Win.notify()
Show a toast notification in Windows 10 (Or tray balloon on older versions of windows)
If you need something more advanced than basic notifications, I'd recommend using node-notifier
// Show toast notification with an image or animated GIF
Win.notify('Title', 'Message', Win.path`C:\path\to\image\or\animated.gif`);
// Show single line toast notification
Win.notify('Message');
Win.path``
Return a properly formatted Windows path for use in Javascript. This allows you to simply copy and paste a path from the File Explorer without having to worry about character-escaping (\
) slashes.
If you are passing in a directory, surround the path with double quotes or escape the last backslash. Surrounding double quotes are always removed.
Win.path`C:\WINDOWS\system32\notepad.exe`;
Win.speak()
Speak text asynchronously. Similar to my async-sayjs package (Yep, that started here), but with some benefits and enhancments.
You can set the default text to speech voice with Win.set.preferences
, like so:
Win.set.preferences({
TTSVoice: 'Microsoft Eva Mobile'
});
Usage:
// Speak something asynchronously (wait for each request to finish before moving on)
Win.speak('The quick brown fox');
// Speak something synchronously (Say it right now, even if something is already being said)
Win.speak.now('Jumped over the lazy dog');
// Supply a string as the second parameter to change the TTS voice
Win.speak('As it ran through the woods', 'Microsoft David Desktop');
// Speak something, but slowly
Win.speak('Lorem ipsum dolor sit amet', 'Microsoft Zira Desktop', 0.5);
// Speak something, then fire a callback
Win.speak('Lorem ipsum dolor sit amet', 'Microsoft David Desktop', 0.5, (err) => {
console.log('Done');
});
// Speak something and Win.log() it (Same as Win.log.speak(''))
Win.speak.log('Lorem ipsum dolor sit amet');
// Stop anything currently being spoken (Queued text will continue after that)
Win.speak.stop(callback);
Win.appManager
The App Manager is possibly the biggest part of Windows Interact. It allows you to:
- Register applications and manage them in one simple place
- Run code when a registered app is launched or killed
- Quickly launch or kill an app
- Get the title of an app window
- Check if an app is currently running
- Hide an app
- Switch to an app
To get started, you need to register your apps. You will need the absolute path of the executable at the minimum. To easily format a Windows path for use in Javascript, it is recommended that you use Win.path`C:\absolute\path`
Register a new application
Win.appManager.register({
'Pad': {
path: Win.path`C:\WINDOWS\system32\notepad.exe`
},
'Code': {
path: Win.path`C:\Program Files\Microsoft VS Code\Code.exe`,
onLaunch: function() {
Win.speak('VSCode was launched');
},
onKill: function() {
Win.speak('VSCode was killed');
}
},
'Mozilla': {
path: Win.path`C:\Program Files\Mozilla Firefox\firefox.exe`,
onKill: function() {
Win.log('firefox killed');
},
onLaunch: function() {
Win.log('firefox launch');
}
}
});
Group together registered apps
Win.appManager.register.group({
"Stuff": {
apps: ["Pad", "Mozilla"],
onLaunch: function(appName) {
console.log(appName + ' launched');
},
onKill: function(appName) {
console.log(appName + ' killed');
}
}
});
Retrieve registered applications
Win.appManager.registeredApplications
Launch a registered application
Win.appManager.launch('notepad');
Kill a registered application
Win.appManager.kill('notepad');
Launch a registered group of apps
Win.appManager.launch.group('Stuff');
Kill a registered group of apps
Win.appManager.kill.group('Stuff');
Hide a registered application
Win.appManager.hide('notepad');
Switch to a registered application
Win.appManager.switchTo('notepad');
Win.process
Win.process
is very similar to appManager
, but can be used for unregistered apps. Use sparcely and avoid loops, this is not as efficient as appManager
.
Get PID of a running process
Returns an array of PIDs associated with a running process. If no process is found, false is returned. The data is piped into a callback.
Win.process.getPid('notepad', function(output) {
Win.log(output);
});
Kill a running app
Kill an app by either process name or PID
Win.process.kill('notepad', callback);
Run a callback when a process is killed
App must already be running, if not, it will wait until it has started and then tell powershell to wait until the app is done before continuing.
Win.process.onKill('notepad', function() {
Win.log('Notepad killed');
});
Get Window Title of running application
Win.process.getWindowTitle('notepad', function(output) {
Win.log(output);
});
Hide an application by process name
Win.process.hide('notepad');
Check if a process is running
Win.process.isRunning('notepad', function(bool) {
Win.log(bool);
});
Win.window()
Control a Window's state
Minimize a window
If no processName is specified, it will minimize the current window in the foreground.
// Minimize a window by process name. The ".exe" is optional.
Win.window.minimize('firefox.exe');
// Minimize the current window
Win.window.minimize();
Maximize a window
If no processName is specified, it will maximize the current window in the foreground.
// Maximize a window by process name. The ".exe" is optional
Win.window.maximize('firefox.exe');
// Maximize the current window
Win.window.maximize();
Restore a window to a windowed state
If no processName is specified, it will restore the current window in the foreground.
// Restore a window by process name. The ".exe" is optional
Win.window.restore('firefox.exe');
// Restore the current window
Win.window.restore();
Resize a window
If no processName is specified, it will resize the current window in the foreground.
Win.window.resize(width, height, processName);
// Resize a window by process name. The ".exe" is optional
Win.window.resize('800', '600', 'firefox.exe');
// Resize the current window
Win.window.resize(960, 1080);
Move a window
- X and Y are relative to the current window position.
- If no processName is specified, it will move the current window in the foreground.
Win.window.move(x, y, processName);
// Move a window by process name. The ".exe" is optional
Win.window.move('-50', '0', 'firefox.exe');
// Move the current window
Win.window.move(0, 50);
Win.cmd()
Run a command in Command Prompt.
Win.cmd('dir');
// Run a command, then do something with the output
Win.cmd('tasklist', function(output) {
doSomething(output);
});
// Run a command, then do something with the output and any possible errors
Win.cmd('tasklist', function(output, errors){
doSomething(output)
if(errors) doSomethingElse(errors)
});
// Run a command, but supress any errors that occur (Don't print them to console or log)
Win.cmd('tasklist', function(output){
doSomething();
}, {suppressErrors: true});
// Run a command, but don't print to log
Win.cmd('tasklist', function(output){
doSomething();
}, {noLog: true});
Win.PowerShell()
Run one or more PowerShell commands.
You can run a single powershell command by passing a string, or run multiple commands in the same powershell instance by passing commands in an array.
When you pass an array to run multiple commands, the returned output and errors will be an array, not a string. The indexes of commands will matche the indexes of output returned
This is playing with real power. See here and here for resources on what you can do with PowerShell to automate and interact with Windows, beyond what Windows interact provides
Win.PowerShell(string|array: command, callback, options);
Win.PowerShell('ls');
// Run a command, then do something with the output
Win.PowerShell('Move-Item -Path C:\\test.txt -Destination E:\\Temp\\tst.txt', function(output) {
doSomething(output);
});
// Run a command, then do something with the output and any possible errors
Win.PowerShell('Move-Item -Path C:\\Temp -Destination C:\\Logs', function(output, errors){
doSomething(output)
if(errors) doSomethingElse(errors)
});
// Run a command, but suppress any errors that occurr (Don't print them to console or log)
Win.PowerShell('Move-Item -Path .\\*.txt -Destination C:\\Logs', function(output){
doSomething();
}, {suppressErrors: true});
// Run a command, but do not log the output and supress any errors that occurr (Don't print them to console or log)
Win.PowerShell('Restart-Service -Name Audiosrv', function(output){
doSomething();
}, {suppressErrors: true, noLog: true});
// Run multiple commands in the same powershell window
Win.PowerShell(['$somevariable="Hello World!"', 'Write-Host "$somevariable"'], function(output, errors){
console.log(output); // ['Hello World!']
if(errors.length > 0) Win.error('Something went wrong');
}, {noLog: true});
Keeping a PowerShell session open for later use
To keep a PowerShell session open, pass keepAlive: true
and ID: 'someid'
into the options
object.
Win.PowerShell.newCommand(id, command)
Issue a new command to an open PowerShell session by the assigned ID
// Keep a windows open first
Win.PowerShell('$tester = "Hello world"', (result, err) => {
console.log('First run')
}, { noLog: false, keepAlive: true, id: 'test' });
// Then add a new command
Win.PowerShell.endSession(id, callback)
End an open PowerShell session by ID
Win.requestTo()
Make an HTTP request the easy way.
To simplify this feature and make using it more natural, there is some flexibility with the parameters
- There are 4 default parameters which will work in every scenario (no shorthand):
url, method, formData, callback
- If the all parameters are ommited, an assumed GET request will be made.
- If the second paramter is a function, it will assume that this is a callback and an assumed GET request will be made
- If the third parameter is an object, it will send this as form data.
- If the third parameter is a function, it execute it as a callback
Win.requestTo(url, method, formData, callback);
// Make a POST request
Win.requestTo('http://httpbin.org/post/', 'POST', {
property: 'value'
});
// Make a POST request, then do something with the response
Win.requestTo('http://httpbin.org/post/', 'POST', {
property: 'value'
}, function(response) {
Win.log(response);
});
// Make a GET request
Win.requestTo('http://httpbin.org/get/', 'GET', function(response) {
Win.log(response)
});
// Make an assumed GET request
Win.requestTo('http://httpbin.org/get/', function(response) {
Win.log(response)
});
// Make an assumed GET request to a predefined URL, and do nothing else
Win.requestTo('http://httpbin.org/get/');
// Make a PUT request
Win.requestTo('http://httpbin.org/put/', 'PUT', {
property: 'value'
});
// Make a PUT request, then do something with the response
Win.requestTo('http://httpbin.org/put/', 'PUT', {
property: 'value'
}, function(response) {
Win.log(response)
});
Win.confirm()
An alternative to the browsers's confirm()
. Unlike the browser, it will not stop execution of code and wait for the user. It will instead show multiple dialog boxes. To chain consecutive dialog boxes, you need to wrap them in an async function (see below).
Win.confirm('Title', 'Question?');
Win.alert('Question');
// Chain consecutive alerts
async function chain() {
if(await Win.confirm('Message?')) {
await Win.alert('Message!');
}
}
chain();
// Super simple self-executing async function
(async ()=>{
if(await Win.confirm('Message?')) {
await Win.alert('Ok!');
} else {
await Win.alert('Canceled...');
}
})();
Win.alert()
An alternative to the browsers's alert()
. Unlike the browser, it will not stop execution of code and wait for the user. It will instead show multiple dialog boxes. To chain consecutive alerts, you need to wrap them in an async function (see below).
// Show an alert box with title and message
Win.alert('Message', 'Title');
Win.alert('Message');
// Chain consecutive alerts
async function chain() {
await Win.alert('Message');
await Win.alert('More message');
}
chain();
// Super simple self-executing async function
(async()=>{
await Win.alert('Message');
await Win.alert('More message');
})();
Win.prompt()
An alternative to the browsers's prompt()
. Unlike the browser, it will not stop execution of code and wait for the user. It will instead show multiple dialog boxes. To chain consecutive prompts, you need to wrap them in an async function (see below).
Win.prompt('Message', 'Title', 'Placeholder');
Win.prompt('Message');
// Chain consecutive alerts
async function chain() {
if(await Win.prompt('Please type bananas') == 'bananas') {
await Win.alert('Thank you for typing bananas');
}
}
chain();
// Super simple self-executing async function
(async()=>{
if(await Win.prompt('Do you like Pie?') == 'Yes') {
await Win.alert('Me too!');
} else {
Win.alert('More for me');
}
})();
Win.filePicker()
Shows the native Windows File Picker (No really!) and returns the path for the selected file. If no file is selected, undefined
is returned instead.
Win.filePicker(windowTitle, initialDirectory, filter, allowMultiSelect, callback);
// Default everything.
// windowTitle will be "Select a file".
// initialDirectory will be C:\
// Filter will be set to "All files"
// multiSelect is disabled
Win.filePicker(null, null, null, null, function(result){
console.log(result); // Path of selected file
});
// Have the user choose an application from Program Files
Win.filePicker('Choose an app', 'C:\\Program Files\\', {filtertext: 'Programs', filterby: '*.exe'}, false, function(result){
console.log(result); // Path of a single chosen .exe file
});
// Have the user choose a very specific file
Win.filePicker('Where is it at?', Win.path`"C:\Users\Owner\OneDrive\Documents\"`, {filtertext: 'Specific file', filterby: 'Essay.docx'}, false, function(result){
console.log(result); // Path of Essay.docx file
});
// Use some defaults and have the user pick a few .png files
Win.filePicker(null, null, {filterby: '.png'}, true, function(result) {
console.log(result); // Array of paths for the selected .png files
});
// Have the user select an image file
Win.filePicker('Select a picture', Win.path`"C:\Users\Owner\OneDrive\Pictures\"`, {filterby: ['.png', '.jpg', '.gif']}, true, function(result) {
console.log(result); // Array of paths for the selected .png, .jpg, or .gif files
});
Win.playAudio(path);
Play an audio file in the background. Must be a .wav
format. If you try any other format, it will fall back to Windows Media Player to play it (so make sure it's installed through Optional Features).
Win.playAudio(Win.path`"C:\windows\media\tada.wav"`);
Win.stopAudio(path);
--
Stop a playing audio file using the same path supplied to Win.playAudio()
.
Win.playAudio(Win.path`"C:\windows\media\Alarm02.wav"`);
setTimeout(() => {
Win.stopAudio(Win.path`"C:\windows\media\Alarm02.wav"`)
}, 2000);
Win.power()
Shutdown the PC
// If no delay is provided, it will shutdown immediately
Win.power.shutdown(delay);
Restart the PC
// If no delay is provided, it will restart immediately
Win.power.restart(delay);
Lock the PC
// If no delay is provided, it will lock immediately
Win.power.lock(delay);
Put the PC to sleep
// If no delay is provided, it will go to sleep immediately
Win.power.sleep(delay);
Start the screensaver
// If no delay is provided, it will start the screensaver immediately
Win.power.screenSaver(delay);
Show the desktop
Win.showDesktop();
Pause or resume media being played
Same as pressing the play/pause button on keyboard.
Win.toggleMediaPlayback();
Take a screenshot
Win.screenshot(region, path) => : Promise
// Screenshot the entire screen and save to clipboard
Win.screenshot();
Win.screenshot('full');
// Screenshot a region of the screen and save it to clipboard
Win.screenshot('window');
// Screenshot the entire screen and save to file
Win.screenshot('full', Win.path`C:\Users\User\Pictures\Screenshots\screenshot.png`);
// Screenshot the current window only and save to file
Win.screenshot('window', Win.path`C:\Users\User\Pictures\Screenshots\screenshot.png`);