PassThru not working when using SYSTEM account or script location issue?

I have a script that works completely fine when running as admin, locally on a PC. However, when running as SYSTEM (via SCCM package), The exit codes are not being returned from Start-Process. When it shows Exit Code: 0 on my machine, it shows Exit Code: and has various other failures for the installs (not actual powershell errors, but it does not seem to be working as it should. Here is an example of the code I have:

Try {
    "Installing Flash ActiveX" | Out-File $log -Append -Force
    $InstallActiveX = start-process "msiexec.exe" `
                    -arg "/I install_flash_player_20_active_x.msi /qn /norestart" `
                    -Wait -ea stop -PassThru -NoNewWindow
    $ExitCode = $InstallActiveX.ExitCode | Out-String
    $ExitCode = $ExitCode.Trim()
}
Catch {
      "Error: $($_.Exception.Message)" | Out-File $log -Force -Append
      "Error Code: $ExitCode" | Out-File $log -Force -Append
}
Finally {
        "Exit Code: $ExitCode" | Out-File $log -Force -Append
}

The files get copied to their SCCM cached location and then the script runs and executes the files locally under the system account. Why is this behaving completely different then when I run it locally on my machine? Do I have to reference the path of the location for the script instead of just using

start-process “msiexec.exe” -arg “/I install_flash_player_20_active_x.msi /qn /norestart”
?
I have a feeling it is not even running the msi files.

Here is the command line that is used to run the package: powershell.exe -nologo -noprofile -noninteractive -File .\FlashRemediation.ps1

I’ve got a powershell script for pretty much the exact same thing, the only difference is I actually call the current path up to make sure it can find the installer which may help you. Essential the path is always in the context of where the script is running this way:

#Set Install Variables
$Application = '\setup\awesomeinstaller.exe'
$Arguments = '/silent  /Variable "blah blah" /otherstuff'

#If PSVersion is too early, generate $PSScriptRoot variable
If (!$PSScriptRoot) {
	$PSSCriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
    }

#Try the Install and return results
Try {
    $AppFullPath = $PSScriptRoot+'\'+$Application
    start-process -FilePath $AppFullPath -ArgumentList $Arguments -wait
    }
Catch {
    Write-Error -Message $_
    Exit 1
    }
Exit 0

Been using it for a few years and just tweaking the top two variables per package.

Added

$dir = Split-Path $MyInvocation.MyCommand.Path

Try {
    "Installing Flash Plugin" | Out-File $log -Append -Force
    $InstallPlugin = start-process "msiexec.exe" -arg "/I $dir\install_flash_player_20_plugin.msi /qn /norestart" -Wait -ea stop -PassThru -NoNewWindow
    $ExitCode = $InstallPlugin.ExitCode | Out-String
    $ExitCode = $ExitCode.Trim()
}
Catch {
      "Error: $($_.Exception.Message)" | Out-File $log -Force -Append
      "Error Code: $ExitCode" | Out-File $log -Force -Append
}
Finally {
        "Exit Code: $ExitCode" | Out-File $log -Force -Append
}

So I basically added in the variable for $dir and added it to the path for the MSI. That look about right? Seems to be working locally at least. Weird part is, I have another uninstall that doesn’t even use a local MSI, but just an uninstall string that is found in the registry and I still receive Exit Code: (null). It is not even trying to grab anything in the same directory as the script so I’m not sure why I would get a blank exit code for that as well (only with SCCM script package, not local):

 
ForEach ($app in $FlashApps) {

        If ($app.UninstallString) {
            Try {
                $uninstall = $app.UninstallString -Replace "msiexec.exe","" -Replace "/I","" -Replace "/X",""
                $uninstall = $uninstall.Trim()
                "FlashUtil32 or FlashUtil64 doesn't exist - Uninstalling $($app.DisplayName)" | Out-File $log -Force -Append
                $UninstallActiveX = start-process "msiexec.exe" -arg "/X $uninstall /qn /norestart" -Wait -PassThru -ea stop -NoNewWindow
                $ExitCode = $UninstallActiveX.ExitCode | Out-String
                $ExitCode = $ExitCode.Trim()
                }
            Catch {
                  "Error: $($_.Exception.Message)" | Out-File $log -Force -Append
                  "Error Code: $ExitCode" | Out-File $log -Force -Append
            }
            Finally {
                    "Exit Code: $ExitCode" | Out-File $log -Force -Append
            }
        }
    }

Well something of note when playing in the world of SCCM: just because SCCM expects an expect code 0, doesn’t mean it will get one from the installer. That’s why I deliberately end my install script with Exit 0 because at the end of the day: you can’t trust everyone to write their .msi the same way.

Also, II’d highly recommend you grab psexec so you can open up a command prompt in the system context for testing your scripts (as that’s what SCCM will run under).

We are kind of “beyond PS” honestly as you admited it runs fine in the user context. This reads more like understanding the ccmcache directory and context that the SCCM Agent runs under.