Client variable in on-boarding script

First off, let me apologize if this has already been addressed on forum, already built-in to product or just obvious; but I’ve spent the better part of this evening trying various methods with limited success. I’m looking to provide a single on-boarding policy or script that will download the appropriate file & wallpaper based on a client ID variable. I’ve successfully setup the customer short ID custom field, and have been able to pull it into most areas of a script however I’m unable once trying to use it in a “Start-Process” function. I can write the ID and recall it fine. I was even able to get the script to download file with the variable. However, I’m not able to get it to be called from within the execution of BGInfo call. What I’m trying to achieve is;
*** -1 Script to be used for all clients**
*** -Setup the client variable for each client or site (e.g. CLIENT1, CLIENT2, CLIENT3, etc)**
*** -Have script download BGInfo, download .bgi file & company wallpaper specific to the particular client based on client variable (e.g. CLIENT1.bgi & CLIENT1.jpg)**
*** -Excecute BGInfo with the arguments for C:\BGInfo%clientid%.bgi which also contains reference to C:\BGInfo%clientid%.jpg wallpaper**
That’s the basic idea of what I’m trying to achieve but consistently hit a wall when attempting to execute on the client side. I’ve also tried to even set a system environment variable without success that I thought I may be able to use when calling from the far side in a batch file once I was unable to get it to work in syncro script directly. Any thoughts or direction is greatly appreciate. Obviously I could create a specific script per client and assign, but it seems long term this would be better for updates.

My guess it’s some sort of escaping or syntax issue. Can you share your code?

This was initially a much cleaner, more concise script but thru hours of attempts has gotten a bit murkier… Regardless;

Import-Module $env:SyncroModule
[System.Environment]::SetEnvironmentVariable('XXID2',$XXClientID)
$DownloadURL = "https://XXXXXX/files/BGInfo/"
$Download1 = "$XXClientID.bgi"
$Download2 = "$XXClientID.jpg"
$filelocation = "C:\XXXXXX"
$sixtyFourBit = Test-Path -Path "C:\Program Files (x86)"
$ArgPathID = "$filelocation\$XXClientID.bgi /SILENT /TIMER:0 /NOLICPROMPT"
$SixT4Bit = "$filelocation\BGInfo64.exe"
$Not64Bit = "$filelocation\BGInfo.exe"
$RunProcResults = "-FilePath $SixT4Bit -ArgumentList $ArgPathID"

### For $filelocation include full path. Example: C:\temp\
### For $filename include file name and extension. Example: syncro.exe

#Creating file path if it doesn't already exist
if(!(Test-Path -Path $filelocation )){
    New-Item -ItemType directory -Path $filelocation
}
else
{
}

#Getting start time 
$start_time = Get-Date

#Downloading the file
Start-BitsTransfer -Source $DownloadURL$Download1 -Destination $filelocation\$Download1
Start-BitsTransfer -Source $DownloadURL$Download2 -Destination $filelocation\$Download2

#Confirmation Message
Write-Output "It took $((Get-Date).Subtract($start_time).Seconds) seconds to download $Download1 to $filelocation from this URL: $DownloadURL$Download1"
Write-Output "It took $((Get-Date).Subtract($start_time).Seconds) seconds to download $Download2 to $filelocation from this URL: $DownloadURL$Download2"
Write-Output $SixT4Bit\$ArgPathID

if($sixtyFourBit){
 Start-Process -FilePath $SixT4Bit -ArgumentList $ArgPathID
 [Environment]::GetEnvironmentVariable('XXID2')
 }
else {
  Start-Process -FilePath $Not64Bit -ArgumentList $ArgPathID
}

I have tried various double quotes and single encapsulations with no luck either, but perhaps I still didn’t have it quite right. Typical output, although varied throughout the process;

It took 5 seconds to download XXXXXX.bgi to C:\XXXXXX from this URL: https://XXXXXX/files/BGInfo/XXXXXX.bgi
It took 5 seconds to download XXXXXX.jpg to C:\XXXXXX from this URL: https://XXXXXX/files/BGInfo/XXXXXX.jpg
C:\XXXXXX\BGInfo64.exe\C:\XXXXXX\XXXXXX.bgi /SILENT /TIMER:0 /NOLICPROMPT
XXXXXX

Hard to troubleshoot this without all the exact code/setup, but try:

$ArgPathID = "`"$filelocation\$XXClientID.bgi`"","/SILENT","/TIMER:0","/NOLICPROMPT"

That formats the output on multiple lines when I attempt to use. I’m still surprised I guess that this isn’t common place. Are other users not using unique variables based on each client?

Sorry, that should have been an array:

$ArgPathID = @("`"$filelocation\$XXClientID.bgi`"","/SILENT","/TIMER:0","/NOLICPROMPT")

I don’t use bginfo, never seen a need. For DNSFilter I do this, but apparently that’s not working in your case.

$arguments = "/qn /i $homepath\dnsfilter.msi NKEY=$sitekey TRAYICON=disabled ARPSYSTEMCOMPONENT=1"
Start-Process -FilePath msiexec -ArgumentList $arguments -Wait

In a watered down attempt;

Import-Module $env:SyncroModule
$filelocation = "C:\MSP"
$ArgPathID = @"
$filelocation\$MSPClientID.bgi /SILENT /TIMER:0 /NOLICPROMPT
"@
$SixT4Bit = "$filelocation\BGInfo64.exe"
$RunString = $SixT4Bit +" "+ $ArgPathID




### For $filelocation include full path. Example: C:\temp\
### For $filename include file name and extension. Example: syncro.exe


#Confirmation Message
Write-Output $RunString
#Start-Process $RunString

Write-Output -FilePath $SixT4Bit -ArgumentList $ArgPathID
Start-Process -FilePath $SixT4Bit -ArgumentList $ArgPathID

Resulting Error:

C:\MSP\BGInfo64.exe C:\MSP\MSP.bgi /SILENT /TIMER:0 /NOLICPROMPT
-FilePath
C:\MSP\BGInfo64.exe
-ArgumentList
C:\MSP\MSP.bgi /SILENT /TIMER:0 /NOLICPROMPT
error> Start-Process : This command cannot be run due to the error: The system cannot find the file specified.
error> At C:\ProgramData\Syncro\bin\ba734c2e-8b08-4c23-9ad1-7f723f1b61fb.ps1:23 char:1
error> + Start-Process -FilePath $SixT4Bit -ArgumentList $ArgPathID
error> + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error>     + CategoryInfo          : InvalidOperation: (:) [Start-Process], InvalidOperationException
error>     + FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand
error>  

I can get it to display the line perfectly still, but can’t get it to actually execute as written…

So after continued trial and error I’ve found that if use the run as SYSTEM it can’t run BGInfo and pass variables properly. If I run as Current User it works as expected. Any idea as to why the exact same would work as one and not the other for powershell? Presumably something to do with security. My test machine is Windows 11.

Oh, well that’s logical, yes. Even if it does run as SYSTEM you wouldn’t see any change as there’s no desktop for the SYSTEM user. Definitely would need to run as Current User. That does mean if the script runs when the user isn’t logged in that the script will fail though, unfortunately.

Coincidentally I just came across this in a Discord group that might be of use, it makes a shortcut in the all users startup folder

if (!(Test-Path -Path "C:\BGInfo")) {
    New-Item -Path "C:\" -Name "BGInfo" -ItemType "directory" | Out-Null
}
$files = "bg.bgi", "Bginfo.exe", "Bginfo64.exe"
Write-Output "Downloading BGInfo Files"
foreach ($file in $files) {
    $url = "https://domain.com/1p92unbr987nbcv08zw67sbv086b1/$file"
    $path = "C:\BGInfo\$file"
    try {
        (New-Object Net.WebClient).DownloadFile($url, $path) 
    } catch {
        throw "Unable to download $file"
    }
}
Write-Output "Creating BGInfo Shortcut in All Users startup"
if ([Environment]::Is64BitOperatingSystem) {
    $objShell = New-Object -ComObject ("WScript.Shell")
    $objShortCut = $objShell.CreateShortcut("C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\BGInfo.lnk")
    $objShortCut.TargetPath ="C:\BGInfo\BGInfo64.exe"
    $objShortCut.Arguments = "c:\BGInfo\bg.bgi /silent /timer0 /nolicprompt"
    $objShortCut.WorkingDirectory = "C:\BGInfo\"
    $objShortCut.Save()
} else {
    $objShell = New-Object -ComObject ("WScript.Shell")
    $objShortCut = $objShell.CreateShortcut("C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\BGInfo.lnk")
    $objShortCut.TargetPath ="C:\BGInfo\BGInfo.exe"
    $objShortCut.Arguments = "c:\BGInfo\bg.bgi /silent /timer0 /nolicprompt"
    $objShortCut.WorkingDirectory = "C:\BGInfo\"
    $objShortCut.Save()
}

Perhaps this would be of use to you as well. I wrote this a while back to help someone else who just wanted to standardize a wallpaper deployment as well. Note this will force log off users so it can mount their registry hives to set the proper items…



Function New-FileDownload {
    param(
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Url,
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Destination
    )
    $webClient = New-Object System.Net.WebClient
    $webClient.DownloadFile($Url, $Destination)
    if (Test-Path -LiteralPath $Destination) {
        Write-Verbose "File downloaded Successfully"
        return $true
    }
    else {
        Write-Verbose "File download Failed"
        return $false
    }
}

$ImageURL = "ENTERIMAGEURLIFDOWNLOADINGFROMEXTERNAL"
$Destination = "$($env:systemdrive)\Users\Public\Pictures\wallpaper.png"
$ImageDownload = New-FileDownload -Url $ImageURL -Destination $Destination
if ($ImageDownload) {
    Write-Output "Image downloaded. Continuing..."
}
else {
    Write-Output "Failed to download. Exiting."
    Exit 1
}

$Users = (Get-ChildItem "$($env:systemdrive)\users").Name

foreach ($User in $Users) {
    if ($User -eq $env:username) {
        Set-ItemProperty -Path "Registry::HKEY_CURRENT_USER\Control Panel\Desktop" -Name "Wallpaper" -value "$Destination"
    }
    if ($User -eq "Public" -or $User -eq "Administrator" -or $User -eq "Default") {
        Write-Output "Skipping $User"
    }
    else {
        $Sessions = Query Session
        $SessionID = $Sessions | Where-Object { $_ -match "$($User)" }
        if ($SessionID) {
            $ID = $SessionID.Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)
            LogOff $ID[2]
            Start-Sleep -Seconds 20
        }
        $LoadHive = REG LOAD HKU\temp "$($env:systemdrive)\Users\$user\ntuser.dat"
        if ($LoadHive -match "successfully") {
            Set-ItemProperty -Path "Registry::HKEY_USERS\Temp\Control Panel\Desktop" -Name "Wallpaper" -value "$Destination"
            Write-Output "Image set for $User."
            [GC]::Collect()
            [GC]::WaitForPendingFinalizers()
            $UnloadHive = REG UNLOAD HKU\temp
            if ($UnloadHive -match "successfully") {
                Write-Output "Hive unloaded successfully."
            } 
            else {
                Write-Output "Failed to unload hive. Exiting."
                Exit 1
            }
        }
        else {
            Write-Output "Failed to load Hive for $User"
        }
    }
}

RUNDLL32.EXE USER32.DLL, UpdatePerUserSystemParameters , 1 , True