In this case roughly
was putting it mildly
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.
In this case roughly
was putting it mildly
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ā
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?
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.
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"