Archive for the 'プロセス関連(process)' Category

09/20 アプリケーションの状態を調べる

AppleScriptからアプリケーションの状態を調べたい、というニーズは多いようで……検索エンジンのキーワードで割と頻繁に調べられているようです。

個別のノウハウについては本Blog上で紹介していますが、体系的にノウハウを整理したことはないので、ここでまとめて紹介しておきます。

(1)アプリケーションがインストールされているかを調べる

アプリケーションの状態を調べるといっても、それがインストールされていなければ調べようがありません。最初にやるべきなのは、AppleScriptを実行するマシンにコントロール対象のアプリケーションがインストールされているかどうかを確認することです。

アプリケーションの存在確認は、Info.plistに書かれているCFBundleIdentifierを確認する必要があります。

appinfo1.jpg

Info.plistの内容確認は、Xcode Toolsをインストールすると一緒にインストールされる、「Property List Editor」で閲覧/編集が可能です。

appinfo2.jpg

Property List Editor上でキー値がそのまま表示されていない場合には、メニューの「View」から「Show Raw Keys/Values」を実行するとCFBundleIdentifierを確認できます。

appinfo4.jpg

appinfo3.jpg

このid値をもとに、Finderに対してapplicaion fileを求めると、インストールされている場合にはそのうち一番新しいバージョンのアプリケーションファイルへのaliasが得られます

(2)起動中のアプリケーションから情報を取得する

インストールされていることが確認できたら、launchなりactivateのコマンドを送って起動。そののち、起動中のアプリケーションから各種情報を取得する、というのが定石です。

たいていは、アプリケーションのプロパティを取得すれば、アプリケーションが持っている情報が得られます。ただし、ここで得られる情報はアプリケーション側のAppleScript対応度によってまちまちで、バージョン情報やアプリケーション名が分るだけ、というケースもあれば……現在選択中のオブジェクトの情報が分ったり、各種環境設定情報が分る場合もあります。

スクリプト名:アプリケーションのプロパティを取得する
tell application “iPhoto”
  properties
end tell

–> {last months album:album id 4.295966298E+9 of application “iPhoto”, selection:{album id 4.295966334E+9 of application “iPhoto”}, photo library album:album id 4.295966296E+9 of application “iPhoto”, name:”iPhoto”, version:”8.1.2″, frontmost:false, class:application, last import album:album id 4.295966297E+9 of application “iPhoto”,……(以下省略)

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

さらに、アプリケーションのプロパティを複数まとめて「properties」で取得できないアプリケーション(iTunesなど)もあるため、そういう場合にはAppleScript用語辞書をしらべて、ひとつひとつプロパティ値を取得する必要があります。

(3)System Events経由でプロセス情報を調べる

アプリケーションに対して直接問い合わせを行った場合に、環境設定情報やドキュメントの情報は取得できますが、アプリケーションプロセス自体の情報はあまり調べられません。

そこで、アプリケーション本体ではなく、System Eventsにプロセス情報を確認することになります。

スクリプト名:System Evewntsで指定IDのプロセスの状態を調べる
tell application “System Events”
  set pList to properties of first item of (every process whose bundle identifier = “com.apple.iPhoto”)
end tell
–>{enabled:missing value, unix id:46789, file:alias “Cherry:Applications:iPhoto.app:”, creator type:”iPho”, subrole:missing value, entire contents:{}, selected:missing value, application file:alias “Cherry:Applications:iPhoto.app:”, orientation:missing value, role:”AXApplication”, accepts high level events:true, file type:”APPL”, value:missing value, position:missing value, id:20128561, displayed name:”iPhoto”, name:”iPhoto”, class:application process, background only:false, frontmost:false, size:missing value, visible:true, Classic:false, role description:”アプリケーション”, maximum value:missing value, architecture:”i386″, partition space used:0, short name:”iPhoto”, focused:missing value, minimum value:missing value, help:missing value, title:”iPhoto”, accepts remote events:false, description:”アプリケーション”, total partition size:0, accessibility description:missing value, has scripting terminology:true, bundle identifier:”com.apple.iPhoto”}

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

ここでは、CFBundleIdentifierによってプロセスの特定を行っていますが、Mac OS X上で気をつけるべき点があります。たとえば、Adobe Illustratorであれば……複数の異なるバージョンをインストールして、同時に複数バージョンを起動しているケースがあるということです。

そのため、厳密にアプリケーションプロセスを指定する場合には、バージョン情報なども指定する必要も出てくることでしょう。

ただし、System Eventsから取得する意義があるのは、アプリケーションが最前面にあるかどうかを示す「frontmost」、可視状態になっているかどうかを示す「visible」、そしてUNIXから見た場合のプロセスIDである「unix id」ぐらいです。

unix idを取得できれば、あとはshellのpsコマンドをdo shell scriptコマンド経由で実行し(ps -lp [process id])アプリケーションプロセスの状態を調べられます。

ここまでくれば、PhotoshopだろうがiPhotoだろうがPreviewだろうが、単なるUNIXのプロセスとして扱えます。killするなりゾンビプロセスになっていないか調べるなり、CPUへの負荷状態を調べたりできることになります。

だいたい、AppleScriptでアプリケーションプロセスの「状態」を調べるノウハウというのは、こんな感じです。

06/10 指定のアプリケーションの起動を待つ

IDで指定した複数のアプリケーションの起動を行い、起動が行われたかどうかチェックを行うAppleScriptです。

とりあえずループで300秒待っていますが、もっと短い時間で済むはずです。

スクリプト名:指定のアプリケーションの起動を待つ
set appIDlist to {“com.apple.Automator”, “com.apple.mail”, “com.adobe.Photoshop”, “com.adobe.distiller”}

set aRes to checkAppInstallation(appIDlist) of me
if aRes = false then return –指定IDのアプリケーションが実行環境にインストールされていない場合はリターン

–起動実行
repeat with i in appIDlist
  tell application id i to launch
end repeat

–起動チェック
repeat 300 times
  if waitAppsActive(appIDlist) of me = true then
    exit repeat
  end if
  
delay 1
end repeat

–指定IDのプロセスが起動しているか確認
on waitAppsActive(appIDlist)
  tell application “System Events”
    set appList to bundle identifier of every process whose visible is true
  end tell
  
  
repeat with i in appIDlist
    if i is not in appList then return false
  end repeat
  
  
return true
end waitAppsActive

–指定IDのアプリケーションがHDD上に存在するかを確認
on checkAppInstallation(appIDlist)
  repeat with i in appIDlist
    tell application “Finder”
      try
        set aRes to exists of application file id i
      on error
        return false
      end try
    end tell
  end repeat
  
  
return true
end checkAppInstallation

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

06/16 FireFoxでオープンしているURLを取得。Leopard対応版

FireFoxでオープンしているURLを取得するAppleScriptの、Leopard以降で実装された機能を活用して記述したものです。

Mac OS X 10.4などでは、System Eventsにプロセス一覧を尋ねて、その中にFireFoxが入っていないかどうかを確認することになりますが、Mac OS X 10.5ではrunningというプロパティを取得できるようになったので、これを参照するのがスマートでよいでしょう。

もともとは、shellからAppleScriptを呼び出して、FireFoxの状態を取得したいという相談(?)を持ちかけられたもので……osascriptコマンドでこのAppleScriptを呼び出すといった感じになるかと>masuiさん

スクリプト名:FireFoxでオープンしているURLを取得。Leopard対応版
tell application "Firefox"
  if running then Mac OS X 10.5 or later
    set aURL to «class curl» of window 1
  else
    set aURL to ""
  end if
end tell
return aURL

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

04/03 指定名称のプログラムを強制終了させる

指定名称のプログラムを強制終了させるAppleScriptです。指定文字列を含むプロセスを取得して、killコマンドで強制終了させます。

スクリプト名:指定名称のプログラムを強制終了させる
kill_aProc("InDesign CS3") of me

指定名称のプログラムを強制終了させる
on kill_aProc(aProcName)
  tell application "System Events"
    set procList to every process whose name contains aProcName
    
if procList is not equal to {} then
      set aProc to contents of first item of procList
      
tell aProc
        set anID to unix id
      end tell
      
do shell script "kill -9 " & (anID as string)
    end if
  end tell
end kill_aProc

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

05/31 クリエーターコードを指定してアプリケーションを起動する

普通、クリエーターコードを指定して該当するアプリケーションのパスを取得して、そのパスをFinderでオープンすれば、該当するクリエーターコードのアプリケーションを起動することは可能です。Mac OS X 10.5であれば、そのあたりの機能が追加されているものですが……10.4.xではその機能を利用することはできません。

クリエーターコードで指定すれば該当するアプリケーションのパスが得られる……というのが通常のアプリケーションの動作ですが、Adobe Acrobat Professionalだけは、クリエーターコードからパスを取得すると、アプリケーションバンドル内のヘルパーアプリケーションのパスが返ってきてしまいます。

そこで、対策するコードを作ってみた次第です。こんな処理は、Acrobat以外には必要ないのですが……Adobeのアプリケーションには、ほとほと苦労させられどおしです。
(more…)

05/30 指定クリエーターコードを持つアプリケーションプロセスの個数を数える

異なるバージョンのアプリケーションが同時に複数起動している場合、AppleScriptからコントロールするのは大変です。InDesignのCS2とCS3が同時に起動しているケースとかいったものは、ユーザー環境では日常茶飯事です。そこで、Script実行時に複数のバージョンが同時に起動していたら、警告を発したり処理そのものを中止するといった対策が必要になります。そのため、同一のクリエーターコードで指定したアプリケーションのプロセスが複数起動していないかを検出するサブルーチンを作成した次第です。

スクリプト名:指定クリエーターコードを持つアプリケーションプロセスの個数を数える
countProcWithCreatorCode("CARO") of meAcrobat Professional
countProcWithCreatorCode("8BIM") of me –Acrobat Professional

指定クリエーターコードを持つアプリケーションプロセス(起動中)の個数を数える
on countProcWithCreatorCode(aCode)
  try
    tell application "System Events"
      set pList to every process whose creator type = aCode
      
return length of pList
    end tell
  on error
    return 0
  end try
end countProcWithCreatorCode

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

05/02 指定の名称およびバージョンに該当するアプリケーションプロセスが起動しているかどうかをチェック

指定の名称およびバージョンのアプリケーションが起動しているかどうかをチェックするサブルーチンです。

スクリプト名:指定の名称およびバージョンに該当するアプリケーションプロセスが起動しているかどうかをチェック
set apName to "Microsoft Excel"
set apRes to getExistenceOfRunnningProcess(apName, "12.") of me
Excel 2008が起動していればtrue、起動していなければfalseが返る

指定の名称およびバージョンに該当するアプリケーションプロセスが起動しているかどうかをチェック
on getExistenceOfRunnningProcess(apName, apVer)
  tell application "System Events"
    set exF to exists of application process apName
    
if exF = true then
      tell application process apName
        set apProp to properties
        
set apFile to file of apProp
      end tell
    else
      return false
    end if
  end tell
  
tell application "Finder"
    set aVer to version of apFile
  end tell
  
if aVer begins with apVer then
    return true
  else
    return false
  end if
end getExistenceOfRunnningProcess

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

04/07 Front Rowが実行中かどうかを調べる

Front Rowが実行中かどうかを調べます。Front Row実行中のみ動作するようなScriptを作成する際に使えることでしょう………………いつ役立つのかさっぱり分りませんが、そういうScriptを作りためておくとイザという時に役立つものです。

スクリプト名:Front Rowが実行中かどうかを調べる
tell applicationFront Row
  set a to isVisible
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

04/06 警告を出しつつ再起動

再起動を行う方法としては、System Eventsに対して「restart」コマンドを実行させるのが常套手段ですが、すぐにアプリケーションを終了させて再起動してしまいます。本Scriptでは、普通にメニューから再起動コマンドを実行したのと同様に、再起動ダイアログで警告を表示させつつユーザーに再起動してよいかどうかの許可を求めます。

スクリプト名:警告を出しつつ再起動
tell applicationloginwindowto «event aevtrrst»

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

04/05 指定プロセスの可視_不可視切り替え

指定アプリケーションを操作する途中で、どうしても処理内容をユーザーに見せたくないケースがあります。そうした時に本ルーチンを用いて非表示状態にします。表示状態に戻すときにはaBooleanをtrueにして本ルーチンを呼び出してください。

スクリプト名:指定プロセスの可視_不可視切り替え

set aRes to setVisibleOfSpecifiedProcess("Finder", false) of mefalseで不可視に

指定プロセスの可視/不可視切り替え
on setVisibleOfSpecifiedProcess(aProc, aBoolean)
  tell application "System Events"
    if exists process aProc then
      set visible of process aProc to aBoolean
      
set resF to true
    else
      set resF to false
    end if
  end tell
  
return resF
end setVisibleOfSpecifiedProcess

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

03/09 指定クリエータのアプリケーションの情報を返す

スクリプト名:指定クリエータのアプリケーションの情報を返す

Illustrator CS/CS2のどちらかがHDD上にインストールされていることを確認
set aList to retVerFromCreator(”com.adobe.illustrator“) of me
aList

> {Name:”Adobe Illustrator.app”, creation date:date “2007年 10月 5日 金曜日 0:00:10 PM”, modification date:date “2008年 3月 1日 土曜日 9:17:52 AM”, input path:{0, 0}, size:3.06324335E+8, folder:true, alias:false, package folder:true, visible:true, extension hidden:true, name extension:”app”, displayed name:”Adobe Illustrator CS3″, short name:”Illustrator”, default application:alias “Mikan:Applications:Adobe Illustrator CS3:Adobe Illustrator.app:”, kind:”アプリケーション”, short version:”13.0.3″, long version:”13.0.3, Copyright © 1987-2007 Adobe Systems Inc. All rights reserved.”, bundle identifier:”com.adobe.illustrator”, file type:”APPL”, file creator:”ART5″, type identifier:”com.apple.application-bundle”, busy status:false}

指定クリエータのアプリケーションの情報を返す
on retVerFromCreator(createrCode)
  if createrCode = “” then
    –Creator Codeに何も指定されていなかったらエラー
    
return falseエラーでもリストで返す
  end if
  
  
tell applicationFinder
    try
      set appFile to (application file id createrCode)
      
set appFile to appFile as alias
      
      
set aFinfo to info for appFile
      
      –
念のため、short verとlong verを返す
      
set vInfo to {short version of aFinfo, long version of aFinfo}
      
return vInfoリストで返す
    on error
      return false
    end try
  end tell
  
return false
end retVerFromCreator

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

03/09 プロセス名一覧を取得

スクリプト名:プロセス名一覧を取得
tell application "System Events"
  set a to name of every process whose visible is true
  
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

03/09 起動中のアプリのうちScriptableなものをリストにして選択

これは、スクリプトエディタのコンテクストメニューから呼び出す、AppleScript自動記述用スクリプト「コンテクストメニュー」アシスタントのために作ったサブルーチンです。起動中のアプリケーションのうちスクリプタブルなものを選ぶ、という操作は一般のAppleScriptでは必要のない種類のものですが、AppleScriptの自動記述用には必要となってくるものです。

スクリプト名:起動中のアプリのうちScriptableなものをリストにして選択.scpt
getScriptableAppName() of me

on getScriptableAppName()
  tell applicationSystem Events
    set a to name of every process whose (accepts high level events is true) and (has scripting terminology is true) and (visible is true)
  end tell
  
set b to choose from list a with prompttellするアプリケーションを選択してください
  
if b is false then
    returnApplicationName
  else
    set b to item 1 of b
    
return b
  end if
end getScriptableAppName

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

03/09 指定アプリの存在確認

AppleScriptでは、割と登場頻度の高い処理です。何かのアプリケーションに依頼して処理を行ってもらうという「他力本願」がAppleScriptの醍醐味。でも、アテにしていたアプリケーションが存在しない環境で実行されてしまったら困ります。そういう事態を防ぐためにも、あらかじめ指定したアプリケーションがAppleScript実行中のマシン上に存在するかどうかを確認しておく必要があります。1人で使うだけのScriptであれば、そんな調査を行っておく必要はありませんが、広域にバラ撒くとか、客先に納品するとかいった場合には、必須の処理といえるでしょう。

スクリプト名:指定アプリの存在確認
tell application “Finder”
  set the iPhoto_check to exists (application file id “com.apple.iphoto”)
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に