Skip to content
View in the app

A better way to browse. Learn more.

Pulseway

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

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. 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

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.