あまつぶ

9.30【ログイン時に起動する】

 ログインしたときにアプリケーションを起動させる設定というのは「ログイン」コントロールパネルで行うわけだけど、アプリケーションからその設定をすることはできないのだろうか。
 ~/Library/Preferencesにそれらしい設定ファイルがないかと探してみると、「loginwindow.plist」というものを発見。中身は、

 loginwindow.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
<plist version="0.9">
<dict>
  <key>AutoLaunchedApplicationDictionary</key>
  <array>
    <dict>
      <key>Hide</key>
      <false/>
      <key>Path</key>
      <string>/Applications/WebColorX.app</string>
    </dict>
    <dict>
      <key>Hide</key>
      <false/>
      <key>Path</key>
      <string>/Applications/Phut.app</string>
    </dict>
  </array>
</dict>
</plist>


こんな具合。9.9に書いた初期設定ファイルと同じだ。今回は、起動するアプリケーションが複数あるので、AutoLaunchedApplicationDictionaryキーに対して、配列(array)が設定されている。その中はDictionaryで、Hideキー(起動時に隠すかどうか)とPathキー(起動するアプリケーションのパス)が入っている。このファイルを編集してやればいけそうな感じだ。

 GetLoginPreferences(CoreFoundation/CoreFoundation.hをインクルード)
/* get login preferences */
CFIndex GetLoginPreferences(void)
{
  CFArrayRef    array;
  CFIndex      result = -1;
  
  
/* AutoLaunchedApplicationDictionary */
  array = CFPreferencesCopyValue(
      CFSTR("AutoLaunchedApplicationDictionary"),
      CFSTR("loginwindow"),
      kCFPreferencesCurrentUser,
      kCFPreferencesAnyHost);
  
if (array)
  {
    CFIndex      index,numValues;
    CFDictionaryRef  dict;
    CFStringRef    string,applPath;
    
    numValues = CFArrayGetCount(array);
    
    
/* if array contains no values */
    
if (numValues == 0)
    {
      CFRelease(array);
      
return result;
    }
    
    
/* get application's path */
    applPath = GetApplicationPath();
    
    
/* search application */
    
for (index = 0; index < numValues; index++)
    {
      dict = CFArrayGetValueAtIndex(array,index);
      
if (dict)
      {
        string = CFDictionaryGetValue(dict,CFSTR("Path"));
        
        
if (CFStringCompare(
          string,applPath,kCFCompareLocalized)
            == kCFCompareEqualTo)
        {
          result = index;
          
break;
        }
      }
    }
    
    CFRelease(applPath);
    CFRelease(array);
  }
  
  
return result;
}

 早速、読み込み部分のソース。上記の設定ファイルの中に、自分自身のパスが登録されているかを探し、見つかればその場所(インデックス)を、見つからなければ-1を返すというもの。インデックスを返すのは、削除するときにも使えるようにするため。(※ 最初に掲載した際にはCFPreferencesCopyAppValueを使用していたが、CFPreferencesCopyValueに修正(02.7.20))
 まず、CFPreferencesCopyValue()でAutoLaunchedApplicationDictionaryキーのデータを得る(Copyなので、あとでReleaseすることを忘れないように)。正しく得られたら、CFArrayGetCount()で配列の大きさを調べる(Array関係のAPIは、CFArray.hにある)。配列の大きさが0なら、データがないので、終わり。
 次に、アプリケーション自身のパスを得る。この部分は、別関数を使って行った。パスは、POSIX形式(で、いいのかな?)のようなので、MoreFilesを使って……というわけにはいかない。少し調べてみると、Files.hにFSRefMakePath()というAPIを発見。これを使えば、FSRefからUTF-8形式のC文字列であらわされたパスが得られる。FSRefは、GetCurrentProcess()でProcessSerialNumberを調べ、そこからGetProcessBundleLocation()で得るという流れになるだろうか。また、得られた文字列を、CFStringCreateWithCString()でCFStringにする……というのがGetApplicationPath()という関数の内容。
 準備ができたら、配列の中を順に調べていく。配列からデータを取り出すのはCFArrayGetValueAtIndex()を使い、CFStringの比較はCFStringCompare()を使う。配列のインデックスは、0から始まると、上記CFArray.hに書いてある。
 書き込みについては、次回。

 Project Builderで作ったアプリケーションはパッケージ形式になっているのだが、これを9.xで見ると、単なる白紙アイコンになってしまう。コンテクストメニューで「パッケージの内容を表示」してみると、ちゃんと中身が表示される。あれ、そういえば、AppleWorksって、9.xでもXでも使えるパッケージになっていたよな。ってことは、ひょっとすると、このパッケージの中に9.xで動くアプリケーションを入れて、そのエイリアスをパッケージの直下に配置したら9.xで動くようになるのか?
 早速試してみると、まさにそのとおり。しかも、アイコンもちゃんと表示されてなかなかいい感じ。アプリケーションだけでなく、書類でも大丈夫みたい。ってことは、X専用のアプリケーションだけど、9.xで開くと「X専用です」って表示するアプリケーション(じゃなくてSimpleTextの書類でもいいけど)ってのもできるわけだ。これは結構おもしろいかも。

 9.16に書いた改行の件は、解決。P503iでの話だが、マナーモードにする時に押すボタンのところに改行の記号らしいものが書いてあって、試しに押してみたら改行された。うーん、わかりにくいぞ(笑)。

September 23, 2001 ↑ September index → October 5, 2001