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
This commit is contained in:
@@ -19,6 +19,10 @@ Categories (the `[type]` tag): _(none)_ = skill/command execution failure ·
|
|||||||
|
|
||||||
<!-- Append entries below this line -->
|
<!-- Append entries below this line -->
|
||||||
|
|
||||||
|
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<6C>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 | 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]
|
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]
|
||||||
|
|||||||
@@ -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 ===="
|
|
||||||
@@ -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 =="
|
|
||||||
@@ -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 =="
|
|
||||||
@@ -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 =="
|
|
||||||
@@ -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 ===="
|
|
||||||
@@ -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 =="
|
|
||||||
@@ -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 ===="
|
|
||||||
@@ -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 ===="
|
|
||||||
@@ -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 =="
|
|
||||||
@@ -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)" }
|
|
||||||
@@ -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 =="
|
|
||||||
@@ -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 ====="
|
|
||||||
@@ -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 ===="
|
|
||||||
Reference in New Issue
Block a user