Python library for Windows Remote Management (WinRM) service enabling remote command execution and PowerShell scripts on Windows machines.
—
Response containers that encapsulate command execution results including output streams and exit codes. Response objects provide a standardized interface for accessing command results from both Session and Protocol operations.
Container for command execution results with decoded output streams and status information.
class Response:
std_out: bytes
std_err: bytes
status_code: int
def __init__(self, args: tuple[bytes, bytes, int]) -> None:
"""
Initialize Response with command execution results.
Parameters:
- args: tuple of (stdout, stderr, status_code)
- stdout: command standard output as bytes
- stderr: command standard error as bytes
- status_code: command exit code (0 for success, non-zero for error)
"""
def __repr__(self) -> str:
"""
String representation showing status code and truncated output.
Returns:
Formatted string with response details for debugging
"""Direct access to command execution results for processing and analysis.
Standard Output (std_out)
Standard Error (std_err)
Status Code (status_code)
import winrm
s = winrm.Session('windows-host', auth=('user', 'password'))
# Execute command and process response
r = s.run_cmd('ipconfig', ['/all'])
# Check execution success
if r.status_code == 0:
output = r.std_out.decode('utf-8')
print("Network configuration:")
print(output)
else:
error = r.std_err.decode('utf-8')
print(f"Command failed with code {r.status_code}: {error}")
# Response representation
print(repr(r)) # <Response code 0, out b'Windows IP Configuration...', err b''># PowerShell script with structured output
ps_script = """
Get-Service | Where-Object {$_.Status -eq 'Running'} |
Select-Object Name, Status, StartType |
ConvertTo-Json -Depth 2
"""
r = s.run_ps(ps_script)
if r.status_code == 0:
import json
services = json.loads(r.std_out.decode('utf-8'))
print(f"Found {len(services)} running services")
for service in services[:5]: # Show first 5
print(f"- {service['Name']}: {service['Status']}")
else:
# PowerShell errors are cleaned by Session.run_ps()
print("PowerShell error:", r.std_err.decode('utf-8'))def execute_with_retry(session, command, args=None, max_retries=3):
"""Execute command with retry logic based on response status."""
args = args or []
for attempt in range(max_retries):
r = session.run_cmd(command, args)
if r.status_code == 0:
return r.std_out.decode('utf-8')
print(f"Attempt {attempt + 1} failed (code {r.status_code})")
if attempt < max_retries - 1:
time.sleep(2 ** attempt) # Exponential backoff
# Final failure
error_msg = r.std_err.decode('utf-8') if r.std_err else "Unknown error"
raise Exception(f"Command failed after {max_retries} attempts: {error_msg}")
# Usage
try:
result = execute_with_retry(s, 'net', ['user', 'testuser'])
print("User info:", result)
except Exception as e:
print("Command execution failed:", e)# Command that produces binary output
r = s.run_cmd('type', ['C:\\Windows\\System32\\calc.exe'])
if r.status_code == 0:
# Handle binary data
binary_data = r.std_out
print(f"Binary file size: {len(binary_data)} bytes")
# Save to file
with open('downloaded_calc.exe', 'wb') as f:
f.write(binary_data)
else:
print("Failed to read binary file")# Handle different text encodings
r = s.run_cmd('chcp') # Check current code page
if r.status_code == 0:
# Windows often uses CP1252 or other code pages
try:
output = r.std_out.decode('utf-8')
except UnicodeDecodeError:
# Fallback to common Windows encoding
output = r.std_out.decode('cp1252', errors='replace')
print("Code page info:", output.strip())
# Force UTF-8 output in PowerShell
ps_script = """
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
Get-Date -Format "yyyy-MM-dd HH:mm:ss"
"""
r = s.run_ps(ps_script)
if r.status_code == 0:
timestamp = r.std_out.decode('utf-8').strip()
print(f"Server time: {timestamp}")def analyze_response(response):
"""Analyze response object and provide summary information."""
analysis = {
'success': response.status_code == 0,
'status_code': response.status_code,
'stdout_size': len(response.std_out),
'stderr_size': len(response.std_err),
'has_output': len(response.std_out) > 0,
'has_errors': len(response.std_err) > 0
}
# Try to decode output for content analysis
try:
stdout_text = response.std_out.decode('utf-8')
analysis['stdout_lines'] = len(stdout_text.splitlines())
analysis['stdout_preview'] = stdout_text[:100] + '...' if len(stdout_text) > 100 else stdout_text
except UnicodeDecodeError:
analysis['stdout_encoding'] = 'binary_or_unknown'
try:
stderr_text = response.std_err.decode('utf-8')
analysis['stderr_lines'] = len(stderr_text.splitlines())
analysis['stderr_preview'] = stderr_text[:100] + '...' if len(stderr_text) > 100 else stderr_text
except UnicodeDecodeError:
analysis['stderr_encoding'] = 'binary_or_unknown'
return analysis
# Usage
r = s.run_cmd('systeminfo')
analysis = analyze_response(r)
print(f"Command {'succeeded' if analysis['success'] else 'failed'}")
print(f"Output: {analysis['stdout_lines']} lines, {analysis['stdout_size']} bytes")
if analysis.get('stdout_preview'):
print(f"Preview: {analysis['stdout_preview']}")Install with Tessl CLI
npx tessl i tessl/pypi-pywinrm