Structure: - asset-collection/: Local PC data collection scripts - remote-execution/: WinRM remote execution scripts - setup-utilities/: Configuration and testing utilities - registry-backup/: GE registry backup scripts - winrm-https/: WinRM HTTPS certificate setup - docs/: Complete documentation Each folder includes a README with detailed documentation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1431 lines
62 KiB
PowerShell
1431 lines
62 KiB
PowerShell
# Admin not required for data collection - WinRM setup will be skipped if not admin
|
|
<#
|
|
.SYNOPSIS
|
|
Complete PC asset collection and database update via hybrid proxy/dashboard architecture.
|
|
|
|
.DESCRIPTION
|
|
This script performs comprehensive PC asset management:
|
|
1. Collects system information (hostname, serial, manufacturer, user, etc.)
|
|
2. Determines PC type (Engineer/Shopfloor/Standard)
|
|
3. For shopfloor PCs: Collects machine assignment and network/comm configurations
|
|
4. Gets Dell warranty information via proxy server (bypasses network restrictions)
|
|
5. Stores all collected data in database via dashboard API
|
|
|
|
.NOTES
|
|
Author: System Administrator
|
|
Date: 2025
|
|
Version: 1.0
|
|
Architecture: PowerShell -> Proxy (warranty) -> Dashboard API (storage)
|
|
#>
|
|
|
|
param(
|
|
[Parameter(Mandatory=$false)]
|
|
[string]$ProxyURL = "http://10.48.130.158/vendor-api-proxy.php",
|
|
|
|
[Parameter(Mandatory=$false)]
|
|
[string]$DashboardURL = "https://tsgwp00525.rd.ds.ge.com/shopdb/api.asp",
|
|
|
|
[Parameter(Mandatory=$false)]
|
|
[switch]$SkipWarranty = $true, # DEFAULT TO TRUE - Skip warranty lookups
|
|
|
|
[Parameter(Mandatory=$false)]
|
|
[switch]$TestConnections = $false
|
|
)
|
|
|
|
# =============================================================================
|
|
# SSL/TLS Certificate Bypass for HTTPS connections
|
|
# =============================================================================
|
|
# This allows connections to servers with self-signed or untrusted certificates
|
|
try {
|
|
# For PowerShell 5.x - use .NET callback
|
|
if (-not ([System.Management.Automation.PSTypeName]'TrustAllCertsPolicy').Type) {
|
|
Add-Type @"
|
|
using System.Net;
|
|
using System.Security.Cryptography.X509Certificates;
|
|
public class TrustAllCertsPolicy : ICertificatePolicy {
|
|
public bool CheckValidationResult(
|
|
ServicePoint srvPoint, X509Certificate certificate,
|
|
WebRequest request, int certificateProblem) {
|
|
return true;
|
|
}
|
|
}
|
|
"@
|
|
}
|
|
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
|
|
} catch {
|
|
# Silently continue if already set
|
|
}
|
|
|
|
# Set TLS 1.2 as minimum (required for modern HTTPS)
|
|
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
|
|
|
# Import shopfloor configuration functions
|
|
. "$PSScriptRoot\Get-ShopfloorConfig.ps1"
|
|
|
|
# Setup logging
|
|
$script:LogFile = "$PSScriptRoot\logs\Update-PC-CompleteAsset-$(Get-Date -Format 'yyyy-MM-dd').log"
|
|
$script:LogDir = "$PSScriptRoot\logs"
|
|
|
|
function Write-Log {
|
|
param(
|
|
[string]$Message,
|
|
[string]$Level = "INFO",
|
|
[string]$ForegroundColor = "White"
|
|
)
|
|
|
|
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
|
$logMessage = "[$timestamp] [$Level] $Message"
|
|
|
|
# Write to console
|
|
Write-Host $Message -ForegroundColor $ForegroundColor
|
|
|
|
# Write to log file
|
|
try {
|
|
if (-not (Test-Path $script:LogDir)) {
|
|
New-Item -ItemType Directory -Path $script:LogDir -Force | Out-Null
|
|
}
|
|
Add-Content -Path $script:LogFile -Value $logMessage -ErrorAction SilentlyContinue
|
|
} catch {
|
|
# Silently continue if logging fails
|
|
}
|
|
}
|
|
|
|
function Reset-WinRMConfiguration {
|
|
<#
|
|
.SYNOPSIS
|
|
Resets and configures WinRM for HTTP remote management
|
|
.DESCRIPTION
|
|
Removes existing WinRM listeners and configures fresh HTTP listener on port 5985
|
|
#>
|
|
|
|
Write-Log " Resetting WinRM configuration..." -Level "INFO" -ForegroundColor Yellow
|
|
|
|
try {
|
|
# First, check and fix network profile if set to Public
|
|
Write-Log " Checking network profile..." -Level "INFO" -ForegroundColor Gray
|
|
$profiles = Get-NetConnectionProfile
|
|
|
|
foreach ($profile in $profiles) {
|
|
Write-Log " Interface '$($profile.Name)': $($profile.NetworkCategory)" -Level "INFO" -ForegroundColor Gray
|
|
}
|
|
|
|
# Fix #1: Set machine network interfaces (192.168.x.x) to Private
|
|
# These shouldn't try to detect domain - they're for machine communication
|
|
Write-Log " Checking for machine network interfaces..." -Level "INFO" -ForegroundColor Gray
|
|
$adapters = Get-NetAdapter | Where-Object { $_.Status -eq 'Up' }
|
|
foreach ($adapter in $adapters) {
|
|
$ipConfig = Get-NetIPAddress -InterfaceIndex $adapter.ifIndex -AddressFamily IPv4 -ErrorAction SilentlyContinue
|
|
if ($ipConfig.IPAddress -match '^192\.168\.') {
|
|
Write-Log " Found machine network: $($adapter.Name) ($($ipConfig.IPAddress))" -Level "INFO" -ForegroundColor Cyan
|
|
$profile = Get-NetConnectionProfile -InterfaceIndex $adapter.ifIndex -ErrorAction SilentlyContinue
|
|
if ($profile -and $profile.NetworkCategory -ne 'Private') {
|
|
Write-Log " Setting machine network '$($adapter.Name)' to Private..." -Level "INFO" -ForegroundColor Gray
|
|
Set-NetConnectionProfile -InterfaceIndex $adapter.ifIndex -NetworkCategory Private -ErrorAction SilentlyContinue
|
|
Write-Log " [OK] Machine network set to Private" -Level "SUCCESS" -ForegroundColor Green
|
|
}
|
|
}
|
|
}
|
|
|
|
# Fix #5: Check and repair machine account trust relationship
|
|
Write-Log " Checking domain trust relationship..." -Level "INFO" -ForegroundColor Gray
|
|
$secureChannel = Test-ComputerSecureChannel -ErrorAction SilentlyContinue
|
|
if ($secureChannel) {
|
|
Write-Log " [OK] Domain trust relationship is healthy" -Level "SUCCESS" -ForegroundColor Green
|
|
} else {
|
|
Write-Log " [WARN] Domain trust may be broken, attempting repair..." -Level "WARN" -ForegroundColor Yellow
|
|
try {
|
|
# This requires domain admin creds or machine account to still be somewhat valid
|
|
$repairResult = Test-ComputerSecureChannel -Repair -ErrorAction SilentlyContinue
|
|
if ($repairResult) {
|
|
Write-Log " [OK] Domain trust repaired successfully" -Level "SUCCESS" -ForegroundColor Green
|
|
} else {
|
|
Write-Log " [WARN] Could not auto-repair trust - may need manual rejoin to domain" -Level "WARN" -ForegroundColor Yellow
|
|
}
|
|
} catch {
|
|
Write-Log " [WARN] Trust repair failed: $($_.Exception.Message)" -Level "WARN" -ForegroundColor Yellow
|
|
}
|
|
}
|
|
|
|
# Now handle remaining Public profiles on corporate network
|
|
$publicProfiles = Get-NetConnectionProfile | Where-Object { $_.NetworkCategory -eq 'Public' }
|
|
|
|
if ($publicProfiles) {
|
|
Write-Log " Found Public network profile(s), attempting to fix..." -Level "INFO" -ForegroundColor Yellow
|
|
|
|
# Restart NLA service to re-detect domain
|
|
Write-Log " Restarting NLA service to detect domain..." -Level "INFO" -ForegroundColor Gray
|
|
Restart-Service NlaSvc -Force -ErrorAction SilentlyContinue
|
|
Start-Sleep -Seconds 5
|
|
|
|
# Re-check profiles after NLA restart
|
|
$publicProfiles = Get-NetConnectionProfile | Where-Object { $_.NetworkCategory -eq 'Public' }
|
|
|
|
foreach ($profile in $publicProfiles) {
|
|
# Check if this is a corporate network (not 192.168.x.x)
|
|
$adapter = Get-NetAdapter -InterfaceIndex $profile.InterfaceIndex -ErrorAction SilentlyContinue
|
|
$ipConfig = Get-NetIPAddress -InterfaceIndex $profile.InterfaceIndex -AddressFamily IPv4 -ErrorAction SilentlyContinue
|
|
|
|
if ($ipConfig.IPAddress -notmatch '^192\.168\.') {
|
|
Write-Log " Corporate interface '$($profile.Name)' still Public after NLA restart" -Level "WARN" -ForegroundColor Yellow
|
|
}
|
|
|
|
# Set to Private as fallback (can't manually set Domain)
|
|
Write-Log " Setting '$($profile.Name)' to Private..." -Level "INFO" -ForegroundColor Gray
|
|
Set-NetConnectionProfile -InterfaceIndex $profile.InterfaceIndex -NetworkCategory Private -ErrorAction SilentlyContinue
|
|
Write-Log " [OK] '$($profile.Name)' set to Private" -Level "SUCCESS" -ForegroundColor Green
|
|
}
|
|
} else {
|
|
Write-Log " [OK] All network profiles are Private/Domain" -Level "SUCCESS" -ForegroundColor Green
|
|
}
|
|
|
|
# Stop WinRM service first
|
|
Write-Log " Stopping WinRM service..." -Level "INFO" -ForegroundColor Gray
|
|
Stop-Service WinRM -Force -ErrorAction SilentlyContinue
|
|
Start-Sleep -Seconds 2
|
|
Write-Log " WinRM service stopped" -Level "INFO" -ForegroundColor Gray
|
|
|
|
# Delete all existing listeners
|
|
Write-Log " Removing existing WinRM listeners..." -Level "INFO" -ForegroundColor Gray
|
|
Remove-Item -Path WSMan:\localhost\Listener\* -Recurse -Force -ErrorAction SilentlyContinue
|
|
Write-Log " Existing listeners removed" -Level "INFO" -ForegroundColor Gray
|
|
|
|
# Start WinRM service
|
|
Write-Log " Starting WinRM service..." -Level "INFO" -ForegroundColor Gray
|
|
Start-Service WinRM -ErrorAction Stop
|
|
Set-Service WinRM -StartupType Automatic
|
|
Write-Log " WinRM service started and set to Automatic" -Level "INFO" -ForegroundColor Gray
|
|
|
|
# Run quick config to set defaults
|
|
Write-Log " Running WinRM quickconfig..." -Level "INFO" -ForegroundColor Gray
|
|
$quickConfigResult = winrm quickconfig -quiet 2>&1
|
|
Write-Log " WinRM quickconfig completed" -Level "INFO" -ForegroundColor Gray
|
|
|
|
# Create HTTP listener on all addresses
|
|
Write-Log " Creating HTTP listener on port 5985..." -Level "INFO" -ForegroundColor Gray
|
|
$existingHttp = Get-ChildItem WSMan:\localhost\Listener -ErrorAction SilentlyContinue |
|
|
Where-Object { $_.Keys -contains "Transport=HTTP" }
|
|
|
|
if (-not $existingHttp) {
|
|
New-Item -Path WSMan:\localhost\Listener -Transport HTTP -Address * -Force | Out-Null
|
|
Write-Log " HTTP listener created" -Level "INFO" -ForegroundColor Gray
|
|
} else {
|
|
Write-Log " HTTP listener already exists" -Level "INFO" -ForegroundColor Gray
|
|
}
|
|
|
|
# Configure WinRM settings
|
|
Write-Log " Configuring WinRM authentication settings..." -Level "INFO" -ForegroundColor Gray
|
|
Set-Item WSMan:\localhost\Service\Auth\Basic -Value $false
|
|
Set-Item WSMan:\localhost\Service\Auth\Negotiate -Value $true
|
|
Set-Item WSMan:\localhost\Service\Auth\Kerberos -Value $true
|
|
Set-Item WSMan:\localhost\Service\Auth\CredSSP -Value $false
|
|
Set-Item WSMan:\localhost\Service\AllowUnencrypted -Value $false
|
|
Write-Log " Auth: Basic=false, Negotiate=true, Kerberos=true, CredSSP=false" -Level "INFO" -ForegroundColor Gray
|
|
|
|
# Set MaxMemoryPerShellMB for better performance
|
|
Set-Item WSMan:\localhost\Shell\MaxMemoryPerShellMB -Value 1024 -ErrorAction SilentlyContinue
|
|
Write-Log " MaxMemoryPerShellMB set to 1024" -Level "INFO" -ForegroundColor Gray
|
|
|
|
# Enable LocalAccountTokenFilterPolicy for remote admin access
|
|
Write-Log " Enabling LocalAccountTokenFilterPolicy..." -Level "INFO" -ForegroundColor Gray
|
|
$regPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"
|
|
Set-ItemProperty -Path $regPath -Name "LocalAccountTokenFilterPolicy" -Value 1 -Type DWord -Force -ErrorAction SilentlyContinue
|
|
Write-Log " LocalAccountTokenFilterPolicy enabled" -Level "INFO" -ForegroundColor Gray
|
|
|
|
# Grant WinRM access to Remote Management Users and Administrators
|
|
Write-Log " Configuring WinRM security descriptor..." -Level "INFO" -ForegroundColor Gray
|
|
try {
|
|
# Get current SDDL
|
|
$sddl = (Get-Item WSMan:\localhost\Service\RootSDDL).Value
|
|
Write-Log " Current SDDL: $sddl" -Level "INFO" -ForegroundColor Gray
|
|
|
|
# Enable PSRemoting to set proper permissions
|
|
Enable-PSRemoting -Force -SkipNetworkProfileCheck 2>&1 | Out-Null
|
|
Write-Log " PSRemoting enabled" -Level "INFO" -ForegroundColor Gray
|
|
} catch {
|
|
Write-Log " Note: Could not update SDDL directly, using Enable-PSRemoting" -Level "INFO" -ForegroundColor Gray
|
|
}
|
|
|
|
# Restart WinRM to apply all changes
|
|
Write-Log " Restarting WinRM service to apply changes..." -Level "INFO" -ForegroundColor Gray
|
|
Restart-Service WinRM -Force
|
|
Start-Sleep -Seconds 2
|
|
Write-Log " WinRM service restarted" -Level "INFO" -ForegroundColor Gray
|
|
|
|
# Configure firewall rule
|
|
Write-Log " Configuring firewall rule..." -Level "INFO" -ForegroundColor Gray
|
|
$ruleName = "Windows Remote Management (HTTP-In)"
|
|
$existingRule = Get-NetFirewallRule -DisplayName $ruleName -ErrorAction SilentlyContinue
|
|
|
|
if (-not $existingRule) {
|
|
New-NetFirewallRule -DisplayName $ruleName `
|
|
-Name "WINRM-HTTP-In-TCP" `
|
|
-Profile Domain,Private `
|
|
-LocalPort 5985 `
|
|
-Protocol TCP `
|
|
-Direction Inbound `
|
|
-Action Allow `
|
|
-Enabled True | Out-Null
|
|
Write-Log " Firewall rule '$ruleName' created" -Level "INFO" -ForegroundColor Gray
|
|
} else {
|
|
Enable-NetFirewallRule -DisplayName $ruleName -ErrorAction SilentlyContinue
|
|
Write-Log " Firewall rule '$ruleName' enabled" -Level "INFO" -ForegroundColor Gray
|
|
}
|
|
|
|
# Verify listener is working
|
|
Write-Log " Verifying WinRM listener..." -Level "INFO" -ForegroundColor Gray
|
|
$listeners = winrm enumerate winrm/config/listener 2>&1
|
|
|
|
if ($listeners -match "Transport = HTTP" -and $listeners -match "Port = 5985") {
|
|
Write-Log " [OK] WinRM HTTP listener configured on port 5985" -Level "SUCCESS" -ForegroundColor Green
|
|
|
|
# Show listener details
|
|
$portCheck = netstat -an | Select-String ":5985.*LISTENING"
|
|
if ($portCheck) {
|
|
Write-Log " [OK] Port 5985 is listening" -Level "SUCCESS" -ForegroundColor Green
|
|
}
|
|
|
|
return $true
|
|
} else {
|
|
Write-Log " [WARN] WinRM listener may not be configured correctly" -Level "WARN" -ForegroundColor Yellow
|
|
return $false
|
|
}
|
|
}
|
|
catch {
|
|
Write-Log " [FAIL] Error configuring WinRM: $($_.Exception.Message)" -Level "ERROR" -ForegroundColor Red
|
|
return $false
|
|
}
|
|
}
|
|
|
|
function Add-WinRMAdminGroup {
|
|
<#
|
|
.SYNOPSIS
|
|
Adds the WinRM management security group to local Administrators and Remote Management Users
|
|
.DESCRIPTION
|
|
Adds logon\g03078610 to both local Administrators and Remote Management Users groups
|
|
to enable WinRM remote management
|
|
#>
|
|
param(
|
|
[string]$GroupToAdd = "logon\g03078610"
|
|
)
|
|
|
|
Write-Log " Configuring WinRM access groups..." -Level "INFO" -ForegroundColor Yellow
|
|
Write-Log " Target group: $GroupToAdd" -Level "INFO" -ForegroundColor Gray
|
|
|
|
$overallSuccess = $true
|
|
|
|
# Add to Administrators group
|
|
try {
|
|
Write-Log " Checking local Administrators group..." -Level "INFO" -ForegroundColor Gray
|
|
$adminGroup = [ADSI]"WinNT://./Administrators,group"
|
|
$members = @($adminGroup.Invoke("Members")) | ForEach-Object {
|
|
$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)
|
|
}
|
|
|
|
Write-Log " Current Administrators members: $($members -join ', ')" -Level "INFO" -ForegroundColor Gray
|
|
|
|
$groupName = $GroupToAdd.Split('\')[-1]
|
|
|
|
if ($members -contains $groupName) {
|
|
Write-Log " [OK] $GroupToAdd is already in Administrators" -Level "SUCCESS" -ForegroundColor Green
|
|
} else {
|
|
Write-Log " Adding $GroupToAdd to Administrators..." -Level "INFO" -ForegroundColor Yellow
|
|
$result = net localgroup Administrators $GroupToAdd /add 2>&1
|
|
|
|
if ($LASTEXITCODE -eq 0 -or $result -match "already a member") {
|
|
Write-Log " [OK] Added $GroupToAdd to Administrators" -Level "SUCCESS" -ForegroundColor Green
|
|
} else {
|
|
Write-Log " [FAIL] Failed to add to Administrators: $result" -Level "ERROR" -ForegroundColor Red
|
|
$overallSuccess = $false
|
|
}
|
|
}
|
|
}
|
|
catch {
|
|
Write-Log " [FAIL] Error with Administrators group: $($_.Exception.Message)" -Level "ERROR" -ForegroundColor Red
|
|
$overallSuccess = $false
|
|
}
|
|
|
|
# Add to Remote Management Users group
|
|
try {
|
|
Write-Log " Checking Remote Management Users group..." -Level "INFO" -ForegroundColor Gray
|
|
$rmGroup = [ADSI]"WinNT://./Remote Management Users,group"
|
|
$rmMembers = @($rmGroup.Invoke("Members")) | ForEach-Object {
|
|
$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)
|
|
}
|
|
|
|
Write-Log " Current Remote Management Users members: $($rmMembers -join ', ')" -Level "INFO" -ForegroundColor Gray
|
|
|
|
$groupName = $GroupToAdd.Split('\')[-1]
|
|
|
|
if ($rmMembers -contains $groupName) {
|
|
Write-Log " [OK] $GroupToAdd is already in Remote Management Users" -Level "SUCCESS" -ForegroundColor Green
|
|
} else {
|
|
Write-Log " Adding $GroupToAdd to Remote Management Users..." -Level "INFO" -ForegroundColor Yellow
|
|
$result = net localgroup "Remote Management Users" $GroupToAdd /add 2>&1
|
|
|
|
if ($LASTEXITCODE -eq 0 -or $result -match "already a member") {
|
|
Write-Log " [OK] Added $GroupToAdd to Remote Management Users" -Level "SUCCESS" -ForegroundColor Green
|
|
} else {
|
|
Write-Log " [FAIL] Failed to add to Remote Management Users: $result" -Level "ERROR" -ForegroundColor Red
|
|
$overallSuccess = $false
|
|
}
|
|
}
|
|
}
|
|
catch {
|
|
Write-Log " [FAIL] Error with Remote Management Users group: $($_.Exception.Message)" -Level "ERROR" -ForegroundColor Red
|
|
$overallSuccess = $false
|
|
}
|
|
|
|
return $overallSuccess
|
|
}
|
|
|
|
function Get-DashboardURL {
|
|
param([string]$ProvidedURL)
|
|
|
|
if (-not [string]::IsNullOrEmpty($ProvidedURL)) {
|
|
Write-Host " Using provided URL: $ProvidedURL" -ForegroundColor Gray
|
|
return $ProvidedURL
|
|
}
|
|
|
|
# Check environment variable
|
|
$envURL = [Environment]::GetEnvironmentVariable("ASSET_DASHBOARD_URL", "User")
|
|
if (-not [string]::IsNullOrEmpty($envURL)) {
|
|
Write-Host " Using environment variable URL: $envURL" -ForegroundColor Gray
|
|
return $envURL
|
|
}
|
|
|
|
# Check for config file
|
|
$configPath = "$PSScriptRoot\dashboard-config.json"
|
|
if (Test-Path $configPath) {
|
|
try {
|
|
$config = Get-Content $configPath | ConvertFrom-Json
|
|
if ($config.DashboardURL) {
|
|
return $config.DashboardURL
|
|
}
|
|
}
|
|
catch {
|
|
Write-Verbose "Could not read dashboard config file: $_"
|
|
}
|
|
}
|
|
|
|
# Auto-discovery with verbose logging
|
|
Write-Host " Starting dashboard URL auto-discovery..." -ForegroundColor Yellow
|
|
$candidates = @(
|
|
"https://tsgwp00525.rd.ds.ge.com/shopdb/api.asp",
|
|
"http://192.168.122.151:8080/api.asp",
|
|
"http://localhost:8080/api.asp",
|
|
"http://10.48.130.197/dashboard-v2/api.php",
|
|
"http://localhost/test/dashboard/api.php",
|
|
"http://127.0.0.1/test/dashboard/api.php",
|
|
"http://10.48.130.197/api.php",
|
|
"http://localhost/api.php",
|
|
"http://127.0.0.1/api.php"
|
|
)
|
|
|
|
foreach ($url in $candidates) {
|
|
try {
|
|
Write-Host " Testing: $url" -ForegroundColor Gray
|
|
$testResponse = Invoke-RestMethod -Uri "$url?action=getDashboardData" -Method Get -TimeoutSec 5 -ErrorAction Stop
|
|
if ($testResponse.success) {
|
|
Write-Host " [SUCCESS] Dashboard found at: $url" -ForegroundColor Green
|
|
return $url
|
|
} else {
|
|
Write-Host " [FAIL] Dashboard responded but not successful" -ForegroundColor Yellow
|
|
}
|
|
}
|
|
catch {
|
|
Write-Host " [FAIL] Cannot reach: $($_.Exception.Message)" -ForegroundColor Red
|
|
}
|
|
}
|
|
|
|
# If auto-discovery fails, default to the expected URL
|
|
$defaultUrl = "https://tsgwp00525.rd.ds.ge.com/shopdb/api.asp"
|
|
Write-Host " [FALLBACK] Using default URL: $defaultUrl" -ForegroundColor Yellow
|
|
return $defaultUrl
|
|
}
|
|
|
|
function Test-ProxyConnection {
|
|
param([string]$ProxyURL)
|
|
|
|
try {
|
|
Write-Host "Testing proxy connection..." -ForegroundColor Yellow
|
|
|
|
$uri = "$ProxyURL" + "?vendor=dell&action=test-config"
|
|
$response = Invoke-RestMethod -Uri $uri -Method Get -TimeoutSec 15
|
|
|
|
if ($response.success) {
|
|
Write-Host "[OK] Proxy server accessible and Dell API configured" -ForegroundColor Green
|
|
return $true
|
|
} else {
|
|
Write-Host "[FAIL] Proxy issue: $($response.error)" -ForegroundColor Red
|
|
return $false
|
|
}
|
|
}
|
|
catch {
|
|
Write-Host "[FAIL] Cannot reach proxy: $($_.Exception.Message)" -ForegroundColor Red
|
|
return $false
|
|
}
|
|
}
|
|
|
|
function Test-DashboardConnection {
|
|
param([string]$DashboardURL)
|
|
|
|
try {
|
|
Write-Host "Testing dashboard connection..." -ForegroundColor Yellow
|
|
|
|
$response = Invoke-RestMethod -Uri "$DashboardURL?action=getDashboardData" -Method Get -TimeoutSec 10
|
|
if ($response.success) {
|
|
Write-Host "[OK] Dashboard API accessible" -ForegroundColor Green
|
|
return $true
|
|
} else {
|
|
Write-Host "[FAIL] Dashboard not responding properly" -ForegroundColor Red
|
|
return $false
|
|
}
|
|
}
|
|
catch {
|
|
Write-Host "[FAIL] Cannot reach dashboard: $($_.Exception.Message)" -ForegroundColor Red
|
|
return $false
|
|
}
|
|
}
|
|
|
|
function Test-AppsFolder {
|
|
return Test-Path "C:\Apps"
|
|
}
|
|
|
|
function Test-VDriveAccess {
|
|
try {
|
|
$vDrive = Get-PSDrive -Name V -ErrorAction SilentlyContinue
|
|
if ($vDrive) {
|
|
$null = Get-ChildItem V:\ -ErrorAction Stop | Select-Object -First 1
|
|
return $true
|
|
}
|
|
return $false
|
|
}
|
|
catch {
|
|
return $false
|
|
}
|
|
}
|
|
|
|
function Test-WindowsLTSC {
|
|
try {
|
|
$os = Get-CimInstance -ClassName CIM_OperatingSystem
|
|
$osCaption = $os.Caption
|
|
|
|
if ($osCaption -match "LTSC|LTSB") {
|
|
return $true
|
|
}
|
|
|
|
$productName = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name ProductName -ErrorAction SilentlyContinue).ProductName
|
|
if ($productName -match "LTSC|LTSB") {
|
|
return $true
|
|
}
|
|
|
|
return $false
|
|
}
|
|
catch {
|
|
return $false
|
|
}
|
|
}
|
|
|
|
function Get-TrackedApplications {
|
|
try {
|
|
$csvPath = "$PSScriptRoot\applications.csv"
|
|
if (-not (Test-Path $csvPath)) {
|
|
Write-Warning "Applications CSV not found at $csvPath - using fallback patterns"
|
|
return @(
|
|
@{ app_name = "UDC"; search_patterns = "Universal Data Collection"; enabled = $true }
|
|
@{ app_name = "PPDCS"; search_patterns = "PPDCS"; enabled = $true }
|
|
@{ app_name = "Oracle"; search_patterns = "Oracle.*Database"; enabled = $true }
|
|
@{ app_name = "Tanium"; search_patterns = "Tanium"; enabled = $true }
|
|
@{ app_name = "eDNC"; search_patterns = "eDNC"; enabled = $true }
|
|
)
|
|
}
|
|
|
|
$trackedApps = @()
|
|
$csvContent = Import-Csv -Path $csvPath
|
|
|
|
foreach ($row in $csvContent) {
|
|
if ($row.enabled -eq "1") {
|
|
$trackedApps += @{
|
|
app_name = $row.app_name
|
|
app_id = $row.app_id
|
|
search_patterns = $row.search_patterns
|
|
description = $row.description
|
|
}
|
|
}
|
|
}
|
|
|
|
Write-Host " Loaded $($trackedApps.Count) enabled applications from CSV" -ForegroundColor Cyan
|
|
return $trackedApps
|
|
}
|
|
catch {
|
|
Write-Warning "Failed to read applications CSV: $($_.Exception.Message) - using fallback patterns"
|
|
return @(
|
|
@{ app_name = "UDC"; app_id = "2"; search_patterns = "Universal Data Collection"; enabled = $true }
|
|
@{ app_name = "PPDCS"; app_id = "4"; search_patterns = "PPDCS"; enabled = $true }
|
|
@{ app_name = "Oracle"; app_id = "7"; search_patterns = "Oracle.*Database"; enabled = $true }
|
|
@{ app_name = "Tanium"; app_id = "30"; search_patterns = "Tanium"; enabled = $true }
|
|
@{ app_name = "eDNC"; app_id = ""; search_patterns = "eDNC"; enabled = $true }
|
|
)
|
|
}
|
|
}
|
|
|
|
function Get-GEMachineNumber {
|
|
param([string]$Hostname)
|
|
|
|
# Check GE Aircraft Engines registry paths for MachineNo
|
|
$gePaths = @(
|
|
"HKLM:\Software\GE Aircraft Engines\DNC\General",
|
|
"HKLM:\Software\WOW6432Node\GE Aircraft Engines\DNC\General"
|
|
)
|
|
|
|
foreach ($gePath in $gePaths) {
|
|
if (Test-Path $gePath) {
|
|
try {
|
|
$machineNo = Get-ItemProperty -Path $gePath -Name "MachineNo" -ErrorAction Stop
|
|
if ($machineNo.MachineNo) {
|
|
return $machineNo.MachineNo
|
|
}
|
|
}
|
|
catch {
|
|
# Continue to next path
|
|
}
|
|
}
|
|
}
|
|
|
|
# Check if hostname indicates a specific GE machine
|
|
if ($Hostname -match '[HG](\d{3})') {
|
|
$machineNum = $Matches[1]
|
|
return "M$machineNum"
|
|
}
|
|
|
|
return $null
|
|
}
|
|
|
|
function Get-PCType {
|
|
param(
|
|
[bool]$HasAppsFolder,
|
|
[bool]$HasVDriveAccess
|
|
)
|
|
|
|
# Check if on logon.ds.ge.com domain (Shopfloor PCs)
|
|
try {
|
|
$domain = (Get-WmiObject Win32_ComputerSystem).Domain
|
|
Write-Host " Domain detected: $domain" -ForegroundColor Gray
|
|
if ($domain -eq "logon.ds.ge.com") {
|
|
Write-Host " [OK] Shopfloor domain detected" -ForegroundColor Green
|
|
|
|
# Check for specific machine type applications
|
|
$installedApps = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*",
|
|
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" -ErrorAction SilentlyContinue |
|
|
Where-Object { $_.DisplayName } |
|
|
Select-Object -ExpandProperty DisplayName
|
|
|
|
# ================================================================
|
|
# PC Type Detection based on installed software
|
|
# Priority: CMM > Wax Trace > Keyence > EAS1000 > Genspect > Heat Treat > Shopfloor
|
|
# ================================================================
|
|
|
|
# CMM Detection: PC-DMIS, goCMM, DODA
|
|
$hasPcDmis = $installedApps -match "PC-DMIS|PCDMIS"
|
|
$hasGoCMM = $installedApps -match "^goCMM"
|
|
$hasDODA = $installedApps -match "Dovetail Digital Analysis|DODA"
|
|
|
|
# Also check common PC-DMIS installation paths
|
|
if (-not $hasPcDmis) {
|
|
$pcDmisPaths = @(
|
|
"C:\Program Files\Hexagon\PC-DMIS*",
|
|
"C:\Program Files (x86)\Hexagon\PC-DMIS*",
|
|
"C:\Program Files\WAI\PC-DMIS*",
|
|
"C:\Program Files (x86)\WAI\PC-DMIS*",
|
|
"C:\ProgramData\Hexagon\PC-DMIS*"
|
|
)
|
|
foreach ($dmisPath in $pcDmisPaths) {
|
|
if (Test-Path $dmisPath) { $hasPcDmis = $true; break }
|
|
}
|
|
}
|
|
|
|
if ($hasPcDmis -or $hasGoCMM -or $hasDODA) {
|
|
$detected = @()
|
|
if ($hasPcDmis) { $detected += "PC-DMIS" }
|
|
if ($hasGoCMM) { $detected += "goCMM" }
|
|
if ($hasDODA) { $detected += "DODA" }
|
|
Write-Host " [OK] CMM software detected ($($detected -join ', ')) - CMM PC" -ForegroundColor Cyan
|
|
return "CMM"
|
|
}
|
|
|
|
# Wax Trace Detection: FormTracePak, FormStatusMonitor
|
|
$hasFormTracePak = $installedApps -match "FormTracePak|Formtracepak|Form Trace|FormTrace"
|
|
$hasFormStatusMonitor = $installedApps -match "FormStatusMonitor"
|
|
|
|
# Check file path fallback for FormTracePak
|
|
if (-not $hasFormTracePak) {
|
|
$ftPaths = @("C:\Program Files\MitutoyoApp*", "C:\Program Files (x86)\MitutoyoApp*")
|
|
foreach ($ftPath in $ftPaths) {
|
|
if (Test-Path $ftPath) { $hasFormTracePak = $true; break }
|
|
}
|
|
}
|
|
|
|
if ($hasFormTracePak -or $hasFormStatusMonitor) {
|
|
$detected = @()
|
|
if ($hasFormTracePak) { $detected += "FormTracePak" }
|
|
if ($hasFormStatusMonitor) { $detected += "FormStatusMonitor" }
|
|
Write-Host " [OK] Wax Trace software detected ($($detected -join ', ')) - Wax Trace PC" -ForegroundColor Cyan
|
|
return "Wax Trace"
|
|
}
|
|
|
|
# Keyence Detection: VR Series, Keyence VR USB Driver
|
|
$hasKeyence = $installedApps -match "VR-3000|VR-5000|VR-6000|KEYENCE VR"
|
|
|
|
if ($hasKeyence) {
|
|
Write-Host " [OK] Keyence VR Series detected - Keyence PC" -ForegroundColor Cyan
|
|
return "Keyence"
|
|
}
|
|
|
|
# EAS1000 Detection: GageCal, NI Software (National Instruments)
|
|
$hasGageCal = $installedApps -match "^GageCal"
|
|
$hasNISoftware = $installedApps -match "^NI-|National Instruments|NI System|NI Measurement|NI LabVIEW"
|
|
|
|
if ($hasGageCal -or $hasNISoftware) {
|
|
$detected = @()
|
|
if ($hasGageCal) { $detected += "GageCal" }
|
|
if ($hasNISoftware) { $detected += "NI Software" }
|
|
Write-Host " [OK] EAS1000 software detected ($($detected -join ', ')) - EAS1000 PC" -ForegroundColor Cyan
|
|
return "EAS1000"
|
|
}
|
|
|
|
# Genspect detection (could be Keyence or EAS1000 - default to Measuring)
|
|
$hasGenspect = $installedApps -match "^Genspect"
|
|
if ($hasGenspect) {
|
|
Write-Host " [OK] Genspect detected - Measuring Tool PC" -ForegroundColor Cyan
|
|
return "Genspect"
|
|
}
|
|
|
|
# Heat Treat Detection: HeatTreat application
|
|
$hasHeatTreat = $installedApps -match "^HeatTreat"
|
|
if ($hasHeatTreat) {
|
|
Write-Host " [OK] HeatTreat software detected - Heat Treat PC" -ForegroundColor Cyan
|
|
return "Heat Treat"
|
|
}
|
|
|
|
# Part Marker Detection: By machine number (0612, 0613, 0615, 8003) or software
|
|
$machineNo = Get-GEMachineNumber -Hostname $env:COMPUTERNAME
|
|
$isPartMarkerMachine = $false
|
|
if ($machineNo) {
|
|
# Check if machine number matches Part Marker machines (0612, 0613, 0615, 8003)
|
|
if ($machineNo -match "^0?(612|613|615|8003)$" -or $machineNo -match "^M?(612|613|615|8003)$") {
|
|
$isPartMarkerMachine = $true
|
|
Write-Host " [OK] Part Marker machine detected (Machine #$machineNo) - Part Marker PC" -ForegroundColor Cyan
|
|
return "Part Marker"
|
|
}
|
|
}
|
|
|
|
# Also check for Part Marker software
|
|
$hasPartMarker = $installedApps -match "Part\s*Mark|PartMark|Telesis|MECCO|Pryor|Gravotech|SIC Marking"
|
|
if ($hasPartMarker) {
|
|
Write-Host " [OK] Part Marker software detected - Part Marker PC" -ForegroundColor Cyan
|
|
return "Part Marker"
|
|
}
|
|
|
|
return "Shopfloor"
|
|
}
|
|
} catch {
|
|
Write-Host " [WARN] Could not detect domain: $($_.Exception.Message)" -ForegroundColor Yellow
|
|
}
|
|
|
|
if ($HasAppsFolder -and $HasVDriveAccess) {
|
|
return "Engineer"
|
|
}
|
|
else {
|
|
return "Standard"
|
|
}
|
|
}
|
|
|
|
function Collect-SystemInfo {
|
|
Write-Host "Collecting comprehensive system information..." -ForegroundColor Green
|
|
|
|
$systemInfo = @{}
|
|
|
|
# Basic system info
|
|
$systemInfo.Hostname = $env:COMPUTERNAME
|
|
|
|
try {
|
|
$computerSystem = Get-CimInstance -Class CIM_ComputerSystem -ErrorAction Stop
|
|
$bios = Get-CimInstance -Class CIM_BIOSElement -ErrorAction Stop
|
|
$os = Get-CimInstance -Class CIM_OperatingSystem -ErrorAction Stop
|
|
|
|
$systemInfo.Manufacturer = $computerSystem.Manufacturer
|
|
$systemInfo.Model = $computerSystem.Model
|
|
$systemInfo.SerialNumber = $bios.SerialNumber
|
|
$systemInfo.ServiceTag = $bios.SerialNumber # Often same as serial for Dell
|
|
$systemInfo.TotalPhysicalMemory = [Math]::Round($computerSystem.TotalPhysicalMemory / 1GB, 2)
|
|
$systemInfo.DomainRole = $computerSystem.DomainRole
|
|
|
|
# OS Information
|
|
$systemInfo.OSVersion = $os.Caption
|
|
$systemInfo.LastBootUpTime = $os.LastBootUpTime
|
|
$systemInfo.CurrentTimeZone = (Get-TimeZone).Id
|
|
|
|
# Logged-in user
|
|
if ($computerSystem.UserName) {
|
|
$systemInfo.LoggedInUser = $computerSystem.UserName.Split('\')[-1]
|
|
} else {
|
|
$systemInfo.LoggedInUser = "No user logged in"
|
|
}
|
|
|
|
}
|
|
catch {
|
|
Write-Warning "Failed to retrieve WMI information: $_"
|
|
$systemInfo.Manufacturer = "Unknown"
|
|
$systemInfo.Model = "Unknown"
|
|
$systemInfo.SerialNumber = "Unknown"
|
|
$systemInfo.ServiceTag = "Unknown"
|
|
$systemInfo.LoggedInUser = "Unknown"
|
|
$systemInfo.OSVersion = "Unknown"
|
|
}
|
|
|
|
# PC Type determination
|
|
$hasApps = Test-AppsFolder
|
|
$hasVDrive = Test-VDriveAccess
|
|
|
|
$systemInfo.PCType = Get-PCType -HasAppsFolder $hasApps -HasVDriveAccess $hasVDrive
|
|
|
|
# Add application detection for shopfloor PCs
|
|
if ($systemInfo.PCType -eq "Shopfloor") {
|
|
Write-Host " Detecting shopfloor applications (UDC/CLM)..." -ForegroundColor Yellow
|
|
$systemInfo.InstalledApplications = Get-InstalledApplications
|
|
} else {
|
|
Write-Host " Skipping application detection (PC Type: $($systemInfo.PCType))" -ForegroundColor Gray
|
|
$systemInfo.InstalledApplications = @()
|
|
}
|
|
|
|
# GE Machine Number
|
|
$systemInfo.MachineNo = Get-GEMachineNumber -Hostname $systemInfo.Hostname
|
|
|
|
# Collect installed applications for logging and database tracking
|
|
Write-Host " Collecting installed applications..." -ForegroundColor Yellow
|
|
try {
|
|
$installedApps = @()
|
|
$installedApps += Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object {$_.DisplayName}
|
|
$installedApps += Get-ItemProperty HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object {$_.DisplayName}
|
|
|
|
$filteredApps = $installedApps | Select-Object DisplayName, DisplayVersion | Sort-Object DisplayName -Unique
|
|
|
|
Write-Host " Found $($filteredApps.Count) installed applications:" -ForegroundColor Gray
|
|
foreach ($app in $filteredApps) {
|
|
$version = if ($app.DisplayVersion) { " (v$($app.DisplayVersion))" } else { "" }
|
|
Write-Host " - $($app.DisplayName)$version" -ForegroundColor Gray
|
|
}
|
|
|
|
# Prepare application data for database tracking (specific apps only)
|
|
$trackedApps = @()
|
|
$csvTrackedApps = Get-TrackedApplications
|
|
|
|
# Track which appids we've already added to avoid duplicates
|
|
$seenAppIds = @{}
|
|
|
|
foreach ($app in $filteredApps) {
|
|
$appName = $app.DisplayName
|
|
$appVersion = $app.DisplayVersion
|
|
|
|
# Check against CSV-defined applications
|
|
foreach ($csvApp in $csvTrackedApps) {
|
|
# Skip if no app_id defined in CSV
|
|
if (-not $csvApp.app_id -or $csvApp.app_id -eq "") { continue }
|
|
|
|
if ($appName -match $csvApp.search_patterns) {
|
|
$appId = [int]$csvApp.app_id
|
|
|
|
# Skip if we've already tracked this appid
|
|
if ($seenAppIds.ContainsKey($appId)) {
|
|
Write-Host " Skipping duplicate: $($csvApp.app_name) (ID:$appId) = $appName" -ForegroundColor DarkGray
|
|
break
|
|
}
|
|
|
|
$seenAppIds[$appId] = $true
|
|
$trackedApps += @{
|
|
appid = $appId # Database appid
|
|
appname = $csvApp.app_name # Short name from CSV (e.g., "Tanium")
|
|
version = $appVersion # Detected version
|
|
displayname = $appName # Full registry name for reference
|
|
}
|
|
Write-Host " Matched: $($csvApp.app_name) (ID:$appId) = $appName v$appVersion" -ForegroundColor Cyan
|
|
break # Found a match, no need to check other patterns
|
|
}
|
|
}
|
|
}
|
|
|
|
# Detect running processes for UDC and CLM to set isactive
|
|
$udcRunning = $false
|
|
$clmRunning = $false
|
|
$udcProcess = Get-Process -Name "UDC" -ErrorAction SilentlyContinue
|
|
if ($udcProcess) { $udcRunning = $true }
|
|
$clmProcess = Get-Process -Name "PPMon" -ErrorAction SilentlyContinue
|
|
if ($clmProcess) { $clmRunning = $true }
|
|
|
|
# Update tracked apps with isactive status
|
|
foreach ($app in $trackedApps) {
|
|
if ($app.appid -eq 2) {
|
|
# UDC
|
|
$app.isactive = if ($udcRunning) { 1 } else { 0 }
|
|
Write-Host " UDC process running: $udcRunning" -ForegroundColor $(if ($udcRunning) { "Green" } else { "Yellow" })
|
|
} elseif ($app.appid -eq 4) {
|
|
# CLM
|
|
$app.isactive = if ($clmRunning) { 1 } else { 0 }
|
|
Write-Host " CLM (PPMon) process running: $clmRunning" -ForegroundColor $(if ($clmRunning) { "Green" } else { "Yellow" })
|
|
} else {
|
|
# Other apps - default to active if installed
|
|
$app.isactive = 1
|
|
}
|
|
}
|
|
|
|
$systemInfo.TrackedApplications = $trackedApps
|
|
Write-Host " Found $($trackedApps.Count) tracked applications for database" -ForegroundColor Cyan
|
|
}
|
|
catch {
|
|
Write-Host " [WARN] Failed to collect installed applications: $($_.Exception.Message)" -ForegroundColor Yellow
|
|
$systemInfo.TrackedApplications = @()
|
|
}
|
|
|
|
# Collect running processes (for log analysis)
|
|
Write-Host " Running processes:" -ForegroundColor Yellow
|
|
try {
|
|
$processes = Get-Process | Select-Object -ExpandProperty Name | Sort-Object -Unique
|
|
Write-Host " $($processes -join ', ')" -ForegroundColor Gray
|
|
}
|
|
catch {
|
|
Write-Host " [WARN] Failed to collect running processes: $($_.Exception.Message)" -ForegroundColor Yellow
|
|
}
|
|
|
|
# Display collected info
|
|
Write-Host " System Details:" -ForegroundColor Cyan
|
|
Write-Host " Hostname: $($systemInfo.Hostname)"
|
|
Write-Host " Manufacturer: $($systemInfo.Manufacturer)"
|
|
Write-Host " Model: $($systemInfo.Model)"
|
|
Write-Host " Serial: $($systemInfo.SerialNumber)"
|
|
Write-Host " PC Type: $($systemInfo.PCType)"
|
|
Write-Host " User: $($systemInfo.LoggedInUser)"
|
|
if ($systemInfo.MachineNo) {
|
|
Write-Host " Machine No: $($systemInfo.MachineNo)"
|
|
}
|
|
Write-Host " Memory: $($systemInfo.TotalPhysicalMemory) GB"
|
|
Write-Host " OS: $($systemInfo.OSVersion)"
|
|
|
|
return $systemInfo
|
|
}
|
|
|
|
function Collect-ShopfloorInfo {
|
|
param([hashtable]$SystemInfo)
|
|
|
|
if ($SystemInfo.PCType -ne "Shopfloor") {
|
|
return $null
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Host "Collecting shopfloor-specific configurations..." -ForegroundColor Yellow
|
|
|
|
try {
|
|
$shopfloorConfigs = Get-ShopfloorConfigurations
|
|
|
|
Write-Host " Shopfloor Configuration Summary:" -ForegroundColor Cyan
|
|
Write-Host " Network Interfaces: $($shopfloorConfigs.NetworkInterfaces.Count)"
|
|
Write-Host " Communication Configs: $($shopfloorConfigs.CommConfigs.Count)"
|
|
Write-Host " DNC Config: $(if ($shopfloorConfigs.DNCConfig) { 'Yes' } else { 'No' })"
|
|
|
|
return $shopfloorConfigs
|
|
}
|
|
catch {
|
|
Write-Warning "Failed to collect shopfloor configurations: $_"
|
|
return $null
|
|
}
|
|
}
|
|
|
|
function Get-DefaultPrinterFQDN {
|
|
try {
|
|
Write-Host " Collecting default printer information..." -ForegroundColor Yellow
|
|
$defaultPrinter = Get-WmiObject -Query "SELECT * FROM Win32_Printer WHERE Default=$true" -ErrorAction Stop
|
|
|
|
if ($defaultPrinter -and $defaultPrinter.PortName) {
|
|
$portName = $defaultPrinter.PortName
|
|
Write-Host " Default Printer: $($defaultPrinter.Name)" -ForegroundColor Gray
|
|
Write-Host " Port Name: $portName" -ForegroundColor Gray
|
|
|
|
# Check if this is a network printer (not a local/virtual printer)
|
|
$localPorts = @('USB', 'LPT', 'COM', 'PORTPROMPT:', 'FILE:', 'NUL:', 'XPS', 'PDF', 'FOXIT', 'Microsoft')
|
|
$isLocalPrinter = $false
|
|
|
|
foreach ($localPort in $localPorts) {
|
|
if ($portName -like "$localPort*") {
|
|
$isLocalPrinter = $true
|
|
break
|
|
}
|
|
}
|
|
|
|
if ($isLocalPrinter) {
|
|
Write-Host " [SKIP] Local/virtual printer detected (port: $portName) - not sending to database" -ForegroundColor Yellow
|
|
return $null
|
|
}
|
|
|
|
# Strip anything after and including underscore (e.g., 10.80.92.53_2 -> 10.80.92.53)
|
|
$cleanPort = $portName -replace '_.*$', ''
|
|
|
|
Write-Host " [OK] Network printer detected - will send to database" -ForegroundColor Green
|
|
Write-Host " Clean port: $cleanPort" -ForegroundColor Gray
|
|
return $cleanPort
|
|
} else {
|
|
Write-Host " No default printer found or no port available" -ForegroundColor Yellow
|
|
return $null
|
|
}
|
|
}
|
|
catch {
|
|
Write-Warning "Failed to get default printer information: $_"
|
|
return $null
|
|
}
|
|
}
|
|
|
|
function Send-PrinterMappingToDashboard {
|
|
param(
|
|
[string]$Hostname,
|
|
[string]$PrinterFQDN,
|
|
[string]$DashboardURL
|
|
)
|
|
|
|
if ([string]::IsNullOrEmpty($PrinterFQDN)) {
|
|
Write-Host " No printer FQDN to send - skipping printer mapping" -ForegroundColor Gray
|
|
return $true
|
|
}
|
|
|
|
try {
|
|
Write-Host " Sending printer mapping to dashboard..." -ForegroundColor Yellow
|
|
Write-Host " Hostname: $Hostname" -ForegroundColor Gray
|
|
Write-Host " Printer FQDN: $PrinterFQDN" -ForegroundColor Gray
|
|
|
|
$postData = @{
|
|
action = 'updatePrinterMapping'
|
|
hostname = $Hostname
|
|
printerFQDN = $PrinterFQDN
|
|
}
|
|
|
|
$headers = @{
|
|
'Content-Type' = 'application/x-www-form-urlencoded'
|
|
}
|
|
|
|
$response = Invoke-RestMethod -Uri $DashboardURL -Method Post -Body $postData -Headers $headers -TimeoutSec 30
|
|
|
|
# Debug: Show raw response structure
|
|
Write-Host " DEBUG Response: $($response | ConvertTo-Json -Compress)" -ForegroundColor Magenta
|
|
|
|
if ($response.success) {
|
|
Write-Host " [OK] Printer mapping updated successfully!" -ForegroundColor Green
|
|
Write-Host " Printer ID: $($response.data.printerId)" -ForegroundColor Gray
|
|
Write-Host " Machines Updated: $($response.data.machinesUpdated)" -ForegroundColor Gray
|
|
Write-Host " Match Method: $($response.data.matchMethod)" -ForegroundColor Gray
|
|
return $true
|
|
} else {
|
|
Write-Host " [WARN] Printer mapping failed: $($response.message)" -ForegroundColor Yellow
|
|
Write-Host " DEBUG Error Response: $($response | ConvertTo-Json)" -ForegroundColor Red
|
|
return $false
|
|
}
|
|
}
|
|
catch {
|
|
Write-Host " [WARN] Error sending printer mapping: $($_.Exception.Message)" -ForegroundColor Yellow
|
|
return $false
|
|
}
|
|
}
|
|
|
|
function Send-InstalledAppsToDashboard {
|
|
param(
|
|
[string]$Hostname,
|
|
[array]$TrackedApps,
|
|
[string]$DashboardURL
|
|
)
|
|
|
|
if (!$TrackedApps -or $TrackedApps.Count -eq 0) {
|
|
Write-Host " No tracked applications to send - skipping app mapping" -ForegroundColor Gray
|
|
return $true
|
|
}
|
|
|
|
try {
|
|
Write-Host " Sending tracked applications to dashboard..." -ForegroundColor Yellow
|
|
Write-Host " Hostname: $Hostname" -ForegroundColor Gray
|
|
Write-Host " Tracked Apps: $($TrackedApps.Count)" -ForegroundColor Gray
|
|
|
|
# Debug: Show each app with version
|
|
foreach ($app in $TrackedApps) {
|
|
Write-Host " -> appid=$($app.appid), appname='$($app.appname)', version='$($app.version)'" -ForegroundColor Magenta
|
|
}
|
|
|
|
$appsJson = $TrackedApps | ConvertTo-Json -Compress
|
|
Write-Host " DEBUG JSON: $appsJson" -ForegroundColor Magenta
|
|
|
|
$postData = @{
|
|
action = 'updateInstalledApps'
|
|
hostname = $Hostname
|
|
installedApps = $appsJson
|
|
}
|
|
|
|
$headers = @{
|
|
'Content-Type' = 'application/x-www-form-urlencoded'
|
|
}
|
|
|
|
$response = Invoke-RestMethod -Uri $DashboardURL -Method Post -Body $postData -Headers $headers -TimeoutSec 30
|
|
|
|
if ($response.success) {
|
|
Write-Host " [OK] Installed applications updated successfully!" -ForegroundColor Green
|
|
Write-Host " Apps Processed: $($response.appsProcessed)" -ForegroundColor Gray
|
|
Write-Host " Machine ID: $($response.machineid)" -ForegroundColor Gray
|
|
if ($response.debugError) {
|
|
Write-Host " DEBUG ERROR: $($response.debugError)" -ForegroundColor Red
|
|
}
|
|
return $true
|
|
} else {
|
|
Write-Host " [WARN] Application mapping failed: $($response.message)" -ForegroundColor Yellow
|
|
return $false
|
|
}
|
|
}
|
|
catch {
|
|
Write-Host " [WARN] Error sending application mapping: $($_.Exception.Message)" -ForegroundColor Yellow
|
|
return $false
|
|
}
|
|
}
|
|
|
|
function Get-WarrantyFromProxy {
|
|
param(
|
|
[string]$ServiceTag,
|
|
[string]$ProxyURL
|
|
)
|
|
|
|
if ([string]::IsNullOrEmpty($ServiceTag) -or $ServiceTag -eq "Unknown") {
|
|
Write-Host " No valid service tag - skipping warranty lookup" -ForegroundColor Gray
|
|
return $null
|
|
}
|
|
|
|
try {
|
|
Write-Host "Getting warranty data from proxy server..." -ForegroundColor Yellow
|
|
|
|
$uri = "$ProxyURL" + "?vendor=dell&action=warranty&servicetag=$ServiceTag"
|
|
$response = Invoke-RestMethod -Uri $uri -Method Get -TimeoutSec 30
|
|
|
|
if ($response.success -and $response.warranties -and $response.warranties.Count -gt 0) {
|
|
$warranty = $response.warranties[0]
|
|
|
|
Write-Host " [OK] Warranty data retrieved:" -ForegroundColor Green
|
|
Write-Host " Status: $($warranty.warrantyStatus)"
|
|
Write-Host " End Date: $($warranty.warrantyEndDate)"
|
|
Write-Host " Days Remaining: $($warranty.daysRemaining)"
|
|
Write-Host " Service Level: $($warranty.serviceLevel)"
|
|
|
|
return $warranty
|
|
} else {
|
|
Write-Host " [WARN] No warranty data found for service tag: $ServiceTag" -ForegroundColor Yellow
|
|
return $null
|
|
}
|
|
}
|
|
catch {
|
|
Write-Host " [WARN] Error getting warranty from proxy: $($_.Exception.Message)" -ForegroundColor Yellow
|
|
return $null
|
|
}
|
|
}
|
|
|
|
function Send-CompleteDataToDashboard {
|
|
param(
|
|
[hashtable]$SystemInfo,
|
|
[object]$ShopfloorInfo,
|
|
[object]$WarrantyData,
|
|
[string]$DashboardURL
|
|
)
|
|
|
|
try {
|
|
Write-Host "Sending complete asset data to dashboard..." -ForegroundColor Yellow
|
|
Write-Host " Dashboard URL: $DashboardURL" -ForegroundColor Gray
|
|
|
|
# Prepare comprehensive data package
|
|
$postData = @{
|
|
action = 'updateCompleteAsset'
|
|
|
|
# Basic system information
|
|
hostname = $SystemInfo.Hostname
|
|
serialNumber = $SystemInfo.SerialNumber
|
|
serviceTag = $SystemInfo.ServiceTag
|
|
manufacturer = $SystemInfo.Manufacturer
|
|
model = $SystemInfo.Model
|
|
pcType = $SystemInfo.PCType
|
|
loggedInUser = $SystemInfo.LoggedInUser
|
|
machineNo = $SystemInfo.MachineNo
|
|
osVersion = $SystemInfo.OSVersion
|
|
totalPhysicalMemory = $SystemInfo.TotalPhysicalMemory
|
|
domainRole = $SystemInfo.DomainRole
|
|
currentTimeZone = $SystemInfo.CurrentTimeZone
|
|
# Format lastBootUpTime as MySQL datetime (YYYY-MM-DD HH:MM:SS)
|
|
lastBootUpTime = if ($SystemInfo.LastBootUpTime) {
|
|
$SystemInfo.LastBootUpTime.ToString("yyyy-MM-dd HH:mm:ss")
|
|
} else { $null }
|
|
}
|
|
|
|
# Add warranty data if available
|
|
if ($WarrantyData) {
|
|
$postData.warrantyEndDate = $WarrantyData.warrantyEndDate
|
|
$postData.warrantyStatus = $WarrantyData.warrantyStatus
|
|
$postData.warrantyServiceLevel = $WarrantyData.serviceLevel
|
|
$postData.warrantyDaysRemaining = $WarrantyData.daysRemaining
|
|
}
|
|
|
|
# Add shopfloor data if available
|
|
if ($ShopfloorInfo) {
|
|
Write-Host " ShopfloorInfo object contains DNCConfig: $(if ($ShopfloorInfo.DNCConfig) { 'YES' } else { 'NO' })" -ForegroundColor Gray
|
|
Write-Host " ShopfloorInfo object contains GERegistryInfo: $(if ($ShopfloorInfo.GERegistryInfo) { 'YES' } else { 'NO' })" -ForegroundColor Gray
|
|
|
|
$postData.networkInterfaces = $ShopfloorInfo.NetworkInterfaces | ConvertTo-Json -Compress
|
|
$postData.commConfigs = $ShopfloorInfo.CommConfigs | ConvertTo-Json -Compress
|
|
|
|
if ($ShopfloorInfo.DNCConfig) {
|
|
$postData.dncConfig = $ShopfloorInfo.DNCConfig | ConvertTo-Json -Compress
|
|
Write-Host " Sending DNC Config: $(($ShopfloorInfo.DNCConfig | ConvertTo-Json -Compress).Substring(0, 100))..." -ForegroundColor Cyan
|
|
} else {
|
|
Write-Host " No DNC Config to send (ShopfloorInfo.DNCConfig is null or empty)" -ForegroundColor Yellow
|
|
}
|
|
|
|
# Add GE Aircraft Engines registry information
|
|
if ($ShopfloorInfo.GERegistryInfo) {
|
|
$geInfo = $ShopfloorInfo.GERegistryInfo
|
|
$postData.dncDualPathEnabled = if ($geInfo.DualPathEnabled -ne $null) { $geInfo.DualPathEnabled } else { $null }
|
|
$postData.dncPath1Name = $geInfo.Path1Name
|
|
$postData.dncPath2Name = $geInfo.Path2Name
|
|
$postData.dncGeRegistry32Bit = $geInfo.Registry32Bit
|
|
$postData.dncGeRegistry64Bit = $geInfo.Registry64Bit
|
|
$postData.dncGeRegistryNotes = $geInfo.RegistryNotes | ConvertTo-Json -Compress
|
|
|
|
Write-Host " Sending GE Registry Info:" -ForegroundColor Cyan
|
|
Write-Host " 32-bit: $($geInfo.Registry32Bit), 64-bit: $($geInfo.Registry64Bit)" -ForegroundColor Cyan
|
|
Write-Host " DualPath: $(if ($geInfo.DualPathEnabled -ne $null) { $geInfo.DualPathEnabled } else { 'Not Found' })" -ForegroundColor Cyan
|
|
if ($geInfo.Path1Name) { Write-Host " Path1Name: $($geInfo.Path1Name)" -ForegroundColor Cyan }
|
|
if ($geInfo.Path2Name) { Write-Host " Path2Name: $($geInfo.Path2Name)" -ForegroundColor Cyan }
|
|
} else {
|
|
Write-Host " No GE Registry Info to send" -ForegroundColor Yellow
|
|
}
|
|
} else {
|
|
Write-Host " No ShopfloorInfo available" -ForegroundColor Yellow
|
|
}
|
|
|
|
# Add installed applications data for shopfloor PCs
|
|
if ($SystemInfo.InstalledApplications -and $SystemInfo.InstalledApplications.Count -gt 0) {
|
|
$postData.installedApplications = $SystemInfo.InstalledApplications | ConvertTo-Json -Compress
|
|
Write-Host " Sending installed applications data:" -ForegroundColor Cyan
|
|
|
|
$activeApps = $SystemInfo.InstalledApplications | Where-Object { $_.IsActive -eq $true }
|
|
if ($activeApps.Count -gt 0) {
|
|
foreach ($app in $activeApps) {
|
|
Write-Host " - $($app.AppName) (AppID: $($app.AppID)) - ACTIVE (PID: $($app.ProcessID))" -ForegroundColor Green
|
|
}
|
|
} else {
|
|
Write-Host " - No active applications detected" -ForegroundColor Gray
|
|
}
|
|
} else {
|
|
Write-Host " No installed applications to send" -ForegroundColor Gray
|
|
}
|
|
|
|
# Send to dashboard API
|
|
$headers = @{
|
|
'Content-Type' = 'application/x-www-form-urlencoded'
|
|
}
|
|
|
|
$response = Invoke-RestMethod -Uri $DashboardURL -Method Post -Body $postData -Headers $headers -TimeoutSec 30
|
|
|
|
if ($response.success) {
|
|
Write-Host " [OK] Complete asset data stored in database!" -ForegroundColor Green
|
|
$data = $response.data
|
|
Write-Host " PCID: $(if($data.pcid) { $data.pcid } else { 'Unknown' })"
|
|
Write-Host " Updated/Created: $(if($data.operation) { $data.operation } else { 'Unknown' })"
|
|
Write-Host " Records affected: $(if($data.recordsAffected) { $data.recordsAffected } else { 'Unknown' })"
|
|
return $true
|
|
} else {
|
|
Write-Host " [FAIL] Dashboard could not store data: $($response.error)" -ForegroundColor Red
|
|
if ($response.data -and $response.data.debug) {
|
|
Write-Host " Debug - DNC Config Received: $($response.data.debug.dncConfigReceived)" -ForegroundColor Yellow
|
|
} elseif ($response.debug) {
|
|
Write-Host " Debug - DNC Config Received: $($response.debug.dncConfigReceived)" -ForegroundColor Yellow
|
|
}
|
|
return $false
|
|
}
|
|
}
|
|
catch {
|
|
Write-Host " [FAIL] Error sending data to dashboard: $($_.Exception.Message)" -ForegroundColor Red
|
|
|
|
# Try to get more details from the response
|
|
if ($_.Exception -is [System.Net.WebException]) {
|
|
$response = $_.Exception.Response
|
|
if ($response) {
|
|
$responseStream = $response.GetResponseStream()
|
|
$reader = New-Object System.IO.StreamReader($responseStream)
|
|
$responseBody = $reader.ReadToEnd()
|
|
$reader.Close()
|
|
|
|
Write-Host " Server Response:" -ForegroundColor Yellow
|
|
try {
|
|
$errorData = $responseBody | ConvertFrom-Json
|
|
if ($errorData.details) {
|
|
Write-Host " Error: $($errorData.details.message)" -ForegroundColor Red
|
|
Write-Host " File: $($errorData.details.file):$($errorData.details.line)" -ForegroundColor Gray
|
|
} else {
|
|
Write-Host " $responseBody" -ForegroundColor Gray
|
|
}
|
|
} catch {
|
|
Write-Host " $responseBody" -ForegroundColor Gray
|
|
}
|
|
}
|
|
}
|
|
|
|
return $false
|
|
}
|
|
}
|
|
|
|
# Main execution
|
|
try {
|
|
# Log startup
|
|
Write-Log "========================================" -Level "INFO" -ForegroundColor Green
|
|
Write-Log "Complete PC Asset Collection & Storage" -Level "INFO" -ForegroundColor Green
|
|
Write-Log "========================================" -Level "INFO" -ForegroundColor Green
|
|
Write-Log "Computer: $env:COMPUTERNAME" -Level "INFO" -ForegroundColor White
|
|
Write-Log "Log file: $script:LogFile" -Level "INFO" -ForegroundColor Gray
|
|
|
|
# Get dashboard URL
|
|
$dashboardURL = Get-DashboardURL -ProvidedURL $DashboardURL
|
|
Write-Log "Dashboard: $dashboardURL" -Level "INFO" -ForegroundColor Gray
|
|
Write-Log "Note: Warranty lookups disabled (handled by dashboard)" -Level "INFO" -ForegroundColor Gray
|
|
Write-Log "" -Level "INFO" -ForegroundColor White
|
|
|
|
# Test connections if requested
|
|
if ($TestConnections) {
|
|
Write-Host "=== CONNECTION TESTS ===" -ForegroundColor Cyan
|
|
|
|
# Only test dashboard connection since proxy is not accessible from PCs
|
|
Write-Host "Skipping proxy test (not accessible from client PCs)" -ForegroundColor Gray
|
|
$dashboardOK = Test-DashboardConnection -DashboardURL $dashboardURL
|
|
|
|
Write-Host ""
|
|
if ($dashboardOK) {
|
|
Write-Host "[OK] Dashboard connection working!" -ForegroundColor Green
|
|
exit 0
|
|
} else {
|
|
Write-Host "[FAIL] Dashboard connection failed" -ForegroundColor Red
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
# Step 1: Collect system information
|
|
Write-Host "=== STEP 1: COLLECT SYSTEM INFO ===" -ForegroundColor Cyan
|
|
$systemInfo = Collect-SystemInfo
|
|
|
|
# Step 2: Collect shopfloor-specific info (if applicable)
|
|
Write-Host ""
|
|
Write-Host "=== STEP 2: COLLECT SHOPFLOOR INFO ===" -ForegroundColor Cyan
|
|
$shopfloorInfo = Collect-ShopfloorInfo -SystemInfo $systemInfo
|
|
|
|
# Step 3: Get warranty data from proxy (if not skipped and Dell system)
|
|
$warrantyData = $null
|
|
$isDellSystem = $systemInfo.Manufacturer -match "Dell"
|
|
|
|
Write-Host ""
|
|
Write-Host "=== STEP 3: WARRANTY DATA ===" -ForegroundColor Cyan
|
|
Write-Host "Warranty lookups disabled - Dashboard will handle warranty updates" -ForegroundColor Yellow
|
|
Write-Host "PCs cannot reach proxy server from this network" -ForegroundColor Gray
|
|
|
|
# Step 4: Send all data to dashboard for storage
|
|
Write-Host ""
|
|
Write-Host "=== STEP 4: STORE IN DATABASE ===" -ForegroundColor Cyan
|
|
$storeSuccess = Send-CompleteDataToDashboard -SystemInfo $systemInfo -ShopfloorInfo $shopfloorInfo -WarrantyData $warrantyData -DashboardURL $dashboardURL
|
|
|
|
if (-not $storeSuccess) {
|
|
Write-Error "Failed to store asset data in database"
|
|
exit 1
|
|
}
|
|
|
|
# Step 5: Collect and send default printer mapping
|
|
Write-Host ""
|
|
Write-Host "=== STEP 5: PRINTER MAPPING ===" -ForegroundColor Cyan
|
|
$defaultPrinterFQDN = Get-DefaultPrinterFQDN
|
|
$printerMappingSuccess = Send-PrinterMappingToDashboard -Hostname $systemInfo.Hostname -PrinterFQDN $defaultPrinterFQDN -DashboardURL $dashboardURL
|
|
|
|
# Step 6: Send tracked applications to database
|
|
Write-Host ""
|
|
Write-Host "=== STEP 6: APPLICATION MAPPING ===" -ForegroundColor Cyan
|
|
$appMappingSuccess = Send-InstalledAppsToDashboard -Hostname $systemInfo.Hostname -TrackedApps $systemInfo.TrackedApplications -DashboardURL $dashboardURL
|
|
|
|
# Check if running as admin for Steps 7 & 8
|
|
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
|
|
|
|
# Step 7: Reset and configure WinRM for remote management (requires admin)
|
|
Write-Log "" -Level "INFO" -ForegroundColor White
|
|
Write-Log "=== STEP 7: WINRM CONFIGURATION ===" -Level "INFO" -ForegroundColor Cyan
|
|
if ($isAdmin) {
|
|
$winrmSuccess = Reset-WinRMConfiguration
|
|
} else {
|
|
Write-Log " [SKIP] Not running as admin - WinRM configuration skipped" -Level "WARN" -ForegroundColor Yellow
|
|
$winrmSuccess = $false
|
|
}
|
|
|
|
# Step 8: Add WinRM management group to local Administrators (requires admin)
|
|
Write-Log "" -Level "INFO" -ForegroundColor White
|
|
Write-Log "=== STEP 8: WINRM ADMIN GROUP ===" -Level "INFO" -ForegroundColor Cyan
|
|
if ($isAdmin) {
|
|
$adminGroupSuccess = Add-WinRMAdminGroup
|
|
} else {
|
|
Write-Log " [SKIP] Not running as admin - Admin group setup skipped" -Level "WARN" -ForegroundColor Yellow
|
|
$adminGroupSuccess = $false
|
|
}
|
|
|
|
# Final Summary
|
|
Write-Log "" -Level "INFO" -ForegroundColor White
|
|
Write-Log "=== COMPLETE ASSET UPDATE SUCCESS ===" -Level "INFO" -ForegroundColor Green
|
|
Write-Log "Computer: $($systemInfo.Hostname)" -Level "INFO" -ForegroundColor White
|
|
Write-Log "Type: $($systemInfo.PCType)" -Level "INFO" -ForegroundColor White
|
|
Write-Log "Serial: $($systemInfo.SerialNumber)" -Level "INFO" -ForegroundColor White
|
|
if ($systemInfo.MachineNo) {
|
|
Write-Log "Machine: $($systemInfo.MachineNo)" -Level "INFO" -ForegroundColor White
|
|
}
|
|
Write-Log "" -Level "INFO" -ForegroundColor White
|
|
Write-Log "Data Collected & Stored:" -Level "INFO" -ForegroundColor Cyan
|
|
Write-Log "[OK] Basic system information" -Level "SUCCESS" -ForegroundColor Green
|
|
if ($defaultPrinterFQDN) {
|
|
Write-Log "[OK] Default printer mapping ($defaultPrinterFQDN)" -Level "SUCCESS" -ForegroundColor Green
|
|
} else {
|
|
Write-Log "[--] Default printer mapping (no printer found)" -Level "INFO" -ForegroundColor Gray
|
|
}
|
|
if ($systemInfo.TrackedApplications -and $systemInfo.TrackedApplications.Count -gt 0) {
|
|
Write-Log "[OK] Application mapping ($($systemInfo.TrackedApplications.Count) tracked apps)" -Level "SUCCESS" -ForegroundColor Green
|
|
} else {
|
|
Write-Log "[--] Application mapping (no tracked apps found)" -Level "INFO" -ForegroundColor Gray
|
|
}
|
|
|
|
if ($shopfloorInfo) {
|
|
Write-Log "[OK] Shopfloor configurations ($($shopfloorInfo.NetworkInterfaces.Count) network, $($shopfloorInfo.CommConfigs.Count) comm)" -Level "SUCCESS" -ForegroundColor Green
|
|
}
|
|
|
|
if ($warrantyData) {
|
|
Write-Log "[OK] Warranty information ($($warrantyData.warrantyStatus), $($warrantyData.daysRemaining) days)" -Level "SUCCESS" -ForegroundColor Green
|
|
} elseif (-not $SkipWarranty -and $isDellSystem) {
|
|
Write-Log "[WARN] Warranty information (lookup failed)" -Level "WARN" -ForegroundColor Yellow
|
|
}
|
|
|
|
if ($winrmSuccess) {
|
|
Write-Log "[OK] WinRM HTTP listener (port 5985)" -Level "SUCCESS" -ForegroundColor Green
|
|
Write-Log " Note: If remote access still fails, a reboot may be required" -Level "INFO" -ForegroundColor Gray
|
|
} else {
|
|
Write-Log "[WARN] WinRM configuration (may need manual setup)" -Level "WARN" -ForegroundColor Yellow
|
|
}
|
|
|
|
if ($adminGroupSuccess) {
|
|
Write-Log "[OK] WinRM admin group (logon\g03078610)" -Level "SUCCESS" -ForegroundColor Green
|
|
} else {
|
|
Write-Log "[WARN] WinRM admin group (failed to add)" -Level "WARN" -ForegroundColor Yellow
|
|
}
|
|
|
|
Write-Log "" -Level "INFO" -ForegroundColor White
|
|
Write-Log "[OK] Complete PC asset collection finished!" -Level "SUCCESS" -ForegroundColor Green
|
|
Write-Log "All data stored in database via dashboard API." -Level "INFO" -ForegroundColor Gray
|
|
Write-Log "Log file: $script:LogFile" -Level "INFO" -ForegroundColor Gray
|
|
|
|
} catch {
|
|
Write-Log "Complete asset collection failed: $($_.Exception.Message)" -Level "ERROR" -ForegroundColor Red
|
|
Write-Error "Complete asset collection failed: $($_.Exception.Message)"
|
|
exit 1
|
|
} |