Files
PowershellAutomation/README.md
T

262 lines
12 KiB
Markdown

# PowerShell Automation Center
A unified framework for managing Windows automation tasks with a modular, extensible feature system. All configuration and execution flows through a single entry point: `configure.ps1`.
## Quick Start
Clone or extract the repo to any location, then:
```powershell
# Navigate to the repo folder (any path works)
cd <your-repo-path>
# Run the main menu
.\configure.ps1
```
All paths are relative to `configure.ps1`, so the repo is portable.
## Architecture
### Entry Point: `configure.ps1`
The only file you interact with directly. Provides a menu-driven interface for:
- **Check**: View registration status of the background runner task
- **Register**: Create a scheduled task that runs automation features at logon and every 2 minutes
- **Remove**: Unregister the scheduled task
- **Configure**: Adjust per-feature settings (toggles, custom values)
### Core Structure
```
ArnePowershellAutomation/
├── configure.ps1 # Single user entry point
└── internal/
├── runner.ps1 # Scheduled task entry point (runs every 2 min + at logon)
├── lib/ # Shared utilities
│ ├── Logging.ps1 # Centralized logging with rotation
│ ├── Config.ps1 # Configuration and state I/O
│ ├── Elevation.ps1 # UAC elevation helper
│ ├── NetworkUtils.ps1 # DNS suffix detection
│ ├── ToastHelper.ps1 # Windows 11 toast notifications
│ ├── PromptHelper.ps1 # Multi-choice dialog boxes (up to 4 buttons)
│ └── SandwichAutoOrder.ps1 # Browser keyboard automation for sandwich auto-order
├── features/ # Automation feature modules
│ ├── DynamicLock.ps1 # Toggle Dynamic Lock on network presence
│ ├── DefaultBrowser.ps1 # Monitor default browser setting
│ ├── SandwichReminder.ps1 # Time-based reminder with snooze options
│ └── SandwichReminder-AutoOrder.ps1 # Personal browser automation for sandwich ordering
└── data/
├── config.json # Feature toggles & settings (auto-seeded)
├── state/
│ └── state.json # Per-feature runtime state
└── logs/
├── automation-*.log # Daily rotating logs (7-day retention)
├── elevated-process.log # Elevation diagnostics
├── last-register-result.json # Last registration result
└── last-remove-result.json # Last removal result
```
### Execution Flow
**At Logon / Every 2 Minutes:**
1. Scheduled task launches `internal/runner.ps1`
2. Runner loads all lib utilities and feature modules
3. For each enabled feature:
- Reads configuration from `internal/data/config.json`
- Reads previous state from `internal/data/state/state.json`
- Calls `Invoke-Feature` function
- Captures errors; one feature failure doesn't break others
- Saves updated state back to file
4. Logs all activity to `internal/data/logs/automation-YYYY-MM-DD.log`
**For Configuration Changes:**
1. User selects menu option 4 (Configure)
2. Navigate feature menu (numbers to toggle, C<number> for sub-menu)
3. For each setting, enter value or accept default
4. Config is saved to `internal/data/config.json` immediately
5. Changes take effect on next scheduled task run
## Feature Contract
Each feature in `internal/features/` must export:
### `$FeatureMeta` Variable
```powershell
$FeatureMeta = @{
Name = "My Feature"
Description = "What this feature does"
Settings = @(
@{ Key = "settingKey1"; Label = "Display Label"; Type = "string"; Default = "value"; Description = "Help text" }
@{ Key = "settingKey2"; Label = "Port"; Type = "int"; Default = 8080; Description = "Port number" }
@{ Key = "settingKey3"; Label = "Enabled"; Type = "bool"; Default = $true; Description = "Enable this?" }
)
}
```
### `Invoke-Feature` Function
```powershell
function Invoke-Feature {
param(
[Parameter(Mandatory)][hashtable]$Config, # Feature settings from config.json
[Parameter(Mandatory)][hashtable]$State # Feature state from state.json
)
# Perform work here
# Use Write-Log -Feature "MyFeature" for logging
# Return updated $State hashtable
return $State
}
```
### Built-in Utilities Available to Features
- **Logging.ps1**: `Write-Log -Level (Info|Warn|Error) -Message -Feature`
- **Config.ps1**: `Get-Config`, `Save-Config`, `Get-State`, `Save-State`
- **NetworkUtils.ps1**: `Test-DnsSuffixConnected -Suffix`
- **ToastHelper.ps1**: `Show-ToastNotification -Title -Body -Buttons`
- **Elevation.ps1**: `Test-Administrator`, `Request-Elevation`
## Included Features
### DynamicLock
Enables/disables Windows Dynamic Lock based on network connectivity.
- **Settings**: Network domain suffix (e.g., "example.com"), revert timeout in minutes
- **Logic**: When connected to configured network, enables Dynamic Lock (`EnableGoodbye`=1); when disconnected, reverts after timeout
- **State Tracked**: Current connection status, last connected timestamp
### DefaultBrowser
Monitors if your default browser matches expected ProgId (app identifier).
- **Settings**: Target ProgId (e.g., "FirefoxURL", "OperaGXStable")
- **Logic**: On each run, reads current ProgId; if mismatch, shows a Yes/No dialog; "Yes" opens Windows Settings → Default apps for manual selection; max once per day
- **State Tracked**: Last notification date to avoid spam
- **Note**: Windows 11 protects the default browser registry key with a hash; the browser cannot be changed programmatically, hence the guided Settings approach
### SandwichReminder
Shows a reminder dialog at a specific time on a specific network with snooze options.
- **Settings**: Reminder time (HH:MM), network domain suffix, reminder URL, notification window in minutes
- **Logic**: If on configured network AND current time is within window of reminder time AND not shown today, display a 4-choice dialog: Order now / Snooze 15 min / Snooze 1 hour / No
- **State Tracked**: Last shown date, snooze-until timestamp
- **Auto-order delegation**: If `SandwichReminder-AutoOrder` feature is enabled, selecting "Order now" triggers the automated browser flow instead of just opening the URL
### SandwichReminder-AutoOrder
Personal browser automation feature that drives the sandwich ordering website via keyboard navigation.
- **Settings**: Base URL, item ID, browser window title hint, tab counts for each navigation step, delays, calibration mode
- **Logic**: Opens the item modal URL, brings the browser window to the foreground (with retry), then sends keyboard inputs to: toggle option checkboxes → click add-to-cart → refresh page → tab to mini-cart → open cart → tab to confirm order button → open delivery popup
- **Key settings**:
- `tabsToOption1` / `tabsBetweenOptions` / `tabsToAddButton`: navigation within item modal
- `refreshBeforeCart`: send F5 after add-to-cart to reset focus to a known page position
- `tabsToCartButton` / `tabsToConfirmButton`: navigation after refresh
- `calibrationOnly` + `calibrationTabs`: safe mode to manually count tab stops without clicking
- **Note**: Uses WScript.Shell SendKeys (best-effort); relies on stable tab order in the target website
## Usage Guide
### Main Menu
```
1) Check Registration Status
→ Displays current task registration, last run time, next run time
2) Register Runner
→ Creates scheduled task (AtLogon trigger + 2-min repetition)
→ If not admin, prompts for UAC elevation
→ Updates internal/data/logs/last-register-result.json
3) Remove Runner
→ Unregisters the scheduled task
→ If not admin, prompts for UAC elevation
→ Updates internal/data/logs/last-remove-result.json
4) Configure Features
→ Submenu with feature toggles and per-feature settings
→ Enter number to toggle (on/off)
→ Enter C<number> to configure settings
→ Q to return to main menu
→ Saves config.json immediately
Q) Quit
→ Exits configure.ps1
```
### Configuring a Feature
When you select a feature for configuration, you'll be prompted for each setting:
- **Type: string** → Enter any text
- **Type: int** → Enter a number
- **Type: bool** → Enter Y/N (yes/no)
- **Type: time** → Enter HH:MM format
- Press Enter to accept the displayed default
## Known Limitations
- **Default Browser Registry Protection**: On Windows 11, Microsoft protects the default browser registry key with a hash. The DefaultBrowser feature reads the ProgId but cannot *set* the default browser programmatically. The toast provides a link to Settings for manual override.
- **Windows 11 Only for Toasts**: Toast notifications require WinRT (Windows 10+), but full Windows 11 support is assumed. Win10 may work but is untested.
- **Scheduled Task Security**: The runner task executes as the current user with Limited RunLevel (no elevation). Features cannot perform system-wide administrative tasks; they're limited to user-level operations.
- **DNS Suffix Matching**: Network detection relies on `Get-DnsClient` adapter DNS suffix. Make sure your network adapter is configured with the correct suffix for accurate detection.
- **Manual Execution & Repetition Timer**: Executing the runner manually via menu option 5 ("Execute runner now") runs the task immediately but does **not** start the 2-minute repetition timer. The repetition timer only activates on logon/restart. For continuous testing, you may need to restart or wait for next logon.
## Extending with New Features
To add a new automation feature:
1. Create `internal/features/MyFeature.ps1`:
```powershell
#Requires -Version 5.1
param() # Empty; loaded via dot-source
$FeatureMeta = @{
Name = "My Feature"
Description = "Does something cool"
Settings = @(
@{ Key = "enabled"; Label = "Enable"; Type = "bool"; Default = $true; Description = "Turn on/off" }
)
}
function Invoke-Feature {
param([hashtable]$Config, [hashtable]$State)
if (-not $Config.enabled) { return $State }
try {
Write-Log -Level Info -Message "Running My Feature" -Feature "MyFeature"
# Do work here
}
catch {
Write-Log -Level Error -Message "Error: $_" -Feature "MyFeature"
}
return $State
}
```
2. Drop it in `internal/features/` — it will auto-discover on next configure.ps1 run
3. Run `.\configure.ps1` → menu option 4 → Your feature appears with toggles and config sub-menu
## Logging
All activity is logged to `internal/data/logs/automation-YYYY-MM-DD.log` (UTC date).
- **Retention**: 7 days (older logs auto-deleted)
- **Format**: `[YYYY-MM-DD HH:mm:ss] [LEVEL] [Feature] Message`
- **Levels**: Info, Warn, Error
Elevation diagnostics go to `internal/data/logs/elevated-process.log` for troubleshooting registration issues.
## Troubleshooting
**Task not running?**
- Check Task Scheduler (root library) for "PSAutomation-Runner" task
- Verify "Run as current user" and Limited RunLevel
- Check `automation-<date>.log` for errors
**Features not executing?**
- Verify feature is enabled in menu option 4
- Check `internal/data/config.json` for `"enabled": true` on that feature
- Look for errors in `automation-<date>.log` with feature name
**Elevation prompts failing?**
- Check `elevated-process.log` for bootstrap diagnostics
- Ensure PowerShell isn't blocked by execution policy: `Get-ExecutionPolicy`
- If needed, set: `Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser`
## License
None. Use freely.