Deployment script and command reference
- Last updated
- Save as PDF
Who is this article for?
Incydr, yes.
CrashPlan for Enterprise, yes.
Code42 for Enterprise, yes.
CrashPlan for Small Business, no.
Callstack: at xml.select() at (Template:Code42/SiteMapThisPage), /content/body/pre, line 30, column 11 at template() at (Administrator/Cloud/Planning_and_installing/Manage_app_installations_in_your_Code42_environment/Deployment_script_and_command_reference), /content/body/pre[1], line 6, column 9
Overview
When you create a deployment policy in the Code42 console, Code42 generates two essential pieces of code:
- User-detection scripts
- Arguments for Code42 app install commands
This article provides details about both, for Windows, Mac, and Linux devices.
Considerations
This article assumes you understand the introduction to deployment provided by the article Prepare to deploy Code42 client apps.
- These instructions apply to the Code42 cloud. If you work in an on-premises Code42 environment, see Manage app installations in your Code42 environment.
- To use these deployment tools, you need to sign in to your Code42 console as a user with the Customer Cloud Admin role.
- In the Code42 federal environment, app installations must be deployed with a deployment policy to ensure the use of FIPS encryption in the Code42 app. Users cannot download the installation package from the Code42 console or an email message.
Deployment is a secure process:
- During installation, device-server communications are encrypted.
- Devices can use a proxy to reach your authority server. See the PROXY_URL parameter.
- Deployment can run silently, with no intervention from users at devices.
Windows
For Code42 apps on Windows devices, a deployment policy provides:
- A user detection script to provide the Code42 app with a username and home directory for the device. The script can also optionally specify the user's organization.
- Installation properties to serve as the arguments string to a Code42 app install command.
Windows user detection script
When you create a deployment policy, you must also create a custom user detection script. A user detection script examines the host device and provides the Code42 app with a username and home directory. The script resides on the Code42 cloud. The Code42 app retrieves it during the install process.
Because user names in the Code42 cloud must be email addresses, deployments for connection to the Code42 cloud always require a customized user detection script.
You need to create a custom script because Code42 usernames must be email addresses. If you need help, contact your Customer Success Manager (CSM) to engage the Professional Services team.
How the Windows script works
The user detection script for Windows:
- Uses the device's operating system to determine the most recent logged-on username.
- Calculates the typical home directory for that username.
The user detection script then reports these two values to a standard output.
To require users to enter their usernames manually, do not use a detection script. In the deployment policy, leave all operating systems deselected to create a deployment policy without a user detection script.
Tips to create a custom Windows script
Create a custom script and paste your script into your deployment policy. If you need help, contact your Customer Success Manager (CSM) for enterprise support.
When creating your custom script, be aware of the following:
- Every script must end by echoing values for two variables.
echo C42_USERNAME=<value> echo C42_USER_HOME=<value>
- In the Code42 cloud, usernames must be email addresses.
echo C42_USERNAME=%current_user%@example.com
- Optionally, you can also specify the the organization for the user. Use the registration key for the organization. If the organization is not defined, the user registers to the organization specified in the deployment policy.
echo C42_ORG_REG_KEY=<value>
- You must provide values. Null values and empty strings will not work.
- If you cannot write a script to provide a workable value, write a message for the username field of the Code42 app sign in dialog, for example:
echo C42_USERNAME=Enter name and click Sign in
- The values cannot include either single (') or double (") quotation marks.
Example Windows user detection scripts
Following are example user detection scripts for the Windows platform. For help with these scripts, contact your Customer Success Manager (CSM) to engage the Professional Services team.
General usage:
- Replace "domain.com" with your domain name.
- Add users you want to exclude from processing to the blacklist in each script (look for "ExcludedUsers" or "Excluded Users"). This helps IT teams ensure that the Code42 installation is set up for the correct end users, and not the support staff setting up the Windows computers for the first time.
Explorer.exe with ADSI domain lookup script
Professional Services filename: UserDetect_ADSIDomainLookup.bat
The following script detects users running explorer.exe and performs an Active Directory Service Interfaces (ADSI) search against Active Directory to obtain the mail attribute for the users. The script sets the home directory by adding the username to the \Users directory path in Windows. You can adjust this script to look for any attribute in Active Directory, such as userPrincipalName or custom attributes. This script requires an active connection to a Windows domain and PowerShell v.4.0 or later.
<# : batch script @echo off setlocal cd %~dp0 powershell -executionpolicy bypass -Command "Invoke-Expression $([System.IO.File]::ReadAllText('%~f0'))" endlocal goto:eof #> function Find-User { Write-Log "Starting user detection..." $username = (Get-Process -IncludeUserName -Name explorer | Select-Object -ExpandProperty UserName).Split('\')[1] Write-Log "User name found ($username)" $searcher = [adsisearcher]"(samaccountname=$username)" $C42_USERNAME = ($searcher.FindOne().Properties.mail) Write-Log "Email found via ADSI search ($C42_USERNAME)" $ExcludedUsers = @( 'user1' 'user2' 'user3' 'admin' 'Administrator' 'admin-*' ) $ExcludedUsers | ForEach-Object { if ([string]::IsNullOrEmpty($C42_USERNAME) -or $username -like $_) { Write-Log "Excluded or null email address detected ($username). Will retry user detection in 60 minutes, or when reboot occurs." Write-Output "Excluded or null email address detected ($username). Will retry user detection in 60 minutes, or when reboot occurs." exit } } $wmiuser = Get-CimInstance Win32_UserAccount -Filter "Name = '$username'" $C42_USER_HOME = Get-CimInstance Win32_UserProfile -Filter "SID = '$($wmiuser.SID)'" | Select-Object -ExpandProperty LocalPath if (!$C42_USER_HOME) { Write-Log "User home query from WMI failed. Using fallback home detection method" $C42_USER_HOME = "$env:HOMEDRIVE\Users\$username" Write-Log "User home set by appending $username to home path ($C42_USER_HOME)" } ELSE { Write-Log "User home queried from WMI successfully ($C42_USER_HOME)" } Write-Log "Returning C42_USERNAME: $C42_USERNAME" Write-Log "Returning C42_USER_HOME: $C42_USER_HOME" Write-Host C42_USERNAME=$C42_USERNAME Write-Host C42_USER_HOME=$C42_USER_HOME } <# Helper functions below this point. Most likely these will not need to be edited. #> $PROC_LOG = "$env:HOMEDRIVE\ProgramData\CrashPlan\log\userDetect_Result.log" function Write-Log { [CmdletBinding()] Param ( [Parameter(Mandatory=$true, Position=0)] [string]$LogMessage ) Add-Content -Path $PROC_LOG -Value (Write-Output ("{0} - {1}" -f (Get-Date), $LogMessage)) } Find-User
Azure AD script
Professional Services filename: UserDetect_Azure.bat
This script detects a username that has joined the computer to Azure AD by looking at the Microsoft identity cache in the registry. This script requires PowerShell v.4.0 or later.
<# : batch script @echo off setlocal cd %~dp0 powershell -executionpolicy bypass -Command "Invoke-Expression $([System.IO.File]::ReadAllText('%~f0'))" endlocal goto:eof #> function Find-User { Write-Log "Starting user detection..." $username = (Get-Process -IncludeUserName -Name explorer | Select-Object -ExpandProperty UserName).Split('\')[1] Write-Log "User name found: ($username)" $C42_USERNAME = (Get-ItemProperty HKLM:SOFTWARE\Microsoft\IdentityStore\Cache\*\IdentityCache\* | Where-Object {$_.SAMName -eq $username} | Select-Object -Unique -ExpandProperty UserName) Write-Log "Email found in registry: ($C42_USERNAME)" $ExcludedUsers = @( 'user1' 'user2' 'user3' 'admin' 'Administrator' 'admin-*' ) $ExcludedUsers | ForEach-Object { if ([string]::IsNullOrEmpty($C42_USERNAME) -or $username -like $_) { Write-Log "Excluded or null email address detected ($username). Will retry user detection in 60 minutes, or when reboot occurs." Write-Output "Excluded or null email address detected ($username). Will retry user detection in 60 minutes, or when reboot occurs." exit } } $C42_USER_HOME = "$env:HOMEDRIVE\Users\$username" Write-Log "User home set by appending $username to home path ($C42_USER_HOME)" Write-Log "Returning C42_USERNAME: $C42_USERNAME" Write-Log "Returning C42_USER_HOME: $C42_USER_HOME" Write-Host C42_USERNAME=$C42_USERNAME Write-Host C42_USER_HOME=$C42_USER_HOME } <# Helper functions below this point. Most likely these will not need to be edited. #> $PROC_LOG = "$env:HOMEDRIVE\ProgramData\CrashPlan\log\userDetect_Result.log" function Write-Log { [CmdletBinding()] Param ( [Parameter(Mandatory=$true, Position=0)] [string]$LogMessage ) Add-Content -Path $PROC_LOG -Value (Write-Output ("{0} - {1}" -f (Get-Date), $LogMessage)) } Find-User
Explorer.exe script
Professional Services filename: UserDetect_Explorer_AppendDomain.bat
The following script detects users running explorer.exe and appends the domain of the email address. The script sets the home directory by adding the username to the \Users directory path in Windows. This script requires PowerShell v.4.0 or later.
<# : batch script @echo off setlocal cd %~dp0 powershell -executionpolicy bypass -Command "Invoke-Expression $([System.IO.File]::ReadAllText('%~f0'))" endlocal goto:eof #> function Find-User { Write-Log "Starting user detection..." $username = (Get-Process -IncludeUserName -Name explorer | Select-Object -ExpandProperty UserName).Split('\')[1] Write-Log "User name found ($username)" $C42_USERNAME = $username + '@domain.com' Write-Log "Email assembled by appending domain ($C42_USERNAME)" $ExcludedUsers = @( 'user1' 'user2' 'user3' 'admin' 'Administrator' 'admin-*' ) $ExcludedUsers | ForEach-Object { if ([string]::IsNullOrEmpty($C42_USERNAME) -or $username -like $_) { Write-Log "Excluded or null email address detected ($username). Will retry user detection in 60 minutes, or when reboot occurs." Write-Output "Excluded or null email address detected ($username). Will retry user detection in 60 minutes, or when reboot occurs." exit } } $wmiuser = Get-CimInstance Win32_UserAccount -Filter "Name = '$username'" $C42_USER_HOME = Get-CimInstance Win32_UserProfile -Filter "SID = '$($wmiuser.SID)'" | Select-Object -ExpandProperty LocalPath if (!$C42_USER_HOME) { Write-Log "User home query from WMI failed. Using fallback home detection method" $C42_USER_HOME = "$env:HOMEDRIVE\Users\$username" Write-Log "User home set by appending $username to home path ($C42_USER_HOME)" } ELSE { Write-Log "User home queried from WMI successfully ($C42_USER_HOME)" } Write-Log "Returning C42_USERNAME: $C42_USERNAME" Write-Log "Returning C42_USER_HOME: $C42_USER_HOME" Write-Host C42_USERNAME=$C42_USERNAME Write-Host C42_USER_HOME=$C42_USER_HOME } <# Helper functions below this point. Most likely these will not need to be edited. #> $PROC_LOG = "$env:HOMEDRIVE\ProgramData\CrashPlan\log\userDetect_Result.log" function Write-Log { [CmdletBinding()] Param ( [Parameter(Mandatory=$true, Position=0)] [string]$LogMessage ) Add-Content -Path $PROC_LOG -Value (Write-Output ("{0} - {1}" -f (Get-Date), $LogMessage)) } Find-User
Active Directory script
Professional Services filename: UserDetect_FirstLastName_ActiveDirectory.bat
The following script finds the real name of Active Directory users, joins the first name to the last name to create a username of firstname.lastname, and appends the domain of the email address. This script requires an active connection to a domain.
@echo off setlocal REM Gather user and home info. for /f "TOKENS=1,2,*" %%a in ('tasklist /FI "IMAGENAME eq explorer.exe" /FO LIST /V') do if /i "%%a %%b"=="User Name:" set _currdomain_user=%%c for /f "TOKENS=1,2 DELIMS=\" %%a in ("%_currdomain_user%") do set _currdomain=%%a & set currentuser=%%b for /f "tokens=2*" %%a in ('net user "%currentuser%" /domain ^| find /i "Full Name"') do set DisplayName=%%b set RealName=%DisplayName: =.% set Domain=@domain.com REM List of Excluded users that shouldn't be used for Code42 install. FOR %%G IN ("user1" "user2" "user3" "admin" "Administrator") DO ( IF /I "%currentuser%"=="%%~G" GOTO NOMATCH ) :MATCH REM Echo Values for Code42 Installer echo C42_USERNAME=%RealName%%DOMAIN% echo C42_USER_HOME=%HOMEDRIVE%\Users\%currentuser% GOTO :EOF :NOMATCH echo Excluded or null user detected (%currentuser%). Will retry user detection in 60 minutes, or when reboot occurs. GOTO :EOF
Local account script
Professional Services filename: UserDetect_FirstLastName_NoActiveDirectory.bat
The following script retrieves names from a local account, joins the first name to the last name to create a username of firstname.lastname, and appends the domain of the email address. This script needs the Full Name field for a local account to be populated with a user's first name and last name separated by a space. This script requires PowerShell v4.0 or later.
<# : batch script @echo off setlocal cd %~dp0 powershell -executionpolicy bypass -Command "Invoke-Expression $([System.IO.File]::ReadAllText('%~f0'))" endlocal goto:eof #> function Find-User { Write-Log "Starting user detection..." $username = (Get-Process -IncludeUserName -Name explorer | Select-Object -ExpandProperty UserName).Split('\')[1] Write-Log "User name found ($username)" $fullname = (Get-CimInstance -Class Win32_UserAccount -Filter "LocalAccount='True'" | Where-Object -Property Name -like $username).FullName Write-Log "Full name found ($fullname)" $C42_USERNAME = ($fullname -replace " ",".") + '@domain.com' Write-Log "Email assembled from full name ($C42_USERNAME)" $ExcludedUsers = @( 'user1' 'user2' 'user3' 'admin' 'Administrator' 'admin-*' ) $ExcludedUsers | ForEach-Object { if ([string]::IsNullOrEmpty($C42_USERNAME) -or $username -like $_) { Write-Log "Excluded or null email address detected ($username). Will retry user detection in 60 minutes, or when reboot occurs." Write-Output "Excluded or null email address detected ($username). Will retry user detection in 60 minutes, or when reboot occurs." exit } } $wmiuser = Get-CimInstance Win32_UserAccount -Filter "Name = '$username'" $C42_USER_HOME = Get-CimInstance Win32_UserProfile -Filter "SID = '$($wmiuser.SID)'" | Select-Object -ExpandProperty LocalPath if (!$C42_USER_HOME) { Write-Log "User home query from WMI failed. Using fallback home detection method" $C42_USER_HOME = "$env:HOMEDRIVE\Users\$username" Write-Log "User home set by appending $username to home path ($C42_USER_HOME)" } ELSE { Write-Log "User home queried from WMI successfully ($C42_USER_HOME)" } Write-Log "Returning C42_USERNAME: $C42_USERNAME" Write-Log "Returning C42_USER_HOME: $C42_USER_HOME" Write-Host C42_USERNAME=$C42_USERNAME Write-Host C42_USER_HOME=$C42_USER_HOME } <# Helper functions below this point. Most likely these will not need to be edited. #> $PROC_LOG = "$env:HOMEDRIVE\ProgramData\CrashPlan\log\userDetect_Result.log" function Write-Log { [CmdletBinding()] Param ( [Parameter(Mandatory=$true, Position=0)] [string]$LogMessage ) Add-Content -Path $PROC_LOG -Value (Write-Output ("{0} - {1}" -f (Get-Date), $LogMessage)) } Find-User
Text file script
Professional Services filename: UserDetect_ReadFromFile_User.bat
The following script reads a text file (default location C:\Temp\C42_User.txt) for the user email addresses, and sets the home directory by adding the username to the \Users directory path in Windows. This script requires PowerShell v4.0 or later.
<# : batch script @echo off setlocal cd %~dp0 powershell -executionpolicy bypass -Command "Invoke-Expression $([System.IO.File]::ReadAllText('%~f0'))" endlocal goto:eof #> function Find-User { Write-Log "Starting user detection..." $C42_USERNAME = Get-Content $env:HOMEDRIVE\temp\C42_User.txt Write-Log "Email read from file ($username)" $ExcludedUsers = @( 'user1' 'user2' 'user3' 'admin' 'Administrator' 'admin-*' ) $ExcludedUsers | ForEach-Object { if ([string]::IsNullOrEmpty($C42_USERNAME) -or $username -like $_) { Write-Log "Excluded or null email address detected ($username). Will retry user detection in 60 minutes, or when reboot occurs." Write-Output "Excluded or null email address detected ($username). Will retry user detection in 60 minutes, or when reboot occurs." exit } } $wmiuser = Get-CimInstance Win32_UserAccount -Filter "Name = '$username'" $C42_USER_HOME = Get-CimInstance Win32_UserProfile -Filter "SID = '$($wmiuser.SID)'" | Select-Object -ExpandProperty LocalPath if (!$C42_USER_HOME) { Write-Log "User home query from WMI failed. Using fallback home detection method" $C42_USER_HOME = "$env:HOMEDRIVE\Users\$username" Write-Log "User home set by appending $username to home path ($C42_USER_HOME)" } ELSE { Write-Log "User home queried from WMI successfully ($C42_USER_HOME)" } Write-Log "Returning C42_USERNAME: $C42_USERNAME" Write-Log "Returning C42_USER_HOME: $C42_USER_HOME" Write-Host C42_USERNAME=$C42_USERNAME Write-Host C42_USER_HOME=$C42_USER_HOME } <# Helper functions below this point. Most likely these will not need to be edited. #> $PROC_LOG = "$env:HOMEDRIVE\ProgramData\CrashPlan\log\userDetect_Result.log" function Write-Log { [CmdletBinding()] Param ( [Parameter(Mandatory=$true, Position=0)] [string]$LogMessage ) Add-Content -Path $PROC_LOG -Value (Write-Output ("{0} - {1}" -f (Get-Date), $LogMessage)) } Find-User
Last logged on user script
Professional Services filename: UserDetect_Registry_AppendDomain.bat
The following script detects which user last logged in using the LastLoggedOnUser registry value in HKLM, and appends the domain of the email address. The script sets the home directory by adding the username to the \Users directory path in Windows.
<# : batch script @echo off setlocal cd %~dp0 powershell -executionpolicy bypass -Command "Invoke-Expression $([System.IO.File]::ReadAllText('%~f0'))" endlocal goto:eof #> function Find-User { Write-Log "Starting user detection..." $username = (Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Authentication\LogonUI | Select-Object -ExpandProperty LastLoggedOnUser).Split('\')[1] Write-Log "User name found ($username)" $C42_USERNAME = $username + '@domain.com' Write-Log "Email assembled by appending domain ($C42_USERNAME)" $ExcludedUsers = @( 'user1' 'user2' 'user3' 'admin' 'Administrator' 'admin-*' ) $ExcludedUsers | ForEach-Object { if ([string]::IsNullOrEmpty($C42_USERNAME) -or $username -like $_) { Write-Log "Excluded or null email address detected ($username). Will retry user detection in 60 minutes, or when reboot occurs." Write-Output "Excluded or null email address detected ($username). Will retry user detection in 60 minutes, or when reboot occurs." exit } } $wmiuser = Get-CimInstance Win32_UserAccount -Filter "Name = '$username'" $C42_USER_HOME = Get-CimInstance Win32_UserProfile -Filter "SID = '$($wmiuser.SID)'" | Select-Object -ExpandProperty LocalPath if (!$C42_USER_HOME) { Write-Log "User home query from WMI failed. Using fallback home detection method" $C42_USER_HOME = "$env:HOMEDRIVE\Users\$username" Write-Log "User home set by appending $username to home path ($C42_USER_HOME)" } ELSE { Write-Log "User home queried from WMI successfully ($C42_USER_HOME)" } Write-Log "Returning C42_USERNAME: $C42_USERNAME" Write-Log "Returning C42_USER_HOME: $C42_USER_HOME" Write-Host C42_USERNAME=$C42_USERNAME Write-Host C42_USER_HOME=$C42_USER_HOME } <# Helper functions below this point. Most likely these will not need to be edited. #> $PROC_LOG = "$env:HOMEDRIVE\ProgramData\CrashPlan\log\userDetect_Result.log" function Write-Log { [CmdletBinding()] Param ( [Parameter(Mandatory=$true, Position=0)] [string]$LogMessage ) Add-Content -Path $PROC_LOG -Value (Write-Output ("{0} - {1}" -f (Get-Date), $LogMessage)) } Find-User
Windows command and arguments
Deployment policy command arguments need to be imported into your software management tool.
Commands and arguments are detailed here in case you need to modify them for some reason, or to help you deploy without a software management tool.
- To install a Code42 app for all users of a device, sign in to an account with administrative rights and issue a command like the following:
msiexec /i Code42_n.n.n_Win64.msi CP_ARGS="DEPLOYMENT_URL=https://.host &DEPLOYMENT_POLICY_TOKEN=0fb12341-246b-448d-b07f-c6573ad5ad02 &PROXY_URL=http://.host/fname.pac" CP_SILENT=true DEVICE_CLOAKED=false /norestart /qn
- To install for one user only, sign in as that user, and append the following three parameters to the command:
- ALLUSERS=2
- MSIINSTALLPERUSER=1
- INSTALL_PER_USER=1
Here are the individual parts of a command:
Element | Description |
msiexec /i | Windows command to install a product. |
Code42_n.n.n_Win64.msi |
Name of Code42 app installer file, version n.n.n. You must update the filename and version number to match the version being deployed.
In version 8.0 and earlier, the installer file used the format Code42CrashPlan_n.n.n_Win64.msi. |
CP_ARGS=" | Start of the installation properties copied from the deployment policy. |
DEPLOYMENT_URL= https://.host |
The address of your Code42 console. The Code42 app requests its deployment policy from this address. |
DEPLOYMENT_POLICY_TOKEN= | A unique ID string identifies each deployment policy. |
PROXY_URL= http://.host/fname.pac |
The address of a proxy auto-config file. The file tells a Code42 app how to communicate with Code42 through a proxy server. This argument is only present when your policy configuration says Use Org Proxy URL: Yes. If the argument is present, but has no value, the policy says use proxy: yes, but the organization has no proxy addresses defined. |
" | The value of CP_ARGS begins and ends with quote marks. |
CP_SILENT=true or false |
|
DEVICE_CLOAKED=true or false |
The Client Visibility setting for this organization.
This argument only affects client visibility during initial deployment. Future changes to the Client Visibility setting in the Code42 console are automatically pushed to the device. |
/norestart | The Windows operating system does not restart after the Code42 app installs. |
/qn | Quiet: The Windows installer does not open a console and does not prompt the user. |
/l* filename | Code42 app writes installation logs to filename. |
ALLUSERS=2 MSIINSTALLPERUSER=1 INSTALL_PER_USER=1 |
Add these three parameters if you wish to install the Code42 app for only the currently signed-in user, not all users of the device. |
ARPNOREMOVE= |
(Optional) Add this parameter to prevent users from uninstalling the Code42 app from the Start menu and Add/Remove programs in the Control Panel.
The |
Mac
For Code42 apps on Mac devices, a deployment policy provides:
- A detection script to provide the Code42 app with a username and home directory for the device. The script can also optionally specify the user's organization.
- A deploy.properties file to distribute along with the Code42 app installer package.
Before Code42 app installers can run properly, the deploy.properties file must be in placed in the management tool or the device's file system.
Mac user detection script
When you create a deployment policy, you must also create a custom user detection script. A user detection script examines the host device and provides the Code42 app with a username and home directory. The script resides on the Code42 cloud. The Code42 app retrieves it during the install process.
Because user names in the Code42 cloud must be email addresses, deployments for connection to the Code42 cloud always require a customized user detection script.
You need to create a custom script because Code42 usernames must be email addresses. If you need help, contact your Customer Success Manager (CSM) for enterprise support.
How the Mac script works
The user detection script for Mac:
- Uses the device's operating system to determine the most recent logged-on username.
- Calculates the typical home directory for that username.
The detection script then reports these two values to a standard output.
To require users to enter their usernames manually, do not use a detection script. In the deployment policy, leave all operating systems deselected to create a deployment policy without a user detection script.
Python scripting language runtime is deprecated in macOS
According to the macOS Catalina 10.15 Release Notes, Apple deprecated bundling scripting language runtimes, including Python, in the Catalina release of macOS. This means that any Mac user detection script using Python may break in a future macOS.
To prevent this problem, if your user detection script uses Python, replace this:
/usr/bin/python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "\n");'
with this:
echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ && ! /loginwindow/ { print $3 }'
Removing Python calls from your user detection script in this way ensures proper functioning of the script in future macOS versions.
Tips to create a custom Mac script
Create a custom script and paste your script into your deployment policy. If you need help, contact your Customer Success Manager (CSM) for enterprise support.
When creating your custom script, be aware of the following:
- Every script must end by echoing values for two variables:
echo "C42_USERNAME=<value>" echo "C42_USER_HOME=<value>"
- In the Code42 cloud, usernames must be email addresses.
echo "C42_USERNAME=${user}@example.com"
- Optionally, you can also specify the the organization for the user. Use the registration key for the organization. If the organization is not defined, the user registers to the organization specified in the deployment policy.
echo C42_ORG_REG_KEY=<value>
- You must provide values. Null values and empty strings will not work.
- If you cannot write a script to provide a workable value, write a message for the username field of the Code42 app sign in dialog, for example:
echo "C42_USERNAME=Enter name and click Sign in"
- The values cannot include either single (') or double (") quotation marks.
Example Mac user detection scripts
Following are example user detection scripts for the Mac platform. For help with these scripts, contact your Customer Success Manager (CSM) to engage the Professional Services team.
General usage:
- Replace "domain.com" with your domain name.
- Add users you want to exclude from processing to the blacklist in each script (look for "admin1|admin2|admin3"). This helps IT teams ensure that the Code42 installation is set up for the correct users, and not the support staff setting up the Mac computers for the first time.
Prompt for email script
Professional Services filename: Email_prompt_for_email.sh
The following script creates a pop-up notification at Code42 app installation time prompting users to input their email address, which automatically registers the users in Code42 and starts backup. This script provides an alternative when no other scripts work and you want the end user to manually input their email address.
If you are deploying Code42 app version 8.0 or earlier, replace the line tell application "Code42"
with tell application "CrashPlan"
in the sample below.
function main () { writeLog "Starting user detection..." local user=$(echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ && ! /loginwindow/ { print $3 }') writeLog "User name found ($user)" if [[ "$user" =~ ^(admin1|admin2|admin3)$ ]] || [[ -z "$user" ]]; then writeLog "Excluded or null username detected ($user). Will retry user detection in 60 minutes, or when reboot occurs." exit else local C42_USERNAME=$(ask 'CODE42 BACKUP - Please fill in your email address to continue: ') writeLog "Email found from user input ($C42_USERNAME)" local C42_USER_HOME=$(dscl . -read "/users/${user}" NFSHomeDirectory | cut -d ' ' -f 2) writeLog "Home directory read from dscl ($C42_USER_HOME)" writeLog "Returning C42_USERNAME=$C42_USERNAME" writeLog "Returning C42_USER_HOME=$C42_USER_HOME" echo "C42_USERNAME=$C42_USERNAME" echo "C42_USER_HOME=$C42_USER_HOME" fi } function writeLog () { echo "$(date) - $@" >> /Library/Logs/CrashPlan/userDetect_Result.log } function ask () { osascript <<EOF - 2>/dev/null tell application "Code42" activate text returned of (display dialog "$1" default answer "") end tell EOF } main "$@"
First initial and last name script
Professional Services filename: UserDetect_and_modify_firstinitial_dot_lastname.sh
The following script detects the locally logged-in users' first and last names and edits the string to create a username of firstinitial.lastname.
function main() { writeLog "Starting user detection..." local user=$(echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ && ! /loginwindow/ { print $3 }') writeLog "User name found ($user)" if [[ "$user" =~ ^(admin1|admin2|admin3)$ ]] || [[ -z "$user" ]]; then writeLog "Excluded or null username detected ($user). Will retry user detection in 60 minutes, or when reboot occurs." exit else realname="$(dscl . -read /Users/$user RealName | cut -d: -f2)" if [[ ($realname =~ ',') ]]; then writeLog "Real name contains a comma, assuming last, first format." realname="$(echo $realname | sed -e 's/[[:space:]]*//g' | grep -v "^$" | tr '[:upper:]' '[:lower:]' | awk -F , '{print substr($2,1,1) "." $1}')" else realname="$(echo $realname | sed -e 's/^[[:space:]]*//; s/[[:space:]]*$//; s/^\(.\)[^ ]* /\1./' | grep -v "^$" | tr '[:upper:]' '[:lower:]')" fi local C42_USERNAME="$realname@domain.com" writeLog "Email assembled from real name: $C42_USERNAME" local C42_USER_HOME=$(dscl . -read "/users/${user}" NFSHomeDirectory | cut -d ' ' -f 2) writeLog "Home directory read from dscl ($C42_USER_HOME)" writeLog "Returning C42_USERNAME=$C42_USERNAME" writeLog "Returning C42_USER_HOME=$C42_USER_HOME" echo "C42_USERNAME=$C42_USERNAME" echo "C42_USER_HOME=$C42_USER_HOME" fi } function writeLog () { echo "$(date) - $@" >> /Library/Logs/CrashPlan/userDetect_Result.log } main "$@"
First name and last name script
Professional Services filename: UserDetect_and_modify_firstname_dot_lastname.sh
The following script detects the locally logged-in users' first and last names and edits the string to create a username of firstname.lastname.
function main() { writeLog "Starting user detection..." local user=$(echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ && ! /loginwindow/ { print $3 }') writeLog "User name found ($user)" if [[ "$user" =~ ^(admin1|admin2|admin3)$ ]] || [[ -z "$user" ]]; then writeLog "Excluded or null username detected ($user). Will retry user detection in 60 minutes, or when reboot occurs." exit else realname="$(dscl . -read /Users/$user RealName | cut -d: -f2)" if [[ ($realname =~ ',') ]]; then writeLog "Real name contains a comma, assuming last, first format." realname="$(echo $realname | sed -e 's/[[:space:]]*//g' | grep -v "^$" | tr '[:upper:]' '[:lower:]' | awk -F , '{print $2 "." $1}')" else realname="$(echo $realname | sed -e 's/^[[:space:]]*//; s/[[:space:]]*$//; s/ /./' | grep -v "^$" | tr '[:upper:]' '[:lower:]')" fi local C42_USERNAME="$realname@domain.com" writeLog "Email assembled from real name: $C42_USERNAME" local C42_USER_HOME=$(dscl . -read "/users/${user}" NFSHomeDirectory | cut -d ' ' -f 2) writeLog "Home directory read from dscl ($C42_USER_HOME)" writeLog "Returning C42_USERNAME=$C42_USERNAME" writeLog "Returning C42_USER_HOME=$C42_USER_HOME" echo "C42_USERNAME=$C42_USERNAME" echo "C42_USER_HOME=$C42_USER_HOME" fi } function writeLog () { echo "$(date) - $@" >> /Library/Logs/CrashPlan/userDetect_Result.log } main "$@"
Text file script
Professional Services filename: UserDetect_from_text.sh
The following script reads the username from a text file (located by default at /tmp/Code42test.txt). Use when no other logical way of finding the username can be determined and no user interaction is desired.
function main() { writeLog "Starting user detection..." local user=$(echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ && ! /loginwindow/ { print $3 }') writeLog "User name found ($user)" if [[ "$user" =~ ^(admin1|admin2|admin3)$ ]] || [[ -z "$user" ]]; then writeLog "Excluded or null username detected ($user). Will retry user detection in 60 minutes, or when reboot occurs." exit else local C42_USERNAME=$(cat /tmp/Code42test.txt) writeLog "Email read from file: $C42_USERNAME" local C42_USER_HOME=$(dscl . -read "/users/${user}" NFSHomeDirectory | cut -d ' ' -f 2) writeLog "Home directory read from dscl ($C42_USER_HOME)" writeLog "Returning C42_USERNAME=$C42_USERNAME" writeLog "Returning C42_USER_HOME=$C42_USER_HOME" echo "C42_USERNAME=$C42_USERNAME" echo "C42_USER_HOME=$C42_USER_HOME" fi } function writeLog () { echo "$(date) - $@" >> /Library/Logs/CrashPlan/userDetect_Result.log } main "$@"
Last logged on user script
Professional Services filename: UserDetect_last_plus_domain.sh
The following script checks the last known logged in users and narrows down the list to the currently logged-in user.
function main () { writeLog "Starting user detection..." local user=$(last | egrep 'console.*still' | egrep -v 'root|admin|reboot|shutdown|local|_mbsetupuser' | awk '{print $1}' | sort -u | head -n1) writeLog "User name found ($user)" if [[ "$user" =~ ^(admin1|admin2|admin3)$ ]] || [[ -z "$user" ]]; then writeLog "Excluded or null username detected ($user). Will retry user detection in 60 minutes, or when reboot occurs." exit else local C42_USERNAME="${user}@domain.com" writeLog "Username assembled by appending domain ($C42_USERNAME)" local C42_USER_HOME=$(dscl . -read "/users/${user}" NFSHomeDirectory | cut -d ' ' -f 2) writeLog "Home directory read from dscl ($C42_USER_HOME)" writeLog "Returning C42_USERNAME=$C42_USERNAME" writeLog "Returning C42_USER_HOME=$C42_USER_HOME" echo "C42_USERNAME=$C42_USERNAME" echo "C42_USER_HOME=$C42_USER_HOME" fi } function writeLog () { echo "$(date) - $@" >> /Library/Logs/CrashPlan/userDetect_Result.log } main "$@"
Scutil script
Professional Services filename: UserDetect_scutil_user_plus_domain.sh
The following script uses the system configuration utility (scutil) to detect the logged-in user. The client's email domain needs to be appended to the resulting username to get a valid Code42 username.
function main () { writeLog "Starting user detection..." local user=$(echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ && ! /loginwindow/ { print $3 }') writeLog "User name found ($user)" if [[ "$user" =~ ^(admin1|admin2|admin3)$ ]] || [[ -z "$user" ]]; then writeLog "Excluded or null username detected ($user). Will retry user detection in 60 minutes, or when reboot occurs." exit else local C42_USERNAME="${user}@domain.com" writeLog "Username assembled by appending domain ($C42_USERNAME)" local C42_USER_HOME=$(dscl . -read "/users/${user}" NFSHomeDirectory | cut -d ' ' -f 2) writeLog "Home directory read from dscl ($C42_USER_HOME)" writeLog "Returning C42_USERNAME=$C42_USERNAME" writeLog "Returning C42_USER_HOME=$C42_USER_HOME" echo "C42_USERNAME=$C42_USERNAME" echo "C42_USER_HOME=$C42_USER_HOME" fi } function writeLog () { echo "$(date) - $@" >> /Library/Logs/CrashPlan/userDetect_Result.log } main "$@"
DSCL script
Professional Services filename: UserDetect_using_DSCL.sh
The following script obtains the user's email address from the domain records stored on the client using the Directory Service command line utility (DSCL). The Mac must be domain-bound.
function main() { writeLog "Starting user detection..." local user=$(echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ && ! /loginwindow/ { print $3 }') writeLog "User name found ($user)" if [[ "$user" =~ ^(admin1|admin2|admin3)$ ]] || [[ -z "$user" ]]; then writeLog "Excluded or null username detected ($user). Will retry user detection in 60 minutes, or when reboot occurs." exit else local C42_USERNAME=$(dscl . -read /Users/${user} EMailAddress | cut -d ' ' -f 2) writeLog "Username read from dscl ($C42_USERNAME)" local C42_USER_HOME=$(dscl . -read "/users/${user}" NFSHomeDirectory | cut -d ' ' -f 2) writeLog "Home directory read from dscl ($C42_USER_HOME)" writeLog "Returning C42_USERNAME=$C42_USERNAME" writeLog "Returning C42_USER_HOME=$C42_USER_HOME" echo "C42_USERNAME=$C42_USERNAME" echo "C42_USER_HOME=$C42_USER_HOME" fi } function writeLog () { echo "$(date) - $@" >> /Library/Logs/CrashPlan/userDetect_Result.log } main "$@"
Mac deploy.properties file
The typical deploy.properties file reads like this:
DEPLOYMENT_URL=https://.host DEPLOYMENT_POLICY_TOKEN=0fb12341-246b-448d-b07f-c6573ad5ad02 CP_SILENT=true DEVICE_CLOAKED=false PROXY_URL=http://.host/fname.pac
Individual parts of that file are as follows:
Element | Description |
DEPLOYMENT_URL= https://.host |
The address of your Code42 console. The Code42 app requests its deployment policy from this address. |
DEPLOYMENT_POLICY_TOKEN= | A unique ID string identifies each deployment policy. |
CP_SILENT=true or false |
|
DEVICE_CLOAKED=true or false |
The Client Visibility setting for this organization.
This argument only affects client visibility during initial deployment. Future changes to the Client Visibility setting in the Code42 console are automatically pushed to the device. |
PROXY_URL= http://.host/fname.pac |
The address of a proxy auto-config file. The file tells a Code42 app how to communicate with Code42 through a proxy server. This argument is only present when your policy configuration says Use Org Proxy URL: Yes. If the argument is present, but has no value, the policy says use proxy: yes, but the organization has no proxy addresses defined. |
Mac deploy.properties file location
When the Code42 app installer runs on Mac, it looks for the deploy.properties file in three locations, in the following order:
- In the disk image, typically in:
- Version 8.2 and later: /Volumes/Code42
- Version 8.0 and earlier: /Volumes/Code42CrashPlan
- In a Jamf Pro temp directory:
- Version 8.2 and later: /tmp/mountpt/Code42
- Version 8.0 and earlier: /tmp/mountpt/Code42CrashPlan
- (Recommended location) In the directory /Library/Application Support/CrashPlan
Installations for a single user use ~/Library rather than /Library.
For most software management tools, Code42 recommends the third option:
/Library/Application Support/CrashPlan
Location 1, the disk image
Adding deploy.properties to the installer disk image is recommended for users starting an install manually, by clicking on the *.dmg file.
Not all deployment software mounts the disk image in the same location, making deploy.properties in the disk image hard to find.
Add deploy.properties to the disk image as follows:
- Make a writable copy of the disk image.
- Mount the writable copy.
- Copy deploy.properties to the new image's root directory.
- Unmount the image.
- Return the image to the read-only state.
The following example shows the commands needed to add the deploy.properties file to the disk image. This example is for Code42 app version 8.2 and later. For Code42 app version 8.0 and earlier, the installer and volume name use Code42CrashPlan
instead of Code42
:
hdiutil convert -format UDRW Code42_n.n.n_Mac.dmg -o C42_n.n.n_w.dmg hdiutil attach C42_n.n.n_w.dmg cp deploy.properties /Volumes/Code42/deploy.properties hdiutil detach /Volumes/Code42 hdiutil convert -format UDRO C42_n.n.n_w.dmg -o C42_n.n.n_ro.dmg
Location 2, Jamf Pro tmp
- Version 8.2 and later: /tmp/mountpt/Code42
- Version 8.0 and earlier: /tmp/mountpt/Code42CrashPlan
This location is unique to the Jamf Pro device management tool. See the vendor's documentation.
Location 3, Application Support (recommended)
For deployment with most software management tools, including Jamf Pro, Code42 recommends storing the file here:
/Library/Application Support/CrashPlan/deploy.properties
To install for a single user, rather than all users of a device, use ~/Library rather than /Library.
To create the directory and write the file, we recommend a bash script like the following where you replace <deploy.properties>
with the text from your deploy.properties file.
#!/bin/bash mkdir -p /Library/Application\ Support/CrashPlan echo "<deploy.properties>" > /Library/Application\ Support/CrashPlan/deploy.properties
Mac commands
Deployment policy command arguments need to be imported into your software management tool.
Commands and arguments are detailed here in case you need to modify them for some reason, or to help you deploy without a device management tool.
- To install a Code42 app for all users of a device, sign in to an account with administrative rights and issue a command like the following. This example is for Code42 app version 8.2 and later. For Code42 app version 8.0 and earlier, the installer and volume name use
Code42CrashPlan
instead ofCode42
:
hdiutil attach Code42_n.n.n_Mac.dmg installer -package "/Volumes/Code42/Install Code42.pkg" -target LocalSystem hdiutil detach /Volumes/Code42
- To install for one user only, sign in as that user and use
target
CurrentUserHomeDirectory
.
Individual parts of the commands are as follows:
Element | Description |
hdiutil attach Code42_n.n.n_Mac.dmg |
Mount the Code42 app disk image. You must update the name of the installer file to match the exact name and version number being deployed.
In version 8.0 and earlier, the installer file used the format Code42CrashPlan_n.n.n_Mac.dmg. |
installer -package "/Volumes/Code42/Install Code42.pkg" |
Run the install program. Code42 app version 8.0 and earlier used the name Code42CrashPlan instead of Code42. |
-target LocalSystem -target CurrentUserHomeDirectory |
Install the Code42 app for all users of the device. Or, install for only the current user. |
hdiutil detach /Volumes/Code42 |
Unmount the Code42 app disk image.
Code42 app version 8.0 and earlier used the name Code42CrashPlan instead of Code42. |
Linux
For Code42 apps on Linux devices, a deployment policy provides:
- A custom-written detection script to provide the Code42 app with a username and home directory for the device. The script can also optionally specify the user's organization.
- Installation properties to serve as the arguments string to a Code42 app install command.
Linux user detection script
A user detection script examines the host device and provides the Code42 app with a username and home directory. The script resides on the Code42 cloud. The Code42 app retrieves it during the install process.
To require users to enter their usernames manually, do not use a detection script. In the deployment policy, leave all operating systems deselected to create a deployment policy without a user detection script.
Tips to create a custom Linux script
Create a custom script and paste your script into your deployment policy. If you need help, contact your Customer Success Manager (CSM) for enterprise support.
When creating your custom script, be aware of the following:
- Every script must end by echoing values for two variables:
echo C42_USERNAME=<value>; echo C42_USER_HOME=<value>;
- In the Code42 cloud, usernames must be email addresses.
- Optionally, you can also specify the the organization for the user. Use the registration key for the organization. If the organization is not defined, the user registers to the organization specified in the deployment policy.
echo C42_ORG_REG_KEY=<value>
- You must provide values. Null values and empty strings will not work.
- If you cannot write a script to provide a workable value, write a message for the username field of the Code42 app sign in dialog, for example:
echo C42_USERNAME=Enter name and click Sign in;
- The values cannot include either single (') or double (") quotation marks.
Linux commands and arguments
Deployment policy command arguments need to be imported into your software management tool.
Commands and arguments are detailed here in case you need to modify them for some reason, or to help you deploy without a device management tool.
- To install a Code42 app for all users of a device, sign in to an account with root access and issue a command like the following:
tar -xvf Code42_n.n.n_Linux.tgz sudo code42-install/install.sh -q -d "DEPLOYMENT_URL=https://host &DEPLOYMENT_POLICY_TOKEN=0fb12341-246b-448d-b07f-c6573ad5ad02 &SSL_WHITELIST=7746278a457e64737094c44eeb2bbc32357ece44 &PROXY_URL=http://host/filename.pac"
- To install for one user only:
- Version 8.2 and later: Append the
-u
command with a user name. For example:-u "first.last"
- Version 8.0 and earlier: Sign in as that user and specify
-qdu
.
- Version 8.2 and later: Append the
Element | Description |
tar -xvf Code42_n.n.n_Linux.tgz |
Unpack the installer file. You must update the name of the installer file to match the exact name and version number being deployed.
In version 8.0 and earlier, the installer file used the format Code42CrashPlan_n.n.n_Linux.tgz. |
|
Run the Code42 app install script. |
-q -d -u -c |
q: Quiet. Do not open a console. Do not prompt the user. d: Deployment. Apply the following properties. u: Install for the specified username (version 8.2 and later) or for the currently signed-in user only (version 8.0 and earlier). c: Client visibility for this organization is set to Hidden, which hides most Code42 app user interface elements from users. This only affects client visibility during initial deployment. Future changes to the Client Visibility setting in the Code42 console are automatically pushed to the device. |
" | Start and end the following properties with a quote. |
DEPLOYMENT_URL= https://.host |
The address of your Code42 console. The Code42 app requests its deployment policy from that address. |
DEPLOYMENT_POLICY_TOKEN= | A unique ID string identifies each deployment policy. |
PROXY_URL= http://.host/fname.pac |
The address of a proxy auto-config file. The file tells a Code42 app how to communicate with Code42 through a proxy server. This argument is only present when your policy configuration says Use Org Proxy URL: Yes. If the argument is present, but has no value, the policy says use proxy: yes, but the organization has no proxy addresses defined. |
" | Start and end the above properties with a quote. |