Script works in Editor... and fails as app

Hello everyone,

I saw there are a few similar topics out there, but none of these helped me further. I usually try & error until success, but this time I really don’t understand.
This script is supposed to turn the Internet Sharing on or off, depending on it’s initial status.


-- CHECK INTERNET SHARING STATUS
set InternetSharingRunning to ((do shell script "ps -ax") contains "InternetSharing") -- THIS ONE ISN'T WORKING PROPERLY
if InternetSharingRunning is true then
	set order to "Off"
else
	set order to "On"
end if

display dialog ("The fact that Internet Sharing is running is detected as " & InternetSharingRunning) & "."

-- UI
set choice to button returned of (display dialog "Welcome to InternetSharingManager." buttons {"Cancel", "Turn Internet Sharing " & order} with icon 1 with title "InternetSharingManager" default button 2)
if choice is "Cancel" then error number -128


-- STOP INTERNET SHARING...
if choice is "Turn Internet Sharing Off" then
	do shell script "launchctl unload -w /System/Library/LaunchDaemons/com.apple.InternetSharing.plist" with administrator privileges
	do shell script "networksetup -setairportpower off" with administrator privileges
end if


-- ... OR LAUNCH IT
if choice is "Turn Internet Sharing On" then
	do shell script "networksetup -setairportpower on" with administrator privileges
	do shell script "launchctl unload -w /System/Library/LaunchDaemons/com.apple.InternetSharing.plist" with administrator privileges
	do shell script "/bin/launchctl load -w /System/Library/LaunchDaemons/com.apple.InternetSharing.plist" with administrator privileges
	delay 5
	
	do shell script "launchctl unload -w /System/Library/LaunchDaemons/com.apple.InternetSharing.plist" with administrator privileges
	do shell script "/bin/launchctl load -w /System/Library/LaunchDaemons/com.apple.InternetSharing.plist" with administrator privileges
end if

I’m launching Internet Sharing two times because when turning Airport on like this, it will automatically connect to my home’s wifi and Internet Sharing will be disabled, which is quite annoying. Please let me know if someone finds a workout for this too…

But my main problem is that even if this script works fine in the editor, it won’t work as app: it will behave as if Internet Sharing was always running. Try it out: just open this script in your editor an save it as app or as app-bundle, then launch it once from the script editor and second launching the app.

I just don’t understand.

I’d be very thankful for any help.

Model: MacBook
Browser: Safari 533.22.3
Operating System: Mac OS X (10.5)

Sorry but in 10.6 it works not in script editor and as application both… the problem is that the syntax is changed in 10.6

it is since 10.6:

do shell script "networksetup -setairportpower airport on" with administrator privileges

Airport is the device name. By default it is named airport.

Also I don’t have problems with the ps -ax message.

At last some minor tip:
For example when looking for a running process it is better to use system events or ps otherwise because your method will return true when you’re looking for iTunes and iTunes helper is running instead of iTunes.

examples:

tell application "System Events" to set InternetSharingRunning to "InternetSharing" is in name of every process
--OR:
set InternetSharingRunning to "InternetSharing" is in (every paragraph of (do shell script "ps -axc -o command"))

Hi DJ Bazzie Wazzie,

First of all, thanks for your quick response. I didn’t expect any help this fast !

I already feared it would probably be impossible to recreate the error depending on operating systems and versions.

Using the process list from System Events won’t work for me, as Internet Sharing doesn’t appear in it.
About your second tip on how to get the processes list… I replaced this part, and it just WORKS !

I lost about 3 hours today on trying to fix this strange problem, and half an hour after finally posting here someone gets me a solution.

Thank you so much ! You truly saved tomorrow’s day !!

I’m glad I could help and great everything is running normal now.

I forget to welcome you after your first post, better late then never: Welcome!!!

Hi,

the best way to determine the status of a launchd process is launchctl list


on checkInternetSharingStatus()
	try
		return (do shell script "launchctl list | grep com.apple.InternetSharing" with administrator privileges) contains "com.apple.InternetSharing"
	on error
		return false
	end try
end checkInternetSharingStatus

Hi Stefan,

You remain with the same problem there like my example with iTunes and iTunes helper. It still have flaws and therefore in my opinion definitly not the best solution. Also ‘launchctl list’ doesn’t list running processes but jobs, those two are different.

Yes, launchctl list affects only launchd jobs, but this is what we’re talking about.

you’re right, I misread your post as your method was good for looking for running processes, but you never wrote that down. For agents and daemons you could use your method indeed but for running processes not. But I still would change the code to something like this to make it more flawless, like my example of returning true for com.apple.itunes because com.apple.ituneshelper is running.

(items 2 through -1 of (every paragraph of (do shell script "launchctl list | awk '{print substr($0, index($0, $3))}'"))) contains "com.apple.InternetSharing"

Thanks to you two. I’ll try this out once I can.

Just a little echo to your ideas…

StefanK’s code snippet works like a charm, but DJ Bazzie Wazzie’s objection makes sense and I’d prefer to prevent this kind of problem. Unfortunately, DJ’s fix always returns true. I suppose it has something to do with my operating system.
But, hey, some kind person already provided a greatly working fix to my problem, so don’t drive yourself crazy with this. I’m glad I have a working InternetSharingManager.app.

Thanks again for your fast help.

for the grep filter add the -w switch, it displays only lines which match the whole word
for example

do shell script "launchctl list | grep -w com.apple.InternetSharing" with administrator privileges

The first solution I gave you was that you’ll lookup for running processes. Launchctl doesn’t, it looks if a job. When it always returns true it’s probably that you’re job stays available but the process has stopped. When someone demands the process it will be launched through launchd. Since 10.4 (launchd) some processes can get stopped and launched on demand so the OS loose a little weight and improved boot time. If you want to look if the process is running you should stick with your first solution.

In this particular case it’s irrelevant if the process is running or not.
The state of Internet Sharing can be determined reliably by checking the existence of the launchd job

Hi StefanK,

I tried out your new code snippet. That’s exactly what I put into the script, at the beginning:


set InternetSharingRunning to checkInternetSharingStatus

on checkInternetSharingStatus()
	try
		return (do shell script "launchctl list | grep -w com.apple.InternetSharing" with administrator privileges) contains "com.apple.InternetSharing"
	on error
		return false
	end try
end checkInternetSharingStatus

Unfortunately, this one always returns false.

You forgot the parenteses at the end of the first line, variable InternetSharingRunning points to handler checkInternetSharingStatus instead of containing it’s return value.It should be:

set InternetSharingRunning to checkInternetSharingStatus()

on checkInternetSharingStatus()
   try
       return (do shell script "launchctl list | grep -w com.apple.InternetSharing" with administrator privileges) contains "com.apple.InternetSharing"
   on error
       return false
   end try
end checkInternetSharingStatus

That’s why I don’t usually ask for help. In the end, I stop thinking on my own…

I’ll try this out as soon as I can.

Hi again.

Adding the parenteses, it finally works.

Thanks to this, I’m now facing another huge problem: As both of them work flawlessly, which code should I use ?

They work both perfect because InternetSharing is a continuously running process that needs to be kept alive according to the plist file. This means the process isn’t allowed to stop so there is always a running process when InternetSharing is turned on. But to do it correctly (because you’re starting and stopping it with Launchctl) it is better to use Launchctl to check if it’s running or not. Both methods still have their flaws, but it’s more a theoretical issue because in both cases an error will happen in 1 of a million change.

The Flaw of PS can be that the process crashed and it will be restarted by launchd automatically. If you between this restart run ps it will return the process is not running, but only a split second later it is running. The flaw of launchctl is that you don’t know if the process is running, I mean internetsharing is turned on but you don’t know if it runs or even runs successful. So if a process is aborted by launchd it still can give your script teh idea it is running but ps would give you the real result.

Like I said, the chance it will happen is in both cases the same as winning the lottery and can be considered as acceptable flaws. Still I agree that using the launchctl way is more elegant. But, hey, it’s your script and your choice, ps is faster so if that is more important stick with that.

What do you think about this one ? I guess the chance that the two tests give false results are negligible :cool:


set rept to true
repeat while rept is true
	set InternetSharingRunning to checkInternetSharingStatus()
	set InternetSharingRunning2 to "InternetSharing" is in (every paragraph of (do shell script "ps -axc -o command"))
	if InternetSharingRunning is InternetSharingRunning2 then set rept to false
end repeat

It’s more for the script to be perfect than because it’s useful, but well…

Will it end up slowing down the script significantly ?

you’re using a sledgehammer to crack a nut :wink: