OHO's Blog

My 2 cents about everything!

Connect Microsoft Communicator on Mac OS When Network Status Change

I have recently configured on my mac Microsoft Communicator to communicate at work with my Windows desktop colleagues. This is working like a charm and very well linked with Microsoft Outlook for presence and so on. Even video conference and screen sharing work very well for a Microsoft product.

The only thing that was really painfull was that everytime I disconnect my Mac from LAN and come back again, Communicator just stays in it’s “error” mode and I never think of manually reconnect. So, I finaly end up being always “off” until I need to contact someone and only then I realise that “damned, I’m currently disconnected again”!

So I have setup an automatic re-connexion system every time network status does change!

Howto run a script at network connection event

While googleing for ways to detect network changes on mac OS, I found a very nice and useful Blog post that explaining how to just do that. It’s not very complicated, but it’s not that really straight forward to have it setup. As a pre-requesit, you will need to have Python 2.5 installed on your machine.

In a nutshell, you will have to install crankd that will be loaded at launch from your ~/Library/LaunchAgents/ directory. You will need to configure it’s associated plist file which is by default created and installed (at first run of crankd) in:

~/Library/Preferences/com.googlecode.pymacadmin.crankd.plist

This plist file is the place where you will say “at network change notification, run my custom script”.

Crankd run as a daemon/service that will let you launch a script in response to many system events like network changes, filesystem activity, application launching, etc.

Unfortunately, as mentioned in pre-requesits, I beleive crankd does not run on Python greater than 2.5. So you will need to have it installed on your machine! It’s ok to have several python versions. Those installed version can be seen on mac OS in:

/System/Library/Frameworks/Python.framework/Versions/

Possible issue with latest crankd version

In my case I had issues while using the version of crankd shipped with latest PyMacAdmin. I couldn’t find the exact reason why I get errors running clankd. Thanks to Google I could found a version that run well on my environment and that do the job. You can get this crankd version here if needed.

crankd plist file (loaded from /Library/LaunchAgents)

If you put in /Library/LaunchAgents the bellow plist file, system will properly load /usr/local/sbin/crankd.py at startup.

This plist basically say:

  • KeepAlive: service keep running in background
  • RunAtLoad: service is loaded at boot time
  • ProgramArguments: service to run is /usr/local/sbin/crankd.py
(com.oho.crankd.plist) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>KeepAlive</key>
  <true/>
  <key>Label</key>
  <string>com.oho.crankd.plist</string>
  <key>ProgramArguments</key>
  <array>
      <string>/usr/local/sbin/crankd.py</string>
  </array>
  <key>RunAtLoad</key>
  <true/>
</dict>
</plist>

I found very instructive to read Daemons and Services Programming Guide from Apple web site. You will find there all you always wanted to know about Launch daemons and Agents on mac os. You will also have description of all possible parameters you could use on the plist files.

Handle system events managed by crankd

When you run crankd for the first time, it will create a default configuration plist file in:

~/Library/Preferences/com.googlecode.pymacadmin.crankd.plist

This file will looks like:

(default-com.googlecode.pymacadmin.crankd.plist) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>NSWorkspace</key>
  <dict>
      <key>NSWorkspaceDidMountNotification</key>
      <dict>
          <key>command</key>
          <string>/bin/echo &quot;A new volume was mounted!&quot;</string>
      </dict>
      <key>NSWorkspaceDidWakeNotification</key>
      <dict>
          <key>command</key>
          <string>/bin/echo &quot;The system woke from sleep!&quot;</string>
      </dict>
      <key>NSWorkspaceWillSleepNotification</key>
      <dict>
          <key>command</key>
          <string>/bin/echo &quot;The system is about to go to sleep!&quot;</string>
      </dict>
  </dict>
  <key>SystemConfiguration</key>
  <dict>
      <key>State:/Network/Global/IPv4</key>
      <dict>
          <key>command</key>
          <string>/bin/echo &quot;Global IPv4 config changed&quot;</string>
      </dict>
  </dict>
</dict>
</plist>

You can edit this file and modify it to suit your needs. For instance running a script at Network status changes.

SystemConfiguration settings bellow will run my-script.sh at any network status changes:

SystemConfiguration key detail
1
2
3
4
5
6
7
8
  <key>SystemConfiguration</key>
  <dict>
      <key>State:/Network/Global/IPv4</key>
      <dict>
          <key>command</key>
          <string>/path/to/my-script.sh</string>
      </dict>
  </dict>

You can list all possible system events and notification you can monitor with crankd (specific for your machine) using the following command:

/usr/local/sbin/crankd.py --list-events

*Note: you might want to switch your python environment variable to be able to properly run crankd.py that require python 2.5.

To do so, you could type in your terminal:

export PYTHONPATH=/Library/Frameworks/Python.framework/Versions/2.5/bin

For quick switch between python version from command line, you could setup an alias in your .profile like:

# Aliases to switch python version
alias py2.5="export PYTHONPATH=/Library/Frameworks/Python.framework/Versions/2.5/bin"
alias py2.7="export PYTHONPATH=/usr/local/lib/python2.7:/usr/local/bin/python2.7"

Handle specific type of connexion status change

In my case, I want to monitor Ethernet cable connexion changes. I have identified that my network adapter is en2. So I will monitor only specific en2 status changes.

My own SystemConfiguration settings will looks like:

SystemConfiguration key detail
1
2
3
4
5
6
7
8
<key>SystemConfiguration</key>
<dict>
  <key>State:/Network/Interface/en2/IPv4</key>
  <dict>
      <key>command</key>
      <string>/bin/echo &quot;en2 IPv4 config changed&quot;/Users/oho/.rvm/gems/ruby-1.8.7-p358/gems/terminal-notifier-1.4.2/bin/terminal-notifier -message &quot;Trying to reconnect Communicator&quot; -title &quot;Cable connexion IPv4 config changed&quot; -subtitle &quot;Microsoft Communicator&quot; -group &quot;Microsoft Communicator&quot; -activate com.microsoft.Communicator;/usr/bin/open -b com.apple.automator.StartCommunicator</string>
  </dict>
</dict>

So I’m monitoring here only changes in interface en2 (for IPv4) and at each status changes, I display a push notification (Mountain Lion) using terminal-notifier and run a little Apple Script (identified by it’s bundleID) that re-connect Microsoft Communicator.

Re-connect Microsoft Communicator from script

Once that you are ready to launch a script at network interface change, here is the script that will re-connect Microsoft Communicator:

AppleScript used in Automatordownload
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
-- Author: Olivier HO-A-CHUCK
-- Application name: StartCommunicator.app
-- Date: 20 Jan. 2013
-- Note:
--    this quick script have been created to automatically connect Communicator when network is back again
--    It should be launch by crankd. See http://blog.hoachuck.biz/blog/2013/01/20/connect-microsoft-communicator-on-mac-os-when-network-status-change/

on run {input, parameters}
  
  tell application "Microsoft Communicator" to activate
  tell application "System Events"
      key code 53 -- cancel (You may still have an error popup opened)
      key code 36 -- return (click to connect button through return key)
  end tell
  
  
  return input
end run

This script is used in Automator to build an app (that you can download in script window). This app can be launch with ‘open’ command using it’s Bundle ID:

/usr/bin/open -b com.apple.automator.StartCommunicator

*Note: so far, it’s an early dev. Don’t hesitate to comment and bring your 2 cents that can help improve the all process.

You might want to disable questions from Communicator like “do you want to confirm if you want to have the chat saved before closing …”. I might need to improve the script if there are unexpected windows popup open.

Comments