スクリプトで「特定ウィンドウのスクリーン・ショット」を取る

現在はbashでスクリプトを書いています。その中から、條件により「特定ウィンドウの一部」のスクリーン・ショットを記録したいです。


具体的には「System Preferences -> Network」のウィンドウ左ペインの一部の記録に興味があります;


ユーザがアップロードしたファイル




ヒントを頂ければ幸いです。

iPhone 5s, OS X Mavericks (10.9.3), Mac mini(mid 2011), iMac(late 2009)

投稿日 2014/10/20 20:14

返信
返信: 15

2014/10/20 21:27 mNeji への返信

AppleScript to take screenshot of a specific area and save to desktop

https://discussions.apple.com/thread/5641587


Mavericks まではリンク先のスクリプトで大丈夫だと思います。


Yosemite では RubyCocoa がなくなった模様。別途インストールする必要があるようです。PyObjC に翻訳する手もありますが Yosemite で動くかは不明。ASOC は全く分かりません。また、Cocoa な部分での仕様がどうなってるかも分かりません。

2014/10/20 22:57 Hiro__S への返信

Hiro.Sさん、


拝見しました。やはり苦手なAppleScriptで困ったと思いましたが、このスクリプトは不思議と解りやすいので、しばし格闘してみます。

# 参考書は中古で入手はしてますので……。

 

ご教示、有難うございました。

追伸:Yosemite情報も感謝します。ヨウスミテからトライして見ます。

2014/10/20 23:45 Hiro__S への返信

取り敢えず、そのまま動かしてみました 。


なにかスクリーン・ショットは出てきましたが、エラーがでました。

AppleScript Error


/System/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/oc_import.rb:192:in `const_missing': uninitialized constant EOF (NameError)

from -:14


上記ディレクトリは存在しているようです;


u1@MmM11:~ $ ll /System/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc

total 56

-rw-r--r-- 1 root wheel compressed 18K 6 19 01:23 active_record.rb

-rw-r--r-- 1 root wheel compressed 939B 6 19 01:23 application.rb

-rw-r--r-- 1 root wheel compressed 431B 6 19 01:23 cocoa.rb

-rw-r--r-- 1 root wheel compressed 3.3K 6 19 01:23 cocoa_macros.rb

-rw-r--r-- 1 root wheel compressed 1.0K 6 19 01:23 cocoa_macros_appkit.rb

-rw-r--r-- 1 root wheel compressed 576B 6 19 01:23 foundation.rb

-rw-r--r-- 1 root wheel compressed 476B 6 19 01:23 oc_all.rb

-rw-r--r-- 1 root wheel compressed 51K 6 19 01:23 oc_attachments.rb

-rw-r--r-- 1 root wheel compressed 420B 6 19 01:23 oc_attachments_appkit.rb

-rw-r--r-- 1 root wheel compressed 1.4K 6 19 01:23 oc_bundle_support.rb

-rw-r--r-- 1 root wheel compressed 825B 6 19 01:23 oc_exception.rb

-rw-r--r-- 1 root wheel compressed 25K 6 19 01:23 oc_import.rb

-rw-r--r-- 1 root wheel compressed 3.1K 6 19 01:23 oc_types.rb

-rw-r--r-- 1 root wheel compressed 2.1K 6 19 01:23 oc_types_appkit.rb

-rw-r--r-- 1 root wheel compressed 5.0K 6 19 01:23 oc_wrapper.rb

-rw-r--r-- 1 root wheel compressed 3.1K 6 19 01:23 ruby_addition.rb

u1@MmM11:~ $



ご報告まで。

2014/10/21 00:02 Hiro__S への返信

シェルスクリプト部分を抜き出すとこんな感じ

#!/bin/bash /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby <<'EOF' - "$@" require 'osx/cocoa' include OSX raise AugumentError, "Usage: #{File.basename($0)} x, y, w, h" unless ARGV.length == 4 x, y, w, h = ARGV.map {|a| a.to_f} outfile = File.expand_path(%x[date +'%F %H.%M.%S.png'].chomp, '~/Desktop') img = CGDisplayCreateImageForRect(CGMainDisplayID(), CGRectMake(x, y, w, h)) brep = NSBitmapImageRep.alloc.initWithCGImage(img) data = brep.objc_send( :representationUsingType, NSPNGFileType, :properties, {}) data.objc_send( :writeToFile, outfile, :atomically, false) EOF


実行は

$ ./screenshot x y w h


$ ./screenshot 0 0 600 400


ーーーーー


さらに Ruby の部分を抜き出すと

#!/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby require 'osx/cocoa' include OSX raise AugumentError, "Usage: #{File.basename($0)} x, y, w, h" unless ARGV.length == 4 x, y, w, h = ARGV.map {|a| a.to_f} outfile = File.expand_path(%x[date +'%F %H.%M.%S.png'].chomp, '~/Desktop') img = CGDisplayCreateImageForRect(CGMainDisplayID(), CGRectMake(x, y, w, h)) brep = NSBitmapImageRep.alloc.initWithCGImage(img) data = brep.objc_send( :representationUsingType, NSPNGFileType, :properties, {}) data.objc_send( :writeToFile, outfile, :atomically, false)


実行は

$ ./screenshot x y w h

2014/10/21 00:35 Hiro__S への返信

Hiro.Sさん、


はい、Safari経由でコピペしたら動きました。有難うございました。テキストなのに不思議ですね、


なお、向こうのディスカッションはとても面白かったです。私の好みは「bash&ruby」なので、これもトライしたいです。


AppleScriptの詳しいご説明はこれから拝見します、悪しからず。

2014/10/21 03:58 Hiro__S への返信

Hiro.Sさん、


いろいろな注釈有難うございました。


本家での「bash&ruby」版;

https://discussions.apple.com/thread/5641587

Hiroto Dec 9, 2013 12:28 PM

Re: AppleScript to take screenshot of a specific area and

and save to desktop in response to Tony T1

も触ってみました。


ヒア・ドキュメントの末尾、「END 」から空白x2を削除して「END」とすることで目出度く動作するようになりました。


「bash&ruby」がこのような形式で使えるのは嬉しいです。ここに利用されている「ruby script」からrubyにアプローチしたいと思います。


ご指導に多謝。

2014/10/21 05:16 mNeji への返信

ヒア・ドキュメントの末尾、「END 」から空白x2を削除して「END」とすることで目出度く動作するようになりました。


このボードの困った仕様なんですよね。フィードバックはしたんですが、なかなか修正してくれません...。


ところで、スクリーンショットですが、簡単に済ませるなら、screencapture コマンドってのもあります。ご存知かもしれませんが一応。

$ screencapture screenshot.png

$ screencapture -w screenshot.png

$ screencapture -s screenshot.png


Shell Script、Ruby、Ruby Cocoa、AppleScript が使えると可能性は無限大です。頑張ってください。

2014/10/21 07:07 Hiro__S への返信

このボードの困った仕様なんですよね。フィードバックはしたんですが、なかなか修正してくれません...。


このフォーラムに来る人々は「Appleから見ると、釣り上げた魚なので、過剰な餌は控える」のでしょうかね。


私の常用ブラウザではこのフォーラムに書き込めないので、一々、Safariを立ち上げています。まさにシュールな光景です。


ところで、スクリーンショットですが、簡単に済ませるなら、screencapture コマンドってのもあります。ご存知かもしれませんが一応。

そうですね、忘れていました。殆ど「⇧⌘4」を常用しているので、今回のスクリプトをgssとして整備する所存です。


Shell Script、Ruby、Ruby Cocoa、AppleScript が使えると可能性は無限大です。頑張ってください。

Ruby Cocoa」はX11のRuby版なのでしょうか。すこし探してみます。


AppleScriptはまだ鬼門です、笑い。


# 最近、ネットワークの状態変数をコンパクトに表示するのをbashで作りました。

# grepに正規表現が使えるのを知ったのと、全て関数で書けるようになったので、bashは自称中級になりました。

# 次は、目指せruby初級、です。


追伸:

「ruby script」から

  1. 「System Preferences → Network」を開けて、
  2.  ある(x, y)の位置にそのウインドウの左上端を配置させること。

のは、原理的に可能でしょうか?

2014/10/21 08:20 mNeji への返信

「Ruby Cocoa」はX11のRuby版なのでしょうか。


違います。


すこし探してみます。


探すも何も Leopard から Mavericks までは標準で入ってます。というか、今回のスクリプトが RubyCocoa ですよ。Yosemite 以降は自分でインストールする必要がありますが、専用のパッケージは未だリリースされてないようです。ちなみに入手は下のリンク先から。


RubyCocoa - A Ruby/Objective-C Bridge

http://rubycocoa.sourceforge.net/


「ruby script」から

  1. 「System Preferences → Network」を開けて、
  2.  ある(x, y)の位置にそのウインドウの左上端を配置させること。

のは、原理的に可能でしょうか?


やり方はいくつかありますが、AppleScript を呼び出すのが簡単かなと。


RubyCocoa なら NSAppleScript でこんな感じ。

#!/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby require 'osx/cocoa' include OSX cmd = <<'EOS' tell application "System Preferences" activate set current pane to pane "com.apple.preference.network" set {x1, y1, x2, y2} to bounds of window 1 set bounds of window 1 to {0, 22, x2 - x1, y2 - y1 + 22} end tell EOS script = NSAppleScript.alloc.initWithSource(NSString.stringWithCString(cmd)) desc = script.executeAndReturnError(nil)


シェルスクリプトなら osascript でこうでしょうか。

#!/bin/bash osascript <<'OSA' tell application "System Preferences" activate set current pane to pane "com.apple.preference.network" set {x1, y1, x2, y2} to bounds of window 1 set bounds of window 1 to {0, 22, x2 - x1, y2 - y1 + 22} end tell OSA


Snow Leopard では大丈夫ですが、Lion 以降で動くかは全く分かりません。ダメな場合はほかの方の回答を待ってください。

2014/10/21 16:13 Hiro__S への返信

Hiro.Sさん、


詳細なご説明ありがとうございました。


RubyCocoa - A Ruby/Objective-C Bridge

http://rubycocoa.sourceforge.net/

そうですか、存じませんでしたがトライしたいです。


・RubyCocoa なら NSAppleScript でこんな感じ。

・シェルスクリプトなら osascript でこうでしょうか。

なるほど両者同じ雰囲気で利用できるのですね。


ユーザ・インターフェイスに慣れているシェルスクリプトから手をつけてみます。


tell application "System Preferences"

activate

set current pane to pane "com.apple.preference.network"


う〜む、このような親子関係が用意されているのか、感動。


こうなってくると現金なもので、AppleScriptの解説本をパラっと拝見すると、とても親しみやすく感じるようになりました。


では、修行に踏み出してみまする。

2014/10/22 20:25 Hiro__S への返信

Hiro.Sさん:

Snow Leopard では大丈夫ですが、Lion 以降で動くかは全く分かりません。ダメな場合はほかの方の回答を待ってください。


Bash版ですが、Mavericksで動きました;

ユーザがアップロードしたファイル


で、パラメータ「0 -> 100」とすると;

ユーザがアップロードしたファイル

となりました。入れ物は右にシフトするのに、内部の部品はとりのこされているようです。面白いことに、この状態でも「Wi-Fi on」にすると、左ペインの表示は追従します。


旨くすると、アプリケーションの内の必要な部分だけを出来るかなあと感じました。


俄然、AppleScriptに興味が湧いてきました。参考図書で良い物が見当たりませんでしたが、有料pdfが判りやすそうなのでトライしてみます。


中間報告まで。

2014/10/22 22:09 mNeji への返信

確認ありがとうございます。


旨くすると、アプリケーションの内の必要な部分だけを出来るかなあと感じました。


違います。不正なパラメータを与えたので UI が壊れただけです。正しくはこうです。Y座標も同様。


set bounds of window 1 to {100, 22, x2 - x1 + 100, y2 - y1 + 22}


現在の bounds 値を調べるのは下記。System Preferences のウインドウを移動し、都度 bounds 値を取得すると感覚がつかめると思います。bounds 値とは何かはご自分で調べてください。


tell application "System Preferences" get bounds of window 1 end tell


ちなみに「22」はメニューバーの高さです。自動取得する方法もありますが面倒なので定数扱いとしました。Yosemite では変更されてるような記事をどこかで見かけたので、アップグレードする際は注意してください。


あと、パラメータの正当性をチェックするコードを追加した方が良いのかもしれませんが、本件では System Preferences のウインドウを左上に固定すれば良いわけで、そこまでは必要ないような気がします。

2014/10/22 23:07 Hiro__S への返信

Hiro.Sさん:


確認ありがとうございます。



むしろ弟子の一人として、フィードバックさせていただいているだけです。


違います。不正なパラメータを与えたので UI が壊れただけです。正しくはこうです。Y座標も同様。


set bounds of window 1 to {100, 22, x2 - x1 + 100, y2 - y1 + 22}


よく判りました。何となく、( x1, x2 )=( 10, 22 )と誤解をしていました。早く文法を体で覚える必要がありますね。むしろ、必要な情報は自らグラフィカルに生成できるようになりたいものです。


現在の bounds 値を調べるのは下記。System Preferences のウインドウを移動し、都度 bounds 値を取得すると感覚がつかめると思います。bounds 値とは何かはご自分で調べてください。

はい、承知いたしました。躓くまで、修行に励みます。

このスレッドはシステム、またはAppleコミュニティチームによってロックされました。 問題解決の参考になる情報であれば、どの投稿にでも投票いただけます。またコミュニティで他の回答を検索することもできます。

スクリプトで「特定ウィンドウのスクリーン・ショット」を取る

Apple サポートコミュニティへようこそ
Apple ユーザ同士でお使いの製品について助け合うフォーラムです。Apple Account を使ってご参加ください。