SD and OS X version script

In this case roughly was putting it mildly :slight_smile:

The exact implementation has changed in different versions of the OS, and will no doubt change again. But for a lot of people and apps, duplicate IDs should be rare.

So what exactly was wrong with the method Chris wrote and I modified?

Nothing that I noticed. These were just tweaks for (a) speed, and (b) to include the OS build number. On point (a), depending on your network configuration system info can take several seconds to return.

There was nothing wrong with it. I just created a shorter method. Well I tried to until strange stuff happened. I thought you might like to see it with some ASObj-C added but use which ever you like. Also I added the OSX build version Shane suggested. The actual final version ended up being the one shown below. I forgot to post it after all the trouble I ran into with strange problems.

So basically Chris wrote a script and you modified it and I modified your modification, Shane suggested another modification. Basically the script shown below is the result of 3 people modifying an existing script one after the other and you were contributor number 2. My script was based on your script. I didnā€™t come up with a new script.

use scripting additions
use framework "Foundation"

set SDBundle to current application's NSBundle's bundleWithIdentifier:"com.latenightsw.ScriptDebugger6"
set BundleVersion to SDBundle's infoDictionary()'s objectForKey:"CFBundleVersion"
set SystemVersion to system version of (system info)
set SystemBuildNum to do shell script "sw_vers -buildVersion"

tell application id "com.latenightsw.ScriptDebugger6"
	set SDVersion to version
	set ScriptName to name of document 1
end tell

set the clipboard to "Copy " & ScriptName & " SD " & SDVersion & " (" & BundleVersion & ") OSX " & SystemVersion & " (Build " & SystemBuildNum & ")"

Bill

@ShaneStanley, I thought you generally recommended against using shell scripts (& PlistBuddy), especially when there is a simple ASObjC alternative?

I donā€™t think Chris (@ccstone) was aware of these ASObjC statements when he wrote the original script.

Hmmmmā€¦ the changes I made were to rename the file after it runs, so if youā€™re running it from the scripts menu you can just pull down the menu to verify what the values were the last time it ran; and to add ā€œā€“>ā€ to the string so you could insert it at the top of a script as a comment so my contribution = ā€œmissing valueā€ :slight_smile:

In Chrisā€™ script, SD didnā€™t have to be running, and if itā€™s not running this version will take much longer to execute.

Since I donā€™t test early versions of Mac OS, do I need the build number?

This script goes back years, it may predate those.

Iā€™m wondering if there a reason the script was getting OS build info and version from two different sources?

Hereā€™s a tweaked version

use scripting additions
use framework "Foundation"

set fileNameFormat to {"Copy SD ", "version and", " OSX ", "version"}

set sdPath to POSIX path of (path to application id "com.latenightsw.ScriptDebugger6")
set sdPlist to quoted form of (sdPath & "Contents/Info.plist")
set plListCommand to "/usr/libexec/PlistBuddy -c Print:CFBundleShortVersionString -c Print:CFBundleVersion " & sdPlist
set {SDVersion, BundleVersion} to paragraphs of (do shell script plListCommand)
set SystemInfo to do shell script "sw_vers"
set AppleScript's text item delimiters to {":	"}
set SystemVersion to text item 2 of paragraph 2 of SystemInfo
set SystemBuildNum to the last text item of SystemInfo
set AppleScript's text item delimiters to {""}

set infoString to " SD " & SDVersion & " (" & BundleVersion & ") OSX " & SystemVersion & " (Build " & SystemBuildNum & ")"

set the clipboard to "-->" & infoString
set newFileName to "Copy" & infoString

set thisScript to path to me as alias

--Unnote next line and run script to set script name back to default
--set newFileName to fileNameFormat as text

tell application "Finder"
	set oldFileName to the name of thisScript
	if "Unsaved Script Debugger Document" is in oldFileName then return
	if "Untitled" is in oldFileName then return
	set nameExt to the name extension of thisScript
	set newFileName to newFileName & "." & nameExt
	if oldFileName is not newFileName then set the name of thisScript to newFileName
end tell

return the clipboard

My script (with all ASObjC) runs very fast from anywhere.

I think you may have over-complicated things by trying to integrate with SD.
Why not just have the script show a dialog with the version info, and buttons to ā€œCopyā€, ā€œPasteā€, and ā€œOKā€ ?

Then you can run the script from anywhere. It could get the name of the frontmost app, and show a dialog with that as default, but allowing the user to enter a different app.

Just an idea . . .

I think I was referring to the last one Bill posted that had a Tell application Script Debugger.

My script doesnā€™t integrate with SD. My script lives in the userā€™s script menu. When I want to run it, from any application, I just pull down the menu and run it. No need for a dialog, because it sets the clipboard and I just paste. With the versions I posted, the name of the script changes to show the info in the menu, so if I just want to double check what Iā€™ve got installed, I just pull down the menu and see.

I suppose it could be useful to do get the info for other apps, but that sounds like overcomplicating things.

I

OK, this version integrates your methods for getting SD version and build

use scripting additions
use framework "Foundation"
--> SD 6.0.4 (6A198) OSX 10.11.6 (15G1217)

set appID to "com.latenightsw.ScriptDebugger6"
set fileNameFormat to {"Copy SD ", "version and", " OSX ", "version"}

set SDBundle to current application's NSBundle's bundleWithIdentifier:appID

set SDVersion to SDBundle's infoDictionary()'s objectForKey:"CFBundleShortVersionString"
set BundleVersion to SDBundle's infoDictionary()'s objectForKey:"CFBundleVersion"

set SystemInfo to do shell script "sw_vers"
set AppleScript's text item delimiters to {":   ", return}
set SystemInfo to text items of SystemInfo
set AppleScript's text item delimiters to {""}
set SystemVersion to item 4 of SystemInfo
set SystemBuildNum to the last text item of SystemInfo

set infoString to " SD " & SDVersion & " (" & BundleVersion & ") OSX " & SystemVersion & " (" & SystemBuildNum & ")"

set the clipboard to "-->" & infoString
set newFileName to "Copy" & infoString

set thisScript to path to me as alias

--Unnote next line and run script to set script name back to default
--set newFileName to fileNameFormat as text

tell application "Finder"
   set oldFileName to the name of thisScript
   if "Unsaved Script Debugger Document" is in oldFileName then return
   if "Untitled" is in oldFileName then return
   set nameExt to the name extension of thisScript
   set newFileName to newFileName & "." & nameExt
   if oldFileName is not newFileName then set the name of thisScript to newFileName
end tell

return the clipboard

Let me try to clarify. My general preference for ASObjC is based on a few factors.

First, do shell script is often slower. I admit, Iā€™m a speed freak.

Second, I prefer a command or method that says it returns what I want, rather than a hack, and many uses of do shell script are hacks doing things like reading implementation files. Thatā€™s not the case with PlistBuddy, but Iā€™m talking more generally.

Third, because theyā€™re at a lower level, some commands are traps. So sort can have trouble with Unicode, ls doesnā€™t know a package from a folder, and so on. These things often work fine in tests and end up in code as bugs waiting to happen.

And finally an awful lot of examples I see also include code using TIDs/awk/sed/whatever to extract the required info from the result, and thatā€™s just another layer of fragile code. Itā€™s hard to test, and if the tool is modified ā€“ and in some cases if the environment changes ā€“ stuff can fall apart apart in hard-to-debug ways.

Now there are plenty of cases that avoid all these, and there are also ASObjC methods that are unusable or impractical. But I like to play the percentages, and I reckon theyā€™re strongly on the side of ASObjC.

And did I mention speed? :slight_smile:

For example, in this very thread: bundleWithIdentifier:. Chris has pointed out to me off-forum that it fails when passed other appsā€™ IDs in Script Debugger 5, and from FastScripts. I have know idea why. But FWIW, hereā€™s an alternative:

set theURL to current application's NSWorkspace's sharedWorkspace()'s URLForApplicationWithBundleIdentifier:appID
set SDBundle to current application's NSBundle's bundleWithURL:theURL

Note that this should also include:

use framework "AppKit"

for NSWorkspace.

And for JMā€™s info, the documentation for URLForApplicationWithBundleIdentifier: is a little more forthcoming, if not much more enlightening:

This uses various (currently unspecified) heuristics in case multiple apps have the same bundle ID.

But it still has calls to shell script.

I guess I missed a key factor that your script ONLY gets the version info for SD. Thatā€™s useful, but I very often need to know (and post) the version info for other apps.

Hereā€™s a script that does that, and does NOT use shell scripts, only ASObjC statements.

EDIT: 2017-02-22 11:40 PM CT

###AppleScript Using Only ASObjC
NOTE: TextWrangler was the FrontMost app.
Executed script from Apple script menu.

####Example Output

(*
  VER:  1.1    Date: 2017-02-22
  Revised per Shane Stanley's fix using app URL to get Bundle.
*)
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use scripting additions

tell application "System Events" to Ā¬
  set appName to item 1 of (get name of processes whose frontmost is true)

set currentApp to appName

set msgStr to "Confirm or Change App Name"
set titleStr to "Get Version Info for App and macOS"
set ansStr to appName

display dialog msgStr Ā¬
  with title titleStr Ā¬
  with icon caution Ā¬
  default answer ansStr

set ansRec to result
set buttonStr to button returned of ansRec
set appName to text returned of ansRec

set macOS to system version of (system info)

try
  set appID to get id of application appName
  
  set appURL to current application's NSWorkspace's sharedWorkspace()'s URLForApplicationWithBundleIdentifier:appID
  set appBundle to current application's NSBundle's bundleWithURL:appURL
  
  set appVer to appBundle's infoDictionary()'s objectForKey:"CFBundleShortVersionString"
  set appBuild to appBundle's infoDictionary()'s objectForKey:"CFBundleVersion"
  set aName to appBundle's infoDictionary()'s objectForKey:"CFBundleExecutable"
  set appName to (aName as text)
  
on error errStr number errorNumber
  display dialog "ERROR: " & errStr with title titleStr
  return
  
end try

set verStr to appName & " " & (appVer as text) & Ā¬
  " (" & (appBuild as text) & Ā¬
  ")" & " on macOS " & macOS

set ansRec to display dialog verStr Ā¬
  with title Ā¬
  titleStr buttons {"Copy", "Paste", "OK"} Ā¬
  default button Ā¬
  "OK" with icon note

set buttonStr to button returned of ansRec

if (buttonStr = "Copy") then
  set the clipboard to verStr
  display notification verStr with title "Copied to Clipboard"
  
else if (buttonStr = "Paste") then
  set the clipboard to verStr
  delay 0.2
  tell application currentApp
    activate
    tell application "System Events"
      keystroke "v" using command down
    end tell
  end tell -- App
  
end if

--- EXAMPLE RESULTS ---
-->Adobe Acrobat Pro 11.0.19 (11.0.19) on macOS 10.11.6

Is there a way to get the OS build number without using shell scripts?

Didnā€™t Shane post that above?

OK, hereā€™s a full version of the script I want (SD and OS versions and builds; sets clipboard; changes scriptā€™s file name) without any shell scripting or UI scripting. (it should be pretty easy to repurpose to other apps for Michaelā€™s needs).

use scripting additions
use framework "Foundation"

set fileNameFormat to {"Copy SD ", "version and", " OSX ", "version"}
set appName to "SD"
set appId to "com.latenightsw.ScriptDebugger6"

set appBundle to current application's NSBundle's bundleWithIdentifier:appId
set appVersion to appBundle's infoDictionary()'s objectForKey:"CFBundleShortVersionString"
set appBundleVersion to appBundle's infoDictionary()'s objectForKey:"CFBundleVersion"

set SystemInfo to current application's NSProcessInfo's processInfo()'s operatingSystemVersionString()
set AppleScript's text item delimiters to {" ", ")"}
set SystemInfo to text items of (SystemInfo as text)
set AppleScript's text item delimiters to {""}
set SystemVersion to item 2 of SystemInfo
set SystemBuildNum to item 4 of SystemInfo

set infoString to appName & appVersion & " (" & appBundleVersion & ") OSX " & SystemVersion & " (" & SystemBuildNum & ")"

set the clipboard to "-->" & infoString
set newFileName to "Copy" & infoString

set thisScript to path to me as alias

--Unnote next line and run script to set script name back to default
--set newFileName to fileNameFormat as text

tell application "Finder"
	set oldFileName to the name of thisScript
	if "Unsaved Script Debugger Document" is in oldFileName then return
	if "Untitled" is in oldFileName then return
	set nameExt to the name extension of thisScript
	set newFileName to newFileName & "." & nameExt
	if oldFileName is not newFileName then set the name of thisScript to newFileName
end tell

return the clipboard

Hi Shane,

OMM this returns incorrect information. Any thoughts on this?

What I get:

SD 6.0.1 (6A170)

Versus, what I should get:

SD 6.0.4 (6A198)

Stan C.

Thanks, but as you may have not noticed, I already a great working script (posted above). No need for a repurpose. :wink:

If you have multiple copies of an app, itā€™s always a bit of a crap-shoot. Launch Services is ultimately responsible, and it often moves in mysterious ways.

An alternative is to use a path:

set SDBundle to current application's NSBundle's bundleWithPath:"/Applications/Script Debugger"