From 4e148b6dc5da9d3f31b513da451aa0b551e65410 Mon Sep 17 00:00:00 2001 From: Howard Enos Date: Tue, 7 Jul 2026 21:05:37 -0700 Subject: [PATCH] sync: auto-sync from HOWARD-HOME at 2026-07-07 21:05:08 Author: Howard Enos Machine: HOWARD-HOME Timestamp: 2026-07-07 21:05:08 --- errorlog.md | 4 ++++ scratch-bkuprecon.ps1 | 18 --------------- scratch-dry-ca.ps1 | 20 ----------------- scratch-dry-promo.ps1 | 22 ------------------- scratch-dry-robo.ps1 | 13 ----------- scratch-mkshare.ps1 | 28 ----------------------- scratch-mkstage.ps1 | 22 ------------------- scratch-preflight.ps1 | 50 ------------------------------------------ scratch-preflight2.ps1 | 29 ------------------------ scratch-prepcheck.ps1 | 27 ----------------------- scratch-preseed.ps1 | 15 ------------- scratch-qbcopy.ps1 | 30 ------------------------- scratch-qbwc.ps1 | 41 ---------------------------------- scratch-startbkup.ps1 | 26 ---------------------- 14 files changed, 4 insertions(+), 341 deletions(-) delete mode 100644 scratch-bkuprecon.ps1 delete mode 100644 scratch-dry-ca.ps1 delete mode 100644 scratch-dry-promo.ps1 delete mode 100644 scratch-dry-robo.ps1 delete mode 100644 scratch-mkshare.ps1 delete mode 100644 scratch-mkstage.ps1 delete mode 100644 scratch-preflight.ps1 delete mode 100644 scratch-preflight2.ps1 delete mode 100644 scratch-prepcheck.ps1 delete mode 100644 scratch-preseed.ps1 delete mode 100644 scratch-qbcopy.ps1 delete mode 100644 scratch-qbwc.ps1 delete mode 100644 scratch-startbkup.ps1 diff --git a/errorlog.md b/errorlog.md index 6f300c85..57d27cc2 100644 --- a/errorlog.md +++ b/errorlog.md @@ -19,6 +19,10 @@ Categories (the `[type]` tag): _(none)_ = skill/command execution failure · +2026-07-08 | Howard-Home | rmm/ps-encoded.sh | [friction] iconv not found on HOWARD-HOME Git-Bash -> ps-encoded.sh fails 'encoding produced nothing'; fell back to jq --rawfile direct dispatch [ctx: ref=ps-encoded.sh] + +2026-07-08 | Howard-Home | ps-encoded | encode produced empty output [ctx: src=C:UsersHowardAppDataLocalTempclaudeC--claudetools‰88c32-7d31-4efa-b061-8d4521258192scratchpadcheck-sqlmem.ps1] + 2026-07-08 | Howard-Home | bash/background-task | [friction] added shell '& ... disown' on top of run_in_background:true -> shell forks the long-running wait and exits 0 immediately, orphaning it; the blocking read never notifies. Twice this session. Fix: with run_in_background:true, run the command in the FOREGROUND of that shell (no trailing &, no disown) - the harness does the backgrounding. [ctx: ref=discord ask-forum.sh --wait] 2026-07-08 | Howard-Home | rmm/deploy-beast | [friction] cannot git-fetch Gitea submodule as SYSTEM via RMM: credential.helper=manager (GCM) fails with 'Must specify at least one OAuthAuthenticationModes' when no guru desktop session is logged on; new commit not fetchable, so remote SYSTEM deploy of the discord-bot is blocked. Restart-Service works as SYSTEM, but pull must run in guru context (interactive /sync on BEAST) first. [ctx: host=GURU-BEAST-ROG repo=acg-discord-bot] diff --git a/scratch-bkuprecon.ps1 b/scratch-bkuprecon.ps1 deleted file mode 100644 index 60c32866..00000000 --- a/scratch-bkuprecon.ps1 +++ /dev/null @@ -1,18 +0,0 @@ -$ErrorActionPreference='SilentlyContinue' -"==== WINDOWS SERVER BACKUP FEATURE ====" -(Get-WindowsFeature Windows-Server-Backup | Select-Object Name,Installed | Out-String) -"==== ALL DISKS (spot a USB/backup disk) ====" -Get-Disk | Select-Object Number,FriendlyName,BusType,@{n='SizeGB';e={[math]::Round($_.Size/1GB,0)}},OperationalStatus,PartitionStyle | Format-Table -Auto | Out-String -"==== VOLUMES ====" -Get-Volume | Where-Object {$_.DriveType -ne 'CD-ROM'} | Select-Object DriveLetter,FileSystemLabel,DriveType,@{n='SizeGB';e={[math]::Round($_.Size/1GB,1)}},@{n='FreeGB';e={[math]::Round($_.SizeRemaining/1GB,1)}} | Format-Table -Auto | Out-String -"==== C: USED (what we must protect) ====" -$c=Get-CimInstance Win32_LogicalDisk -Filter "DeviceID='C:'" -"Used GB: $([math]::Round(($c.Size-$c.FreeSpace)/1GB,1)) Free GB: $([math]::Round($c.FreeSpace/1GB,1))" -"==== VSS WRITER HEALTH (must be stable/no-error before backup) ====" -$w = vssadmin list writers 2>$null -($w | Select-String -Pattern 'Writer name:|State:|Last error:' | Out-String) -"==== EXISTING WBADMIN BACKUP HISTORY ====" -wbadmin get versions 2>&1 | Out-String -"==== REACH NEW SERVER? ====" -Test-NetConnection -ComputerName TPS-SVR -Port 445 -InformationLevel Quiet 2>$null -"==== DONE ====" diff --git a/scratch-dry-ca.ps1 b/scratch-dry-ca.ps1 deleted file mode 100644 index 524575bf..00000000 --- a/scratch-dry-ca.ps1 +++ /dev/null @@ -1,20 +0,0 @@ -$ErrorActionPreference='SilentlyContinue' -"== CA service + identity ==" -Get-Service CertSvc | Select-Object Name,Status,StartType | Format-Table -Auto | Out-String -certutil -cainfo 2>&1 | Select-String 'CA name|CA type|Subject|Expires|Provider|hash' | Out-String -"== CA database + log files (backup sizing) ==" -Get-ChildItem 'C:\Windows\System32\CertLog' -File 2>$null | Select-Object Name,@{n='MB';e={[math]::Round($_.Length/1MB,2)}} | Format-Table -Auto | Out-String -"== Private-key provider / exportability (determines backupKey method) ==" -certutil -store My 2>&1 | Select-String 'TPS-TPS-SERVER-CA|Provider =|Private key is NOT exportable|Signature test|Key Container' | Out-String -"== Config to reproduce on the rebuilt CA ==" -"-- Validity period --" -certutil -getreg CA\ValidityPeriodUnits 2>&1 | Select-String 'Values|=' | Out-String -certutil -getreg CA\ValidityPeriod 2>&1 | Select-String 'Values|=' | Out-String -"-- CRL publication URLs --" -certutil -getreg CA\CRLPublicationURLs 2>&1 | Out-String -"-- AIA publication URLs --" -certutil -getreg CA\CACertPublicationURLs 2>&1 | Out-String -"-- CRL period --" -certutil -getreg CA\CRLPeriodUnits 2>&1 | Select-String 'Values|=' | Out-String -certutil -getreg CA\CRLPeriod 2>&1 | Select-String 'Values|=' | Out-String -"== DONE ==" diff --git a/scratch-dry-promo.ps1 b/scratch-dry-promo.ps1 deleted file mode 100644 index 91b96f10..00000000 --- a/scratch-dry-promo.ps1 +++ /dev/null @@ -1,22 +0,0 @@ -$ErrorActionPreference='SilentlyContinue' -Import-Module ActiveDirectory -ErrorAction SilentlyContinue -"== OS / edition (must be Std/DC-capable) ==" -$os=Get-CimInstance Win32_OperatingSystem; "$($os.Caption) $($os.Version)" -"== AD DS deployment module (needed to promote + to run Test-ADDSDomainControllerInstallation) ==" -Get-Module -ListAvailable ADDSDeployment | Select-Object Name,Version | Format-Table -Auto | Out-String -"== Secure channel to domain ==" -nltest /sc_query:TPS.local 2>&1 | Out-String -"== Locate a DC for the domain ==" -nltest /dsgetdc:TPS.local 2>&1 | Out-String -"== Port reachability to current DC 192.168.1.125 (need all OPEN) ==" -foreach($p in 53,88,135,389,445,3268,636){ $r=Test-NetConnection -ComputerName 192.168.1.125 -Port $p -WarningAction SilentlyContinue; "{0,-6} {1}" -f $p, $(if($r.TcpTestSucceeded){'OPEN'}else{'CLOSED'}) } -"== Time offset vs DC (Kerberos needs < 5 min) ==" -w32tm /stripchart /computer:192.168.1.125 /samples:1 /dataonly 2>&1 | Select-Object -Last 3 | Out-String -"== Schema objectVersion (87=2016, 88=2019 -> promotion auto-adpreps if 87) ==" -$sch=(Get-ADRootDSE).schemaNamingContext -"objectVersion: $((Get-ADObject $sch -Property objectVersion).objectVersion)" -"== Free space C: (NTDS + SYSVOL target) ==" -$v=Get-Volume -DriveLetter C; "Free GB: $([math]::Round($v.SizeRemaining/1GB,1))" -"== This box's current DNS (post-promo it should point to itself) ==" -Get-DnsClientServerAddress -AddressFamily IPv4 | Where-Object {$_.ServerAddresses} | Select-Object InterfaceAlias,@{n='DNS';e={$_.ServerAddresses -join ','}} | Format-Table -Auto | Out-String -"== DONE ==" diff --git a/scratch-dry-robo.ps1 b/scratch-dry-robo.ps1 deleted file mode 100644 index 04e459a5..00000000 --- a/scratch-dry-robo.ps1 +++ /dev/null @@ -1,13 +0,0 @@ -$ErrorActionPreference='SilentlyContinue' -function DryCopy($src){ - if(-not (Test-Path $src)){ "### $src`nMISSING`n"; return } - $out = robocopy $src 'C:\__dryrun_nul__' /L /E /NFL /NDL /NP /R:0 /W:0 /BYTES /XJ 2>&1 - "### $src" - ($out | Select-String 'Dirs :|Files :|Bytes :|ERROR|Access is denied') | Out-String -} -DryCopy 'C:\Share\Quickbooks' -DryCopy 'C:\ServerFolders\Users' -DryCopy 'C:\ServerFolders\Company' -DryCopy 'C:\ServerFolders\Folder Redirection' -DryCopy 'C:\Share\Deployment' -"== DONE ==" diff --git a/scratch-mkshare.ps1 b/scratch-mkshare.ps1 deleted file mode 100644 index 81ea40d9..00000000 --- a/scratch-mkshare.ps1 +++ /dev/null @@ -1,28 +0,0 @@ -$ErrorActionPreference='Stop' -$path='C:\Backups\TPS-SERVER' -New-Item -ItemType Directory -Path $path -Force | Out-Null - -# SMB share granting the old server's machine account + Domain Admins -if(Get-SmbShare -Name 'TPSBackup' -ErrorAction SilentlyContinue){ - Write-Host "share TPSBackup already exists" -} else { - New-SmbShare -Name 'TPSBackup' -Path $path -FullAccess 'TPS\Domain Admins','TPS\TPS-SERVER$' -CachingMode None | Out-Null - Write-Host "created share TPSBackup" -} - -# NTFS ACL: SYSTEM, Administrators, Domain Admins, TPS-SERVER$ full control -$acl = Get-Acl $path -foreach($id in @('TPS\Domain Admins','TPS\TPS-SERVER$','BUILTIN\Administrators','NT AUTHORITY\SYSTEM')){ - try { - $rule = New-Object System.Security.AccessControl.FileSystemAccessRule($id,'FullControl','ContainerInherit,ObjectInherit','None','Allow') - $acl.AddAccessRule($rule) - } catch { Write-Host "acl skip $id : $_" } -} -Set-Acl -Path $path -AclObject $acl - -"==== RESULT ====" -Get-SmbShare -Name TPSBackup | Format-List Name,Path,FullAccess | Out-String -"UNC: \\TPS-SVR\TPSBackup" -$v=Get-Volume -DriveLetter C -"Target free space GB: $([math]::Round($v.SizeRemaining/1GB,1))" -"==== DONE ====" diff --git a/scratch-mkstage.ps1 b/scratch-mkstage.ps1 deleted file mode 100644 index e962fdc9..00000000 --- a/scratch-mkstage.ps1 +++ /dev/null @@ -1,22 +0,0 @@ -$ErrorActionPreference='Stop' -"== post-reboot state ==" -$pfro=(Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager' -Name PendingFileRenameOperations -ErrorAction SilentlyContinue).PendingFileRenameOperations -"PendingFileRenameOperations now: $([bool]$pfro)" -$os=Get-CimInstance Win32_OperatingSystem -"Last boot: $($os.LastBootUpTime) Uptime min: $([math]::Round(((Get-Date)-$os.LastBootUpTime).TotalMinutes,0))" -"Activation: $((Get-CimInstance SoftwareLicensingProduct -Filter "ApplicationID='55c92734-d682-4d71-983e-d6ec3f16059f' AND LicenseStatus=1" | Select-Object -First 1 -Expand LicenseStatus) ) (1 = Licensed)" - -"== create staging root + share (push target for pre-seed) ==" -New-Item -ItemType Directory -Path 'C:\Share' -Force | Out-Null -if(Get-SmbShare -Name 'Share' -ErrorAction SilentlyContinue){ "share 'Share' already exists" } else { - New-SmbShare -Name 'Share' -Path 'C:\Share' -FullAccess 'TPS\Domain Admins','TPS\TPS-SERVER$' -CachingMode None | Out-Null - "created share 'Share'" -} -$acl=Get-Acl 'C:\Share' -foreach($id in @('TPS\Domain Admins','TPS\TPS-SERVER$','BUILTIN\Administrators','NT AUTHORITY\SYSTEM')){ - $r=New-Object System.Security.AccessControl.FileSystemAccessRule($id,'FullControl','ContainerInherit,ObjectInherit','None','Allow'); $acl.AddAccessRule($r) -} -Set-Acl 'C:\Share' $acl -Get-SmbShareAccess -Name Share | Select-Object AccountName,AccessRight,AccessControlType | Format-Table -Auto | Out-String -"UNC ready: \\TPS-SVR\Share -> C:\Share" -"== DONE ==" diff --git a/scratch-preflight.ps1 b/scratch-preflight.ps1 deleted file mode 100644 index 4970e57e..00000000 --- a/scratch-preflight.ps1 +++ /dev/null @@ -1,50 +0,0 @@ -$ErrorActionPreference='SilentlyContinue' -Import-Module ActiveDirectory -ErrorAction SilentlyContinue - -"==== FUNCTIONAL LEVELS + DOMAIN ====" -$f=Get-ADForest; $d=Get-ADDomain -"Forest mode: $($f.ForestMode) Domain mode: $($d.DomainMode)" -"Domain: $($d.DNSRoot) NetBIOS: $($d.NetBIOSName) PDC: $($d.PDCEmulator)" - -"`n==== CURRENT DOMAIN CONTROLLERS ====" -Get-ADDomainController -Filter * | Select-Object Name,IPv4Address,IsGlobalCatalog,OperatingSystem,Site | Format-Table -Auto | Out-String - -"==== FSMO HOLDERS ====" -netdom query fsmo 2>&1 | Out-String - -"==== LINGERING TPS-SVR DC METADATA (must be clean before promo) ====" -$cfg=(Get-ADRootDSE).configurationNamingContext -"-- computer object(s) matching TPS-SVR --" -Get-ADComputer -Filter 'Name -like "*SVR*"' -Properties operatingSystem,whenCreated | Select-Object Name,DistinguishedName,operatingSystem,whenCreated | Format-Table -Auto | Out-String -"-- 'server' objects in config Sites (each real/former DC has one) --" -Get-ADObject -SearchBase "CN=Sites,$cfg" -Filter "objectClass -eq 'server'" -Properties dNSHostName | Select-Object Name,dNSHostName | Format-Table -Auto | Out-String -"-- nTDSDSA (NTDS Settings) objects = active DC replicas --" -Get-ADObject -SearchBase "CN=Sites,$cfg" -Filter "objectClass -eq 'nTDSDSA'" | Select-Object DistinguishedName | Format-Table -Auto | Out-String -"-- Domain Controllers OU members --" -Get-ADComputer -SearchBase "OU=Domain Controllers,$($d.DistinguishedName)" -Filter * | Select-Object Name | Format-Table -Auto | Out-String - -"==== AD REPLICATION HEALTH ====" -repadmin /replsummary 2>&1 | Out-String - -"==== DHCP AUTHORIZED IN AD (empty => MS DHCP not authoritative) ====" -Get-DhcpServerInDC 2>&1 | Out-String - -"==== CERTIFICATE AUTHORITY (assess if in use) ====" -certutil -cainfo 2>&1 | Select-String 'CA type|CA name|Subject|Expires|Provider' | Out-String -"-- issued (non-revoked, non-expired-status) cert rows, first 30 --" -certutil -view -restrict "Disposition=20" -out "RequestID,CommonName,CertificateTemplate,NotAfter" csv 2>&1 | Select-Object -First 30 | Out-String -"-- total issued rows --" -$rows = certutil -view -restrict "Disposition=20" -out "RequestID" csv 2>&1 -"issued cert rows (incl header): $(($rows | Measure-Object -Line).Lines)" - -"==== OLD SERVER IP CONFIG (plan Option B swap) ====" -Get-NetIPConfiguration | ForEach-Object { - "IF: $($_.InterfaceAlias) IP: $($_.IPv4Address.IPAddress) GW: $($_.IPv4DefaultGateway.NextHop) DNS: $($_.DNSServer.ServerAddresses -join ',')" -} -"-- all IPv4 addrs --" -Get-NetIPAddress -AddressFamily IPv4 | Where-Object {$_.IPAddress -notlike '169.*' -and $_.IPAddress -ne '127.0.0.1'} | Select-Object IPAddress,PrefixLength,InterfaceAlias | Format-Table -Auto | Out-String - -"==== DFS NAMESPACES (Folder Redirection / Shared Folders use these) ====" -Get-DfsnRoot 2>&1 | Out-String - -"==== DONE ====" diff --git a/scratch-preflight2.ps1 b/scratch-preflight2.ps1 deleted file mode 100644 index 336cce83..00000000 --- a/scratch-preflight2.ps1 +++ /dev/null @@ -1,29 +0,0 @@ -$ErrorActionPreference='SilentlyContinue' - -"==== A. WHAT USES EACH SERVER IP ====" -"-- DNS A records pointing at the server's IPs --" -$targets = '192.168.1.120','192.168.1.125','10.10.10.5' -Get-DnsServerResourceRecord -ZoneName 'TPS.local' -RRType A 2>$null | - Where-Object { $_.RecordData.IPv4Address.IPAddressToString -in $targets } | - Select-Object HostName,@{n='IP';e={$_.RecordData.IPv4Address.IPAddressToString}} | - Sort-Object IP | Format-Table -Auto | Out-String - -"-- TCP listeners bound to a SPECIFIC IP (reveals services pinned to .120/.125/10.x) --" -Get-NetTCPConnection -State Listen 2>$null | - Where-Object { $_.LocalAddress -notin '0.0.0.0','::','127.0.0.1','::1' } | - Select-Object LocalAddress,LocalPort,@{n='Process';e={(Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).ProcessName}} | - Sort-Object LocalAddress,LocalPort | Format-Table -Auto | Out-String - -"-- IIS websites + bindings (Essentials Remote Web Access, etc.) --" -Import-Module WebAdministration -ErrorAction SilentlyContinue -Get-Website 2>$null | Select-Object Name,State,@{n='Bindings';e={ ($_.bindings.Collection | ForEach-Object { $_.protocol + ':' + $_.bindingInformation }) -join ' | ' }} | Format-Table -Auto -Wrap | Out-String - -"==== B. IS THE CA STILL ACTIVELY ISSUING? ====" -"-- Templates the CA is currently published to issue --" -certutil -CATemplates 2>&1 | Out-String -"-- MOST RECENT issued certs (highest RequestIDs = newest) --" -certutil -view -restrict "Disposition=20" -out "RequestID,CommonName,CertificateTemplate,NotAfter" csv 2>&1 | Select-Object -Last 15 | Out-String -"-- Any GPO that might drive cert autoenrollment --" -Get-GPO -All 2>$null | Select-Object DisplayName,ModificationTime | Sort-Object DisplayName | Format-Table -Auto | Out-String - -"==== DONE ====" diff --git a/scratch-prepcheck.ps1 b/scratch-prepcheck.ps1 deleted file mode 100644 index 44c50233..00000000 --- a/scratch-prepcheck.ps1 +++ /dev/null @@ -1,27 +0,0 @@ -$ErrorActionPreference='SilentlyContinue' -"== PENDING REBOOT CHECKS (all should be False) ==" -"CBS RebootPending: $([bool](Test-Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending'))" -"WindowsUpdate RebootRequired: $([bool](Test-Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired'))" -$pfro = (Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager' -Name PendingFileRenameOperations -ErrorAction SilentlyContinue).PendingFileRenameOperations -"PendingFileRenameOperations: $([bool]$pfro)" -$cn1=(Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName').ComputerName -$cn2=(Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName').ComputerName -"Rename pending: $($cn1 -ne $cn2) (active=$cn1 / configured=$cn2)" - -"== ROLE / SERVICE STATE (is AD DS ready to promote?) ==" -Get-WindowsFeature AD-Domain-Services,RSAT-ADDS,DNS,DHCP | Select-Object Name,InstallState | Format-Table -Auto | Out-String -Get-Service NTDS,DNS,DHCPServer,Netlogon,W32Time | Select-Object Name,Status,StartType | Format-Table -Auto | Out-String - -"== EXISTING TARGET PATHS (for data pre-seed) ==" -foreach($p in 'C:\Share','C:\Share\Quickbooks','C:\Share\Deployment'){ "$p exists: $(Test-Path $p)" } - -"== DISK C: ==" -Get-Volume -DriveLetter C | Select-Object @{n='FreeGB';e={[math]::Round($_.SizeRemaining/1GB,1)}},@{n='SizeGB';e={[math]::Round($_.Size/1GB,1)}} | Format-Table -Auto | Out-String - -"== UPTIME / LAST BOOT ==" -$os=Get-CimInstance Win32_OperatingSystem -"Last boot: $($os.LastBootUpTime) Uptime days: $([math]::Round(((Get-Date)-$os.LastBootUpTime).TotalDays,1))" - -"== PENDING WINDOWS UPDATES (a big backlog = reboot churn) ==" -try { $s=(New-Object -ComObject Microsoft.Update.Session).CreateUpdateSearcher(); $r=$s.Search("IsInstalled=0 and IsHidden=0"); "Pending updates: $($r.Updates.Count)" } catch { "update query n/a: $_" } -"== DONE ==" diff --git a/scratch-preseed.ps1 b/scratch-preseed.ps1 deleted file mode 100644 index ede4a6bd..00000000 --- a/scratch-preseed.ps1 +++ /dev/null @@ -1,15 +0,0 @@ -$ErrorActionPreference='Stop' -$log='C:\Windows\Temp\tps-preseed.log' -# Pre-seed: data+attributes+timestamps only (ACLs re-applied fresh at cutover, avoids remote-privilege issues). -# /B backup mode reads open/locked files where possible; locked live QB .QBW skips fast (/R:1) and is recopied clean at cutover. -$rc = 'robocopy "C:\Share" "\\TPS-SVR\Share" /E /COPY:DAT /DCOPY:DAT /B /R:1 /W:2 /Z /XJ /MT:16 /NFL /NDL /NP /LOG:' + $log -$action = New-ScheduledTaskAction -Execute 'cmd.exe' -Argument ('/c ' + $rc) -$principal = New-ScheduledTaskPrincipal -UserId 'NT AUTHORITY\SYSTEM' -LogonType ServiceAccount -RunLevel Highest -$settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Hours 12) -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -$task = New-ScheduledTask -Action $action -Principal $principal -Settings $settings -Register-ScheduledTask -TaskName 'TPS-Preseed-Copy' -InputObject $task -Force | Out-Null -Start-ScheduledTask -TaskName 'TPS-Preseed-Copy' -Start-Sleep -Seconds 12 -"Task state: $((Get-ScheduledTask -TaskName 'TPS-Preseed-Copy').State)" -"-- log head --" -if(Test-Path $log){ Get-Content $log -TotalCount 14 } else { "(log not created yet)" } diff --git a/scratch-qbcopy.ps1 b/scratch-qbcopy.ps1 deleted file mode 100644 index 6aa9e721..00000000 --- a/scratch-qbcopy.ps1 +++ /dev/null @@ -1,30 +0,0 @@ -$ErrorActionPreference='Continue' -$src='C:\Share\Quickbooks' -$dst='\\TPS-SVR\Share\Quickbooks' -$qbw='schoonerQB2025.QBW' -$tlg='schoonerQB2025.QBW.TLG' - -"== stop QB hosting services (prevents re-lock during copy) ==" -foreach($s in 'QuickBooksDB34','QBCFMonitorService'){ Stop-Service $s -Force -ErrorAction SilentlyContinue; Start-Sleep 1; "$s -> $((Get-Service $s -ErrorAction SilentlyContinue).Status)" } -Start-Sleep 3 - -try { - "== confirm company file is unlocked ==" - try { $fs=[System.IO.File]::Open((Join-Path $src $qbw),'Open','Read','None'); $fs.Close(); "UNLOCKED - copying" } - catch { "STILL LOCKED: $($_.Exception.Message)" } - - "== copy clean company file + transaction log ==" - $out = robocopy $src $dst $qbw $tlg /COPY:DAT /R:2 /W:3 /NP /NJH - ($out | Select-String 'schoonerQB2025|Bytes :|ERROR|New File') | Out-String - "robocopy exit code: $LASTEXITCODE (0-7 = success)" -} -finally { - "== restart QB services (users resume on OLD server) ==" - foreach($s in 'QBCFMonitorService','QuickBooksDB34'){ Start-Service $s -ErrorAction SilentlyContinue; Start-Sleep 1; "$s -> $((Get-Service $s -ErrorAction SilentlyContinue).Status)" } -} - -"== verify copied file matches source ==" -$s=(Get-Item (Join-Path $src $qbw) -ErrorAction SilentlyContinue).Length -$d=(Get-Item (Join-Path $dst $qbw) -ErrorAction SilentlyContinue).Length -"SRC: $([math]::Round($s/1MB,1)) MB DST: $([math]::Round($d/1MB,1)) MB MATCH: $($s -eq $d -and $s -gt 0)" -"== DONE ==" diff --git a/scratch-qbwc.ps1 b/scratch-qbwc.ps1 deleted file mode 100644 index e285121b..00000000 --- a/scratch-qbwc.ps1 +++ /dev/null @@ -1,41 +0,0 @@ -$ErrorActionPreference='SilentlyContinue' - -"===== .QWC application files (define the connected app) =====" -$roots = @('C:\Share\Quickbooks','C:\ProgramData\Intuit','C:\Program Files\Common Files\Intuit','C:\Program Files (x86)\Common Files\Intuit','C:\Program Files (x86)\Intuit','C:\Program Files\Intuit') -$qwc = @() -# top-level of the QB data folder (where apps usually drop the .qwc) -$qwc += Get-ChildItem 'C:\Share\Quickbooks' -Filter *.qwc -ErrorAction SilentlyContinue -# recursive in the (small) profile + program locations -foreach($r in @('C:\Users','C:\ProgramData\Intuit','C:\Program Files\Common Files\Intuit','C:\Program Files (x86)\Common Files\Intuit')){ - if(Test-Path $r){ $qwc += Get-ChildItem $r -Recurse -Filter *.qwc -ErrorAction SilentlyContinue } -} -$qwc = $qwc | Sort-Object FullName -Unique -if(-not $qwc){ "(no .qwc files in searched locations)" } -foreach($f in $qwc){ - "### $($f.FullName) (modified $($f.LastWriteTime))" - try { [xml]$x = Get-Content $f.FullName -Raw - " AppName : $($x.QBWCXML.AppName)" - " AppURL : $($x.QBWCXML.AppURL)" - " AppSupport : $($x.QBWCXML.AppSupport)" - " AppDescription: $($x.QBWCXML.AppDescription)" - " UserName : $($x.QBWCXML.UserName)" - } catch { " raw:"; (Get-Content $f.FullName -Raw) } -} - -"`n===== Web Connector data dirs (per-user) =====" -Get-ChildItem 'C:\Users\*\AppData\Local\Intuit\QBWebConnector' -Directory -ErrorAction SilentlyContinue | ForEach-Object { - "-- $($_.FullName) --" - Get-ChildItem $_.FullName -Recurse -ErrorAction SilentlyContinue | Select-Object @{n='KB';e={[math]::Round($_.Length/1KB,1)}},FullName,LastWriteTime | Format-Table -Auto -Wrap | Out-String -} - -"`n===== Web Connector LOG - app names / URLs it talks to =====" -$logs = Get-ChildItem 'C:\Users\*\AppData\Local\Intuit\QBWebConnector','C:\ProgramData\Intuit\QBWebConnector' -Recurse -Include *.txt,*.log -ErrorAction SilentlyContinue -foreach($l in $logs){ - "### $($l.FullName)" - Select-String -Path $l.FullName -Pattern 'AppName|App Name|AppURL|Connecting|http' -ErrorAction SilentlyContinue | ForEach-Object { $_.Line.Trim() } | Sort-Object -Unique | Select-Object -Last 25 | Out-String -} - -"`n===== registry-registered Web Connector apps =====" -reg query "HKLM\SOFTWARE\Intuit\QBWebConnector" /s 2>$null -reg query "HKLM\SOFTWARE\WOW6432Node\Intuit\QBWebConnector" /s 2>$null -"===== DONE =====" diff --git a/scratch-startbkup.ps1 b/scratch-startbkup.ps1 deleted file mode 100644 index f263c165..00000000 --- a/scratch-startbkup.ps1 +++ /dev/null @@ -1,26 +0,0 @@ -$ErrorActionPreference='Stop' -$target='\\TPS-SVR\TPSBackup' - -# Pre-flight: confirm we can write to the target as the machine account -$probe = Join-Path $target ("_probe_{0}.txt" -f $env:COMPUTERNAME) -try { Set-Content -Path $probe -Value 'ok' -ErrorAction Stop; Remove-Item $probe -Force; Write-Host "target writable: YES" } -catch { Write-Host "target writable: NO -> $_"; throw } - -# Detached one-time scheduled task so the backup outlives this RMM command -$log = 'C:\Windows\Temp\tps-bmr.log' -$cmd = "wbadmin start backup -backupTarget:$target -allCritical -vssCopy -quiet" -$action = New-ScheduledTaskAction -Execute 'cmd.exe' -Argument "/c $cmd > `"$log`" 2>&1" -$principal = New-ScheduledTaskPrincipal -UserId 'NT AUTHORITY\SYSTEM' -LogonType ServiceAccount -RunLevel Highest -$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -ExecutionTimeLimit (New-TimeSpan -Hours 12) -$task = New-ScheduledTask -Action $action -Principal $principal -Settings $settings -Register-ScheduledTask -TaskName 'TPS-BMR-Backup' -InputObject $task -Force | Out-Null -Start-ScheduledTask -TaskName 'TPS-BMR-Backup' -Start-Sleep -Seconds 12 - -"==== TASK STATE ====" -Get-ScheduledTask -TaskName 'TPS-BMR-Backup' | Select-Object TaskName,State | Format-Table -Auto | Out-String -"==== WBADMIN STATUS ====" -wbadmin get status 2>&1 | Out-String -"==== LOG HEAD ====" -if(Test-Path $log){ Get-Content $log -TotalCount 15 | Out-String } else { "(log not created yet)" } -"==== DONE ===="