Turn Bluetooth off and on programmatically - objective-c

Is there a way to programmatically turn on and off the Bluetooth connection on OSX in a way that will be accepted by the Mac App Store?
From my previous question, I've found about blueutil, but it uses private APIs.

It would be somewhat surprising if Apple approved an app that modified the user's antenna settings. It sounds like the kind of thing they typically frown on, no matter how you do it. But then, sometimes I get surprised.
You can definitely do it through Applescript:
tell application "System Preferences"
set current pane to pane "com.apple.preferences.Bluetooth"
tell application "System Events"
tell process "System Preferences"
set isOnCheckbox to checkbox "On" of window "Bluetooth"
if value of isOnCheckbox is 0 then
click isOnCheckbox
end if
end tell
end tell
quit
end tell
Note that this will take over System Preferences and at the end close it even if the user was running it. That's not the best user experience, and I definitely wouldn't do it without first warning the user. But of course, I wouldn't recommend modifying the bluetooth settings without warning the user.
EDIT
Because you asked, I'll take a moment to rant here....
Regarding how to learn to read and write the above, first note that it, like most AppleScript I write professionally, was cobbled together from google searches and experimentation. I'm a purist programmer at heart, and I believe in really understanding the technology you use. Even I cobble together things in AppleScript until they "kind of work."
I wish there were a really good document. Of course there's the language guide, but it's kind of like learning Cocoa from the ObjC language definition. My current recommendations are Beginning AppleScript and then AppleScript: The Definitive Guide. Neuburg in particular does not sugarcoat the language or pretend that it makes sense. Applescript, even worse than the original COBOL (ADD X TO Y GIVING Z), is very hard to write because it tries so hard to be easy. I love and respect many languages. AppleScript is crap.
It is, however, the most supported way to interact with most of the Mac system functions, so a good Mac developer needs to at least be able to get by in it. Even if you use the new ScriptingBridge via ObjC (or MacRuby), the underlying object model is still AppleScript based. In my experience, to get ScriptingBridge code to work well, you generally have to write it first in AppleScript and then translate it into Cocoa.

This worked for me in 10.15.6, I might have over complicated my solution which is running script 1 (turn bluetooth off) and then script 2 (turn bluetooth on).
Script 1. This is for turning bluetooth OFF
tell application "System Events" to tell process "SystemUIServer"
tell (menu bar item 1 of menu bar 1 where description is "bluetooth")
click
click menu item "Turn Bluetooth Off" of menu 1
end tell
tell window 1
click button "Turn Bluetooth Off"
end tell
end tell
Script 2. This is for turning bluetooth ON
tell application "System Events" to tell process "SystemUIServer"
tell (menu bar item 1 of menu bar 1 where description is "bluetooth")
click
click menu item "Turn Bluetooth On" of menu 1
end tell
end tell
So I execute one command which will run one script after the other, the sleep is for the UI to update properly.
osascript bluetooth_off.scpt && sleep 3s && osascript bluetooth_on.scpt
You can just save the command in a file and execute it using: (they have to be in the same directory).
~ bash <fileName>
Note: You will need to give access to the terminal on Preferences > Security & Privacy

Related

Create a new PSD file and copy/paste new layer with AppleScript

I try to make a code assembly to create my own applescript to create an image in Photoshop but unfortunately I have an error and I can't find where it comes from.
The first part of the script works, the random image is well copied to the clipboard but the rest is problematic.
-- Select random image
tell application "Finder"
set bg_img to file (random number from 1 to (count files of folder "HD:Works:Club:LAYERS:0-BG")) of folder "HD:Works:Club:LAYERS:0-BG"
end tell
tell application "Preview"
activate
open bg_img
end tell
-- Select and copy image to clipboard
tell application "System Events"
tell process "Preview"
keystroke "a" using command down
keystroke "c" using command down
end tell
end tell
-- Quit Preview Application
tell application "Preview" to quit
tell application "Adobe Photoshop 2022"
-- Create a new document
set docRef to make new document with properties {width:1200, height:1200, resolution:72}
tell docRef
-- Unlock the background layer and fill it with gray color
set background layer of layer 1 of docRef to false
fill selection with contents {class:RGB color, red:200, green:200, blue:200}
end tell
end tell
-- Paste image to new layer
tell application "System Events"
tell process "Adobe Photoshop 2022"
set newLayer to make art layer with properties {name:"LayerA"}
keystroke "v" using command down
end tell
end tell
Ok, a compilation error; I got it now. Try this:
-- Paste image to new layer
tell application "Adobe Photoshop 2022"
activate
set newLayer to make art layer with properties {name:"LayerA"}
end tell
tell application "System Events"
tell process "Adobe Photoshop 2022"
keystroke "v" using command down
end tell
end tell
Remember, you use a tell application "NAME" … end tell block to 1. tell AppleScript which app to send commands to, and 2. the app from which to get the custom terminology (keywords) for commands and objects.
Thus your tell application "System Events"…end tell block uses SE terminology and commands. The tell process "Photoshop"…end tell block inside it is still addressed to System Events. process is an SE-defined keyword for an SE-specific object. Likewise keystroke is an SE-specific command.
To make a new art layer in Photoshop, you have to put that command inside its own tell application block which is targeted at PS.
Yeah, AppleScript is often confusing. And System Events is 10× more confusing than that, thanks to it being not-obvious what is GUI Scripting and what isn’t. Good luck.
--
p.s. I’ve a feeling the tell process block is totally redundant, and is only necessary when using GUI Scripting to manipulate an app’s windows. IIRC the keystroke command doesn’t know or care what app receives those keys, in which case what’s important is that you activate Photoshop before you start “pressing” keys. I’ll leave it to you to determine if you can discard the tell process.
p.p.s. AppleScriptable apps usually don’t include cut and paste commands, usually ’cos they already provide far better ways of getting and setting content. Photoshop, however, does. So if you’ve not already tried it, try inserting a paste command at the end of your “tell Photoshop” block, then comment out the “tell System Events” block, and see if that works for you. If so, you can get rid of that System Events block entirely!
p.p.p.s. It’s also worth investigating PS’s dictionary further, to see if it can open and place your “bg_file” directly. If so, you can eliminate the “tell Preview” and the rest of that System Events horridness too!!

Close access navigation pane even if there is no search result

When starting our vba-access-application (which is done by a VBE-add-in which starts a VBA-function) we used to close the navigation-pane with this code:
DoCmd.SelectObject acMacro, "Autoexec", True
DoCmd.RunCommand acCmdWindowHide
As I started to use the built-in search/filter bar inside the navigation-pane, this code did not work anymore when the macro "Autoexec" is not visible. So I changed it to:
DoCmd.NavigateTo "acNavigationCategoryObjectType"
DoCmd.RunCommand acCmdWindowHide
This seems to work fine as long as there are any search results left. When I write "nothing with that name" inside the search bar(=the filter), the navigation pane will not close.
Does anyone know a way to close the navigation pane even if there is no search result visible?
DoCmd.NavigateTo "acNavigationCategoryModifiedDate"
DoCmd.NavigateTo "acNavigationCategoryObjectType"
DoCmd.RunCommand acCmdWindowHide
In order for the command DoCmd.RunCommand acCmdWindowHide to successfully close the Navigation Pane, the Navigation Pane must have the focus. But for an Access window to have the focus, a control within the window must have focus. It turns out that the NavigateTo command will never place the focus in the Search textbox, so if the search results are blank and there is nothing to select, then focus will not change to the Navigation Pane (even though technically the Navigation Pane's selected group may have been updated.)
If you play with the Navigation Pane long enough, you'll find that the Navigation search results and textbox are reset when switching between the highest-level Navigation categories. Hence my suggested code... it changes between two Navigation categories so that the search results are cleared during that action, so that the Navigation window will eventually gain focus when one of its listed objects finally gets focus.
(Really, using the NavigateTo command in this case is just a stupid trick to place focus on the Navigation Pane. It's just another glaring deficiency of the Access interface that there is no direct commands/objects for controlling the Navigation Pane.)
I suggest you don't write any code—but just use the built in Access settings to prevent (hide) the nav pane.
So work, then you hold down the shift key during startup.
(shift key by-pass).
The shift key development dance:
You will find that you can launch + develop a lot of code and work on forms/reports without having to exit.
However, you STILL will have done a shift key start-up bypass. The reason of course is that on start up, you code may well hide the ribbon. (Or launch a custom one). Same goes for start-up form—it may run a bunch of code, ask for logon, check table links.
And then there is the start-up settings you have. You likely have a start-up form (you don’t want that running). You likely have un-checked the display nav pane, but you need this during development. And what about if you have a custom ribbon? (Again a setting in tools→options). And use special keys—again turned off for users, but REQUIRED for developers.
And then there is the auto keys macro. This is used to re-purpose the F1 key (help—either disable or launch your own custom help—say a pdf or word file).
And any re-purpose such as say an f12 to popup some custom search box etc.
So, all of these custom setup is going to be rather LARGE amount of settings. Many will be from tools→options (main form, ribbon, etc.). And some will be from your code.
You REALLY (but REALLY) can’t code out all of these settings, and some require a re-start anyway. In a typical application there really going to be a lot of settings that are changed for your users vs you as the developer.
On start-up you thus hold down shift key. This will not only prevent your start up code from running, but ALSO your start up settings – even things like nav pane, and especially the tools→settings area (shift key ignores most of those settings).
So during a day of development, I will do this shift key dance all day long.
However, there are two tricks and shortcuts you can use here that will minimize this exit + re-enter down to a dull roar.
One great tick is to always place a custom compact repair button on the QAT. So QAT button is now ONE mouse click and always available to you. So if I am working on a form in design mode, flipping into view mode will often suffice, but in those cases where I need a full exit + re-start to test? I don’t even save the form, I just do a quick simple one click on that QAT compact + repair button.
One click! (Might have to answer yes to save). At this point, the application will re-start without you having to exit. And you don’t hold down the shift key—so all your start up settings run. You now flipped into user test mode, and it only took ONE mouse click.
This allows you to flip from developer mode and into “user test” mode with ease and only one mouse click.
So you can now run your application as it will appear to the end user.
To flip back into developer mode, just one simple click on your custom C+R button. (And you HOLD down shift key). This will flip you back into developer mode (you nav pane, your function keys, everything and all those start up settings are now ignored – you are free to develop without all those hassles and issues in your way). Full wide open use of Access as if no settings at all occurred.
And as noted, you get a c+r to boot, and you need + want to do that multiple times during the day anyway.
And as noted, for a good many changes, you not have to do this flip and can stay in developer mode.
Of course in some cases your “user mode” will REALLY lock down the Access and thus you have to exit (you lose the QAT trick). So you often be able to jump from developer to user, but not back the other way. Again, you not have to run + test everything in user mode all the time, but often some global variables, start up, password stuff will force this issue on you.
So, in this case?
I use a quick hit of alt+f4 to exit the application. AT this point, the accDB file should STILL be highlighted in the windows explorer. So, now it just a quick tap of the enter key to re-launch the accDB. And if wanting “user mode”, then simply don’t hold down the shift key. Do some testing, now alt+f4, and then a simple quick tap of the enter key (we back to the windows file explore and that accDB file is highlight). However, this time you WILL hold down the shift key, and thus you now back into developer mode.
And often, I will call my start up code before testing.
Ctrl+g (jumps to debug window), type in MyStartup
(MyStartup is assumed to be your first start up routine that does all that setup and THEN launches the main form – so in some applications I don’t use the built in start-up form setting, but use the autoexec macro to call my main start up routine (MyStartup)
So in a good many cases, I don’t have to exit Access to flip into test mode.
And of course some reports and forms can be used, viewed, developed on without having to full run the application with all that “user” start-up code stuff.
So some report might work, but then again it may well require some form to be open for it to work. (Or a system wide function and company name setting may be required + set in your start up code). So how badly you need to exit vs that of being able to do “some” development will often vary here.
So I will say that often I am forced to exit + re-load the application (alt+f4, tap enter key). So it only really 2 key combo to exit out and re-load/re-enter Access.
At the end of the day, if you can’t use that QAT shortcut suggestion, then you will exit + re-enter MANY MANY times during the day.
As noted, for a good number of forms etc., then you can flip between view and design mode. (But you of course be running access without all that start up crap stuff that prevents you the developer from working).
The simple matter is at the end of the day, there is going to be FAR MORE settings then just the nav pane (or lack of) that going to mess up your development process. So, the above shift key dance and QAT suggestion ALSO solves all of the OTHER many settings, and does so without you having to write one line of code to deal with this issue.
Of course, once all is working, then you will compile the application down to an accDE. And then apply the shift key by-pass code to that to lock the application further down.

openWorldWithSpec making it impossible to return to previous windows

Reading the book "The Spec UI framework". Trying to implement the part described in chapter "Taking over the entire screen".
After executing the code suggested in the book:
WindowExample new openWorldWithSpec
it seems to be impossible to return to previous state. Tried to delete the new WorldMorph in the inspector. Also tried with halos, as the book suggests but those buttons that are available in the halo menu don't allow it to be closed.
Is it an intended behaviour for this (to be executed to prepare an end-user environment and disable programming UI) or am I missing something?
Working in Pharo 5.0, Mac OS X version.
That is indeed intended behaviour, as part of making applications that do not allow access to the development environment anymore. But you can take a look at the code for PharoLauncher to see how you can enable a developer mode
You can actually get back to normal by:
Alt-Ctrl-Clicking on the Morph (macOS combo may be different, this is for Windows).
Clicking on the little wrench and ask for inspect.
In the evaluation pane, do:
self delete
World menu is available again.
Open a browser.
Done.
If one disables halos in settings, this is a tad harder.

Change Dialog Box Text With AppleScript?

Simply, is it possible to change a "static text" field in an Apple system dialog box? Specifically I am looking into changing some label text of a password popup. I have tried using AppleScript via GUI scripting:
tell application "System Events"
try
tell window 1 of process "loginwindow"
repeat until not (value of static text 4 is equal to "")
set value of static text 4 to "this is a test"
delay 0.5
end repeat
end tell
end try
end tell
Although this does not seem to work at all. Any other methods? Perhaps Scripting Bridge or other? I'd prefer not to code my own dialogs from scratch (not for difficulty reasons, I could easily do it, I'd just prefer to interface rather than emulate.)
Thanks!
Here's an idea... I don't think you can change the login window text itself but you can change the background picture of the login window. Therefore you may be able to setup some images, and then use those images during the login process to display what you want.
I never tried it but this post shows how to do this... here.
After much research, I'm not sure that this is possible - it would be best to write a screen saver, implement it's own password protection, and enable that dialog to be modified from behind the screen saver.

Locking a screen in 10.6

How would I go about locking a screen like Keychain does, meaning preventing all access to Dock, menubar, desktop, etc. Basically just a black screen that I can add a password field to, for the user to return to the desktop? I am well aware of the Carbon method, but I want the NSApplication method because this is an all Cocoa application.
Thanks~
If you can get away with not writing this code yourself, all for the better. It is usually a terrible idea to write your own code to lock the screen, considering the number of vulnerabilities that have been found in screen locking code over the years. If you have a Carbon call that can do it, go ahead and use that... don't worry about the "purity" of your Cocoa code.
However, if you decide to write this yourself, here's what you do:
First, capture all the screens using CoreGraphics. See: http://developer.apple.com/mac/library/documentation/GraphicsImaging/Conceptual/QuartzDisplayServicesConceptual/Articles/DisplayCapture.html
Next, create a new NSWindow and put it in front of the window that's used for capturing the screens. You'll have to call a CG function to get the "order" of the black window covering each screen, and order the new window in front of that. Normally, the black window has an order so far forward that everything is behind it. Put a password field in the window. Do NOT use an ordinary text field or write your own code for password input. The password input field has a ton of special code in it so you can't copy text out of it, and other programs can't listen to keystrokes while you're typing into a password field. So use the one that Apple provides.
Last, put the computer in "kiosk mode". This mode allows you to disable alt-tab, user switching, the menubar and dock, and even the ability to force quit. See: http://developer.apple.com/mac/library/technotes/KioskMode/Introduction/Introduction.html
It's not a lot of code, it just uses a few different APIs so you'll spend most of your time bouncing between API docs. I suggest writing the screen lock code as its own application (just add a new application target to your Xcode project) and then put the screen locker inside your application bundle. This used to be (as of 10.4) how Apple Remote Desktop implemented the "Lock Screen" functionality, but I can't find the app anymore.
I believe the Cocoa replacement to the SetSystemUIMode API was not introduced until 10.6.
If you can live with Snow-Leopard-only code, the answer is - setPresentationOptions: on NSApplication.