It bugged me for a while why Syncro can only send a message when you run scripts as a Logged in user. Most of the scripts required SYSTEM permissions, and there was no way to provide feedback to the user when a script was finished.

I’ve started by reviewing module.psm1 (located in C:\ProgramData\Syncro\bin ) and it looks like function Broadcast-Message could be modified to enable this functionality. Here is improved code for that function:

[sourcecode language="powershell"]

function Broadcast-Message([string]$Title, [string]$Message, [string]$LogActivity) {
  if ([System.Environment]::UserInteractive -ne $true) {
    $when = (Get-Date).AddSeconds($sDelay) | Get-Date -UFormat "%T"
    $argument = "--broadcast-message `"$Message`" --broadcast-title `"$Title`""
    $dUN = @(Get-WmiObject -Query "Select * FROM Win32_Process WHERE Name='explorer.exe'" -ErrorAction SilentlyContinue).GetOwner()
    if ($dUN.Count -ne 0) {
        Foreach ($cUN in $dUN) {
            $username = ($cUN.Domain)+"\"+($cUN.User)
            $action = New-ScheduledTaskAction -Execute "$env:ProgramFiles\RepairTech\Syncro\Syncro.App.Runner.exe" -Argument $argument
            $trigger = New-ScheduledTaskTrigger -Once -At $when
            $principal = New-ScheduledTaskPrincipal -UserId $username
            $task = New-ScheduledTask -Action $action -Trigger $trigger -Principal $principal
            Register-ScheduledTask "BroadcastMessage-$username" -InputObject $task | Out-Null
            #Start-ScheduledTask -TaskName Message
            Start-Sleep -Seconds (30+$sDelay)
            Unregister-ScheduledTask -TaskName "BroadcastMessage-$username" -Confirm:$false
        }
}
  $AppRunner = "$env:ProgramFiles\RepairTech\Syncro\Syncro.App.Runner.exe"
  Start-Process -FilePath $AppRunner -ArgumentList "--broadcast-message `"$Message`" --broadcast-title `"$Title`""

  if (Parse-Bool -Value $LogActivity){
    $ApiPath = "/api/syncro_device/rmm_alerts/log_activity"
    $postParams = ConvertTo-Json20 -InputObject @{
      uuid=$UUID;
      message="A broadcast message was sent.";
      activity_type="broadcast_message";
      event="sent";
      data=@{
        "title"=$Title;
        "message"=$Message;
      }
    }
    Write-Host $postParams
    try {
      WebRequest20 -Uri "https://$($ApiSubDomain).$($ApiBaseURL)$($ApiPath)" -Method POST -Body $postParams -ContentType 'application/json'
    }
    catch {
      Write-Host "ERROR!"
      $_ | Out-Host
    }
  }
}

[/sourcecode]

I did it simply to run a check for any user with explorer.exe running (desktop experience) and set up scheduled tasks to create notifications for these users. Just like that – we can notify any user without worrying about if we run as a user or not.

I’m hoping that Syncro crew will be able to get that pushed into one of the updates. In the meantime, if you need to send message to users when running as SYSTEM – here is function that you could place on the top of your script

[sourcecode language="powershell"]

function MessageAsSystem ([string]$Title,[string]$Message,[int]$sDelay = 15){
    $when = (Get-Date).AddSeconds($sDelay) | Get-Date -UFormat "%T"
    $argument = "--broadcast-message `"$Message`" --broadcast-title `"$Title`""
    $dUN = @(Get-WmiObject -Query "Select * FROM Win32_Process WHERE Name='explorer.exe'" -ErrorAction SilentlyContinue).GetOwner()
    if ($dUN.Count -ne 0) {
        Foreach ($cUN in $dUN) {
            $username = ($cUN.Domain)+"\"+($cUN.User)
            $action = New-ScheduledTaskAction -Execute "$env:ProgramFiles\RepairTech\Syncro\Syncro.App.Runner.exe" -Argument $argument
            $trigger = New-ScheduledTaskTrigger -Once -At $when
            $principal = New-ScheduledTaskPrincipal -UserId $username
            $task = New-ScheduledTask -Action $action -Trigger $trigger -Principal $principal
            Register-ScheduledTask "BroadcastMessage-$username" -InputObject $task | Out-Null
            #Start-ScheduledTask -TaskName Message
            Start-Sleep -Seconds (30+$sDelay)
            Unregister-ScheduledTask -TaskName "BroadcastMessage-$username" -Confirm:$false
        }
    } else {
        Write-Host "Interactive User not DETECTED"
    }
}

[/sourcecode]

you can call it from script simply by:

[sourcecode language=”powershell”]
MessageAsSystem -Message “Test message” -Title “test title”
[/sourcecode]