Automated script to monitor M.E.Doc server updates and send Telegram notifications.
This tool requires PowerShell 7.0 or later. PowerShell 5.1 is not supported.
Why? PowerShell 5.1 reached end-of-support in 2019. PowerShell 7+ is actively maintained by Microsoft with security updates and modern features.
Installation: Follow Microsoft's official PowerShell Installation Guide.
Verify installation:
pwsh -Command '$PSVersionTable.PSVersion'
# Expected output: 7.x or higherIf PowerShell 7+ is not found when running Setup-ScheduledTask.ps1, the script will fail with a clear error directing you to install it.
Intended Platform: Windows (M.E.Doc servers in production)
Development & Testing: Primarily on macOS and Linux with cross-platform PowerShell 7
Testing Coverage:
- ✅ Comprehensive testing on macOS/Linux (CI/CD pipeline)
⚠️ Limited testing on Windows (production usage only on developer's servers)⚠️ Windows-specific features (Event Log, Task Scheduler) need broader user validation
If you use this on Windows servers: Please report any issues you encounter. Windows-specific behavior (Event Log integration, Task Scheduler execution, SYSTEM user context, CMS certificate handling) may benefit from additional testing in your environment before wide deployment.
See TESTING.md - Platform Support for detailed notes on cross-platform behavior.
This project has comprehensive documentation. Choose your entry point based on your role:
| Your Role | Start Here | Learn |
|---|---|---|
| Want to deploy quickly? | DEPLOYMENT.md | Step-by-step setup guide with all deployment options |
| Want to test changes? | TESTING.md | Test procedures, message formats, test data |
| Want to contribute code? | CONTRIBUTING.md | Development guidelines, commit standards, testing |
| Concerned about security? | SECURITY.md | Credential handling, Event Log, best practices |
| AI coding agent? | AGENTS.md | Quick reference (also CLAUDE.md) + 5 specialized guides |
| Need quick overview? | README.md (you are here) | Project overview, features, example messages |
Start with AGENTS.md (or CLAUDE.md symlink), then navigate to specialized guides as needed:
- AGENTS-CODE-STANDARDS.md - Code style, naming conventions, PS7+ features, removed cmdlets
- AGENTS-TESTING.md - Testing procedures, Pester syntax, enum usage
- AGENTS-SECURITY.md - Security best practices, PII concerns, credential handling
- AGENTS-DOCUMENTATION.md - Documentation maintenance, avoiding stale docs
- AGENTS-TOOLS-AND-WORKFLOW.md - Tool selection, git workflow, CI/CD
For complete step-by-step deployment instructions, see DEPLOYMENT.md.
Choose one method:
- Automatic download on target server: Use the API-based approach in DEPLOYMENT.md - Section 1, Option A
- Manual download: Download from Latest Release
- Copy from local machine: Use robocopy or RDP file transfer
IMPORTANT: Store sensitive credentials (BotToken, ChatId) securely. Credentials are encrypted with CMS (Cryptographic Message Syntax) using a self-signed LocalMachine certificate and can be read by SYSTEM user in Task Scheduler.
Run as Administrator on the target server:
cd C:\Apps\medoc-update-check
.\utils\Setup-Credentials.ps1This will:
- ✅ Create self-signed certificate in LocalMachine store (if missing)
- ✅ Prompt for Bot Token and Chat ID
- ✅ Encrypt credentials using CMS with 2048-bit RSA key
- ✅ Save to
$env:ProgramData\MedocUpdateCheck\credentials\telegram.cms - ✅ Restrict file permissions (SYSTEM + Administrators only)
- ✅ Certificate auto-rotates if expiring (< 30 days)
Non-interactive setup (for scripted deployment):
.\utils\Setup-Credentials.ps1 -BotToken "123456:ABC..." -ChatId "-1002825825746"Choose the number of servers you need to monitor:
Copy and edit the template with your actual server hostname:
# Copy using your server's hostname automatically
cp configs/Config.template.ps1 "configs/Config-$env:COMPUTERNAME.ps1"The config file includes:
- Hybrid ServerName auto-detection (uses environment variable or computer name)
- Automatic credential loading from encrypted credentials file
# ServerName auto-detection (default, recommended)
# Strategy: Check in order (first match wins):
# 1. $env:MEDOC_SERVER_NAME environment variable (if set by admin/automation)
# 2. $env:COMPUTERNAME - Windows hostname (fallback)
# 3. Explicit override (uncomment if you need custom name):
# $serverName = "MY_SERVER_NAME"
# Credentials are automatically loaded from encrypted CMS file:
# $env:ProgramData\MedocUpdateCheck\credentials\telegram.cmsMinimal config needed:
$config = @{
ServerName = $env:COMPUTERNAME # Auto-detected
MedocLogsPath = "D:\MedocSRV\LOG" # Directory containing both Planner.log and update_*.log
BotToken = $telegramCreds.BotToken # Loaded from encrypted file
ChatId = $telegramCreds.ChatId # Loaded from encrypted file
# Optional: checkpoint file location
# If not specified, uses $env:ProgramData\MedocUpdateCheck\checkpoints\
# LastRunFile = "$env:ProgramData\MedocUpdateCheck\checkpoints\last_run_server01.txt"
}For each server you want to monitor:
-
Copy template with server hostname:
# Copy using your server's hostname automatically cp configs/Config.template.ps1 "configs/Config-$env:COMPUTERNAME.ps1"
-
Edit with your server settings:
# Edit: MedocLogsPath (path to M.E.Doc logs directory), any server-specific options -
Create Task Scheduler task:
.\utils\Setup-ScheduledTask.ps1 -ConfigPath ".\configs\Config-$env:COMPUTERNAME.ps1"
Repeat for each server. Example:
# Server 1 - On MAINOFFICE server:
cp configs/Config.template.ps1 "configs/Config-$env:COMPUTERNAME.ps1"
# ... edit the config file ...
.\utils\Setup-ScheduledTask.ps1 -ConfigPath ".\configs\Config-$env:COMPUTERNAME.ps1"
# Server 2 - On WAREHOUSE server:
cp configs/Config.template.ps1 "configs/Config-$env:COMPUTERNAME.ps1"
# ... edit the config file ...
.\utils\Setup-ScheduledTask.ps1 -ConfigPath ".\configs\Config-$env:COMPUTERNAME.ps1"Each server needs:
- Its own config file (copy from template, customize)
- A separate Task Scheduler task that calls the specific config
- (Checkpoint files are auto-created in:
$env:ProgramData\MedocUpdateCheck\checkpoints\)
For detailed Task Scheduler setup, see DEPLOYMENT.md - Step 5: Create Scheduled Task.
Each server config is created by copying configs/Config.template.ps1 and customizing it for your server.
| Setting | Description | Example |
|---|---|---|
ServerName |
Display name in Telegram messages | "YOUR_SERVER_NAME" |
MedocLogsPath |
Path to M.E.Doc logs directory | "D:\MedocSRV\LOG" (contains both Planner.log and update_*.log) |
BotToken |
Telegram bot API token from BotFather | "NUMERIC_ID:ALPHANUMERIC_TOKEN" (keep private!) |
ChatId |
Telegram chat or channel ID | "YOUR_CHAT_ID_HERE" (positive or negative number) |
| Setting | Default | Description |
|---|---|---|
LastRunFile |
Auto-generated | Checkpoint file path for tracking processed updates (prevents duplicate notifications). If not provided, auto-generated in $env:ProgramData\MedocUpdateCheck\checkpoints\last_run_SANITIZED_SERVERNAME.txt |
EncodingCodePage |
1251 | Log file encoding (1251=Windows-1251, 65001=UTF-8) |
EventLogSource |
"M.E.Doc Update Check" | Windows Event Log source name |
When LastRunFile is not specified, the script automatically generates the checkpoint filename by sanitizing the ServerName:
-
Sanitization Rule: Non-alphanumeric characters (except hyphens) are replaced with underscores
- Example:
MEDOC-SRV01→last_run_MEDOC-SRV01.txt(hyphen preserved) - Example:
MEDOC@SRV#01→last_run_MEDOC_SRV_01.txt(@ and # replaced) - Example:
СервМедок(Cyrillic) →last_run________________.txt(each character replaced)
- Example:
-
Directory:
$env:ProgramData\MedocUpdateCheck\checkpoints\ -
Auto-created: Directory and file are automatically created on first run
-
Permissions: Restricted to SYSTEM user and Administrators
This ensures ServerName can contain special characters without causing file system errors.
For comprehensive instructions on obtaining and securely storing Telegram credentials, see SECURITY.md - Credentials You Need to Provide.
- Open Telegram and find @BotFather
- Send
/newbot - Follow instructions to create bot
- Copy the Bot Token (format:
NUMERIC_ID:ALPHANUMERIC_TOKEN- KEEP THIS PRIVATE!)
- Send message to your bot
- Visit:
https://api.telegram.org/bot{YOUR_BOT_TOKEN}/getUpdates - Look for
"chat":{"id":YOUR_CHAT_ID}in the response
- Add bot to channel/group as administrator
- Send message to channel
- Visit:
https://api.telegram.org/bot{YOUR_BOT_TOKEN}/getUpdates - Channel ID format: negative number (e.g.,
-1002825825746) - Copy the chat ID from response and use in Config.ps1
Next: Use Setup-Credentials.ps1 to securely encrypt these values (see SECURITY.md)
# Run with your config using server's hostname
.\Run.ps1 -ConfigPath ".\configs\Config-$env:COMPUTERNAME.ps1"
# Or with verbose output
.\Run.ps1 -ConfigPath ".\configs\Config-$env:COMPUTERNAME.ps1" -VerboseAll actions are logged to Windows Event Log. View events in Event Viewer:
Event Viewer → Windows Logs → Application → Filter by Source: "M.E.Doc Update Check"
Event ID Reference:
For complete Event ID reference with troubleshooting steps, see SECURITY.md - Event ID Reference.
Event ID Categories:
- 1000-1099 - Normal flow (success, no update)
- 1100-1199 - Configuration errors (missing keys, invalid values)
- 1200-1299 - Environment/filesystem errors (missing logs, directory issues)
- 1300-1399 - Update validation failures (missing flags)
- 1400-1499 - Notification errors (Telegram API, send failures)
- 1500-1599 - Checkpoint/state persistence errors
- 1900+ - Unexpected/general errors
For comprehensive Event Log query examples (view recent, errors, specific dates, etc.), see TESTING.md - Event Log Query Examples.
When monitoring multiple M.E.Doc servers from one location:
# Copy folder once to shared location or local folder
robocopy "C:\Source\MedocUpdateCheck" "\\YOUR_SERVER_NAME\C$\Script\MedocUpdateCheck" /EThen create multiple Task Scheduler tasks, each pointing to a different config:
# Task 1: Main Office at 5:10 AM
Register-ScheduledTask -TaskName "M.E.Doc Check - MainOffice" `
-Action (New-ScheduledTaskAction -Execute 'powershell.exe' `
-Argument '-NoProfile -ExecutionPolicy Bypass -File "C:\Script\MedocUpdateCheck\Run.ps1" -ConfigPath ".\configs\Config-MainOffice.ps1"' `
-WorkingDirectory 'C:\Script\MedocUpdateCheck') `
-Trigger (New-ScheduledTaskTrigger -Daily -At 5:10AM) `
-RunLevel Highest
# Task 2: Warehouse at 5:15 AM
Register-ScheduledTask -TaskName "M.E.Doc Check - Warehouse" `
-Action (New-ScheduledTaskAction -Execute 'powershell.exe' `
-Argument '-NoProfile -ExecutionPolicy Bypass -File "C:\Script\MedocUpdateCheck\Run.ps1" -ConfigPath ".\configs\Config-Warehouse.ps1"' `
-WorkingDirectory 'C:\Script\MedocUpdateCheck') `
-Trigger (New-ScheduledTaskTrigger -Daily -At 5:15AM) `
-RunLevel HighestCopy the entire folder to each server and use the default config:
# Copy to MainOffice server
robocopy "C:\Source\MedocUpdateCheck" "\\MAINOFFICE\C$\Script\MedocUpdateCheck" /E
# Copy to Warehouse server
robocopy "C:\Source\MedocUpdateCheck" "\\WAREHOUSE\C$\Script\MedocUpdateCheck" /E
# On each server, copy Config.template.ps1 to Config-$env:COMPUTERNAME.ps1 (automatic hostname) and customize
# Then create one Task Scheduler task per server using the customized configWhen ready to manage code from one location:
- Place
lib/MedocUpdateCheck.psm1on SMB share - Each server keeps only
Run.ps1andconfigs/ - Module references network path
- Single code update affects all servers
- ✓ Check
last_run.txthas write permissions - ✓ Check log file path is accessible from that server
- ✓ Check bot token and chat ID are correct
- ✓ Run task as SYSTEM or elevated account
-
Check bot token in Config.ps1 is correct and not expired
-
Check chat ID is correct (test manually with curl or Postman)
-
Verify bot has permission to send messages to the chat/channel
-
Check Windows Event Log for errors (Event ID 1002, 1003)
-
Test API manually: Replace
{TOKEN}and{CHAT_ID}with actual values:curl https://api.telegram.org/bot{YOUR_BOT_TOKEN}/sendMessage -d chat_id={YOUR_CHAT_ID} -d text="test"
- Check log file path is correct
- Check log file encoding matches (1251 vs 65001)
- Manually review
D:\MedocSRV\LOG\Planner.log
- Ensure
libfolder exists withMedocUpdateCheck.psm1 - Check file is not corrupted
- Try:
Test-ModuleManifest ".\lib\MedocUpdateCheck.psm1"
# Navigate to script folder
cd "C:\Script\MedocUpdateCheck"
# Test configuration loads correctly
. ".\Config.ps1"
$config
# Test module loads
Import-Module ".\lib\MedocUpdateCheck.psm1" -Force
Get-Module MedocUpdateCheck
# Test update check function (dual-log validation)
Test-UpdateOperationSuccess -MedocLogsPath "D:\MedocSRV\LOG"
# Run entire check with server's hostname
.\Run.ps1 -ConfigPath ".\configs\Config-$env:COMPUTERNAME.ps1"
# Check Event Log (PowerShell 7+)
Get-WinEvent -FilterHashtable @{
LogName = 'Application'
ProviderName = 'M.E.Doc Update Check'
} -MaxEvents 5M.E.Doc uses two log files with different timestamp formats:
dd.MM.yyyy H:mm:ss Event Text
25.09.2025 5:00:00 Нові оновлення відсутні
25.09.2025 5:00:00 Завантаження оновлення ezvit.11.02.183-11.02.184.upd
25.09.2025 5:07:12 Операція виконана успішно
Timestamp format: 4-digit year (DD.MM.YYYY)
dd.MM.yy H:mm:ss.mmm XXXXXXXX LEVEL Message
25.09.25 11:32:14.150 00000001 INFO IsProcessCheckPassed DI: True, AI: True
25.09.25 11:45:15.200 00000001 INFO Службу ZvitGrp запущено з підвищенням прав
25.09.25 11:47:15.300 00000001 INFO Версія програми - 184
Timestamp format: 2-digit year (DD.MM.YY) with milliseconds Log fields: 2-digit year, milliseconds, 8-digit ID, log level, message
Note: The different timestamp formats are intentional - Planner.log uses 4-digit years while update_*.log uses 2-digit years. Both represent the same calendar dates when parsed (e.g., 25.09.2025 and 25.09.25 both mean 25 September 2025).
- Default: Windows-1251 (Cyrillic)
- Override in Config.ps1 if different
Telegram messages use English with structured data for clarity and international compatibility. Emoji provide quick visual status indication.
For detailed message format examples, see TESTING.md - Message Format Reference.
✅ UPDATE OK | MY-MEDOC-SERVER
Version: 11.02.183 → 11.02.184
Started: 28.10.2025 05:15:23
Completed: 28.10.2025 05:17:20
Duration: 1 min 57 sec
Checked: 28.10.2025 12:33:45
When any of the three success flags are missing, Telegram notification shows:
❌ UPDATE FAILED | MY-MEDOC-SERVER
Version: 11.02.183 → 11.02.184
Started: 28.10.2025 11:32:14
Failed at: 28.10.2025 11:47:15
Flag1 (Infrastructure): ✗
Flag2 (Service Restart): ✓
Flag3 (Version Confirmed): ✓
Reason: Missing success flags
Checked: 28.10.2025 11:50:06
The message lists the status of each validation flag (✓ = passed, ✗ = failed) to help identify the root cause. Windows Event Log receives additional details through separate flag fields (Flag1, Flag2, Flag3) for automated alerting.
ℹ️ NO UPDATE | MY-MEDOC-SERVER
Checked: 28.10.2025 12:33:45
The M.E.Doc Update Check module exports 6 public functions for use in custom scripts:
Test-UpdateOperationSuccess - Analyzes M.E.Doc logs to determine if an update succeeded
Returns status object with fields:
Status: "Success", "NoUpdate", or "Error"ErrorId: MedocEventId enum value (1000-1900+) for categorizing the result- For Success: Also includes Version info, Timestamps, and Flag details
- For NoUpdate: Minimal (just Status + ErrorId)
- For Error: Status + ErrorId + error Message
Supports checkpoint filtering (since parameter) to avoid processing same updates twice.
Invoke-MedocUpdateCheck - Main orchestration function
- Calls Test-UpdateOperationSuccess to get update status
- Formats messages for Telegram and Event Log based on status
- Writes to Windows Event Log with appropriate EventId (using MedocEventId enum)
- Sends Telegram notification with formatted message
- Returns $true on success, $false on error
Format-UpdateTelegramMessage - Creates Telegram notification text based on status
Returns based on status:
- Success:
✅ UPDATE OK | ServerName\nVersion: X → Y\nStarted: time\nCompleted: time\nDuration: X min Y sec\nChecked: time - NoUpdate:
ℹ️ NO UPDATE | ServerName\nChecked: time(informational, not an error) - Error:
❌ UPDATE FAILED | ServerName\nVersion: X → Y\nValidation Failures: [missing flags]\nReason: [error]\nChecked: time
Format-UpdateEventLogMessage - Creates Event Log entry text based on status
Returns key=value format based on status:
- Success:
Server=X | Status=UPDATE_OK | FromVersion=X | ToVersion=Y | UpdateStarted=time | UpdateCompleted=time | Duration=X | CheckTime=time - NoUpdate:
Server=X | Status=NO_UPDATE | CheckTime=time - Error:
Server=X | Status=UPDATE_FAILED | FromVersion=X | ToVersion=Y | Flag1=value | Flag2=value | Flag3=value | Reason=[error] | CheckTime=time
Get-VersionInfo - Extracts version information from M.E.Doc logs
- Parses version strings like "11.02.185-11.02.186.upd"
- Returns object with FromVersion and ToVersion properties
- Used internally by Test-UpdateOperationSuccess
Write-EventLogEntry - Writes messages to Windows Event Log with structured EventId
- Accepts Message (required) and EventId (MedocEventId enum value preferred, defaults to 1000)
- Creates event source if missing (requires admin)
- Logs with appropriate level (Information/Warning/Error)
- Respects platform limitations (non-Windows systems safely skip Event Log)
- EventLog entries use centralized MedocEventId enum for consistent event filtering and monitoring
All Event Log entries use standardized EventIDs for monitoring and troubleshooting. For complete details, see SECURITY.md - Event ID Reference:
Quick Reference:
| ID | Status | Meaning |
|---|---|---|
| 1000 | ✅ Info | Update completed successfully |
| 1001 | ℹ️ Info | No update detected (normal) |
| 1100-1101 | ❌ Error | Configuration errors |
| 1200-1204 | ❌ Error | Filesystem/environment errors |
| 1300-1303 | ❌ Error | Update validation failures |
| 1400-1401 | ❌ Error | Telegram/notification errors |
| 1500 | ❌ Error | Checkpoint write failed |
| 1900 | ❌ Error | Unexpected/general error |
For detailed explanations and troubleshooting steps for each EventID, see SECURITY.md - Event ID Reference.
- ✅ Analyzes M.E.Doc log files
- ✅ Determines update success/failure
- ✅ Sends Telegram notifications
- ✅ Checkpoint-based filtering (avoids duplicates)
- ✅ Windows Event Log integration
- ✅ Graceful error handling
- ✅ Configurable encoding (Windows-1251, UTF-8, etc.)
- ✅ Configurable update timeout
- ✅ Single-server deployment model
- ✅ Ready for SMB-based shared module (future iteration)
For different audiences, see:
- DEPLOYMENT.md - Step-by-step deployment checklist for production (start here!)
- SECURITY.md - Security procedures, credential management, and best practices
- TESTING.md - How to run tests and validate the system
- CONTRIBUTING.md - How to contribute to this project (code standards, testing, documentation, git practices - for developers and community members)
For detailed release notes and version history, check GitHub Releases.
View available versions:
# See all released versions
git tag -l
# See current version
git describe --tagsCommon terms used throughout this project and documentation:
-
M.E.Doc - Ukrainian enterprise accounting and tax software (target application being monitored)
-
Server / Target Server - Windows server running M.E.Doc software that we monitor for updates
-
Update - M.E.Doc software version change (e.g., from version 11.02.183 to 11.02.184)
-
Event Log / Application Event Log - Windows Application Event Log where script writes status messages (viewable in Event Viewer)
-
Telegram - Messaging platform used to send notifications about updates (separate from Event Log)
-
Telegram Message - Human-readable notification sent via Telegram with emoji and structured text (e.g., "✅ UPDATE OK")
-
Event Log Message - Structured key=value format message written to Windows Event Log (machine-readable, for compliance)
-
Checkpoint / Checkpoint File - Stores timestamp of last successful run to prevent duplicate Telegram notifications
-
Config File - Server-specific configuration file (Config-ComputerName.ps1) containing server name, Telegram credentials, log file paths
-
CMS / Cryptographic Message Syntax - Certificate-based encryption method used to encrypt Telegram credentials at machine level (supported by Windows Task Scheduler SYSTEM user)
-
Self-signed Certificate - X.509 certificate generated locally for encrypting credentials; stored in LocalMachine certificate store with 5-year validity and NonExportable private key
-
Task Scheduler - Windows service that runs this script on a schedule (daily, weekly, etc.)
-
SYSTEM User - Special Windows account used by Task Scheduler for running scheduled tasks with elevated permissions
-
Windows-1251 Encoding - Cyrillic character encoding used by M.E.Doc logs (not UTF-8)
-
PowerShell 7+ - Modern PowerShell version (required, not PowerShell 5.1)
-
Get-WinEvent - PowerShell 7+ cmdlet for reading Event Log (replacement for deprecated Get-EventLog)
- Bohdan Potishuk - Lead developer
- Dmytro Kravchuk - Co-author
This project is licensed under the Apache License, Version 2.0. See LICENSE file for details.
This project includes a NOTICE file with additional information about dependencies and credits.
Run.ps1 returns exit codes for Task Scheduler alerting:
- 0 — Update check completed normally (Success or NoUpdate)
- 1 — Operational or configuration error
- 2 — Update detected but validation failed
Operators should configure alerts on exit codes 1 and 2. For detailed documentation, see DEPLOYMENT.md - Exit Codes for Scheduling/Monitoring.