v1.5.0: API logging to ShopDB
- Logs events (started, cleaned, ok, failed, error, stopped) to ShopDB API - Tracks installations and stats per hostname in ednc_installations table - Event history stored in ednc_logs table - Added CLAUDE.md with project instructions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
134
CLAUDE.md
Normal file
134
CLAUDE.md
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
# eDNC Special Character Fix - Claude Code Instructions
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
PowerShell utility that monitors DNC folders and removes invalid special characters (0xFF) from .pun files in real-time. Deployed to CNC workstations via network share.
|
||||||
|
|
||||||
|
## Technology Stack
|
||||||
|
|
||||||
|
- **Language:** PowerShell 5.1+
|
||||||
|
- **Deployment:** Network share (S:\DT\cameron\eDNC-Fix\) → Local (C:\eDNC-Fix\)
|
||||||
|
- **Logging:** ShopDB API (http://geitshopdb/api.asp)
|
||||||
|
- **Version Control:** Gitea (localhost:3000/cproudlock/edncfix)
|
||||||
|
|
||||||
|
## IMPORTANT: After Making Changes
|
||||||
|
|
||||||
|
**Always do the following after any code changes:**
|
||||||
|
|
||||||
|
1. **Update version numbers** in ALL of these files:
|
||||||
|
- `eDNC-SpecialCharFix.ps1` - `$ScriptVersion` variable (line ~81)
|
||||||
|
- `eDNC-SpecialCharFix.ps1` - `.NOTES` section Version field
|
||||||
|
- `version.ini` - `Version=x.x.x`
|
||||||
|
- `README.md` - Version History table
|
||||||
|
|
||||||
|
2. **Commit and push to Gitea:**
|
||||||
|
```bash
|
||||||
|
cd /home/camp/projects/powershell/edncfix
|
||||||
|
git add -A
|
||||||
|
git commit -m "vX.X.X: Description of changes"
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Version format:** Use semantic versioning (MAJOR.MINOR.PATCH)
|
||||||
|
- MAJOR: Breaking changes
|
||||||
|
- MINOR: New features
|
||||||
|
- PATCH: Bug fixes
|
||||||
|
|
||||||
|
## File Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
/home/camp/projects/powershell/edncfix/
|
||||||
|
├── eDNC-SpecialCharFix.ps1 # Main script
|
||||||
|
├── Run-eDNCFix.bat # Manual launcher (auto-elevates)
|
||||||
|
├── Install-ScheduledTask.ps1 # Creates Windows scheduled task
|
||||||
|
├── Deploy.bat # Copies from S: to C:\eDNC-Fix\
|
||||||
|
├── version.ini # Version file for auto-updates
|
||||||
|
├── README.md # Documentation
|
||||||
|
└── CLAUDE.md # This file
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration (Hardcoded)
|
||||||
|
|
||||||
|
| Setting | Value | Location |
|
||||||
|
|---------|-------|----------|
|
||||||
|
| Watch Folder | `C:\Dnc_Files\Q` | eDNC-SpecialCharFix.ps1 |
|
||||||
|
| File Filter | `*.pun` | eDNC-SpecialCharFix.ps1 |
|
||||||
|
| Update Source | `S:\DT\cameron\eDNC-Fix` | eDNC-SpecialCharFix.ps1 |
|
||||||
|
| API URL | `http://geitshopdb/api.asp` | eDNC-SpecialCharFix.ps1 |
|
||||||
|
| Update Interval | 300 seconds (5 min) | eDNC-SpecialCharFix.ps1 |
|
||||||
|
|
||||||
|
## ShopDB API Integration
|
||||||
|
|
||||||
|
The script logs events to ShopDB via the API. Reference the ShopDB API documentation at:
|
||||||
|
- **ShopDB Project:** `/home/camp/projects/windows/shopdb/`
|
||||||
|
- **API File:** `/home/camp/projects/windows/shopdb/api.asp`
|
||||||
|
- **Standards Doc:** `/home/camp/projects/windows/shopdb/docs/STANDARDS.md`
|
||||||
|
|
||||||
|
### API Endpoint: logDNCEvent
|
||||||
|
|
||||||
|
**Method:** POST
|
||||||
|
**URL:** `http://geitshopdb/api.asp`
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
| Parameter | Type | Required | Description |
|
||||||
|
|-----------|------|----------|-------------|
|
||||||
|
| action | string | Yes | Must be "logDNCEvent" |
|
||||||
|
| hostname | string | Yes | PC hostname |
|
||||||
|
| eventType | string | Yes | Event type: started, cleaned, ok, failed, error, stopped |
|
||||||
|
| filename | string | No | File being processed |
|
||||||
|
| bytesRemoved | int | No | Number of bytes removed |
|
||||||
|
| version | string | No | Script version |
|
||||||
|
| message | string | No | Additional details |
|
||||||
|
| watchFolder | string | No | Folder being watched |
|
||||||
|
| fileFilter | string | No | File filter pattern |
|
||||||
|
|
||||||
|
**Database Tables:**
|
||||||
|
- `ednc_logs` - Individual event log entries
|
||||||
|
- `ednc_installations` - Per-hostname installation tracking
|
||||||
|
|
||||||
|
### API Endpoint: getDNCStats
|
||||||
|
|
||||||
|
**Method:** GET
|
||||||
|
**URL:** `http://geitshopdb/api.asp?action=getDNCStats`
|
||||||
|
|
||||||
|
Returns JSON with all eDNC installations and their stats.
|
||||||
|
|
||||||
|
## Deployment Workflow
|
||||||
|
|
||||||
|
1. **Development:** Edit files in `/home/camp/projects/powershell/edncfix/`
|
||||||
|
2. **Update versions:** Bump all version numbers
|
||||||
|
3. **Commit:** Push to Gitea
|
||||||
|
4. **Stage:** Copy files to `S:\DT\cameron\eDNC-Fix\`
|
||||||
|
5. **Deploy:** On target PC, run `Deploy.bat` from S: drive
|
||||||
|
6. **Install:** Run `Install-ScheduledTask.ps1` as Admin
|
||||||
|
|
||||||
|
## Auto-Update Mechanism
|
||||||
|
|
||||||
|
Running instances check `S:\DT\cameron\eDNC-Fix\version.ini` every 5 minutes.
|
||||||
|
If a newer version is found, they automatically:
|
||||||
|
1. Copy new files from S: to C:\eDNC-Fix\
|
||||||
|
2. Restart themselves
|
||||||
|
|
||||||
|
**To deploy an update to all PCs:**
|
||||||
|
1. Update version.ini with new version number
|
||||||
|
2. Copy updated files to S:\DT\cameron\eDNC-Fix\
|
||||||
|
3. Wait up to 5 minutes for auto-update
|
||||||
|
|
||||||
|
## Quick Reference
|
||||||
|
|
||||||
|
### Test API endpoint:
|
||||||
|
```bash
|
||||||
|
curl -X POST http://192.168.122.151:8080/api.asp \
|
||||||
|
-d "action=logDNCEvent&hostname=TESTPC&eventType=started&version=1.5.0"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check installations:
|
||||||
|
```bash
|
||||||
|
curl "http://192.168.122.151:8080/api.asp?action=getDNCStats"
|
||||||
|
```
|
||||||
|
|
||||||
|
### View logs in database:
|
||||||
|
```sql
|
||||||
|
SELECT * FROM ednc_logs ORDER BY created DESC LIMIT 20;
|
||||||
|
SELECT * FROM ednc_installations;
|
||||||
|
```
|
||||||
@@ -130,6 +130,7 @@ The script uses exponential backoff (500ms → 1s → 2s → 4s → up to 16s) f
|
|||||||
|
|
||||||
| Version | Date | Changes |
|
| Version | Date | Changes |
|
||||||
|---------|------|---------|
|
|---------|------|---------|
|
||||||
|
| 1.5.0 | 2025-12-12 | API logging to ShopDB (started, cleaned, failed, stopped events) |
|
||||||
| 1.4.0 | 2025-12-12 | Auto-update from S:\DT\cameron\eDNC-Fix\version.ini every 5 min |
|
| 1.4.0 | 2025-12-12 | Auto-update from S:\DT\cameron\eDNC-Fix\version.ini every 5 min |
|
||||||
| 1.3.1 | 2025-12-12 | Added Install-ScheduledTask.ps1 for running as SYSTEM service |
|
| 1.3.1 | 2025-12-12 | Added Install-ScheduledTask.ps1 for running as SYSTEM service |
|
||||||
| 1.3.0 | 2025-12-12 | Fixed header UI, live status/stats, auto-elevate to Administrator |
|
| 1.3.0 | 2025-12-12 | Fixed header UI, live status/stats, auto-elevate to Administrator |
|
||||||
|
|||||||
@@ -36,9 +36,13 @@
|
|||||||
|
|
||||||
.NOTES
|
.NOTES
|
||||||
Author: GE Aerospace - Rutland
|
Author: GE Aerospace - Rutland
|
||||||
Version: 1.4.0
|
Version: 1.5.0
|
||||||
Date: 2025-12-12
|
Date: 2025-12-12
|
||||||
|
|
||||||
|
v1.5.0 - API logging:
|
||||||
|
- Logs events (started, cleaned, ok, failed, error, stopped) to ShopDB API
|
||||||
|
- Tracks installations and stats per hostname
|
||||||
|
|
||||||
v1.4.0 - Auto-update:
|
v1.4.0 - Auto-update:
|
||||||
- Checks S:\DT\cameron\eDNC-Fix\version.ini every 5 minutes
|
- Checks S:\DT\cameron\eDNC-Fix\version.ini every 5 minutes
|
||||||
- Auto-downloads and restarts if newer version found
|
- Auto-downloads and restarts if newer version found
|
||||||
@@ -78,7 +82,7 @@ param(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Script info
|
# Script info
|
||||||
$ScriptVersion = "1.4.0"
|
$ScriptVersion = "1.5.0"
|
||||||
$ScriptName = "eDNC Special Character Fix"
|
$ScriptName = "eDNC Special Character Fix"
|
||||||
|
|
||||||
# Auto-update settings
|
# Auto-update settings
|
||||||
@@ -87,6 +91,10 @@ $LocalPath = "C:\eDNC-Fix"
|
|||||||
$UpdateCheckInterval = 300 # Check every 5 minutes (in seconds)
|
$UpdateCheckInterval = 300 # Check every 5 minutes (in seconds)
|
||||||
$script:LastUpdateCheck = [DateTime]::MinValue
|
$script:LastUpdateCheck = [DateTime]::MinValue
|
||||||
|
|
||||||
|
# API logging settings
|
||||||
|
$ApiUrl = "http://geitshopdb/api.asp"
|
||||||
|
$script:Hostname = $env:COMPUTERNAME
|
||||||
|
|
||||||
# Header display function
|
# Header display function
|
||||||
function Show-Header {
|
function Show-Header {
|
||||||
param([int]$Cleaned = 0, [int]$Failed = 0, [string]$Status = "Watching...")
|
param([int]$Cleaned = 0, [int]$Failed = 0, [string]$Status = "Watching...")
|
||||||
@@ -205,6 +213,35 @@ function Invoke-Update {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# API logging function
|
||||||
|
function Send-DNCEvent {
|
||||||
|
param(
|
||||||
|
[string]$EventType,
|
||||||
|
[string]$Filename = "",
|
||||||
|
[int]$BytesRemoved = 0,
|
||||||
|
[string]$Message = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
try {
|
||||||
|
$body = @{
|
||||||
|
action = "logDNCEvent"
|
||||||
|
hostname = $script:Hostname
|
||||||
|
filename = $Filename
|
||||||
|
eventType = $EventType
|
||||||
|
bytesRemoved = $BytesRemoved
|
||||||
|
version = $ScriptVersion
|
||||||
|
message = $Message
|
||||||
|
watchFolder = $WatchFolder
|
||||||
|
fileFilter = $FileFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
$null = Invoke-WebRequest -Uri $ApiUrl -Method POST -Body $body -ContentType "application/x-www-form-urlencoded" -UseBasicParsing -TimeoutSec 5
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
# Silently fail - don't disrupt file watching for API issues
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Initialize console
|
# Initialize console
|
||||||
Clear-Host
|
Clear-Host
|
||||||
$script:HeaderHeight = Show-Header -Status "Initializing..."
|
$script:HeaderHeight = Show-Header -Status "Initializing..."
|
||||||
@@ -223,6 +260,9 @@ Show-Header -Status "Watching for files... (Ctrl+C to stop)" | Out-Null
|
|||||||
Write-Host "Removing bytes: $($CharactersToRemove -join ', ') (0x$($CharactersToRemove | ForEach-Object { '{0:X2}' -f $_ } | Join-String -Separator ', 0x'))" -ForegroundColor DarkGray
|
Write-Host "Removing bytes: $($CharactersToRemove -join ', ') (0x$($CharactersToRemove | ForEach-Object { '{0:X2}' -f $_ } | Join-String -Separator ', 0x'))" -ForegroundColor DarkGray
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
|
|
||||||
|
# Log startup to API
|
||||||
|
Send-DNCEvent -EventType "started" -Message "Script started"
|
||||||
|
|
||||||
# Statistics
|
# Statistics
|
||||||
$script:FilesProcessed = 0
|
$script:FilesProcessed = 0
|
||||||
$script:BytesRemoved = 0
|
$script:BytesRemoved = 0
|
||||||
@@ -267,6 +307,25 @@ $action = {
|
|||||||
[Console]::SetCursorPosition(0, $savedPos)
|
[Console]::SetCursorPosition(0, $savedPos)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Helper to log to API
|
||||||
|
$logToApi = {
|
||||||
|
param($eventType, $file, $bytes, $msg)
|
||||||
|
try {
|
||||||
|
$body = @{
|
||||||
|
action = "logDNCEvent"
|
||||||
|
hostname = $Event.MessageData.Hostname
|
||||||
|
filename = $file
|
||||||
|
eventType = $eventType
|
||||||
|
bytesRemoved = $bytes
|
||||||
|
version = $Event.MessageData.Version
|
||||||
|
message = $msg
|
||||||
|
watchFolder = $Event.MessageData.WatchFolder
|
||||||
|
fileFilter = $Event.MessageData.FileFilter
|
||||||
|
}
|
||||||
|
$null = Invoke-WebRequest -Uri $Event.MessageData.ApiUrl -Method POST -Body $body -ContentType "application/x-www-form-urlencoded" -UseBasicParsing -TimeoutSec 5
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
|
||||||
# Debounce check - skip if we processed this file recently
|
# Debounce check - skip if we processed this file recently
|
||||||
$now = Get-Date
|
$now = Get-Date
|
||||||
if ($script:RecentlyProcessed.ContainsKey($path)) {
|
if ($script:RecentlyProcessed.ContainsKey($path)) {
|
||||||
@@ -328,9 +387,11 @@ $action = {
|
|||||||
$script:BytesRemoved += $removed
|
$script:BytesRemoved += $removed
|
||||||
& $updateStatus "CLEANED: $fileName ($removed bytes)" "Green"
|
& $updateStatus "CLEANED: $fileName ($removed bytes)" "Green"
|
||||||
& $updateStats
|
& $updateStats
|
||||||
|
& $logToApi "cleaned" $fileName $removed "Removed $removed byte(s)"
|
||||||
} else {
|
} else {
|
||||||
Write-Host " [OK] No special characters found" -ForegroundColor Gray
|
Write-Host " [OK] No special characters found" -ForegroundColor Gray
|
||||||
& $updateStatus "OK: $fileName (no changes)" "Gray"
|
& $updateStatus "OK: $fileName (no changes)" "Gray"
|
||||||
|
& $logToApi "ok" $fileName 0 "No changes needed"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Mark as recently processed
|
# Mark as recently processed
|
||||||
@@ -350,6 +411,7 @@ $action = {
|
|||||||
$script:FailedFiles++
|
$script:FailedFiles++
|
||||||
& $updateStatus "FAILED: $fileName" "Red"
|
& $updateStatus "FAILED: $fileName" "Red"
|
||||||
& $updateStats
|
& $updateStats
|
||||||
|
& $logToApi "failed" $fileName 0 "Could not access file after $maxRetries attempts"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
@@ -357,6 +419,7 @@ $action = {
|
|||||||
$script:FailedFiles++
|
$script:FailedFiles++
|
||||||
& $updateStatus "ERROR: $fileName" "Red"
|
& $updateStatus "ERROR: $fileName" "Red"
|
||||||
& $updateStats
|
& $updateStats
|
||||||
|
& $logToApi "error" $fileName 0 $_.Exception.Message
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
@@ -374,6 +437,10 @@ $messageData = @{
|
|||||||
DebounceSeconds = $script:DebounceSeconds
|
DebounceSeconds = $script:DebounceSeconds
|
||||||
StatusLine = 14 # Line number for status updates
|
StatusLine = 14 # Line number for status updates
|
||||||
FileFilter = $FileFilter
|
FileFilter = $FileFilter
|
||||||
|
ApiUrl = $ApiUrl
|
||||||
|
Hostname = $script:Hostname
|
||||||
|
Version = $ScriptVersion
|
||||||
|
WatchFolder = $WatchFolder
|
||||||
}
|
}
|
||||||
|
|
||||||
# Register event handlers
|
# Register event handlers
|
||||||
@@ -397,6 +464,9 @@ try {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
# Log shutdown to API
|
||||||
|
Send-DNCEvent -EventType "stopped" -Message "Script stopped. Cleaned: $script:FilesProcessed, Failed: $script:FailedFiles"
|
||||||
|
|
||||||
# Cleanup on exit
|
# Cleanup on exit
|
||||||
$watcher.EnableRaisingEvents = $false
|
$watcher.EnableRaisingEvents = $false
|
||||||
$watcher.Dispose()
|
$watcher.Dispose()
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
[eDNC-Fix]
|
[eDNC-Fix]
|
||||||
Version=1.4.0
|
Version=1.5.0
|
||||||
|
|||||||
Reference in New Issue
Block a user