从Mac OS 10.9 Mavericks开始,Apple requires that Assistive Access must be enabled explicitly for each application that wants to use it。
对于给定的应用程序,我编写了以下AppleScript函数来处理此问题。该脚本适用于我,但它有两个缺陷:
当操作系统以非英语语言运行时,硬编码按钮名称将出错,脚本将失败。我怎样才能发现操作系统运行的语言,以及"点击锁定进行更改的名称。"按钮会有那种语言吗?或者,有没有办法确定此按钮是否处于locked
,authenticating
或unlocked
状态,而不读取按钮的名称?
脚本在等待用户输入管理员用户名和密码时使用紧密重复循环。有没有更好的策略可以用来等待对话框成功解除?
====
set output to allowAssistiveAccessFor("Skype")
if (the |quitWhenDone| of output) then
tell application "System Preferences" to quit
end if
on allowAssistiveAccessFor(applicationName)
set quitWhenDone to not (application "System Preferences" is running)
set output to {quitWhenDone:quitWhenDone}
tell application "System Preferences"
activate
reveal anchor "Privacy_Accessibility" of pane id "com.apple.preference.security"
tell application "System Events"
tell process "System Preferences"
-- Find the table that contains the application icons and checkboxes
try
set appTable to table 1 of scroll area 1 of group 1 of tab group 1 of window "Security & Privacy"
on error errorMessage
return output & {state:-1, message:errorMessage}
end try
set total to the number of rows of appTable
-- Find the row that refers to applicationName
repeat with rowNumber from 1 to total
if (name of UI element 1 of row rowNumber of appTable = applicationName) then
set appCheckbox to checkbox 1 of UI element 1 of row rowNumber of appTable
if (value of appCheckbox as boolean) then
-- Assistive access is already enabled for this application
return output & {state:0, message:"Already enabled"}
else
-- Click the “Click the lock to make changes.” button.
if exists button "Click the lock to make changes." of window "Security & Privacy" then
click button "Click the lock to make changes." of window "Security & Privacy"
-- The user will now have to enter an admin password. This can take some time.
-- The name of the button will change to "Authenticating"...
set unlocking to button "Authenticating…" of window "Security & Privacy"
repeat while exists unlocking
end repeat
-- ... and then to "Click the lock to prevent further changes." ... unless the user cancelled
if exists button "Click the lock to make changes." of window "Security & Privacy" then
return output & {state:-1, message:"User cancelled"}
end if
end if
-- Click the <applicationName> checkbox.
-- If we had to unlock the Security & Privacy pane, then an immediate click might not have
-- an effect. Try as many times as possible for 1 second, and give up if unsuccessful
set failMessage to "Cannot allow the " & applicationName & " application to control your computer"
set endDate to (current date) + 1.0 -- 1 second from now
repeat
try
if ((current date) > endDate) then
-- Time's up
return output & {state:-1, message:failMessage}
end if
click appCheckbox
if (value of appCheckbox as boolean) then
return output & {state:0, message:"Success"}
end if
on error errorMessage
-- Something dreadful happened. Keep trying until time is up
end try
end repeat
end if
end if
end repeat
end tell
end tell
end tell
return output & {state:-1, message:"Application " & applicationName & " not found"}
end allowAssistiveAccessFor
答案 0 :(得分:2)
您可以将窗口称为“窗口1”而将锁定按钮称为“按钮4”,而不是使用窗口和按钮名称。然后系统使用的语言无关紧要。
tell application "System Preferences"
activate
reveal anchor "Privacy_Accessibility" of pane id "com.apple.preference.security"
tell application "System Events"
tell process "System Preferences"
tell button 4 of window 1 to click
end tell
end tell
end tell
用户通过身份验证后,按钮4的名称会发生变化。所以你可以循环直到你看到那个变化。以下不是一个完美的解决方案,因为它只适用于英语语言系统,但也许它可以让你更近一步。
tell application "System Preferences"
activate
reveal anchor "Privacy_Accessibility" of pane id "com.apple.preference.security"
tell application "System Events"
tell process "System Preferences"
tell button 4 of window 1 to click
with timeout of 180 seconds
repeat until button "Click the lock to prevent further changes." of window 1 exists
end repeat
display dialog "Preference pane unlocked." with title (the name as text) buttons {"OK"} default button "OK" giving up after 60
end timeout
end tell
end tell
end tell
答案 1 :(得分:0)
无论操作系统使用何种语言,此版本的脚本都能正常运行。使用法语和俄语进行测试。它仍然使用紧密的重复循环来检查用户是否已关闭身份验证对话框,但这似乎不会影响性能。
set output to allowAssistiveAccessFor("skype")
if (the |quitWhenDone| of output) then
tell application "System Preferences" to quit
end if
get output
on allowAssistiveAccessFor(applicationName)
set quitWhenDone to not (application "System Preferences" is running)
set output to {quitWhenDone:quitWhenDone}
tell application "System Preferences"
reopen -- to ensure that the application will be open and window 1 will contain a tab group
activate
-- Open the Accessibility pane of the Security & Privacy Preferences
reveal anchor "Privacy_Accessibility" of pane id "com.apple.preference.security"
-- The "Security & Privacy" window and its contents are only available through System Events
tell application "System Events" to tell process "System Preferences"
-- Find the table that contains the application icons and checkboxes. This will be in
-- window 1 which is called "Security & Privacy" in English. If assistive access is
-- not enabled for AppleScript, then we will have no access to any window.
try
set securityAndPrivacyWindow to window 1
set appTable to table 1 of scroll area 1 of group 1 of tab group 1 of securityAndPrivacyWindow
on error errorMessage
return output & {state:-1, message:errorMessage}
end try
-- If we get here, then the assistive access is enabled for AppleScript.
-- Let's find the row that refers to applicationName
set total to the number of rows of appTable
repeat with rowNumber from 1 to total
if (name of UI element 1 of row rowNumber of appTable = applicationName) then
-- We have found the row containing the applicationName checkbox
set appCheckbox to checkbox 1 of UI element 1 of row rowNumber of appTable
if (value of appCheckbox as boolean) then
-- Assistive access is already enabled for this application
return output & {state:0, message:"Already enabled"}
else
(* Attempt to click on appCheckbox. If its value changes then the
Security & Privacy window was already unlocked. If it fails, then we will
need to ask the user to enter an admin name and password
*)
click appCheckbox
if (value of appCheckbox as boolean) then
return output & {state:0, message:"Success"}
end if
(* If we get here, then the click on appCheckbox had no effect, presumably
because this window is locked. We need to simulate a click on the
“Click the lock to make changes.” button. This may have different names in
different languages. All we know for certain is:
• It is button 4 (in Mavericks at least)
• Its name will change to something meaning "Authenticating…" when it is
clicked
• If it was in its locked state:
- a dialog will now show, and it will take the user a significant amount of
time to respond to the dialog
- Its name will change again when the user clicks on one of the buttons
in the dialog
- If its name reverts to the name it had before, then the user canceled
the dialog
- If its name becomes something new, then the user successfully
entered an admin name and password
• If it were in its unlocked state, it would immediately lock and its name would
not change again, so we would wait forever in the `repeat while` loop
However, if it were in its unlocked state then we would already have changed
the state of the applicationName checkbox, so we would not be here.
*)
set lockButton to button 4 of securityAndPrivacyWindow
click lockButton
-- The name of the button will have changed to something like "Authenticating"...
set unlocking to button 4 of securityAndPrivacyWindow
-- The user will now have to enter an admin password. This can take some time.
repeat while exists unlocking
-- The user has not yet clicked on either the Cancel or the Unlock button yet
end repeat
(* The user has closed the dialog. If s/he clicked Cancel then:
• The original name of the button will have been restored
• We cannot continue
*)
if exists lockButton then
return output & {state:-1, message:"User canceled"}
end if
-- If we get here, we can simulate a click on the <applicationName> checkbox.
click appCheckbox
if (value of appCheckbox as boolean) then
return output & {state:0, message:"Success after authentication"}
else
return output & {state:-1, message:"Failure after authentication"}
end if
end if
end if
end repeat
end tell
end tell
return output & {state:-1, message:"Application " & applicationName & " not found"}
end allowAssistiveAccessFor