Jump to content
Pulseway 9.14 🔥

Paul

Administrators
  • Joined

  • Last visited

Posts posted by Paul

  1. Update, we've identified the issue and we've built a correction script that must be executed as an administrator on affected machines:

    # Function to calculate file hash
    function Get-FileHashLower {
        param (
            [string]$FilePath,
            [string]$Algorithm = "MD5"
        )
    
        if (-not (Test-Path -Path $FilePath)) {
            Write-Output "Error: File not found - $FilePath"
            return $null
        }
    
        try {
            return (Get-FileHash -Path $FilePath -Algorithm $Algorithm).Hash.ToLower()
        } catch {
            Write-Output "Error: Unable to calculate hash for $FilePath. $_"
            return $null
        }
    }
    
    
    Write-Output "Environment Variables:"
    Get-ChildItem Env: | Sort-Object Name
    
    # Enable TLS 1.2
    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
    
    # Step 0: Locate "PC Monitor" service binary folder
    $ServiceName = "PC Monitor"
    $Service = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
    
    if (-not $Service) {
        Write-Output "Error: '$ServiceName' service not found."
        exit 1
    }
    
    $BinaryPath = (Get-WmiObject Win32_Service | Where-Object { $_.Name -eq $ServiceName }).PathName.Trim('"')
    if (-not $BinaryPath) {
        Write-Output "Error: Unable to find binary path for '$ServiceName'."
        exit 1
    }
    
    $BinaryFolder = Split-Path -Path $BinaryPath -Parent
    Write-Output "Binary folder located: $BinaryFolder"
    
    # Step 1: Download and verify update.zip
    $UpdateUrl = "https://updates.pulseway.com/update.zip"
    $DownloadedFile = "$env:Temp\update.zip"
    
    try {
        $WebClient = New-Object System.Net.WebClient
        $WebClient.DownloadFile($UpdateUrl, $DownloadedFile)
        Write-Output "File downloaded successfully to $DownloadedFile"
    } catch {
        Write-Output "Error: Failed to download the update file. $_"
        exit 1
    }
    
    $ExpectedMD5 = "9235318c553c3f770ba95ab673566a4e"
    $DownloadedMD5 = Get-FileHashLower -FilePath $DownloadedFile
    
    if ($DownloadedMD5 -ne $ExpectedMD5) {
        Write-Output "Error: MD5 hash of the downloaded file does not match. Expected: $ExpectedMD5, Found: $DownloadedMD5"
        exit 1
    }
    
    # Step 2: Extract the archive
    $ExtractedFolder = "$env:Temp\update_extracted"
    Write-Output "Extracted Path: $TargetPath"
    if (Test-Path $ExtractedFolder) { Remove-Item -Recurse -Force $ExtractedFolder }
    New-Item -ItemType Directory -Path $ExtractedFolder | Out-Null
    Add-Type -AssemblyName System.IO.Compression.FileSystem
    [System.IO.Compression.ZipFile]::ExtractToDirectory($DownloadedFile, $ExtractedFolder)
    Write-Output "Extracted Files: ----"
    Get-ChildItem -Path $ExtractedFolder -Recurse | ForEach-Object { Write-Output $_.FullName }
    Write-Output "Extracted Files: ++++"
    
    # Step 3: Compare hashes of files
    $DiscrepantFiles = @()
    foreach ($File in Get-ChildItem -Recurse -Path $ExtractedFolder) {
        # Normalize and resolve paths
        $ResolvedExtractedFolder = (Get-Item $ExtractedFolder).FullName
        $ResolvedFilePath = (Get-Item $File.FullName).FullName
    
        # Calculate relative path
        $RelativePath = $ResolvedFilePath.Substring($ResolvedExtractedFolder.Length).TrimStart('\')
    
        Write-Output "Resolved Extracted Folder: $ResolvedExtractedFolder"
        Write-Output "Resolved File Path: $ResolvedFilePath"
        Write-Output "Calculated Relative Path: $RelativePath"
    
        # Calculate target path
        $TargetPath = Join-Path -Path $BinaryFolder -ChildPath $RelativePath
        Write-Output "Calculated Target Path: $TargetPath"
    
        if ($File.PSIsContainer) {
            # Create folder if it does not exist
            if (-not (Test-Path $TargetPath)) {
                Write-Output "Creating folder in target path: $RelativePath"
                New-Item -ItemType Directory -Path $TargetPath -Force | Out-Null
            }
        } else {
            # Compare files
            if (-not (Test-Path $TargetPath)) {
                Write-Output "File not found in target folder: $RelativePath"
                $DiscrepantFiles += $RelativePath
            } else {
                $SourceHash = Get-FileHashLower -FilePath $File.FullName
                $TargetHash = Get-FileHashLower -FilePath $TargetPath
    
                if ($SourceHash -eq $null -or $TargetHash -eq $null) {
                    Write-Output "Skipping comparison due to hash error: $RelativePath"
                    continue
                }
    
                if ($SourceHash -ne $TargetHash) {
                    Write-Output "Hash mismatch for file: $RelativePath"
                    $DiscrepantFiles += $RelativePath
                }
            }
        }
    }
    
    # Step 3.5: Exit if no discrepancies found
    if ($DiscrepantFiles.Count -eq 0) {
        Write-Output "No discrepancies found. Exiting."
        exit 0
    }
    
    # Step 4: Print the list of discrepant files
    Write-Output "Discrepant files:"
    $DiscrepantFiles | ForEach-Object { Write-Output $_ }
    
    # Step 5: Stop "PC Monitor" service and related processes
    $ProcessesToKill = @("pcmonitormanager.exe", "pcmonitorsrv.exe", "pcmontask.exe", "pcmonusertask.exe", "cli.exe", "addonmanager.exe", "pcmupdate.exe")
    
    for ($i = 1; $i -le 5; $i++) {
        if ($Service.Status -eq "Running") {
            Stop-Service -Name $ServiceName -Force -ErrorAction SilentlyContinue
        }
    
        foreach ($ProcessName in $ProcessesToKill) {
            Get-Process -Name $ProcessName -ErrorAction SilentlyContinue | Stop-Process -Force
        }
    
        Start-Sleep -Seconds 1
        if ((Get-Service -Name $ServiceName).Status -eq "Stopped" -and -not (Get-Process -Name $ProcessesToKill -ErrorAction SilentlyContinue)) {
            break
        }
    
        Write-Output "Retrying stop operation... ($i/5)"
        if ($i -eq 5) {
            Write-Output "Error: Failed to stop all processes after 5 attempts."
            exit 1
        }
    }
    
    # Step 6: Copy discrepant files
    foreach ($File in $DiscrepantFiles) {
        $SourceFile = Join-Path $ExtractedFolder $File
        $TargetFile = Join-Path $BinaryFolder $File
        $TargetFolder = Split-Path -Path $TargetFile -Parent
    
        if (-not (Test-Path $TargetFolder)) {
            New-Item -ItemType Directory -Path $TargetFolder | Out-Null
        }
    
        for ($i = 1; $i -le 5; $i++) {
            Copy-Item -Path $SourceFile -Destination $TargetFile -Force -ErrorAction SilentlyContinue
            if (Test-Path $TargetFile) { break }
            Write-Output "Retrying copy operation for $File... ($i/5)"
            Start-Sleep -Seconds 1
        }
    
        if (-not (Test-Path $TargetFile)) {
            Write-Output "Error: Failed to copy $File after 5 attempts."
            exit 1
        }
    }
    
    # Step 7: Verify hashes again
    $PostVerificationFailures = @()
    foreach ($File in $DiscrepantFiles) {
        $SourceFile = Join-Path $ExtractedFolder $File
        $TargetFile = Join-Path $BinaryFolder $File
    
        $SourceHash = Get-FileHashLower -FilePath $SourceFile
        $TargetHash = Get-FileHashLower -FilePath $TargetFile
    
        if ($SourceHash -ne $TargetHash) {
            $PostVerificationFailures += $File
        }
    }
    
    if ($PostVerificationFailures.Count -gt 0) {
        Write-Output "Post-repair verification failed for the following files:"
        $PostVerificationFailures | ForEach-Object { Write-Output $_ }
        exit 1
    }
    
    # Step 8: Start the "PC Monitor" service
    Start-Service -Name $ServiceName
    Write-Output "Agent repair successful."
    exit 0

    We apologize for the inconvenience caused.

    -Paul

  2. @KerryC for the crashes, did you see any "Application Error" error too? Can you please send us a screenshot of that event too?

    If the service is marked for deletion it should be removed upon a reboot. Once it's removed, you can use installutil from the C:\Windows\Microsoft.NET\Framework64\v4.0.30319 folder to manually register the service:

    C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe "c:\program files\pulseway\pcmonitorsrv.exe"

    -Paul

  3. Incidentally Google Firebase has deprecated their v1 push notification API which is what has caused the Pro / Free tier to stop sending Push notifications. We've patched it for the team plan but for the Pro / Free plan we're unable to fix it as it's running a really old version of the server software.

    Trust me when I am saying that we're not deprecating the Free and Pro plans because of an attempt to convert the user base to paid plans, it's just impossible for us to support that business model in the server software as we've been fighting compatibility issues for 9 years now since the launch of the multitenancy model on the Team plan.

    This was not an easy decision to make and we're doing what we can to make the transition smoother.

    -Paul

  4. Posted

    We've discovered that some old installations of the Pulseway app are incorrectly displaying the "This application version is no longer supported, please update it" message. To resolve the issue, you just have to sign in again. Our development team is working on releasing an update that detects this situation and prompts you to re-authenticate automatically.

    On the Android app, if you don't can't use the "Log out" function, just long press on the app from the home screen and select "Clear storage" and you should be prompted to authenticate when you open the app.

    We apologize for the inconvenience caused.

    -Paul

  5. @Jerdal, I cannot locate your email by date nor by address hence why I need your email headers to identify the message IDs and see if our email provider has received it. In the meantime, just PM me your instance name, username and the last 4 digits on the credit card on profile.

    -Paul

  6. Hello Jerdal,

    I do see a support ticket from July 2023 and which was replied to 30 minutes later, did you not receive the reply?

    Edit: I've looked all over for your email on June 19th. Can you please PM me the email headers so I can take a deep dive on it?

    -Paul

  7. Hi @techtedg,

    You can definitely do this through an automation script. You can create a custom field called "AssignedUser" and make it be of system scope. Then assign the custom field to the systems you want to name (you don't have to do it for all systems, the script I have built below will only overwrite the computer name for systems that have a custom field value assigned). Then you will need to create a powershell automation script, add an input variable that is bound to the custom field you've just created and use the powershell script below:

    $AssignedUser = ''; # this will get automatically generated for you when you create the input variable, you don't need to add this line
    
    if ([string]::IsNullOrEmpty($AssignedUser)) {
        Write-Output "Missing AssignedUser custom field value, aborting...";
    	exit 0;
    }
    
    $newComputerName = "$AssignedUser $env:COMPUTERNAME";
    Set-ItemProperty -Path 'HKLM:\SOFTWARE\MMSOFT Design\PC Monitor' -Name 'ComputerName' -Value $newComputerName;
    Write-Output "Computer display name changed to '$newComputerName'.";
    exit 0;

    Let me know how it goes

    -Paul