<# +====================================================================+ | | | TEKWITCH DEVICE BASELINE COLLECTOR | | | | Version 1.0.0 | | Author: TEKWITCH | | Date: 2026-08-14 | | | | ~ A Small Instrument of Knowing ~ | | | +====================================================================+ __...--~~~~~-._ _.-~~~~~--...__ // `V' \\ // | \\ //__...--~~~~~~-._ | _.-~~~~~~--...__\\ //__.....----~~~~._\ | /_.~~~~----.....__\\ ====================\|/==================== Purpose: Collect a bounded, read-only hardware and operating-system baseline for inspection, remote support, upgrade planning, troubleshooting, or later automated host assessment. Design: - Device agnostic. - Suitable for laptops and desktops. - Makes no system configuration changes. - Makes no firmware changes. - Installs no software. - Retrieves no passwords, product keys, or BitLocker recovery keys. - Writes only its own report artifacts. - Packages results into one ZIP file for transfer. Output: TEKWITCH-Device-Baseline-v1.0.0-YYYYMMDD-HHMMSS.zip Operator instruction: Send the output file to TEKWITCH. Publisher stated in this artifact: TEKWITCH.com Licensing terms: https://tekwitch.com/terms/toy-use/1.0/ Public license: Prosperity Public License 3.0.0 Current permission: no-charge personal, organizational, and commercial use, including paid client work; no 30-day limit on covered uses. Release note: v1.0.0 aligns with the standing no-charge permission. Collector behavior is unchanged from v0.2.2. +====================================================================+ #> # ==================================================================== # COLLECTOR IDENTITY # ==================================================================== $ScriptVersion = "1.0.0" $Timestamp = Get-Date -Format "yyyyMMdd-HHmmss" $Desktop = [Environment]::GetFolderPath("Desktop") $WorkDir = Join-Path $Desktop "TEKWITCH-Device-Baseline-$Timestamp" $Report = Join-Path $WorkDir "Device-Baseline.txt" $BatteryReport = Join-Path $WorkDir "battery-report.html" $ZipFile = Join-Path $Desktop ( "TEKWITCH-Device-Baseline-v$ScriptVersion-$Timestamp.zip" ) New-Item -ItemType Directory -Path $WorkDir -Force | Out-Null # ==================================================================== # HELPERS # ==================================================================== function Add-Section { param( [string]$Title, [object]$Data ) Add-Content -Path $Report -Value "" Add-Content -Path $Report -Value ("=" * 70) Add-Content -Path $Report -Value $Title Add-Content -Path $Report -Value ("=" * 70) if ($null -eq $Data) { Add-Content -Path $Report -Value "No data returned." } else { $Data | Out-String -Width 220 | Add-Content -Path $Report } } function Clean-Text { param( [object]$Value ) if ($null -eq $Value) { return "" } return ([string]$Value).Trim() } function Convert-WindowsLicenseStatus { param( [int]$Status ) switch ($Status) { 0 { return "Unlicensed" } 1 { return "Licensed" } 2 { return "Initial grace period" } 3 { return "Additional grace period" } 4 { return "Non-genuine grace period" } 5 { return "Notification" } 6 { return "Extended grace period" } default { return "Unknown ($Status)" } } } # ==================================================================== # HEADER # ==================================================================== "TEKWITCH Device Baseline" | Set-Content $Report ("Collector version : " + $ScriptVersion) | Add-Content $Report ("Generated : " + (Get-Date)) | Add-Content $Report ("Computer name : " + $env:COMPUTERNAME) | Add-Content $Report # ==================================================================== # SYSTEM IDENTITY # ==================================================================== try { $ComputerSystem = Get-CimInstance Win32_ComputerSystem $ComputerProduct = Get-CimInstance Win32_ComputerSystemProduct $BIOS = Get-CimInstance Win32_BIOS $BaseBoard = Get-CimInstance Win32_BaseBoard Add-Section "SYSTEM IDENTITY" ([PSCustomObject]@{ Manufacturer = $ComputerSystem.Manufacturer Model = $ComputerSystem.Model SystemFamily = $ComputerSystem.SystemFamily SystemSKU = $ComputerSystem.SystemSKUNumber SerialNumber = $BIOS.SerialNumber UUID = $ComputerProduct.UUID }) Add-Section "SYSTEM BOARD" ([PSCustomObject]@{ Manufacturer = $BaseBoard.Manufacturer Product = $BaseBoard.Product Version = $BaseBoard.Version SerialNumber = $BaseBoard.SerialNumber }) } catch { Add-Section "SYSTEM IDENTITY" ( "Unable to collect complete system identity information. Error: " + $_.Exception.Message ) } # ==================================================================== # OPERATING SYSTEM # ==================================================================== try { $OS = Get-CimInstance Win32_OperatingSystem Add-Section "OPERATING SYSTEM" ([PSCustomObject]@{ Edition = $OS.Caption Version = $OS.Version BuildNumber = $OS.BuildNumber Architecture = $OS.OSArchitecture InstallDate = $OS.InstallDate LastBoot = $OS.LastBootUpTime }) } catch { Add-Section "OPERATING SYSTEM" ( "Unable to query operating system information. Error: " + $_.Exception.Message ) } # ==================================================================== # WINDOWS ACTIVATION # # Reports activation state only. # Does NOT retrieve or display the Windows product key. # ==================================================================== try { $WindowsApplicationId = "55c92734-d682-4d71-983e-d6ec3f16059f" $WindowsLicenses = @( Get-CimInstance ` -ClassName SoftwareLicensingProduct ` -ErrorAction Stop | Where-Object { $_.ApplicationID -eq $WindowsApplicationId -and $_.PartialProductKey } ) if ($WindowsLicenses.Count -gt 0) { $ActivationInfo = $WindowsLicenses | ForEach-Object { [PSCustomObject]@{ Name = Clean-Text $_.Name Description = Clean-Text $_.Description ActivationStatus = Convert-WindowsLicenseStatus $_.LicenseStatus LicenseStatusCode = $_.LicenseStatus GracePeriodMinutes = $_.GracePeriodRemaining } } Add-Section "WINDOWS ACTIVATION" $ActivationInfo } else { Add-Section "WINDOWS ACTIVATION" ( "No installed Windows licensing record with an associated product key " + "was returned. Activation state could not be determined by this query." ) } } catch { Add-Section "WINDOWS ACTIVATION" ( "Unable to query Windows activation status. Error: " + $_.Exception.Message ) } # ==================================================================== # CPU # ==================================================================== try { $CPU = Get-CimInstance Win32_Processor | Select-Object Name, Manufacturer, NumberOfCores, NumberOfLogicalProcessors, MaxClockSpeed Add-Section "CPU" $CPU } catch { Add-Section "CPU" ( "Unable to query processor information. Error: " + $_.Exception.Message ) } # ==================================================================== # MEMORY # # Reports installed memory devices only. # # Deliberately DOES NOT infer: # - maximum supported RAM, # - number of physical upgrade sockets, # - soldered versus socketed memory, # - supported future configurations. # # Those conclusions should be made from manufacturer documentation # after the exact host has been identified. # ==================================================================== try { $RAMRaw = @(Get-CimInstance Win32_PhysicalMemory) $RAM = $RAMRaw | ForEach-Object { [PSCustomObject]@{ DeviceLocator = $_.DeviceLocator BankLabel = $_.BankLabel CapacityGB = [math]::Round($_.Capacity / 1GB, 0) SpeedMHz = $_.Speed ConfiguredSpeedMHz = $_.ConfiguredClockSpeed Manufacturer = Clean-Text $_.Manufacturer PartNumber = Clean-Text $_.PartNumber SerialNumber = Clean-Text $_.SerialNumber } } $TotalRAMBytes = ( $RAMRaw | Measure-Object -Property Capacity -Sum ).Sum if ($TotalRAMBytes) { $TotalRAMGB = [math]::Round($TotalRAMBytes / 1GB, 0) } else { $TotalRAMGB = 0 } Add-Section "INSTALLED MEMORY DEVICES" $RAM Add-Section "MEMORY SUMMARY" ([PSCustomObject]@{ MemoryDevicesDetected = @($RAM).Count TotalInstalledRAM_GB = $TotalRAMGB Note = "Determine physical slots and maximum supported RAM from manufacturer documentation." }) } catch { Add-Section "MEMORY" ( "Unable to query installed memory. Error: " + $_.Exception.Message ) } # ==================================================================== # STORAGE # # Uses the modern Windows storage interface where available. # # Windows may expose true hardware alongside file-backed or other # virtual storage objects. These are retained rather than silently # discarded, but explicitly classified. # ==================================================================== try { $PhysicalDisksRaw = @( Get-PhysicalDisk -ErrorAction Stop ) $StorageDevices = $PhysicalDisksRaw | ForEach-Object { $BusTypeText = Clean-Text $_.BusType $DeviceClass = if ( $BusTypeText -match "Virtual" ) { "Virtual" } else { "Hardware" } [PSCustomObject]@{ DeviceClass = $DeviceClass FriendlyName = Clean-Text $_.FriendlyName SerialNumber = Clean-Text $_.SerialNumber MediaType = Clean-Text $_.MediaType BusType = $BusTypeText HealthStatus = Clean-Text $_.HealthStatus OperationalStatus = ( Clean-Text ($_.OperationalStatus -join ", ") ) CapacityGB = [math]::Round($_.Size / 1GB, 0) } } Add-Section "STORAGE DEVICES REPORTED BY WINDOWS" $StorageDevices } catch { Add-Section "STORAGE DEVICES REPORTED BY WINDOWS" ( "Unable to obtain modern storage-device information. Error: " + $_.Exception.Message ) } # ==================================================================== # GRAPHICS # ==================================================================== try { $GPU = Get-CimInstance Win32_VideoController | Select-Object Name, DriverVersion, DriverDate, VideoProcessor Add-Section "GRAPHICS" $GPU } catch { Add-Section "GRAPHICS" ( "Unable to query graphics hardware. Error: " + $_.Exception.Message ) } # ==================================================================== # BIOS / UEFI # ==================================================================== try { if (-not $BIOS) { $BIOS = Get-CimInstance Win32_BIOS } Add-Section "BIOS / UEFI" ([PSCustomObject]@{ Manufacturer = $BIOS.Manufacturer Version = $BIOS.SMBIOSBIOSVersion ReleaseDate = $BIOS.ReleaseDate SMBIOS = ( $BIOS.SMBIOSMajorVersion.ToString() + "." + $BIOS.SMBIOSMinorVersion.ToString() ) }) } catch { Add-Section "BIOS / UEFI" ( "Unable to query BIOS/UEFI information. Error: " + $_.Exception.Message ) } # ==================================================================== # TPM # ==================================================================== try { $TPM = Get-Tpm -ErrorAction Stop try { $TPMCim = Get-CimInstance ` -Namespace "root\CIMV2\Security\MicrosoftTpm" ` -ClassName Win32_Tpm ` -ErrorAction Stop } catch { $TPMCim = $null } Add-Section "TPM" ([PSCustomObject]@{ Present = $TPM.TpmPresent Ready = $TPM.TpmReady Enabled = $TPM.TpmEnabled Activated = $TPM.TpmActivated SpecVersion = if ($TPMCim) { Clean-Text $TPMCim.SpecVersion } else { "Not reported" } Manufacturer = if ($TPMCim) { Clean-Text $TPMCim.ManufacturerIdTxt } else { Clean-Text $TPM.ManufacturerIdTxt } ManufacturerVersion = if ($TPMCim) { Clean-Text $TPMCim.ManufacturerVersion } else { Clean-Text $TPM.ManufacturerVersion } }) } catch { Add-Section "TPM" ( "TPM information unavailable. Error: " + $_.Exception.Message ) } # ==================================================================== # SECURE BOOT # # A successful False result means Secure Boot is supported in the # current UEFI environment but is presently disabled. # # A failed query is reported as UNKNOWN rather than guessed. # ==================================================================== try { $SecureBootEnabled = Confirm-SecureBootUEFI -ErrorAction Stop Add-Section "SECURE BOOT" ([PSCustomObject]@{ QuerySucceeded = $true Supported = $true Enabled = $SecureBootEnabled }) } catch { Add-Section "SECURE BOOT" ([PSCustomObject]@{ QuerySucceeded = $false Supported = "Unknown" Enabled = "Unknown" Note = $_.Exception.Message }) } # ==================================================================== # NETWORK HARDWARE # ==================================================================== try { $Network = Get-NetAdapter -Physical -ErrorAction Stop | Select-Object Name, InterfaceDescription, Status, LinkSpeed, MacAddress Add-Section "PHYSICAL NETWORK ADAPTERS" $Network } catch { Add-Section "PHYSICAL NETWORK ADAPTERS" ( "Unable to query physical network adapters. Error: " + $_.Exception.Message ) } # ==================================================================== # BATTERY # # Battery support is optional. # # Microsoft powercfg is used instead of vendor-specific or WMI battery # capacity calls because it proved more portable during validation. # # On a desktop or other machine without a battery, failure to produce # useful battery information is not treated as a device fault. # ==================================================================== $BatteryIncluded = $false try { powercfg /batteryreport /output "$BatteryReport" | Out-Null if (Test-Path $BatteryReport) { $BatteryIncluded = $true Add-Section "BATTERY REPORT" ([PSCustomObject]@{ Status = "Battery report created" File = "battery-report.html" Note = "Review design capacity, full-charge capacity, cycle count, and capacity history where available." }) } else { Add-Section "BATTERY REPORT" ( "No battery report was produced. This may be normal for a device without a battery." ) } } catch { Add-Section "BATTERY REPORT" ( "Battery report unavailable. This may be normal for a device " + "without a battery. Error: " + $_.Exception.Message ) } # ==================================================================== # BITLOCKER / DEVICE ENCRYPTION # # Reports status only. # # Recovery passwords and recovery keys are NOT retrieved. # ==================================================================== try { $BitLocker = Get-BitLockerVolume -ErrorAction Stop | Select-Object MountPoint, VolumeType, ProtectionStatus, EncryptionMethod, VolumeStatus, EncryptionPercentage Add-Section "BITLOCKER / DEVICE ENCRYPTION" $BitLocker } catch { Add-Section "BITLOCKER / DEVICE ENCRYPTION" ( "Unable to query BitLocker/device-encryption status. Error: " + $_.Exception.Message ) } # ==================================================================== # PRESENT DEVICE PROBLEMS # # PresentOnly prevents disconnected, historical, or obsolete devices # from creating irrelevant warnings. # ==================================================================== try { $Problems = Get-PnpDevice ` -PresentOnly ` -ErrorAction Stop | Where-Object { $_.Status -ne "OK" } | Select-Object Class, FriendlyName, Status, InstanceId if ($Problems) { Add-Section "PRESENT DEVICE PROBLEMS" $Problems } else { Add-Section "PRESENT DEVICE PROBLEMS" ( "No currently present Plug-and-Play devices with non-OK status were found." ) } } catch { Add-Section "PRESENT DEVICE PROBLEMS" ( "Unable to query Plug-and-Play devices. Error: " + $_.Exception.Message ) } # ==================================================================== # END REPORT # ==================================================================== Add-Content -Path $Report -Value "" Add-Content -Path $Report -Value ("=" * 70) Add-Content -Path $Report -Value "END OF DEVICE BASELINE" Add-Content -Path $Report -Value ("Collector version: " + $ScriptVersion) Add-Content -Path $Report -Value ("Finished: " + (Get-Date)) Add-Content -Path $Report -Value ("=" * 70) # ==================================================================== # PACKAGE RESULTS # # Successful completion leaves one ZIP on the Desktop. # # The temporary working directory is removed only after the ZIP has # been successfully created. # ==================================================================== $FilesToPackage = @($Report) if ($BatteryIncluded -and (Test-Path $BatteryReport)) { $FilesToPackage += $BatteryReport } try { Compress-Archive ` -Path $FilesToPackage ` -DestinationPath $ZipFile ` -Force ` -ErrorAction Stop if (-not (Test-Path $ZipFile)) { throw "ZIP archive was not created." } Remove-Item ` -Path $WorkDir ` -Recurse ` -Force ` -ErrorAction SilentlyContinue Write-Host "" Write-Host "============================================================" Write-Host "" Write-Host " DONE" Write-Host "" Write-Host " No system settings were changed." Write-Host "" Write-Host " Send this file to TEKWITCH:" Write-Host "" Write-Host " $ZipFile" Write-Host "" Write-Host "============================================================" Write-Host "" } catch { Write-Host "" Write-Host "============================================================" Write-Host "" Write-Host " Inspection completed, but packaging failed." Write-Host "" Write-Host " No system settings were changed." Write-Host "" Write-Host " Send this folder to TEKWITCH:" Write-Host "" Write-Host " $WorkDir" Write-Host "" Write-Host " Packaging error:" Write-Host " $($_.Exception.Message)" Write-Host "" Write-Host "============================================================" Write-Host "" } <# +====================================================================+ | LICENSE | +====================================================================+ Publisher stated in this artifact: TEKWITCH.com Licensing terms: https://tekwitch.com/terms/toy-use/1.0/ # The Prosperity Public License 3.0.0 Contributor: TEKWITCH Source Code: https://tekwitch.com/toys/ ## Purpose This license allows you to use and share this software for noncommercial purposes for free and to try this software for commercial purposes for thirty days. ## Agreement In order to receive this license, you have to agree to its rules. Those rules are both obligations under that agreement and conditions to your license. Don't do anything with this software that triggers a rule you can't or won't follow. ## Notices Make sure everyone who gets a copy of any part of this software from you, with or without changes, also gets the text of this license and the contributor and source code lines above. ## Commercial Trial Limit your use of this software for commercial purposes to a thirty-day trial period. If you use this software for work, your company gets one trial period for all personnel, not one trial per person. ## Contributions Back Developing feedback, changes, or additions that you contribute back to the contributor on the terms of a standardized public software license such as [the Blue Oak Model License 1.0.0](https://blueoakcouncil.org/license/1.0.0), [the Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0.html), [the MIT license](https://spdx.org/licenses/MIT.html), or [the two-clause BSD license](https://spdx.org/licenses/BSD-2-Clause.html) doesn't count as use for a commercial purpose. ## Personal Uses Personal use for research, experiment, and testing for the benefit of public knowledge, personal study, private entertainment, hobby projects, amateur pursuits, or religious observance, without any anticipated commercial application, doesn't count as use for a commercial purpose. ## Noncommercial Organizations Use by any charitable organization, educational institution, public research organization, public safety or health organization, environmental protection organization, or government institution doesn't count as use for a commercial purpose regardless of the source of funding or obligations resulting from the funding. ## Defense Don't make any legal claim against anyone accusing this software, with or without changes, alone or with other technology, of infringing any patent. ## Copyright The contributor licenses you to do everything with this software that would otherwise infringe their copyright in it. ## Patent The contributor licenses you to do everything with this software that would otherwise infringe any patents they can license or become able to license. ## Reliability The contributor can't revoke this license. ## Excuse You're excused for unknowingly breaking [Notices](#notices) if you take all practical steps to comply within thirty days of learning you broke the rule. ## No Liability ***As far as the law allows, this software comes as is, without any warranty or condition, and the contributor won't be liable to anyone for any damages related to this software or this license, under any kind of legal claim.*** ### TEKWITCH No-charge Toy Use Permission 1.0 Standing terms: https://tekwitch.com/terms/toy-use/1.0/ This no-charge grant supplements the Prosperity Public License above. Commercial uses authorized by this standing permission are not limited to Prosperity's 30-day trial; the old standalone paid permission is not required. Earlier purchased grants remain valid. ## Who this applies to Any natural person or legal entity may use a covered TEKWITCH Toy for personal, educational, organizational, and commercial work without payment, individual approval, registration, or activation. ## Covered Toys and releases This standing permission covers Device Baseline Collector, Revision Drift Auditor, Parallax, and LLM System Capability Review under their stable TEKWITCH Toy identities. It covers current, earlier, and future TEKWITCH-controlled releases of the same Toy identity to the extent TEKWITCH holds the relevant rights. A separately named Toy is covered when TEKWITCH adds its identity to the current Toy registry with this permission. This grant does not apply to Bander. ## What you may do Use a covered Toy in your own work, including paid client work; copy, install, operate, and modify it within your own environment; use it with people, devices and AI systems within your organization; and commercially publish, sell, or otherwise use your own outputs created with it. ## What you may not do under this permission This permission does not authorize redistributing or selling the Toy itself or a modified version, sublicensing or transferring the Toy to others, including it in a product distributed to third parties, offering Toy functionality as a customer-facing hosted service, or embedding it in an OEM/commercial service for third parties. Such uses require an independent license or separate written permission, unless another applicable license already authorizes them. ## Integration and custom work Ordinary integration within your own organization is free. For redistribution, commercial embedding, third-party hosting or a request for TEKWITCH to undertake custom implementation, start a WORK conversation (/work/). An inquiry itself grants no additional rights or service commitment. ## Availability, warranties, and support Toys are supplied as available, without any promise of support, future updates, compatibility, uptime, fitness, or maintenance. To the fullest extent permitted by applicable law, TEKWITCH disclaims express and implied warranties and liability for indirect or consequential loss. Rights that cannot legally be disclaimed are unaffected. ## Relationship to previous releases This standing permission supplements the public license included with a covered Toy. Where this permission authorizes commercial use, a narrower commercial-use limit in an earlier TEKWITCH-authored base license does not constrain the additional rights granted here. Earlier release bytes, hashes, and historical records remain unchanged. Other applicable rights remain intact. ## Delegated project exception Bander follows the Bander project licensing scheme (https://github.com/tek-witch/bander/blob/main/docs/BANDER_LICENSING_SCHEME.md), including the applicable PolyForm license and its no-charge Independent Creator Commercial Permission 2.0 (/terms/independent-creator-commercial-use/2.0/). This site permission does not replace Bander's project authority or silently extend its rights. ## Third-party components and rights TEKWITCH grants only rights it controls. Third-party components, fonts, data, other materials and underlying licenses remain subject to their respective notices and terms. No TEKWITCH trademark rights are granted. ## Version TEKWITCH No-charge Toy Use Permission 1.0, effective October 9, 2026. Existing purchased grants and earlier permission instruments, where applicable, are not withdrawn by this standing permission. +====================================================================+ #>