Command executes localy just fine but gets skipped via SCCM

Hi,

im trying to deploy the software “Rustdesk” with PSADT via SCCM. Locally it install/uninstall perfectly fine. Trying to create a file as “detection method” for SCCM in the PSADT script, locally it creates folder and file but if I deploy it via SCCM it just skips the creation of these files.
I’m really dont have any ideas anymore. Do someone have a helpful tip for me or maybe got a solution?

Kind regards from Germany

This ‘sounds’ like it could be a permissions issue when creating the files (or when it is being deployed by SCCM the files are not being created in the loacation you expect).
Could you share your PSADT Deploy-Application.ps1 file (or at least some snippets of the code from the Pre-Installation section upto and including the Post-Installation section)?

N.B. Please remember to paste any code between three back ticks ` before and three back ticks ` after your code block, alternatively you can paste your code, then select all lines on your code and press Ctrl + E which will automatically put the code formatting in place.

This is so the code outputs correctly, e.g.

# This is my code example

Of course I can share the code. It’s very simple nothing special. In previous versions of that software it worked in a similar way but with the new one every detection method I tried like checking for an registry key or folder/file it always install the software but gives an error…

- The install deployment type is broken down into 3 main sections/phases: Pre-Install, Install, and Post-Install.

The script dot-sources the AppDeployToolkitMain.ps1 script which contains the logic and functions required to install or uninstall an application.

PSApppDeployToolkit is licensed under the GNU LGPLv3 License - (C) 2023 PSAppDeployToolkit Team (Sean Lillis, Dan Cunningham and Muhammad Mashwani).

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the
Free Software Foundation, either version 3 of the License, or any later version. This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.

.PARAMETER DeploymentType

The type of deployment to perform. Default is: Install.

.PARAMETER DeployMode

Specifies whether the installation should be run in Interactive, Silent, or NonInteractive mode. Default is: Interactive. Options: Interactive = Shows dialogs, Silent = No dialogs, NonInteractive = Very silent, i.e. no blocking apps. NonInteractive mode is automatically set if it is detected that the process is not user interactive.

.PARAMETER AllowRebootPassThru

Allows the 3010 return code (requires restart) to be passed back to the parent process (e.g. SCCM) if detected from an installation. If 3010 is passed back to SCCM, a reboot prompt will be triggered.

.PARAMETER TerminalServerMode

Changes to "user install mode" and back to "user execute mode" for installing/uninstalling applications for Remote Desktop Session Hosts/Citrix servers.

.PARAMETER DisableLogging

Disables logging to file for the script. Default is: $false.

.EXAMPLE

powershell.exe -Command "& { & '.\Deploy-Application.ps1' -DeployMode 'Silent'; Exit $LastExitCode }"

.EXAMPLE

powershell.exe -Command "& { & '.\Deploy-Application.ps1' -AllowRebootPassThru; Exit $LastExitCode }"

.EXAMPLE

powershell.exe -Command "& { & '.\Deploy-Application.ps1' -DeploymentType 'Uninstall'; Exit $LastExitCode }"

.EXAMPLE

Deploy-Application.exe -DeploymentType "Install" -DeployMode "Silent"

.INPUTS

None

You cannot pipe objects to this script.

.OUTPUTS

None

This script does not generate any output.

.NOTES

Toolkit Exit Code Ranges:
- 60000 - 68999: Reserved for built-in exit codes in Deploy-Application.ps1, Deploy-Application.exe, and AppDeployToolkitMain.ps1
- 69000 - 69999: Recommended for user customized exit codes in Deploy-Application.ps1
- 70000 - 79999: Recommended for user customized exit codes in AppDeployToolkitExtensions.ps1

.LINK

https://psappdeploytoolkit.com
#>


[CmdletBinding()]
Param (
    [Parameter(Mandatory = $false)]
    [ValidateSet('Install', 'Uninstall', 'Repair')]
    [String]$DeploymentType = 'Install',
    [Parameter(Mandatory = $false)]
    [ValidateSet('Interactive', 'Silent', 'NonInteractive')]
    [String]$DeployMode = 'Interactive',
    [Parameter(Mandatory = $false)]
    [switch]$AllowRebootPassThru = $false,
    [Parameter(Mandatory = $false)]
    [switch]$TerminalServerMode = $false,
    [Parameter(Mandatory = $false)]
    [switch]$DisableLogging = $false
)

Try {
    ## Set the script execution policy for this process
    Try {
        Set-ExecutionPolicy -ExecutionPolicy 'ByPass' -Scope 'Process' -Force -ErrorAction 'Stop'
    }
    Catch {
    }

    ##*===============================================
    ##* VARIABLE DECLARATION
    ##*===============================================
    ## Variables: Application
    [String]$appVendor = ''
    [String]$appName = ''
    [String]$appVersion = ''
    [String]$appArch = ''
    [String]$appLang = 'EN'
    [String]$appRevision = '01'
    [String]$appScriptVersion = '1.0.0'
    [String]$appScriptDate = 'XX/XX/20XX'
    [String]$appScriptAuthor = '<author name>'
    ##*===============================================
    ## Variables: Install Titles (Only set here to override defaults set by the toolkit)
    [String]$installName = ''
    [String]$installTitle = ''

    ##* Do not modify section below
    #region DoNotModify

    ## Variables: Exit Code
    [Int32]$mainExitCode = 0

    ## Variables: Script
    [String]$deployAppScriptFriendlyName = 'Deploy Application'
    [Version]$deployAppScriptVersion = [Version]'3.9.3'
    [String]$deployAppScriptDate = '02/05/2023'
    [Hashtable]$deployAppScriptParameters = $PsBoundParameters

    ## Variables: Environment
    If (Test-Path -LiteralPath 'variable:HostInvocation') {
        $InvocationInfo = $HostInvocation
    }
    Else {
        $InvocationInfo = $MyInvocation
    }
    [String]$scriptDirectory = Split-Path -Path $InvocationInfo.MyCommand.Definition -Parent

    ## Dot source the required App Deploy Toolkit Functions
    Try {
        [String]$moduleAppDeployToolkitMain = "$scriptDirectory\AppDeployToolkit\AppDeployToolkitMain.ps1"
        If (-not (Test-Path -LiteralPath $moduleAppDeployToolkitMain -PathType 'Leaf')) {
            Throw "Module does not exist at the specified location [$moduleAppDeployToolkitMain]."
        }
        If ($DisableLogging) {
            . $moduleAppDeployToolkitMain -DisableLogging
        }
        Else {
            . $moduleAppDeployToolkitMain
        }
    }
    Catch {
        If ($mainExitCode -eq 0) {
            [Int32]$mainExitCode = 60008
        }
        Write-Error -Message "Module [$moduleAppDeployToolkitMain] failed to load: `n$($_.Exception.Message)`n `n$($_.InvocationInfo.PositionMessage)" -ErrorAction 'Continue'
        ## Exit the script, returning the exit code to SCCM
        If (Test-Path -LiteralPath 'variable:HostInvocation') {
            $script:ExitCode = $mainExitCode; Exit
        }
        Else {
            Exit $mainExitCode
        }
    }

    #endregion
    ##* Do not modify section above
    ##*===============================================
    ##* END VARIABLE DECLARATION
    ##*===============================================


    If ($deploymentType -ine 'Uninstall' -and $deploymentType -ine 'Repair') {
        ##*===============================================
        ##* PRE-INSTALLATION
        ##*===============================================
        [String]$installPhase = 'Pre-Installation'

        ## Show Welcome Message, close Internet Explorer if required, allow up to 3 deferrals, verify there is enough disk space to complete the install, and persist the prompt
        Show-InstallationWelcome -CloseApps 'rustdesk' -AllowDefer -DeferTimes 3 -CheckDiskSpace -PersistPrompt

        ## Show Progress Message (with the default message)
        Show-InstallationProgress

        ## <Perform Pre-Installation tasks here>


        ##*===============================================
        ##* INSTALLATION
        ##*===============================================
        [String]$installPhase = 'Installation'

        ## Handle Zero-Config MSI Installations
        If ($useDefaultMsi) {
            [Hashtable]$ExecuteDefaultMSISplat = @{ Action = 'Install'; Path = $defaultMsiFile }; If ($defaultMstFile) {
                $ExecuteDefaultMSISplat.Add('Transform', $defaultMstFile)
            }
            Execute-MSI @ExecuteDefaultMSISplat; If ($defaultMspFiles) {
                $defaultMspFiles | ForEach-Object { Execute-MSI -Action 'Patch' -Path $_ }
            }
        }

        ## <Perform Installation tasks here>
        ## <Perform Installation tasks here>
        New-Item -Path 'C:\Temp\RustDesk' -ItemType Directory -ErrorAction SilentlyContinue -Force
        Start-Sleep -seconds 2
        New-Item C:\Temp\RustDesk\RDD.txt -ErrorAction SilentlyContinue -Force
        Start-Sleep -seconds 2
        Set-Content C:\Temp\RustDesk\RDD.txt 'This file is for SCCM Detection only.' -ErrorAction SilentlyContinue -Force
        Start-Sleep -seconds 2
        Execute-Process -Path "rustdesk-1.2.3-x86_64.exe" -Parameters "--silent-install" -PassThru -CreateNoWindow
        Start-Sleep -seconds 5
        
        
        ##*===============================================
        ##* POST-INSTALLATION
        ##*===============================================
        [String]$installPhase = 'Post-Installation'

        ## <Perform Post-Installation tasks here>

        ## Display a message at the end of the install
        If (-not $useDefaultMsi) {
            Show-InstallationPrompt -Message 'You can customize text to appear at the end of an install or remove it completely for unattended installations.' -ButtonRightText 'OK' -Icon Information -NoWait
        }
    }
    ElseIf ($deploymentType -ieq 'Uninstall') {
        ##*===============================================
        ##* PRE-UNINSTALLATION
        ##*===============================================
        [String]$installPhase = 'Pre-Uninstallation'

        ## Show Welcome Message, close Internet Explorer with a 60 second countdown before automatically closing
        Show-InstallationWelcome -CloseApps 'iexplore' -CloseAppsCountdown 60

        ## Show Progress Message (with the default message)
        Show-InstallationProgress

        ## <Perform Pre-Uninstallation tasks here>


        ##*===============================================
        ##* UNINSTALLATION
        ##*===============================================
        [String]$installPhase = 'Uninstallation'

        ## Handle Zero-Config MSI Uninstallations
        If ($useDefaultMsi) {
            [Hashtable]$ExecuteDefaultMSISplat = @{ Action = 'Uninstall'; Path = $defaultMsiFile }; If ($defaultMstFile) {
                $ExecuteDefaultMSISplat.Add('Transform', $defaultMstFile)
            }
            Execute-MSI @ExecuteDefaultMSISplat
        }

        ## <Perform Uninstallation tasks here>
        Execute-Process -CreateNoWindow -Path "rustdesk-1.2.3-x86_64.exe" -Parameters "--uninstall"
        
        Start-Sleep -seconds 2
        Remove-Item -Path "C:\Users\$Env:UserName\AppData\Roaming\RustDesk\" -Recurse -ErrorAction SilentlyContinue -Force
        
        Start-Sleep -seconds 2
        Remove-Item -Path "C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\RustDesk\" -Recurse -ErrorAction SilentlyContinue -Force
        
        Start-Sleep -seconds 2
        Remove-Item -Path "$env:ProgramFiles\RustDesk\" -Recurse -ErrorAction SilentlyContinue -Force

        ##*===============================================
        ##* POST-UNINSTALLATION
        ##*===============================================
        [String]$installPhase = 'Post-Uninstallation'

        ## <Perform Post-Uninstallation tasks here>


    }
    ElseIf ($deploymentType -ieq 'Repair') {
        ##*===============================================
        ##* PRE-REPAIR
        ##*===============================================
        [String]$installPhase = 'Pre-Repair'

        ## Show Welcome Message, close Internet Explorer with a 60 second countdown before automatically closing
        Show-InstallationWelcome -CloseApps 'iexplore' -CloseAppsCountdown 60

        ## Show Progress Message (with the default message)
        Show-InstallationProgress

        ## <Perform Pre-Repair tasks here>

        ##*===============================================
        ##* REPAIR
        ##*===============================================
        [String]$installPhase = 'Repair'

        ## Handle Zero-Config MSI Repairs
        If ($useDefaultMsi) {
            [Hashtable]$ExecuteDefaultMSISplat = @{ Action = 'Repair'; Path = $defaultMsiFile; }; If ($defaultMstFile) {
                $ExecuteDefaultMSISplat.Add('Transform', $defaultMstFile)
            }
            Execute-MSI @ExecuteDefaultMSISplat
        }
        ## <Perform Repair tasks here>

        ##*===============================================
        ##* POST-REPAIR
        ##*===============================================
        [String]$installPhase = 'Post-Repair'

        ## <Perform Post-Repair tasks here>


    }
    ##*===============================================
    ##* END SCRIPT BODY
    ##*===============================================

    ## Call the Exit-Script function to perform final cleanup operations
    Exit-Script -ExitCode $mainExitCode
}
Catch {
    [Int32]$mainExitCode = 60001
    [String]$mainErrorMessage = "$(Resolve-Error)"
    Write-Log -Message $mainErrorMessage -Severity 3 -Source $deployAppScriptFriendlyName
    Show-DialogBox -Text $mainErrorMessage -Icon 'Stop'
    Exit-Script -ExitCode $mainExitCode
}

OK, so a few things to debug here…
But before I do I’d recommend you do a little more customising of the script so it is more re-usable for future releases
I’ve noticed you have not defined any of the Variables in this section:

##*===============================================
    ##* VARIABLE DECLARATION
    ##*===============================================
    ## Variables: Application
    [String]$appVendor = ''
    [String]$appName = ''
    [String]$appVersion = ''
    [String]$appArch = ''
    [String]$appLang = 'EN'
    [String]$appRevision = '01'
    [String]$appScriptVersion = '1.0.0'
    [String]$appScriptDate = 'XX/XX/20XX'
    [String]$appScriptAuthor = '<author name>'
    ##*===============================================

Although these settings are not entirely required it does make the dialogs and log file names a lot clearer and the populated details are useful as they can easily be presented to your users in the various PSADT dialogs
If I may be so bold I’d suggest:

##*===============================================
    ##* VARIABLE DECLARATION
    ##*===============================================
    ## Variables: Application
    [String]$appVendor = 'Purslane Ltd'
    [String]$appName = 'Rustdesk'
    [String]$appVersion = '1.2.3'
    [String]$appArch = 'x64'
    [String]$appLang = 'EN'
    [String]$appRevision = '01'
    [String]$appScriptVersion = '1.0.0'
    [String]$appScriptDate = '19/10/2023'
    [String]$appScriptAuthor = 'Your Name'
    ##*===============================================

‘Assuming’ the installers are always available using the same naming convention, “rustdesk-1.2.3-x86_64.exe”, “rustdesk-1.2.4-x86_64.exe”, “rustdesk-1.3.0-x86_64.exe” etc. The above would also be useful for reducing the modifications you need to make to the script, so on the Install and Uninstall commands, you could replace the version number with $($appVersion). You could also use this info to inject into you RDD.txt file.
e.g. Install:

Execute-Process -Path "rustdesk-$($appVersion)-x86_64.exe" -Parameters "--silent-install" -PassThru -CreateNoWindow

Uninstall:

Execute-Process -CreateNoWindow -Path "rustdesk-$($appVersion)-x86_64.exe" -Parameters "--uninstall"

Add to text file (Note change of quotes)

Set-Content C:\Temp\RustDesk\RDD.txt "This file is for SCCM Detection only for $($appName) Version: $($appVersion)." -ErrorAction SilentlyContinue -Force

So, on to the debugging…

I am not completely familiar with the settings in SCCM (I use Intune), but in which context is your deployment set to install as - System or as the user?
If being deployed as the user, do your users have admin rights on their machines? (N.B. Definitely NOT security best practice!)
Because if it is installed as the user and they do not have admin rights:

New-Item -Path 'C:\Temp\RustDesk' -ItemType Directory -ErrorAction SilentlyContinue -Force

They may not have permission to create the C:\Temp\RustDesk folder (they may not by default have the rights to create folders off the root of C:\), They may also be unable create or modify the RDD.txt file.
Also, by having the -ErrorAction SilentlyContinue parameter set you will not know whether it has succeded or failed, plus, because you are using native PowerShell commands New-Item & Set-Content these events would not be logged to the PSADT log file, @That-Annoying-Guy wrote a good explanation how to log non-PSADT commands to the PSADT log file:

It might be worth reviewing this advice and adjusting your script.

I am going to assume you need to run this deployment as system because in your uninstall commands only the first command would likely work if it was running as a user without admin priviledges

        Start-Sleep -seconds 2
        Remove-Item -Path "C:\Users\$Env:UserName\AppData\Roaming\RustDesk\" -Recurse -ErrorAction SilentlyContinue -Force
        
        Start-Sleep -seconds 2
        Remove-Item -Path "C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\RustDesk\" -Recurse -ErrorAction SilentlyContinue -Force
        
        Start-Sleep -seconds 2
        Remove-Item -Path "$env:ProgramFiles\RustDesk\" -Recurse -ErrorAction SilentlyContinue -Force

So the only major question is - in what context is this being installed?

I hope that gives you a start.
:grinning:

1 Like