51

次の AppleScript を検討してください。

on is_running(appName)
    tell application "System Events" to (name of processes) contains appName
end is_running

set safRunning to is_running("Safari")
if safRunning then
    tell application "Safari"
      -- Stuff I only want executed if Safari is running goes here.
    end tell
    return "Running"
else
    return "Not running"
end if

問題:osascriptコマンド ライン ユーティリティを使用してこれを実行すると、Safari が実行されていない場合、Safari が起動され、スクリプトが「実行中」と報告されます。これは、私が望む、または期待する動作ではありません。AppleScript Editor 内で実行すると、期待どおりに機能することに注意してください。

これはosascriptバグ/既知の問題ですか? それとも、私が見逃している理由で意図された動作ですか?誰でも希望どおりに動作させることができますか? (ところで、OSX 10.7.5 を実行していますosascript。バージョン番号を報告する方法がわかりません)。

tell/行をコメントアウトすると、end tell期待どおりに動作します。Safari が実行されていない場合、起動せず、「実行されていません」と出力されます。だから、Safariが起動する原因のように思えtellますが、実際に実行する必要はなく、スクリプトに存在するだけです...? tellしばらくの間、これが本来の動作なのだろうかと思っていましたが、AppleScript Editor ではこのように動作しないため、そうではないと思います...

実際、同様の動作をする別の茜色のバージョンを次に示します。

on is_running(appName)
    tell application "System Events" to (name of processes) contains appName
end is_running

set safRunning to is_running("Safari")
return safRunning
if false then
    tell application "Safari"
    end tell
end if

return ステートメントの後のブロックtell内にある場合でも、これは常に Safari を起動します! if false(繰り返しになりますが、これは AppleScript Editor では問題ありません。)

ところで、この動作は Safari に限定されませんが、普遍的でもありません。

  • 影響を受けるアプリには、Safari、TextEdit、iPhoto、AppleScript Editor、iTerm などがあります。
  • 影響を受けないアプリには、Google Chrome、iTunes、Preview、Mail、Terminal、Address Book、Echofon などがあります。

それで、これをどのように修正またはルーティングするかについて誰かアイデアがありますか? osascriptバグですか?それとも、AppleScript のセマンティクスについて何かが欠けていますか?

コンテキストについて:開いているブラウザに、開いているタブのURLを照会するスクリプト(Pythonから埋め込まれたり呼び出されたりするスクリプト)を作成しようとしています。開いているかどうかに関係なく、常にSafariを起動することを除いて、すべて正常に動作しています。その望ましくない動作を、上に示した単純なテスト ケースに要約しました。appscriptを使用せずに Python からこのスクリプトを実行する方法osascriptはわかりませんが、 appscriptは開発/サポート/推奨されなくなったため、使用したくありません。

すべての入力/洞察に感謝します!

4

6 に答える 6

62

これが発生する理由は、コマンドラインから osascript を使用してスクリプトを呼び出すたびに、スクリプトがコンパイルされているためだと思われます。

Tellアプリケーションでコンパイルすると、アプリが起動します。

プリコンパイルされたファイルから osascript を使用して、コマンド ラインからスクリプトを呼び出します。scptはコンパイルを行わないため、この動作を引き起こしません。

ただし、プレーン テキスト (.txt、.sh) ファイルから呼び出すと、アプリが起動します。

.scpt ファイルを使用せずにプレーン テキスト ファイルを使用する場合は、applescript にrun scriptコマンドを入れるというトリックを試すことができます。

on is_running(appName)
    tell application "System Events" to (name of processes) contains appName
end is_running

set safRunning to is_running("Safari")
if safRunning then
    run script "tell application \"Safari\" 
    
open location \"http://google.com\"
     
    end tell"
    return "Running"
else
    return "Not running"
end if

実行スクリプト内のスクリプトは、必要な場合にのみコンパイルされます。私の例のように、引用符などの文字をエスケープする必要があります。

最初に通常の AppleScript ドキュメントにスクリプトを記述し、それをコンパイルしてエラーをチェックすると、より簡単になります。

次に、それをプレーン テキスト ファイルにコピーします。


更新**

上記で使用した方法は、ここで回答する前に、この問題を解決するために使用した古いスクリプトからのものです。

答えは機能し、エレガントになろうとはしていません。;-)

私は実際に以下のuser1804762メソッドが好きです。それは機能しますが、回答が十分に明確ではないと感じるので、使用例を示します。

set appName to "Safari"

if application appName is running then
    
    tell application id (id of application appName)
        
        open location "http://google.com"
    end tell
    return "Running"
else
    return "Not running"
end if

このスクリプトは、コマンド ラインから osascriptを使用して実行できます。

例:

osascript /Users/USERNAME/Desktop/foo.scpt

スクリプトがコンパイル済みスクリプトとして保存されることに注意してください。これは問題なく動作し、プレーン テキスト スクリプトとして保存して使用することもできます。

すなわち

osascript /Users/USERNAME/Desktop/foo.applescript

于 2013-04-17T23:14:33.093 に答える
58

いくつかの情報:

「強化されたアプリケーション オブジェクト モデル」:

tell application "iTunes"
    if it is running then
      pause
    end if
end tell

そのようにすることもできます:

if application "iTunes" is running then
    tell application "iTunes" to quit
end if

これを行うこともできます:

get name of application "iTunes"
get version of application "iTunes"

ジャーニーを完了するには:

get id of application "TextEdit" --> "com.apple.TextEdit"
tell application id "com.apple.TextEdit"
    make new document
end tell

それが「拡張アプリケーション オブジェクト モデル」でした。アプリがまだ起動する場合 (たとえば、スクリプトを初めてコンパイルして実行するとき)、AS がアプリから辞書に見つからなかった情報を取得する必要があるためだと思います (またはそのようなもの...? )。

于 2013-04-17T20:48:47.333 に答える
8

OK、この質問は非常に古いことは知っていますが、別の問題を探しているときに偶然見つけて、これらの回答のいくつかがどれほど複雑であるかを検討する必要がありました.

あなたが望むものを達成するための簡単なコードは次のとおりです。

tell application "System Events"
  if application process "Safari" exists then
    -- do stuff you want to do only if Safari exists
  end if
end tell

古いシステムでは、構文は次のように使用されていました。

tell application "System Events"
  if exists of application process "Safari" is true then
    -- do stuff you want to do only if Safari exists
  end if
end tell

これらのいずれかは、アプリが実行されている場合にのみアクションを実行するための Applescript ソリューションの勇敢な検索者であるあなたにとって間違いなく機能するはずです。


おー!おまけのヒント:アプリケーション プロセス名が正確にわからない場合 (通常はアプリ名ですが、常にそうであるとは限りません)、最終的なスクリプト実行をコーディングする前に…</p>

tell application "System Events"
   get every application process
end tell

結果でアプリのプロセス名を見つけます。

これは、そのコマンドを実行した画面のグラブです。(無数のGoogle Chrome Helperインスタンスに注意してください。Google に感謝します!)

ここに画像の説明を入力

チッ!

于 2015-06-23T07:17:12.137 に答える
2

ただし、以前に作成されたすべての回答には同じ問題があります。

彼らはその名前でアプリを探します。ただし、ユーザーがアプリの名前を変更すると、実際には実行されているのに、スクリプトはアプリが実行されていないと認識します。

実行中のアプリを適切に確認するには、ユーザーが変更できないバンドル ID で見つける必要があります。

バンドル ID は、たとえば、アプリが既に実行されている場合に、次のコマンドで照会できます。

tell application "System Events"
    get bundle identifier of application process "Safari"
end tell

または、インストールされているアプリの場合は次のようにします。

get id of application "Safari"

特定のバンドル ID を持つアプリが実行されているかどうかを確認するには、次のコードを使用します。

tell application "System Events"
    set ids to bundle identifier of every application process
    if ids contains "com.apple.safari" then
        return "Running"
    else
        return "Not running"
    end if
end tell

さらに、アプリが実行されているかどうかを確認し、終了してから再起動し、以前に実行されていたのとまったく同じアプリが再起動され、他のコピーが存在しないことを確認する例を次に示します。

set bundleID to "com.apple.safari"
set apps to runningApps(bundleID)
set appCount to length of apps
if appCount is not 0 then
    quit application id bundleID
    repeat while length of runningApps(bundleID) = appCount
        -- wait for the app to quit
    end repeat
    open first item of apps
end if

on runningApps(bundleID)
    -- The try block is to catch the rare case of having more than one
    -- copy of an app running at the same time. Unfortunately, in that
    -- case this code will not run as expected, because we don't get the
    -- correct list of multiple items back then. But at least the script
    -- will not crash from it but handle it gracefully.
    tell application "System Events"
        try
            return application file of (every application process whose bundle identifier = bundleID)
        end try
    end tell
    return {}
end runningApps
于 2016-08-12T18:31:46.370 に答える
1
tell application "Finder"
    set applicationsnames to get the name of every process whose visible is true
end tell

set appName to "Safari"

if applicationsnames does not contain appName then
    say (appName & " is not running")
    --add here what you want to happen

end if
return applicationsnames

{"Finder", "JavaAppLauncher", "firefox", "Microsoft Word", "iTunes", "AppleScript Editor"}これは私に戻ってきます

お役に立てれば

于 2016-01-21T13:19:43.563 に答える