set volume not working in xcode with applescript cocoa objc - xcode

I have an applescript xcode project in xcode 3.2 and am trying to change the system volume...however it doesn't work...it either stops the nstimer or doesnt do anything at all...
Is there a way to log the errors so that I can pinpoint the issue?
Here is my code
set newVolume to 50
set volume output volume newVolume
textName's setStringValue_(currentVolume)
set currentVolume to newVolume
obv this is a much more condense version but this literally does not work...it is inside of an NSTimer but, even when not within an NSTimer it still does not work...newVolume, currentVolume, and textName are all declared...do I need to declare something for the set volume line?

So, your actual question was simply how to log errors from AppleScriptObjC:
AppleScriptObjC will log any errors thrown in your script to the console -- just look in the bottom pane in Xcode. For instance, in your case you should see something like “«script» doesn’t understand the «aevtstvl» message.” (This isn’t terribly clear, but it’s telling you that your script sent a set volume command to a script object, which didn’t have a handler for it.) If you want to capture and log errors yourself, you can put troublesome sections inside a try/on error block, and deal with it yourself in the error handler.
If you’re feeling extra inquisitive, you can also turn on the NSScriptingDebugLogLevel preference, like this:
defaults write com.me.myapp NSScriptingDebugLogLevel 1
...and AppleScriptObjC will log information about every message sent either way across the bridge. (Set it to 0 or use defaults delete to turn it off.)
That’s error logging. Now, what you didn’t actually ask, but I’m going to answer anyway, was “How do I fix my set volume command?”
Short version: add tell current application to:
tell current application to set volume output volume 50
And yes, the range for the “new” volume parameters is 0 to 100. The old compatibility one goes from 0 to 7. (Why? The old Control Panel volume slider had 8 stops.)
Long version:
There’s a bad interaction between the default direct parameter and set volume’s handling of it. When using AppleScriptObjC, “it”, and therefore the default direct parameter, unless you say otherwise, is the current script, and set volume chokes on that. You can force “it” to be nothing by saying tell current application to. (Alternatively, you could give it an explicit direct parameter by using the old-fashioned form set volume x where x is a real number from 0 to 7. However, this doesn’t match the numbers you get from get volume settings, only lets you set the output volume, and doesn’t let you set things like “muted” correctly.)
And by the way, if your AppleScriptObjC project is sufficiently simple (in particular, if you don’t need any interface), you can write it directly in AppleScript Editor: choose File > New from Template > Cocoa-AppleScript Applet, and use the normal AppleScript on run and on open handlers, except that you can now also invoke anything from Cocoa.

Related

Applescript to read notifications to the Apps in Dock

I want to be able to have a script which can detects if I have new messages in my messaging apps.. Slack, lync,.
Is it possible to use applescript to read if there is any active notification on the apps in the Dock..
If you do:
`getconf DARWIN_USER_DIR`/com.apple.notificationcenter/db
(which line I found at Ask Different), you'll get returned:
/var/folders/_d/pg2g_[some_funny_numbers]/0//com.apple.notificationcenter/db: is a directory
Inside this/my folder I found:
db db-shm db-wal db2upgraded
When some action happens (I sent a notification) only db-wal gets updated (nearly) at once.
So, in principle it should be possible to write an AS (saved as Stay Open app) that periodically looks if "db-wal" has changed (comparing saved sizes or change dates) and, ONLY if so, searches it for some keywords (Slack, lync,…) again comparing # of occurrences, thus learning if s.th. new has arrived. Admittedly sounds awkward but could work.
It would be much more elegant to use a folder script, but as no file is moved nor a folder opened/closed such a script can not be invoked.

Using VBScript to control an MMC object

Alright, so, I'm working on a script to execute some commands in an MMC Snapin, and I'm not very experienced with doing this kind of scripting, but i've made a lot of progress...the problem I am having, is if I create a new object every time the script runs, it will massively delay my overall script while the snapin and everything in it loads(which can take as long as five minutes). If it could load the snapin content once and then just take control of it as needed, and only create a new object IF there's not one open already, I'll save a massive amount of time when I run the script sometimes 100 times in a day.
The problem is, I'm not entirely certain how to achieve this. I thought, after some research, that it would be GetObject, but when I do
Dim objMMC
Set objMMC = GetObject("", "MMC20.Application")
It seems to create a new mmc window with no snapins loaded, rather than get the existing one with snapins loaded that I want.
Any advice? Am I just totally off base here, using completely the wrong command, or is there some simple change that I can make to fix this?
Edit:
Is there some weird workaround way I could achieve this, like storing an object to a temporary file so i can at least reuse it through a single session.
I'm in a weird situation where I am trying to add functionality to a powershell script and couldn't find a way to do it directly in powershell, so i'm setting up a vbscript to do one piece of it and calling the vbscript from powershell. I already had to do a lot of research to figure out how to do it in vbscript(and i'm still not sure about all of it) so i guess before i go any further, I'll try to figure out if this is even viable(in vbscript or c# or c++ or any other language someone could suggest)...
What i want to do, overall, is check if an MMC window is open that contains a DHCP snapin. If so, assign it to a variable. If not, create one.
Then it will read from a csv or txt file, and use the values to determine what node to navigate to within the snapin(DHCP>ServerName>IPv4>ScopeName>Scope Options).(I've mostly solved this part in vbscript, but don't know how to do it in C++ or C#)
Finally, I need to be able to execute a right-click menu item to "configure options", navigate the tabs of the popup that comes up, enter a value, and apply the changes/hit ok to close the popup. Worst case, If I can't do it "normally" by actually sending commands to the objects themselves, this part I can do with imitating keystrokes, but i don't want to do that if it's avoidable because it's sloppy.
Then, I basically will just need to somehow alert the powershell script that i'm "finished" so it can continue, or give an alert if there's an error.
I'm not asking anyone to walk me through all this, I just want to know if any of those steps aren't viable as i've described them, especially if I'm going to have to switch to c++ or c# to achieve the first part and therefore relearn the commands needed.
... and only create a new object IF there's not one open already ...
No, this is not possible in VBS, you need to do
Dim objMMC
Set objMMC = WScript.CreateObject("MMC20.Application")
if I create a new object every time the script runs, it will massively delay my overall script
In this case is the VBS the wrong language, you need to use C# or C++ executable.

Applescript: system-wide global variable accessible by all scripts

We have a PDF document processing system, implemented in AppleScript (where we call the scripts from the shell using osascript). In some of the scripts, we call Acrobat Preflight Droplets from the Applescript.
This does usually work without problems. However, in some cases, where the processed document is big or/and complex. the droplet returns control to the script before the report is written and the document is moved to the "success" or "failure" folder. The consequence is that the process continues, but without the moved file, it eventually fails.
The workaround so far has been to add a delay after those droplet calls. This does help, but it is a waste of time for small documents, and there will always be a document big and complex enough to take longer than the delay.
We also found out that the time needed for finishing writing the report and moving the document depends on the speed of the system (had to be expected…).
The workaround would be to calculate the delay from the document size, its number of pages, and a machine-dependent parameter. Document size, and number of pages are no big deal; they can be retrieved in the Applescript.
The problem is the machine-dependent parameter, which can be determined experimentally. But how do I make that parameter available to all the scripts needing it?
Incorporating it into the scripts is not an option, because we have a number of systems installed, and if we would do that, we'd end up in a maintenance nightmare. Passing it as an argument in the initial system call is also not possible, because the calls are many, and again would lead to a maintenance nightmare.
So, is there a way to set up a place where that machine parameter can be stored and easily called from any Applescript, no matter how it itself is called.
Thanks a lot for your advice.
You might find the Property List Suite in System Events useful. It’s a standard means of storing and then retrieving such information. Property List files themselves are simply XML files, so you can even create them outside of AppleScript and then read them within your scripts.
There’s a description with examples at https://apple.stackexchange.com/questions/58007/how-do-i-pass-variables-values-between-subsequent-applescript-runs-persistent
A simple suggestion if you only have one paramater to keep track of would be to just have a text file in a known location on each machine. The only content of the text file would be the machine paramater. I like to use the Application Support folder this kind of thing.
Assuming your machine parameter is CPU speed. You can save a text file in /Library/Application Support/Preflight Scripts/machinecpu.txt with the contents:
2.4
Then in Applescript, you would just read the text file.:
set machineParam to read file "Macintosh HD:Library:Application Support:Preflight Scripts:machinecpu.txt"

VB6 - Set Debug Mode via Registry?

I have a VB6 application that I'm trying to make log out differently. What I have is a flag in the registry (existing) which states if the application is set to Debug mode so that it would log out.
Within my code I then have lots of if statements checking if this is true. This means that there is a lot of processing time checking if a statement is true, which maybe not much really but as it does it so often it's an overhead I would like to reduce.
The code is full of statements like this
If isDebug = True Then
LogMessage("Log what is happening")
End If
So what I'm looking for is a better way to do this. I know I can set a debug mode within Project Properties -> Make, but this needs to be set prior to building the .exe and I want to be able to set this in production via the registry key.
Consider using a command line argument to set debug mode. I used to do this.
Dim sCommandLine() As String
sCommandLine = Split(Command$)
For I = 0 To UBound(sCommandLine)
' do something with each arg
Next I
You can also persist command line args inside the IDE, so you always have them when debugging. When running outside of the IDE, make a shortcut to the compiled application with the arguments in it.
I do something almost identical to what you have in mind in a lot of my code. Add this:
Sub LogDebug(ByVal strMsg As String)
If (isDebug) Then
LogMessage(strMsg)
End If
End Sub
Then just call LogDebug in your main program body, or call LogMessage directly if it's something you always want to log, regardless of the debug flag.
I'm assuming isDebug is a boolean here. If it's a function call, you should just create a global flag that you set at the beginning of the code, and check that instead of looking at the registry over and over. I don't think checking a boolean is that much of a processing load, is it?
You want to call a function if a runtime flag is set. The only thing I can see that could be faster is:
If isDebug Then
LogMessage("Log what is happening")
End If
But I doubt that either would be the cause of performance problems. Most logging frameworks promote code like that and even put the flag/log level as a parameter to the function. Just be sure that you don't have other places where you needlessly compute a log message outside of the conditional statement.
You might evaluate why you need logging and if the logs produced are effective for that purpose.
If you are looking for a problem that can be trapped using VB error handling, consider a good error handling library like HuntERR31. With it you can choose to log only errors instead of the debug message you are now doing. Even if you don't use the library, the docs have a very good description of error handling in VB.
Another answer still:
Read your registry flag into your app so that it's a session based thing (i.e. when you close and restart the app the flag will be checked again - there's no point in checking the registry with every single test).
Then (as per Tom's post) assign the value to a global variable and test that - far faster than a function.
To speed up logging you may want to consider dimensioning a string buffer in your app and, once it has reached a specific size, fire it into your log file. Obviously there are certain problems with this approach, namely the volatility of the memory, but if you want performance over disk access I would recommend such an approach.
This would, of course, be a lot easier if you could show us some code for your logging process etc.

How to resolve "internal table overflow" in Applescript

When attempting to load the iTunes XML/plist file, I get "internal table overflow." After Googling, it looks like Applescript has run out of memory. The file is 18 meg on disk, so while on the larger side of things, it should still work on a Mac with 2 gigs.
How can I resolve this?
Obviously, since it's created by iTunes, I can't control the generate of it much.
Update: The relevant snippet:
tell application "System Events"
tell property list file (itunes_xml_file as string)
tell contents
set my_tracks to value of property list item "Tracks"
repeat with t in items of my_tracks
I guess that AppleScript is simply not made to handle this amount of data. I tried to use AppleScript a while back as well and tried to do something similar (reading an iTunes library). AppleScript's original intention was to automate applications by sending AppleEvents to them - which in combination with the weird syntax of AppleScript, confuses a lot and makes it difficult to do a lot of simple things.
After some frustrating time I decided to use Python instead, as it provides a simple module for reading the plist files: http://docs.python.org/dev/library/plistlib.html
Possibly not what you wanted to hear, but the problem with AppleScript is that it is easily overloaded with data, as the abstraction of data it works with is rather bulky and takes up lot of memory.
I'm sure if you give Python a try, you'll have something up and running in less than a hour. Python is installed on all Macs by default and is really easy to learn.
OS version 10.6.8
Update: Confirmation of validity
After initially writing the below I tried to revert the code at hand but could not reproduce the error and hid the post by "deleting" it.
Just now the error happened when loading one non-existant and one existent file-path in an options-parsing script loaded with a load script call, initially handled by run handler, called by the CLI osascript(1) program. This time it is revertible and I feel confident to un-"delete" it.
In short, my solution is to change anyone_else's POSIX file path_posix to AppleScript's POSIX file path_posix
Some relation
After writing the below I now realize that i first only saw "iTunes" and missed the relevant first line with tell app "system events" and the use of it's property list file which perhaps/actually/somehow could be related to my issue with info for a POSIX file.
A note related to OP/question: file or alias as string gives a colon-separated "HFS"-path. System Events handles both.
My issue
In a script-loading script i got error "Internal table overflow." number -2707 from the block below.
It was issued when i called the block's handler using ~IPC~ (app app_name's handler_name()) (when i investigated it more thoroughly but, i had come across it before - without IPC).
try
set file_modified_date to (info for my POSIX file file_path_posix)'s modification date
true
on error error_message number error_number from error_source partial result error_result to error_class
if {error_number} is not in {-43, -37} then error error_message number error_number from error_source partial result error_result to error_class
false
end try
A (the(?)) parent (used for my) of this script, worth mentioning, is current application (with some levels in between) (compiled and bundled in "AppleScript Editor" to be run as a stand-alone .app)
My solution
Changing
set file_modified_date to (info for my POSIX file file_path_posix)'s modification date
to
set file_modified_date to (info for AppleScript's POSIX file file_path_posix)'s modification date
solved the issue - for now.
Thoughts
I'm guessing different ~modules~ has different "tables" (don't now much C) for handling a thing like POSIX file and info for (open "Scripting Addition" / extension (OSAX) "Standard Additions", as it (both) still is, is it not?).
Hope this helps, and that my level of detail (and parentheses) didn't loose or confuse you :) Good night.
Diggin' 'round the cradles
Around the AS memory grave: (Spam prevention made me downgrade all but 2 hyperlinks - give me some rep. and i'll fix it :p)
• The eminent ~has [on this error code] (http://lists.apple.com/archives/applescript-users/2005/Jul/msg00166.html) with a related but perhaps other source (and mentioning his library loader) via list.apple.com.
• Some [good questioning] (http://lists.apple.com/archives/applescript-implementors/2005/Jun/msg00104.html), some to which the below might be a slightly yawning answer:
• cs.cmu.edu provides (120625) a pascal source from 1992 that defines the same limits as my local /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/OpenScripting.framework/Versions/A/Headers/AppleScript.h
• And finally a more distantly related [issue with large scripts] (http://macscripter.net/viewtopic.php?id=11760) from macscripter.net - a good forum of knowledge and collection of resources around applescript.

Resources