I've created an applescript to boot from snow leopard to lion, but the bless command is failing. Here's the command:
do shell script "bless -mount /Volumes/bootdrive/ -legacy -setBoot -nextonly" password "mypassword" with administrator privileges
On reboot, I get the black screen with 'No bootable device' error. I've run the command directly in the terminal as root (rather than as an applescript) and have gotten the same result. And yes, I've triple-checked that the disk path I'm using is correct and is bootable.
Any idea what the issue could be?
I don't have an appropriate setup to test with, but the -legacy option looks very suspicious to me. According to the man page, that's used to support BIOS-based operating systems, which OS X isn't. Try removing -legacy and see if it works better.
Working solution
The SIP was the first problem I've encountered on Big Sur. Turned it off looks like a bad idea. The second problem was target volumes list items doesn't have actions. Which make impossible to click on them via click or "click at" functions perhaps because of some new additional protections on Big Sur. Click with AST and other scripts also doesn't works due to new MacOS restrictions. The only way I found is using python click(but this leads to a slight delay while script selects target volume).
So here is a fully automated switching:
property targetVolume : "BOOTCAMP" # find name of required volume inside System Preference > Startup Disk
property passwordValue : "yourSystemPassword" # Can be empty
tell application "System Events"
tell application "System Preferences"
set current pane to pane id "com.apple.preference.startupdisk"
activate
end tell
tell application process "System Preferences"
tell window "Startup Disk"
set volumePosition to {0, 0}
set lockFound to false
# Check if auth required
set authButtonText to "Click the lock to make changes."
if exists button authButtonText then
click button authButtonText
# Wait for auth modal
set unlockButtonText to "Unlock"
repeat
if (exists sheet 1) and (exists button unlockButtonText of sheet 1) then exit repeat
end repeat
# Autofill password if setted
if passwordValue is not equal to "" then
set value of text field 1 of sheet 1 to passwordValue
click button unlockButtonText of sheet 1
end if
# Wait for auth success
repeat
if exists button "Click the lock to prevent further changes." then exit repeat
end repeat
end if
# Wait until loading volumes list
repeat
if exists group 1 of list 1 of scroll area 1 then exit repeat
end repeat
# Click on target volume (posible a slight delay because of shell script executing)
repeat with m in (UI element of list 1 of scroll area 1)
if (value of first static text of m = targetVolume) then
tell static text targetVolume of m
set volumePosition to position
end tell
end if
end repeat
set volumePositionX to item 1 of volumePosition
set volumePositionY to item 2 of volumePosition
my customClick(volumePositionX, volumePositionY)
click button "Restart…"
# Wait for restart modal appears
repeat
if (exists sheet 1) and (exists value of first static text of sheet 1) then exit repeat
end repeat
click button "Restart" of sheet 1
end tell
end tell
end tell
# shell script to make click work on target volume
on customClick(x, y)
do shell script "
/usr/bin/python <<END
import sys
import time
from Quartz.CoreGraphics import *
def mouseEvent(type, posx, posy):
theEvent = CGEventCreateMouseEvent(None, type, (posx,posy), kCGMouseButtonLeft)
CGEventPost(kCGHIDEventTap, theEvent)
def mousemove(posx,posy):
mouseEvent(kCGEventMouseMoved, posx,posy);
def mouseclick(posx,posy):
mouseEvent(kCGEventLeftMouseDown, posx,posy);
mouseEvent(kCGEventLeftMouseUp, posx,posy);
ourEvent = CGEventCreate(None);
currentpos=CGEventGetLocation(ourEvent); # Save current mouse position
mouseclick(" & x & "," & y & ");
mousemove(int(currentpos.x),int(currentpos.y)); # Restore mouse position
END"
end customClick
on simpleEncryption(_str)
set x to id of _str
repeat with c in x
set contents of c to c + 100
end repeat
return string id x
end simpleEncryption
on simpleDecryption(_str)
set x to id of _str
repeat with c in x
set contents of c to c - 100
end repeat
return string id x
end simpleDecryption
You just need to change two properties targetVolume and passwordValue. Password can be empty and in that case you can provide it manually. Then just copy this script, paste it to the Script Editor and export via File -> Export -> file format - Application, select Run-only -> Save. You can do the same process for all systems you have, for example Big Sur 1, Big Sur 2, Bootcamp.
Related
Using Xcode, I'm trying to pipe the output of a shell command that I use to check the list of available printers on a print server. It works in Terminal, but the output can only be seen in the debugger, and when I put the script into Script Editor, I get the output displayed as a "Syntax Error".
I'm trying to have it come up as an alert with the Display alert command but I've had no luck.
on Button_(sender)
set Printerlookup to "/usr/local/bin/iprntcmd --listprintersonserver printerserver.com"
set Printers to do shell script Printerlookup
display alert "The available printers are:" & Printers
end Button_
EDIT:
This is the whole appdelegate.
script AppDelegate
property parent : class "NSObject"
property txtBox: ""
-- IBOutlets
property theWindow : missing value
on applicationWillFinishLaunching_(aNotification)
-- Insert code here to initialize your application before any files are opened
end applicationWillFinishLaunching_
on applicationShouldTerminate_(sender)
-- Insert code here to do any housekeeping before your application quits
return current application's NSTerminateNow
end applicationShouldTerminate_
use scripting additions
on Button_(sender)
if txtBox is "" then
display alert "Please enter some text"
else
set iPrntlookup to "/usr/local/bin/iprntcmd --listprintersonserver "& txtBox &"printerserver.com"
set Printers to do shell script Printerlookup
display alert "The available printers are:" & Printers as text
end if
end Button_
end script
This is the expected output, which is found in the debugger area as opposed to the dialog box.
2018-05-07 21:34:12.925412+1000 iPrint Local[29523:430596] MessageTracer:
Falling back to default whitelist
2018-05-07 21:34:17.104407+1000 iPrint Local[29523:430596] *** -[AppDelegate
Button:]: iprntcmd v06.07.01
Listing printers on testprintserver.com.
ipp://testprintserver.com/ipp/printer1
ipp://testprintserver.com/ipp/printer2 (error 1)
Add a use scripting additions statement at the top of your script.
I have a helperScript which has a few basic functions that I frequently use.
My Current script’s flow goes like this:
on SubA()
Set HelperScript to load…..
tell HelperScript
: :
: :
end tell
end SubA
on SubB()
Set HelperScript to load…..
tell HelperScript
::
::
end tell
end SubB
on run paravlist
Set HelperScript to load…..
tell HelperScript
SubA()
SubB()
end tell
end run
I am unable to call SubA() and SubB() as the helper script is being set and used from each of subroutines. If I comment out the usage of helperScript. I am able to call subroutines from one another. What is the best way to deal with a problem like this? I want to use the helperScript in every subroutine.
After reading your question a few more times, I think I've figured out what you're asking. You're trying to load a script within your method and then you want to call a method that is within that script?
If that is the case, I think what you're looking for is this...
set HelperScript to load script...
set theResult to someMethod() of HelperScript
EDIT :
I'm still not clear if you have two scripts or one, so i've updated the answer to reflect both cases.
Dual script example...
property HelperScript : null
on run
try
if not loadScript() then error "Unable to load script"
set rslt1 to SubA() of HelperScript -- This approach assumes HelperScript.scpt is a different script and it contains a method called SubA
set rslt2 to SubB() of HelperScript -- This approach assumes HelperScript.scpt is a different script and it contains a method called SubB
on error errMsg
activate
display dialog "Error: " & errMsg buttons {"OK"} default button 1 giving up after 10
end try
end run
on loadScript()
try
set HelperScript to load script (POSIX file "/Path/To/HelperScript.scpt")
return true
on error
return false
end try
end loadScript
Single script example...
on run
try
set rslt1 to SubA() -- This approach assumes your HelperScript is THIS script
set rslt2 to SubB() -- This approach assumes your HelperScript is THIS script
on error errMsg
activate
display dialog "Error: " & errMsg buttons {"OK"} default button 1 giving up after 10
end try
end run
on SubA()
try
-- Do something here
return true -- or some other value
on error
return false -- or some other value
end try
end SubA
on SubB()
try
-- Do something here
return true -- or some other value
on error
return false -- or some other value
end try
end SubB
AppleScript has included a library loading system since 10.9. It's not great (e.g. avoid the SDEF garbage as it's 1. make-work and 2. bug-injector) but it generally does the job. I recommend you adopt that.
Lets say I have a file a.txt on my C:.
When I press button one in the gui I want to rename C:\a.txt to c:\xyz_a.txt.
When I press button two in the gui I want to rename the file back to c:\a.txt.
How would you do that with ruby shoes? Any hints would be much appriciated.
Here is a Shoes app that with two buttons that will rename file back and forth.
Shoes.app {
file_orig = "E:/abc.txt"
file_renamed = "E:/xyz_a.txt"
stack do
#push_1 = button "Rename"
#push_2 = button "Rename back"
#note = para ""
end
#push_1.click {
begin
File.rename(file_orig, file_renamed)
#note.replace "File #{file_orig} renamed to #{file_renamed}"
rescue => e
#note.replace "Error while renaming #{file_orig} : #{e.message}"
end
}
#push_2.click {
begin
File.rename(file_renamed, file_orig)
#note.replace "File #{file_renamed} renamed BACK to #{file_orig}"
rescue => e
#note.replace "Error while renaming #{file_renamed} : #{e.message}"
end
}
}
Note that my example uses file from E drive. To rename files in C drive, one typically needs administrator privilege. You may get error like: rename': Permission denied # sys_fail2 - (C:/abc.txt, C:/xyz_a.txt) (Errno::EACCES).
To give administrator privilege to your Shoes app, you can launch a command line window using Run as administrator option (Right-click on command icon in application list and select Run as administrator), and from that command window run the shoes app using shoes app.rb.
Here is another simple solution.
The folder is C:\Test\, the file is called A.txt and will be renamed to INACTIVE_A.txt with button one and back to A.txt with button two.
Shoes.app do
stack do
button "Rename A.txt to INACTIVE_A.txt" do
Dir.chdir("C:/Test")
File.rename("A.txt", "INACTIVE_A.txt")
end
button "Rename INACTIVE_A.txt to A.txt" do
Dir.chdir("C:/Test")
File.rename("INACTIVE_A.txt", "A.txt")
end
end
end
new to applescript and this small check is driving me nuts.
I want to check if the input to the script has the substring of "mob".
If i create a varible with mob1234, It works and returns true.
on run {input, parameters}
set testString to "mob1234"
display dialog {"MOB" is in testString}
return input
end run
If i change it to use the input, and set the input to mob1234, it fails and gives me false
on run {input, parameters}
set testString to input
display dialog {"MOB" is in testString}
return input
end run
I have no idea.
You don't say how you're invoking your script. If you're calling the script via Automator, be aware that in this mode input is a list, not a string, so this should work:
set testString to item 1 of input
Since the answer given by iayork seems to be right, here some follow up:
-- When this is saved as compiled script one can call it from Terminal like:
-- `osascript scriptName.scpt MOBstringArg1 arg2`
on run {input, parameters}
if (input's class is list) then set input to (item 1 of input) as text
if "MOB" is in input then
display notification "FOUND MOB" with title "In: " & input
end if
return input
end run
See comment from iayork about calling a script with osascript.
You can also just coerce the input to text directly when you assign it to testString: set testString to input as text, that is, if you aren't going to use any other list item of input.
Can anybody shed some light on why scripting is so slow all of a sudden?
Even this test script does not complete before a 120 second time out.
tell application "Mail"
set selectedEmails to get selection -- returns a list
end tell
This might be a problem with your system. That script does not take much time to execute on my computer.
set time1 to do shell script "perl -e 'use Time::HiRes qw(time); print time'"
tell application "Mail" to set selectedEmails to get selection -- returns a list
set time2 to do shell script "perl -e 'use Time::HiRes qw(time); print time'"
set millisec to (round ((time2 - time1) * 1000))
return "Emails:" & (count of selectedEmails) & " Milliseconds:" & millisec
"Emails:1000 Milliseconds:183"