Mac Installer : How to determine if pkg installation is intercative - macos

Mac Installer: I want to do something (popup dialog) in the postinstall script ONLY if it is an interactive installation. (not through MDM or command line)
How can I determine in my postinstall script if the installation is interactive or not?

Maybe will help to someone in the future:
There are 2 options:
(one can combine those 2 options to have full solutions, depends on its needs)
One of the environment variables set by macos installer is a flag COMMAND_LINE_INSTALL that is set to 1 in case of installer being executed from the terminal.
In my case I just had to check if COMMAND_LINE_INSTALL exists, if not - it means that this is interactive installation.
IMPORTANT: this environment variable exist and value=1 ONLY in case of installation from terminal(command line).
During installation from MDM this variable doesn't exist
=========================================================================
Another solution (that helps me determine if installation is from MDM or not):
From the post install script: run ps and check the existence of "/System/Library/CoreServices/Installer.app/Contents/MacOS/Installer"
If it exists- it means the installation is interactive (via mac installer app).
The lines I used:
INSTALLER_APP_PATH ="/System/Library/CoreServices/Installer.app/Contents/MacOS/Installer"
if ps aux | grep -v grep | grep -q "$INSTALLER_APP_PATH"
then
echo "Interactive installation"
else
echo "Not an interactive installation"
fi

Related

How to run a command on WSL startup using WSL config files?

I added these lines in my WSL settings files
C:\Users\reynadan\.wslconfig:
[boot]
command=bash /home/reynadan/scripts/startup.sh
/etc/wsl.conf:
[boot]
command=bash /home/reynadan/scripts/startup.sh
/home/reynadan/scripts/startup.sh
#!/bin/bash
# Run wsl-vpnkit if not already connected or running
currentlyRunningWsl=$(wsl.exe -l --running | iconv -f UTF16 -t UTF8 | grep wsl-vpnkit | wc -l)
if [[ $currentlyRunningWsl -eq 0 ]]; then
wsl.exe -d wsl-vpnkit service wsl-vpnkit start
fi
# Start Docker daemon automatically when logging in if not running.
RUNNING=`ps aux | grep dockerd | grep -v grep`
if [ -z "$RUNNING" ]; then
sudo dockerd > /dev/null 2>&1 &
disown
fi
NOW=$(date)
echo WSL booted at $(/bin/date +'%Y-%m-%d %H:%M:%S') >> /home/reynadan/wslBootHistory.txt
echo 'startup lanched'
I closed with wsl --shutdown and waited more than 8 seconds before running it again, but /home/reynadan/wslBootHistory.txt is still empty and docker is not running.
How do I make sure WSL runs my script on startup?
As noted in the comments, you are on Windows 10. However, the information in the comments is a bit outdated -- The boot.command feature does now work on Windows 10, but you need the absolute latest release (including optional updates) of both Windows 10 and WSL installed.
First, confirm that your system is running the November "Cumulative Update Preview". If you are, then your UBR (update-build-revision) will be at 2311 or higher. From PowerShell:
(Get-ComputerInfo).WindowsUBR
If it is lower than 2311, then:
First, make sure your system is otherwise completely up-to-date.
Go to Settings -> Check for Updates and press the Check for Updates button.
If you are fully updated on Windows 10 (but still running less than UBR 2311) you should see "2022-11 Cumulative Update Preview for Windows 10 Version 22H2 for x64-based Systems (KB5020030)" available as an optional update. Install it and reboot when prompted.
With that in place, you should now be able to update to the Store version of WSL with a simple:
wsl --update
wsl --version
After the update, you should be at:
WSL version: 1.0.0.0
... or later.
A reboot at this point is recommended for all features to work properly, but not strictly required.
At this point, you should have access to the /etc/wsl.conf's [boot].command feature.
If for some reason it's still not working, then I would recommend removing the script from the equation to troubleshoot. Try something like command=service cron start and see if the Cron service starts when you restart WSL.
Note that this new update also brings a number of other new WSL2 features to Windows 10 users, including:
Systemd support
WSLg: The ability to run Linux GUI applications in WSL2
The --mount argument for adding additional Windows's drives and partitions (including those with other filesystems or even raw partitions).

Using Chocolatey VS Code from within WSL Ubuntu

I cannot get VS Code code.exe to run properly within WSL. (I found a connected question here, but it does not solve this issue - Launch VS Code from WSL Bash).
Within WSL (any distro) we can access any executables on Windows. e.g.
alias chrome="\"/mnt/c/Program Files/Google/Chrome/Application/chrome.exe\"" # Open Chrome from WSL
alias notepad++="\"/mnt/c/Program Files/Notepad++/notepad++.exe\"" # Open Notepad++
Typing chrome in bash will open Chrome and notepad++ ~/.bashrc would open .bashrc in Notepad++
This all works great.
However, I have hit a problem with code.exe provided by the choco inst VisualStudioCode installation. When I try:
alias vscode="\"/mnt/c/ProgramData/chocolatey/bin/code.exe\""
This fails really badly.
[main 2021-01-24T18:44:17.966Z] update#setState idle
(node:20404) Electron: Loading non-context-aware native module in renderer: '\\?\C:\tools\vscode\resources\app\node_modules.asar.unpacked\vscode-sqlite3\build\Release\sqlite.node'. This is deprecated, see https://github.com/electron/electron/issues/18397.
(node:20404) Electron: Loading non-context-aware native module in renderer: '\\?\C:\tools\vscode\resources\app\node_modules.asar.unpacked\spdlog\build\Release\spdlog.node'. This is deprecated, see https://github.com/electron/electron/issues/18397.
(node:18692) Electron: Loading non-context-aware native module in renderer: '\\?\C:\tools\vscode\resources\app\node_modules.asar.unpacked\spdlog\build\Release\spdlog.node'. This is deprecated, see https://github.com/electron/electron/issues/18397.
So, I can ignore that and just use code.exe within Ubuntu (as WSL will scan the path for executables). This sort of works but with the following error:
'\\wsl$\Ubuntu-20.04\home\boss'
CMD.EXE was started with the above path as the current directory.
UNC paths are not supported. Defaulting to Windows directory.
VS Code does open, but if put a filename as an argument that file fails to open (while noting that for the notepad++ example, all files open perfectly run with the above alias).
It seems to be saying that code.exe can't support UNC paths, but it does support UNC paths as I can see from PowerShell. code.exe \\HPEnvy\Drive-D\test.txt opens perfectly.
It would really round out my WSL setup to be able to open code that I'm working on seamlessly with VS Code. Does anyone have an idea why this might be happening / how to fix?
My installation has a shell script for launching VSCode in ../Microsoft VS Code/bin/code. I'm fairly certain that it is installed with VSCode, but there's a chance it comes from the "Remote - WSL" extension.
Is that present in your installation? If so, add that bin directory to your path (the full installer does this automatically). Then just use code rather than code.exe to launch from within WSL.
If not, first make sure the "Remote - WSL" extension is installed in VSCode (or better yet, the "Remote Development" extension pack, which includes the WSL support). If it's still not there after that, here are the contents of the script that should live in VSCode/bin/code:
#!/usr/bin/env sh
#
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
if [ "$VSCODE_WSL_DEBUG_INFO" = true ]; then
set -x
fi
COMMIT="ea3859d4ba2f3e577a159bc91e3074c5d85c0523"
APP_NAME="code"
QUALITY="stable"
NAME="Code"
DATAFOLDER=".vscode"
VSCODE_PATH="$(dirname "$(dirname "$(realpath "$0")")")"
ELECTRON="$VSCODE_PATH/$NAME.exe"
IN_WSL=false
if [ -n "$WSL_DISTRO_NAME" ]; then
# $WSL_DISTRO_NAME is available since WSL builds 18362, also for WSL2
IN_WSL=true
else
WSL_BUILD=$(uname -r | sed -E 's/^[0-9.]+-([0-9]+)-Microsoft.*|.*/\1/')
if [ -n "$WSL_BUILD" ]; then
if [ "$WSL_BUILD" -ge 17063 ]; then
# WSLPATH is available since WSL build 17046
# WSLENV is available since WSL build 17063
IN_WSL=true
else
# If running under older WSL, don't pass cli.js to Electron as
# environment vars cannot be transferred from WSL to Windows
# See: https://github.com/microsoft/BashOnWindows/issues/1363
# https://github.com/microsoft/BashOnWindows/issues/1494
"$ELECTRON" "$#"
exit $?
fi
fi
fi
if [ $IN_WSL = true ]; then
export WSLENV="ELECTRON_RUN_AS_NODE/w:$WSLENV"
CLI=$(wslpath -m "$VSCODE_PATH/resources/app/out/cli.js")
# use the Remote WSL extension if installed
WSL_EXT_ID="ms-vscode-remote.remote-wsl"
ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" --locate-extension $WSL_EXT_ID >/tmp/remote-wsl-loc.txt 2>/dev/null </dev/null
WSL_EXT_WLOC=$(cat /tmp/remote-wsl-loc.txt)
if [ -n "$WSL_EXT_WLOC" ]; then
# replace \r\n with \n in WSL_EXT_WLOC
WSL_CODE=$(wslpath -u "${WSL_EXT_WLOC%%[[:cntrl:]]}")/scripts/wslCode.sh
"$WSL_CODE" "$COMMIT" "$QUALITY" "$ELECTRON" "$APP_NAME" "$DATAFOLDER" "$#"
exit $?
fi
elif [ -x "$(command -v cygpath)" ]; then
CLI=$(cygpath -m "$VSCODE_PATH/resources/app/out/cli.js")
else
CLI="$VSCODE_PATH/resources/app/out/cli.js"
fi
ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" "$#"
exit $?
Permissions on the file are 0777. And, as mentioned above, it should be in your path.

Bash script for Anaconda installer and license agreement

I'm trying to install anaconda in my own docker container with a bash script. The problem is there's a license agreement that you need to hold down a key to agree to, and the length of which depends on your terminal window size. Is there any way to get around this so that I can run Anaconda3-5.1.0-Linux-x86_64.sh from start to finish from another bash script?
I tried echo "\n\n\n\n\n\n\n" | ./Anaconda3-5.1.0-Linux-x86_64.sh, but this only works when the installer asks for an Enter key press the very first time.
bash ./Anaconda3-5.1.0-Linux-x86_64.sh -b -p $HOME/anaconda3
-b — Batch mode with no PATH modifications to ~/.bashrc. Assumes that you agree to the license agreement. Does not edit the .bashrc or .bash_profile files.
-p — Installation prefix/path.
-f — Force installation even if prefix -p already exists.
ref: https://docs.anaconda.com/anaconda/install/silent-mode/#linux-macos
Try the yes command.
yes | ./Anaconda3-5.1.0-Linux-x86_64.sh
As for your question
What if the last option is asking if I want to install Visual Studio
Code, which I'd like to answer no to?
Try this
yes no | ./Anaconda3-5.1.0-Linux-x86_64.sh
Or replace "no" with whatever you feel is the appropriate response.
It seems you've already found the -b flag,
but for reference,
here is small, complete scrip
that installs anaconda in $HOME/anaconda3.
#!/usr/bin/env bash
_anaconda_version=2020.02
_anaconda_file="Anaconda3-${_anaconda_version}-Linux-x86_64.sh"
cd
rm -f ${_anaconda_file}*
rm -rf anaconda3/
wget https://repo.anaconda.com/archive/${_anaconda_file}
bash ${_anaconda_file} -b
echo "y" | conda update --all
rm ${_anaconda_file}
unset _anaconda_version _anaconda_file

When my pkg runs its Post-installation script, how can I know how that happened?

There are two ways this script can be run: When the user opens the pkg file and goes through the normal GUI setup, or when an admin (or savvy user) runs sudo installer -pkg /path/to/Installer.pkg -target /. For the second one, I want to know when the script was run in this mode so I can make more admin-friendly decisions like not opening another GUI. How do I know when my pkg is installed via the command line?
I'm hoping for some environment variable or something similar.
Running the script via sudo will change the values of certain variables and add others in. Your script could check for the existence of those variables (or their values) to make a determination as to whether the installer was run via sudo.
Values that would get updated:
HOME
LOGNAME
MAIL
Values that would get set:
SUDO_COMMAND -- the command that was run via sudo
SUDO_GID -- the GID of the user that ran sudo
SUDO_UID -- the UID of the user that ran sudo
SUDO_USER -- the username of the user that ran sudo
My recommendation would be to check for the existence of the SUDO_COMMAND environment variable; it is unlikely to be set for a non-sudo installation, and would be set for a sudo-based installation.
Reference: sudo 1.8.20 manual - ENVIRONMENT section
Since this was being run by the installer command, the COMMAND_LINE_INSTALL environment variable is set to 1. When opening the pkg normally, this variable is not set at all.
So:
if [ $COMMAND_LINE_INSTALL ]; then
# Do stuff for CLI land
else
# Do stuff for GUI land
fi

Running UIAutomation scripts from Xcode

Did anyone succeed in setting up automated UIAutomation tests in Xcode?
I'm trying to set up a target in my Xcode project that should run all the UIAutomation scripts I prepared. Currently, the only Build Phase of this target is this Run Script block:
TEMPLATE="/Applications/Xcode.app/Contents/Applications/Instruments.app/Contents/PlugIns/AutomationInstrument.bundle/Contents/Resources/Automation.tracetemplate"
MY_APP="/Users/Me/Library/Application Support/iPhone Simulator/6.0/Applications/564ED15A-A435-422B-82C4-5AE7DBBC27DD/MyApp.app"
RESULTS="/Users/Me/Projects/MyApp/Tests/UI/Traces/Automation.trace"
SCRIPT="/Users/Me/Projects/MyApp/Tests/UI/SomeTest.js"
instruments -t $TEMPLATE $MY_APP -e UIASCRIPT $SCRIPT -e UIARESULTSPATH $RESULTS
When I build this target it succeeds after a few seconds, but the script didn't actually run. In the build log I get these errors:
instruments[7222:707] Failed to load Mobile Device Locator plugin
instruments[7222:707] Failed to load Simulator Local Device Locator plugin
instruments[7222:707] Automation Instrument ran into an exception while trying to run the script. UIATargetHasGoneAWOLException
+0000 Fail: An error occurred while trying to run the script.
Instruments Trace Complete (Duration : 1.077379s; Output : /Users/Me/Projects/MyApp/Tests/UI/Traces/Automation.trace)
I am pretty sure, that my javascript and my run script are both correct, because if I run the exact same instruments command in bash it works as expected.
Could this be a bug in Xcode?
I finally found a solution for this problem. It seems like Xcode is running the Run Scripts with limited rights. I'm not entirely sure, what causes the instruments command to fail, but using su to change to your user will fix it.
su $USER -l -c <instruments command>
Obviously, this will ask you for your password, but you can't enter it when running as a script. I didn't find a way to specify the password for su, however if you run it as root, you don't have to specify one. Luckily sudo can accept a password via the pipe:
echo <password> | sudo -S su $USER -l -c <instruments command>
If you don't want to hardcode your password (always a bad idea), you could use some AppleScript to ask for the password.
I posted the resulting script below. Copy that to a *.sh file in your project and run that script from a Run Script.
#!/bin/bash
# This script should run all (currently only one) tests, independently from
# where it is called from (terminal, or Xcode Run Script).
# REQUIREMENTS: This script has to be located in the same folder as all the
# UIAutomation tests. Additionally, a *.tracetemplate file has to be present
# in the same folder. This can be created with Instruments (Save as template...)
# The following variables have to be configured:
EXECUTABLE="TestApp.app"
# Optional. If not set, you will be prompted for the password.
#PASSWORD="password"
# Find the test folder (this script has to be located in the same folder).
ROOT="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# Prepare all the required args for instruments.
TEMPLATE=`find $ROOT -name '*.tracetemplate'`
EXECUTABLE=`find ~/Library/Application\ Support/iPhone\ Simulator | grep "${EXECUTABLE}$"`
SCRIPTS=`find $ROOT -name '*.js'`
# Prepare traces folder
TRACES="${ROOT}/Traces/`date +%Y-%m-%d_%H-%M-%S`"
mkdir -p "$TRACES"
# Get the name of the user we should use to run Instruments.
# Currently this is done, by getting the owner of the folder containing this script.
USERNAME=`ls -l "${ROOT}/.." | grep \`basename "$ROOT"\` | awk '{print $3}'`
# Bring simulator window to front. Depending on the localization, the name is different.
osascript -e 'try
tell application "iOS Simulator" to activate
on error
tell application "iOS-Simulator" to activate
end try'
# Prepare an Apple Script that promts for the password.
PASS_SCRIPT="tell application \"System Events\"
activate
display dialog \"Password for user $USER:\" default answer \"\" with hidden answer
text returned of the result
end tell"
# If the password is not set directly in this script, show the password prompt window.
if [ -z "$PASSWORD" ]; then
PASSWORD=`osascript -e "$PASS_SCRIPT"`
fi
# Run all the tests.
for SCRIPT in $SCRIPTS; do
echo -e "\nRunning test script $SCRIPT"
COMMAND="instruments -t \"$TEMPLATE\" \"$EXECUTABLE\" -e UIASCRIPT \"$SCRIPT\""
COMMAND="echo '$PASSWORD' | sudo -S su $USER -l -c '$COMMAND'"
echo "$COMMAND"
eval $COMMAND > results.log
SCRIPTNAME=`basename "$SCRIPT"`
TRACENAME=`echo "$SCRIPTNAME" | sed 's_\.js$_.trace_g'`
mv *.trace "${TRACES}/${TRACENAME}"
if [ `grep " Fail: " results.log | wc -l` -gt 0 ]; then
echo "Test ${SCRIPTNAME} failed. See trace for details."
open "${TRACES}/${TRACENAME}"
exit 1
break
fi
done
rm results.log
It seems as though this really might be an Xcode problem; at any rate, at least one person has filed a Radar report on it. Someone in this other thread claims you can work around this exception by disconnecting any iDevices that are currently connected to the computer, but I suspect that does not apply when you're trying to run the script as an Xcode target.
I would suggest filing a Radar report as well; you may get further details on the issue from Apple, or at least convince them that many people are having the problem and they ought to figure out what's going on.
Sorry for a not-terribly-helpful answer (should have been a comment, but comments and links/formatting do not mix very well). Please update this question with anything you find out on the issue.
Note: this is not a direct answer to the question, but it is an alternative solution to the underlying problem.
While searching for in-depth information about UIAutomation, I stumbled across a framework by Square called KIF (Keep it functional). It is a integration testing framework that allows for many of the same features as UIAutomation, but the great thing about is is that you can just write your integration tests in Objective-C.
It is very easy to setup (via CocoaPods), they have good examples too, and the best thing is that it's a breeze to set up with your CI system like Jenkins.
Have a look at: http://github.com/square/KIF
Late to the game but I have a solution that works for Xcode 5.1. Don't know if that's what broke the above solution or not. With the old solution I was still getting:
Failed to load Mobile Device Locator plugin, etc.
However, this works for the release version of Xcode 5.1.
echo <password> | sudo -S -u username xcrun instruments
Notice I removed the unneeded su command and added the xcrun command. The xcrun was the magic that was needed.
Here is my complete command:
echo <password> | sudo -S -u username xcrun instruments\
-w "iPhone Retina (3.5-inch) - Simulator - iOS 7.1"\
-D "${PROJECT_DIR}/TestResults/Traces/Traces.trace"\
-t "${DEVELOPER_DIR}/Instruments.app/Contents/PlugIns/AutomationInstrument.bundle/Contents/Resources/Automation.tracetemplate"\
"${BUILT_PRODUCTS_DIR}/MyApp.app"\
-e UIARESULTSPATH "${PROJECT_DIR}/TestResults"\
-e UIASCRIPT "${PROJECT_DIR}/UITests/main.js"
By the way if you type:
instruments -s devices
you will get a list of all the supported devices you can use for the -w option.
Edit: To make this work for different people checking out the project replace the following:
echo <password> | sudo -S -u username xcrun instruments
with
sudo -u ${USER} xcrun instruments
Since you are just doing an sudo to the same user no password is required.
Take a look at this tutorial that explains how to have Automated UI testing with Jenkins. It also uses Jasmine in the tutorial though. http://shaune.com.au/automated-ui-testing-for-ios-apps-uiautomation-jasmine-jenkins/ hope this helps. It has an example project file so you can download that as a template. Hope this helps.
In XCode - if you load up organizer (XCode->Window->Organizer)
Then select your machine under devices -> 'Enable Developer Mode'
This should remove the need for prompts with instruments.

Resources