winrm-client
v0.0.12
Published
Make WinRM service calls from NodeJS
Downloads
4,854
Readme
winrm-client
⚠️ This is an updated fork of the original nodejs-winrm project that doesn't seem to be maintained anymore.
winrm-client is a production-ready NodeJS client to access WinRM (Windows Remote Management) SOAP web service. It allows to execute commands on target windows machines. Please visit Microsoft's WinRM site for WINRM details.
⬆️ Migration from nodejs-winrm
Replace shell and command with Shell and Command.
// CommonJS
const { Shell, Command } = require('winrm-client');
// ES6
import { Shell, Command } from 'winrm-client';Installation
# Using npm
npm install winrm-client
# Using pnpm
pnpm add winrm-client
# Using yarn
yarn add winrm-clientFeatures
- 🔁 Supports both CommonJS and ES6 modules.
- 🏗️ Has types for all exported functions and interfaces.
- 🔐 Supports both Basic and NTLM authentication (auto-detected based on username format)
- 🔁 Supports interactive commands that can automatically respond to prompts using three types of detection methods: (see Interactive Commands)
- Regex Patterns (traditional method)
- Custom Sync Detectors (new)
- Custom Async Detectors (new)
- 🔍 Supports debug logging using the
DEBUGenvironment variable (see Debug Logging) - 🧪 Supports testing (see Testing)
Supported NodeJS Versions
Supports NodeJS Version >= 16.0.0
Tested on NodeJS versions 16, 18, 20, and latest LTS.
Supported WinRM Versions
As of now Winrm Version 3 is tested.
> winrm id
IdentifyResponse
ProtocolVersion = http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd
ProductVendor = Microsoft Corporation
ProductVersion = OS: 10.0.xxxx SP: 0.0 Stack: 3.0Remote Installation
On the remote host, a PowerShell prompt, using the Run as Administrator option and paste in the following lines:
> winrm quickconfig
y
> winrm set winrm/config/service/Auth '@{Basic="true"}'
> winrm set winrm/config/service '@{AllowUnencrypted="true"}'
> winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="1024"}'On the client side where NodeJS is installed
npm install winrm-client
Authentication
winrm-client supports two authentication methods that are automatically detected based on the username format:
Basic Authentication
Used for local usernames (no domain prefix). Requires enabling Basic auth on the WinRM service.
// Local username - uses Basic authentication
await runCommand('hostname', 'server', 'Administrator', 'password', 5985);NTLM Authentication
Used for domain accounts. Automatically enabled when using domain-prefixed usernames.
// Domain prefix format (DOMAIN\user) - uses NTLM authentication
await runCommand(
'hostname',
'server',
'DOMAIN\\Administrator',
'password',
5985
);
// UPN format ([email protected]) - uses NTLM authentication
await runCommand('hostname', 'server', '[email protected]', 'password', 5985);Username Format Support
| Username Format | Auth Method | Example |
| --------------- | ----------- | ----------------- |
| Local | Basic | Administrator |
| Domain prefix | NTLM | DOMAIN\user |
| UPN | NTLM | [email protected] |
Remote Host Configuration for NTLM
For NTLM authentication, ensure the remote WinRM service allows Negotiate authentication:
# Enable Negotiate authentication (includes NTLM)
> winrm set winrm/config/service/Auth '@{Negotiate="true"}'Development Workflow
For development with TypeScript:
# Install dependencies
npm install
# Build TypeScript to JavaScript
npm run build
# Watch mode for development
npm run build:watch
# Lint TypeScript files
npm run lint
# Format code with Prettier
npm run format
# Check formatting
npm run format:checkDebug Logging
To enable debug logging, set the DEBUG environment variable to winrm or winrm:*.
Possible values for namespace are:
*// Enable debug logging for all namespaceshttpshellcommandinteractiverunCommandrunPowershell
To enable debug logging for all namespaces, set the DEBUG environment variable to winrm:*.
DEBUG=winrm:* node index.jsExamples
Run a Single Command
JavaScript
const winrm = require('winrm-client');
winrm.runCommand(
'mkdir D:\\winrmtest001',
'10.xxx.xxx.xxx',
'username',
'password',
5985
);
winrm.runCommand(
'ipconfig /all',
'10.xxx.xxx.xxx',
'username',
'password',
5985
);TypeScript
import { runCommand, runPowershell } from 'winrm-client';
async function executeCommand(): Promise<void> {
try {
const result = await runCommand(
'mkdir D:\\winrmtest001',
'10.xxx.xxx.xxx',
'username',
'password',
5985
);
console.log('Command result:', result);
const ipResult = await runCommand(
'ipconfig /all',
'10.xxx.xxx.xxx',
'username',
'password',
5985
);
console.log('IP Config:', ipResult);
} catch (error) {
console.error('Error executing command:', error);
}
}
executeCommand();Run Command with NTLM Authentication
For domain-joined machines or Azure AD accounts:
import { runCommand, runPowershell } from 'winrm-client';
async function executeDomainCommand(): Promise<void> {
try {
// Using DOMAIN\user format
const result = await runCommand(
'whoami',
'server.company.com',
'CORPORATE\\admin',
'password',
5985
);
console.log('Current user:', result);
// Using UPN format ([email protected])
const psResult = await runPowershell(
'Get-Process | Select-Object -First 5',
'server.company.com',
'[email protected]',
'password',
5985
);
console.log('Processes:', psResult);
} catch (error) {
console.error('Error:', error);
}
}
executeDomainCommand();Interactive Commands
WinRM Client supports interactive commands that can automatically respond to prompts using three types of detection methods:
- Regex Patterns (traditional method)
- Custom Sync Detectors (new)
- Custom Async Detectors (new)
Basic Interactive Command
const winrm = require('winrm-client');
const prompts = [
{
pattern: /Enter your name:/i,
response: 'John Doe',
},
{
pattern: /Password:/i,
response: 'secret123',
isSecure: true, // Won't log the response
},
];
const result = await winrm.runInteractivePowershell(
'my-interactive-script.ps1',
'host',
'username',
'password',
5985,
prompts,
30000 // timeout in milliseconds
);Custom Sync Detectors
Use custom synchronous functions for complex prompt detection logic:
const prompts = [
{
detector: (output) => {
// Custom logic for detecting prompts
const lines = output.split('\n');
return lines.some(
(line) =>
line.toLowerCase().includes('password') ||
line.toLowerCase().includes('passphrase')
);
},
response: 'myPassword123',
isSecure: true,
},
{
detector: (output) => {
// Multi-condition detection
return output.includes('Continue?') && output.includes('(y/n)');
},
response: 'y',
},
];Custom Async Detectors
Use async functions for detection that requires external API calls, LLM responses, database lookups, or other async operations:
const prompts = [
{
asyncDetector: async (output) => {
// Example: External API validation
const errorCodeMatch = output.match(/Error Code: (\d+)/);
if (errorCodeMatch) {
try {
// Make external API call
const response = await fetch(
`https://api.example.com/errors/${errorCodeMatch[1]}`
);
const data = await response.json();
return data.requiresConfirmation ? 'yes' : '';
} catch {
return 'no'; // Fallback to regex pattern if available
}
}
return 'no';
},
pattern: /Do you want to retry/i, // Fallback pattern
},
];Detection Priority and Fallback
The detection methods are prioritized as follows:
- Async Detector (highest priority)
- Sync Detector
- Regex Pattern (fallback)
If a custom detector fails with an error, the system will automatically fall back to the regex pattern if available:
Error Handling
Custom detectors are wrapped in try-catch blocks to prevent failures from breaking the interactive flow:
- If a custom detector throws an error, it falls back to the regex pattern
- If both custom detector and regex pattern fail, the prompt is skipped
- Errors are logged for debugging purposes
Testing
npm test
Test Server Setup (Windows)
For e2e testing, use the included setup script on a Windows Server (AWS EC2, etc.):
# Via SSH
ssh Administrator@<IP> "powershell -ExecutionPolicy Bypass" < scripts/setup-winrm.ps1This configures WinRM + AD DS with a test user. See WINRM_SETUP.md for details.
Maintainers
- Sebastien Hideux (https://github.com/shide1989)
