Skip to main content
added 1936 characters in body; added 18 characters in body
Source Link
CJK
  • 5.6k
  • 9
  • 19

IGNORE EVERYTHING BELOW FOR NOW

I Noticed that someRe-opening documents

By employing the use of synchronised .savedState files are stored in ~/Library/Saved Application State as aliases, the hope is that, once an application on one system re-initialises (symbolic linkssay, by closing and opening it again) instead of, it will re-open documents that were open on the actual file itselfother. These typically link to ~/Library/Containers/%bundle-id%/Data/Library/Saved Application State/%file% where %bundle-id% is, for example

However, it may be prudent store our own list of documents that we can detect com.apple.Preview,(to the best of our abilities) are open and its corresponding %file% is com.apple.Preview.savedStateactive.


[NOTES FOR ME TO INTEGRATE INTO ANSWER]

  • I Noticed that some .savedState files are stored in ~/Library/Saved Application State as aliases (symbolic links) instead of the actual file itself. These typically link to ~/Library/Containers/%bundle-id%/Data/Library/Saved Application State/%file% where %bundle-id% is, for example, com.apple.Preview, and its corresponding %file% is com.apple.Preview.savedState.
  • .savedState files are deleted whenever an application exits cleanly. Therefore, bear in mind that closing applications on one system will delete those data files, then potentially synchronise these deletions with the other machine.

IGNORE EVERYTHING BELOW FOR NOW

I Noticed that some .savedState files are stored in ~/Library/Saved Application State as aliases (symbolic links) instead of the actual file itself. These typically link to ~/Library/Containers/%bundle-id%/Data/Library/Saved Application State/%file% where %bundle-id% is, for example, com.apple.Preview, and its corresponding %file% is com.apple.Preview.savedState.

Re-opening documents

By employing the use of synchronised .savedState files, the hope is that, once an application on one system re-initialises (say, by closing and opening it again), it will re-open documents that were open on the other.

However, it may be prudent store our own list of documents that we can detect (to the best of our abilities) are open and active.


[NOTES FOR ME TO INTEGRATE INTO ANSWER]

  • I Noticed that some .savedState files are stored in ~/Library/Saved Application State as aliases (symbolic links) instead of the actual file itself. These typically link to ~/Library/Containers/%bundle-id%/Data/Library/Saved Application State/%file% where %bundle-id% is, for example, com.apple.Preview, and its corresponding %file% is com.apple.Preview.savedState.
  • .savedState files are deleted whenever an application exits cleanly. Therefore, bear in mind that closing applications on one system will delete those data files, then potentially synchronise these deletions with the other machine.
added 1936 characters in body; added 18 characters in body
Source Link
CJK
  • 5.6k
  • 9
  • 19

Writing the settings that need to be saved can be done withto a .plist.plist file, which stores key/value pairskey/value pairs of data along with the data types. This allows any value to be saved and retrieved by its name. They're also relatively simply to read and edit programmatically using either AppleScript or the command line utility plutil.

Cleverlywhere the variable OpenApps is taken from the AppleScript snippet above. Cleverly, the make new property list command will overwriteoverwrite any existing key/value item that already has the name "OpenApps", so it won't be duplicated.

Bash:

lsof | egrep -i -e 'windows\.plist'

Doesn't include menu bar apps.

lsof = list of open files, filtered for windows.plist files that each open application (with a window) updates regularly. When the application closes, so does the .plist file.

Slow, and not really designed for this purpose, but useful to be aware.

This filter pattern retrieves an exhaustive list of all running user apps, including menu apps:

lsof | egrep -i -e '/Applications/.+\.app/Contents/MacOS/[^/]+$'

ps is fast and accurate:

IFS=$'\r\n'; basename $( ps -U 501 -o 'comm' | egrep -i '^/Applications/.*\\.app/Contents/MacOS/[^/]+$' ) | sort -u

lsappinfo visibleProcessList | egrep -io -e '"[^"]+"' | tr -d \" | tr '_' ' '

IFS=$'\r\n'; basename -s '.app' $(lsappinfo list | egrep -io -e '(\w|\s)+\.app"$' | tr -d \")

lsappinfo find | egrep -io -e '"[^"]+"' | tr -d \" | tr '_' ' '

That last one is every single running application process (87 of them on my system right now)


.savedState files

Some degree of usefulness in obtaining open documents. The relevant file is windows.plist contained within theI Noticed that some .savedState folder. Thefiles are stored in plist~/Library/Saved Application State as aliases (symbolic links) instead of the actual file itself is of limited usefulness if relying on it to manually extract information about open windows and their states; and they contain data objects not conventional. These typically link to plist~/Library/Containers/%bundle-id%/Data/Library/Saved Application State/%file% formats, which makes them un-parsable by common methods. But the command line utilitywhere plutil%bundle-id% can pick out what's usable.

I wrote these commands in FiSh shell, so it's a little different to Bash, but easily translatable:

cd ~/Library
for f in (find . -iregex '.*\/.*\.savedState\/.*\.plist')
    set -l furl (plutil -p "$f" | egrep -io -e '"file:///[^"]+"' | egrep -io -e '/[^/][^"]+')
    set -l id (basename -s '.savedState' (printf "$f" | egrep -io -e '[^/]+\.savedState'))
   [ -n "$furl" ]; and printf '%s' "$id:"\n\n $furl\n \n\n
end

The output for me is:

com.apple.ScriptEditor2:

/Users/CK/Documents/Scripts/AppleScript/scripts/Download%20Tumblr%20Posts.applescript
/Users/CK/Documents/Scripts/AppleScript/scripts/_.applescript
/Users/CK/Library/Mobile%20Documents/com~apple~ScriptEditor2/Documents/Untitled%202.scpt


com.apple.Automator:

/Users/CK/Library/Mobile%20Documents/com~apple~Automator/Documents/Untitled.workflow


com.luckymarmot.Paw:

/Users/CK/Library/Mobile%20Documents/com~apple~CloudDocs/Paw/Tumblr.paw

Script Editor is currently open with those three documents. The other two applications are closed, but their last open documents were as listed. Thereforefor example, cross-matching the results of this with a list of running applications would be a method to bear in mind.

Howevercom.apple.Preview, it failed to list a photo image I had open for editing inand its corresponding Affinity. But it did list it when I opened it in%file% is Previewcom.apple.Preview.savedState.

This means that ~/Library/Containers will likely have to be synchronised between the two machines as well.

Writing the settings that need to be saved can be done with a .plist file, which stores key/value pairs of data along with the data types. This allows any value to be saved and retrieved by its name.

Cleverly, the make new property list command will overwrite any existing key/value item that already has the name "OpenApps", so it won't be duplicated.

Bash:

lsof | egrep -i -e 'windows\.plist'

Doesn't include menu bar apps.

lsof = list of open files, filtered for windows.plist files that each open application (with a window) updates regularly. When the application closes, so does the .plist file.

Slow, and not really designed for this purpose, but useful to be aware.

This filter pattern retrieves an exhaustive list of all running user apps, including menu apps:

lsof | egrep -i -e '/Applications/.+\.app/Contents/MacOS/[^/]+$'

ps is fast and accurate:

IFS=$'\r\n'; basename $( ps -U 501 -o 'comm' | egrep -i '^/Applications/.*\\.app/Contents/MacOS/[^/]+$' ) | sort -u

lsappinfo visibleProcessList | egrep -io -e '"[^"]+"' | tr -d \" | tr '_' ' '

IFS=$'\r\n'; basename -s '.app' $(lsappinfo list | egrep -io -e '(\w|\s)+\.app"$' | tr -d \")

lsappinfo find | egrep -io -e '"[^"]+"' | tr -d \" | tr '_' ' '

That last one is every single running application process (87 of them on my system right now)


.savedState files

Some degree of usefulness in obtaining open documents. The relevant file is windows.plist contained within the .savedState folder. The plist file itself is of limited usefulness if relying on it to manually extract information about open windows and their states; and they contain data objects not conventional to plist formats, which makes them un-parsable by common methods. But the command line utility plutil can pick out what's usable.

I wrote these commands in FiSh shell, so it's a little different to Bash, but easily translatable:

cd ~/Library
for f in (find . -iregex '.*\/.*\.savedState\/.*\.plist')
    set -l furl (plutil -p "$f" | egrep -io -e '"file:///[^"]+"' | egrep -io -e '/[^/][^"]+')
    set -l id (basename -s '.savedState' (printf "$f" | egrep -io -e '[^/]+\.savedState'))
   [ -n "$furl" ]; and printf '%s' "$id:"\n\n $furl\n \n\n
end

The output for me is:

com.apple.ScriptEditor2:

/Users/CK/Documents/Scripts/AppleScript/scripts/Download%20Tumblr%20Posts.applescript
/Users/CK/Documents/Scripts/AppleScript/scripts/_.applescript
/Users/CK/Library/Mobile%20Documents/com~apple~ScriptEditor2/Documents/Untitled%202.scpt


com.apple.Automator:

/Users/CK/Library/Mobile%20Documents/com~apple~Automator/Documents/Untitled.workflow


com.luckymarmot.Paw:

/Users/CK/Library/Mobile%20Documents/com~apple~CloudDocs/Paw/Tumblr.paw

Script Editor is currently open with those three documents. The other two applications are closed, but their last open documents were as listed. Therefore, cross-matching the results of this with a list of running applications would be a method to bear in mind.

However, it failed to list a photo image I had open for editing in Affinity. But it did list it when I opened it in Preview.

Writing the settings that need to be saved can be done to a .plist file, which stores key/value pairs of data along with the data types. This allows any value to be saved and retrieved by its name. They're also relatively simply to read and edit programmatically using either AppleScript or the command line utility plutil.

where the variable OpenApps is taken from the AppleScript snippet above. Cleverly, the make new property list command will overwrite any existing key/value item that already has the name "OpenApps", so it won't be duplicated.

I Noticed that some .savedState files are stored in ~/Library/Saved Application State as aliases (symbolic links) instead of the actual file itself. These typically link to ~/Library/Containers/%bundle-id%/Data/Library/Saved Application State/%file% where %bundle-id% is, for example, com.apple.Preview, and its corresponding %file% is com.apple.Preview.savedState.

This means that ~/Library/Containers will likely have to be synchronised between the two machines as well.

added 1936 characters in body; added 18 characters in body
Source Link
CJK
  • 5.6k
  • 9
  • 19
    tell application "System Events" to set POpenApps to the ¬
        name of every application process whose ¬
        class of its menu barsbar contains menu bar and ¬
        POSIX path of the application file does not start with "/System" and ¬
        POSIX path of the application file does not start with "/System/Library/"Library"

Storing information in a shared settings file

Writing the settings that need to be saved can be done with a .plist file, which stores key/value pairs of data along with the data types. This allows any value to be saved and retrieved by its name.

Let's assume the shared settings file will be saved at ~/Example/savedState.plist where ~/Example/ is some sort of shared folder (e.g. a cloud storage folder) to which both computers have access.

Using AppleScript, this is how one might save a list of applications that are currently open:

    property plist : "~/Example/SavedState.plist"
    
    tell application "System Events"
        if not (the file plist exists) then make new property list file ¬
            with properties {name:plist}
        
        set plistf to the property list file named plist
        
        tell plistf to make new property list item with properties ¬
            {name:"OpenApps", kind:list, value:OpenApps}
    end tell

Cleverly, the make new property list command will overwrite any existing key/value item that already has the name "OpenApps", so it won't be duplicated.

Next, we need a way to quit applications on a system:

    to kill(A as list, X as list)
        local A, X
        
        if A = {} then return
        
        script jury
            property A0 : item 1 of A
            property An : rest of A
            property OK : A0 is not in X
        end script
        
        tell the jury
            ignoring application responses
                if its OK then quit the application named (its A0)
                kill(its An, X)
            end ignoring
        end tell
    end kill

This is a recursive handler that is passed a list of applications to quit (parameter A) and a list of applications that are to be excluded (parameter X). It then goes through the list one by one and checks the application isn't one of the ones in X before quitting it and moving onto the rest of the list.

    tell application "System Events" to set P to the ¬
        name of every process whose ¬
        class of menu bars contains menu bar and ¬
        POSIX path of the application file ¬
        does not start with "/System/Library/"
    tell application "System Events" to set OpenApps to the ¬
        name of every application process whose ¬
        class of its menu bar contains menu bar and ¬
        POSIX path of the application file does not start with "/System" and ¬
        POSIX path of the application file does not start with "/Library"

Storing information in a shared settings file

Writing the settings that need to be saved can be done with a .plist file, which stores key/value pairs of data along with the data types. This allows any value to be saved and retrieved by its name.

Let's assume the shared settings file will be saved at ~/Example/savedState.plist where ~/Example/ is some sort of shared folder (e.g. a cloud storage folder) to which both computers have access.

Using AppleScript, this is how one might save a list of applications that are currently open:

    property plist : "~/Example/SavedState.plist"
    
    tell application "System Events"
        if not (the file plist exists) then make new property list file ¬
            with properties {name:plist}
        
        set plistf to the property list file named plist
        
        tell plistf to make new property list item with properties ¬
            {name:"OpenApps", kind:list, value:OpenApps}
    end tell

Cleverly, the make new property list command will overwrite any existing key/value item that already has the name "OpenApps", so it won't be duplicated.

Next, we need a way to quit applications on a system:

    to kill(A as list, X as list)
        local A, X
        
        if A = {} then return
        
        script jury
            property A0 : item 1 of A
            property An : rest of A
            property OK : A0 is not in X
        end script
        
        tell the jury
            ignoring application responses
                if its OK then quit the application named (its A0)
                kill(its An, X)
            end ignoring
        end tell
    end kill

This is a recursive handler that is passed a list of applications to quit (parameter A) and a list of applications that are to be excluded (parameter X). It then goes through the list one by one and checks the application isn't one of the ones in X before quitting it and moving onto the rest of the list.

added 953 characters in body
Source Link
CJK
  • 5.6k
  • 9
  • 19
Loading
added 2244 characters in body
Source Link
CJK
  • 5.6k
  • 9
  • 19
Loading
added 358 characters in body
Source Link
CJK
  • 5.6k
  • 9
  • 19
Loading
added 358 characters in body
Source Link
CJK
  • 5.6k
  • 9
  • 19
Loading
added 1972 characters in body
Source Link
CJK
  • 5.6k
  • 9
  • 19
Loading
Source Link
CJK
  • 5.6k
  • 9
  • 19
Loading