Menu

Skip to content
AppleScriptの穴
  • Home
  • Products
  • Books
  • Docs
  • Events
  • Forum
  • About This Blog
  • License
  • 仕事依頼

AppleScriptの穴

Useful & Practical AppleScript archive. Click '★Click Here to Open This Script' Link to download each AppleScript

カテゴリー: AppleScript Application on Xcode

AppleScriptでキースキャン

Posted on 2月 26, 2020 by Takaaki Naganoya

Xcode上で作成するAppleScript Cocoa Applicationで、キースキャンを試してみました。

ふだん作っているものだと、各種パラメータをGUI上で設定する程度のもので、キースキャンを行う必要などこれっぽっちもないのですが、いま作っているアプリケーションでキースキャンが必要になってしまったので、昔作ったものを引っ張り出してきました。

AppleScriptのプログラムでキースキャンを行うといえば、AppleScript Appletの起動時に何らかのModifier Keys(ShiftとかOptionとかCommandとかControlとか)が押されていることを検出して動作を変更するといった処理が一般的です。ループ処理中でも、これらのキー入力を定期的に監視することはよく行なっています(処理中に停止したいという要求はあるので)。

–> Watch Demo Movie

–> Download Xcode Project Archive

本プログラムでは、Modifier Keysにかぎらずキーボード入力全般を受け付けています。ただし、キースキャン可能なのは本プログラムが最前面にある場合のみです。

掲載しているコードからではわかりませんが、キー入力の受け付けをNSWindowで行なっています。FirstResponderまわりを一切いじくらずにほぼプログラミングなしでキー受け付けを行おうとした結果NSWindowで行うことになったというわけで、これがベストとも思いません。

とりあえず「こうすればできた」というレベルをおさえておいて、そこから自分の好きな方向に機能を変更していけばよいと思います。

AppleScript名:AppDelegate.applescript
—
— AppDelegate.applescript
— keyEvents
—
— Created by Takaaki Naganoya on 2014/05/09.
— Copyright (c) 2014年 Takaaki Naganoya. All rights reserved.
—

script AppDelegate
  property parent : class "NSObject"
  
  
— IBOutlets
  
property theWindow : missing value
  
property aButton : missing value
  
  
property xMax : 500
  
property yMax : 500
  
  
property aStep : 50
  
  
on applicationWillFinishLaunching:aNotification
    —
  end applicationWillFinishLaunching:
  
  
on applicationShouldTerminate:sender
    return current application’s NSTerminateNow
  end applicationShouldTerminate:
  
  
  
on buttonMove:(aCode as integer)
    set curFrame to aButton’s frame()
    
copy curFrame to {{x, y}, {xWidth, yHeight}}
    
    
if aCode = 123 then
      –Left
      
if x > 0 then
        set x to x – aStep
      end if
    else if aCode = 124 then
      –Right
      
if x < xMax then
        set x to x + aStep
      end if
      
    else if aCode = 126 then
      –Up
      
if y < yMax then
        set y to y + aStep
      end if
      
    else if aCode = 125 then
      –Down
      
if y > 10 then
        set y to y – aStep
      end if
    else if aCode = 125 then
      
    end if
    
    
set newRect to {{x, y}, {xWidth, yHeight}}
    
aButton’s setFrame:newRect
    
aButton’s setNeedsDisplay()
  end buttonMove:
end script

★Click Here to Open This Script 

AppleScript名:keyEventWin.applescript
script keyEvWin
  
  
property parent : class "NSWindow"
  
  
property aButton : missing value
  
  
  
on canBecomeKeyWindow:sender
    return true
  end canBecomeKeyWindow:
  
  
on canBecomeMainWindow:sender
    return true
  end canBecomeMainWindow:
  
  
  
on keyDown:theEvent
    set aCode to (theEvent’s keyCode) as integer
    
    
if aCode = 123 then
      –左
      
current application’s NSApp’s delegate()’s performSelector:"buttonMove:" withObject:(aCode)
      
    else if aCode = 124 then
      –右
      
current application’s NSApp’s delegate()’s performSelector:"buttonMove:" withObject:(aCode)
      
    else if aCode = 126 then
      –上
      
current application’s NSApp’s delegate()’s performSelector:"buttonMove:" withObject:(aCode)
      
    else if aCode = 125 then
      –下
      
current application’s NSApp’s delegate()’s performSelector:"buttonMove:" withObject:(aCode)
      
    end if
    
    
  end keyDown:
  
end script

★Click Here to Open This Script 

Posted in AppleScript Application on Xcode GUI | Tagged 10.13savvy 10.14savvy 10.15savvy NSButton NSEvent NSWindow | Leave a comment

AppleScriptでCoreAnimationを利用

Posted on 2月 13, 2020 by Takaaki Naganoya

Xcode上で作成するCocoa AppleScript Applicationにおいて、CoreAnimationを利用するサンプルProjectです。

–> Download Xcode Project Test with Xcode 11.3.1 + macOS 10.14.6

ひととおり(このぐらい)CoreAnimationでGUI部品をアニメーションするテストを行なっていました。あまり使いすぎるのは下品に見えるとの判断から、実際のアプリケーションでは最低限の地味な利用にとどめていました。

–> Watch Demo (1) Double PDF

–> Watch Demo (2) This Project

Mac App Storeで販売している100% AppleScriptで記述したアプリケーション「Double PDF 2.0」においても、コマンド実行後にメニューを更新する際、更新したメニューを点滅表示するぐらいの「節度あるお付き合い」にとどめていました。

それが、ここ最近組んでいるアプリケーションではド派手に利用する必要があるようで、再度こうした試作品を引っ張り出してテストしだしています。

AppleScript名:AppDelegate.applescript
—
— AppDelegate.applescript
— GUI Animation
—
— Created by Takaaki Naganoya on 2017/02/13.
— Copyright 2017 Takaaki Naganoya. All rights reserved.
—
— http://liu044100.blogspot.jp/2013/07/cabasicanimation.html
script AppDelegate
  property parent : class "NSObject"
  
  
— IBOutlets
  
property theWindow : missing value
  
property aPopup : missing value
  
  
property gui1 : missing value
  
property gui2 : missing value
  
property gui3 : missing value
  
property gui4 : missing value
  
property gui5 : missing value
  
property gui6 : missing value
  
property gui7 : missing value
  
property gui8 : missing value
  
property gui9 : missing value
  
property guiA : missing value
  
property guiB : missing value
  
property guiC : missing value
  
  
  
  
on applicationWillFinishLaunching:aNotification
    — Insert code here to initialize your application before any files are opened
  end applicationWillFinishLaunching:
  
  
on applicationShouldTerminate:sender
    return current application’s NSTerminateNow
  end applicationShouldTerminate:
  
  
on clicked:sender
    set aInd to aPopup’s indexOfSelectedItem()
    
set guiList to {gui1, gui2, gui3, gui4, gui5, gui6, gui7, gui8, gui9, guiA, guiB, guiC}
    
repeat with i in guiList
      if aInd = 0 then
        (my blinkObject:i)
      else if aInd = 1 then
        (my scaleObject:i)
      else if aInd = 2 then
        (my rotateObject:i forAxis:"x")
      else if aInd = 3 then
        (my rotateObject:i forAxis:"y")
      else if aInd = 4 then
        (my rotateObject:i forAxis:"z")
      else if aInd = 5 then
        (my moveObject:i)
      else if aInd = 6 then
        –my mixtureAnimeObject:i
      end if
      
delay 0.1
    end repeat
  end clicked:
  
  
  
  
on blinkObject:aObject
    set animation to current application’s CABasicAnimation’s animationWithKeyPath:"opacity"
    
animation’s setDuration:0.1
    
animation’s setAutoreverses:true
    
animation’s setRepeatCount:4
    
animation’s setFromValue:(current application’s NSNumber’s numberWithFloat:1.0)
    
animation’s setToValue:(current application’s NSNumber’s numberWithFloat:0.0)
    
aObject’s layer()’s addAnimation:animation forKey:"blink"
  end blinkObject:
  
  
on scaleObject:aObject
    set animation to current application’s CABasicAnimation’s animationWithKeyPath:"transform.scale"
    
animation’s setDuration:0.1
    
animation’s setAutoreverses:true
    
animation’s setRepeatCount:2
    
animation’s setFromValue:(current application’s NSNumber’s numberWithFloat:1.0)
    
animation’s setToValue:(current application’s NSNumber’s numberWithFloat:2.0)
    
aObject’s layer()’s addAnimation:animation forKey:"scale-layer"
  end scaleObject:
  
  
on rotateObject:aObject forAxis:anAxis
    set animation to current application’s CABasicAnimation’s animationWithKeyPath:("transform.rotation." & anAxis)
    
animation’s setDuration:2.0
    
–animation’s setAutoreverses:false
    
animation’s setRepeatCount:1
    
animation’s setFromValue:(current application’s NSNumber’s numberWithFloat:0.0)
    
animation’s setToValue:(current application’s NSNumber’s numberWithFloat:4.0 * 3.1415926)
    
aObject’s layer()’s addAnimation:animation forKey:"rotate-layer"
  end rotateObject:forAxis:
  
  
  
on moveObject:aObject
    set aFrame to aObject’s frame()
    
copy aFrame to {{fx1, fy1}, {fx2, fy2}}
    
set animation to current application’s CABasicAnimation’s animationWithKeyPath:"position"
    
animation’s setDuration:0.4
    
animation’s setAutoreverses:false
    
animation’s setRepeatCount:1
    
animation’s setFromValue:(current application’s NSValue’s valueWithCGRect:(aObject’s frame()))
    
animation’s setToValue:(current application’s NSValue’s valueWithCGRect:(current application’s CGRectMake(100, 100, fx2, fy2)))
    
aObject’s layer()’s addAnimation:animation forKey:"move-layer"
  end moveObject:
  
  
–Not Work Yet…..
  
(*
  on mixtureAnimeObject:aObject
    set animation1 to current application’s CABasicAnimation’s animationWithKeyPath:"transform.translation.x"
    animation1’s setToValue:(current application’s NSNumber’s numberWithFloat:80.0)
    animation1’s setDuration:3.0
    
    set animation2 to current application’s CABasicAnimation’s animationWithKeyPath:"transform.rotation.z"
    animation2’s setFromValue:(current application’s NSNumber’s numberWithFloat:0.0)
    animation2’s setToValue:(current application’s NSNumber’s numberWithFloat:4.0 * 3.1415926)
    animation2’s setDuration:3.0
    
    set aGroup to current application’s CAAnimationGroup’s animation()
    aGroup’s setDuration:3.0
    aGroup’s setRepeatCount:1.0
    aGroup’s setAnimations:(current application’s NSArray’s arrayWithObjects:{animation1, animation2, missing value})
    aObject’s layer()’s addAnimation:aGroup forKey:"move-rotate-layer"
  end mixtureAnimeObject:
*)
end script

★Click Here to Open This Script 

Posted in Animation AppleScript Application on Xcode GUI | Tagged 10.13savvy 10.14savvy 10.15savvy CABasicAnimation NSNumber | Leave a comment

アラビア語ローカライズしたアプリケーションの挙動の変化

Posted on 12月 22, 2019 by Takaaki Naganoya

Xcode上でAppleScriptのアプリケーションを作って(Double PDF)、各国語にローカライズしていたときに、最難関言語として名高いアラビア語(Arabic)を試してみたことがありました。

ローカライズ作業自体にもAppleScriptを投入し、テキストエディタ上でオープンしているstringsファイルを読み取ってGoogle Translate APIを呼び出して指定言語に数秒で翻訳。記号類だけから構成されるフィールドは翻訳しないなど、その場でScriptを調整しながら大幅な翻訳作業の省力化を実現(ほかの方法もあるようなので、これがベストとは言いませんが、、、)。このScriptなしに他の言語への翻訳などというめんどくさい作業はやろうとは思いませんでした。

この翻訳用AppleScriptの威力で30言語ぐらい翻訳。主要言語のうち、最後に残ったのが、文字が右から左に流れるアラビア語とヘブライ語でした。

まずは、挙動がどのぐらい違うのか確認。Xcodeでローカライズ言語にアラビア語を追加。stringファイルの内容自体はオリジナルの英語のままの状態で、実行時のアプリケーションの言語環境に「アラビア語」を指定して起動してみました。

起動してびっくり!


▲左:日本語環境、右:アラビア語環境


▲日本語環境を指定して起動したところ@macOS 10.14.6


▲アラビア語環境を指定して起動したところ@macOS 10.14.6


▲アラビア語環境で表示したメニュー@macOS 10.14.6


▲アラビア語環境で表示したAbout Box@macOS 10.14.6。スクロールバーが右側ではなく左側に

ツールバーアイコンはデフォルトの英語環境や日本語環境では、左→右の順で並びますが、アラビア語環境ではウィンドウ上部右→左と並びました。メニューの内容も右側にタイトルが来て、左側にキーボードショートカットが並ぶなど、予想外の配置です。

これは、バグとかいった種類の話ではなく、はじめてアラビア語環境で自作のアプリケーションを起動して、その挙動の違いに驚かされたという話であります。

2つのPDFViewを並べてあり、それぞれ右とか左とか言わなくてもわかるよう、左側には青色のラベル、右側には赤色のラベルを貼っておいたのですが、ツールバーアイコンの左右も入れ替わってしまい、自分の意図したとおりのレイアウトからはかけ離れたものとなってしまいました。

アプリケーション内部で、アプリケーション起動環境から言語がアラビア語やヘブライ語のように右→左の表示を行う言語だった場合には何か処理を行なってツールバーボタンの入れ替えなどを行う必要があることでしょうか。ちょっとノーアイデアで分からないところ。ひたすら驚かされました。他の言語は軒並みGoogle Translation APIをAppleScriptから呼び出して翻訳できたのですが、アラビア語とヘブライ語は難敵でした。攻略できていないので、そこんとこなかなか辛いです。

Double PDF v2.0自体はMac App Storeで絶賛レビュー中です。In Reviewの状態に入ってからはや10日が経過し、さすがに不安になってDeveloper Connectionに電話して聞いてしまいましたが、わかったのは本当にまだレビュー作業中で、レビューにさらなる時間がかかるということだけです。

そろそろ、実際にアップデート作業にかけた時間よりもレビューにかかっている時間のほうが長くなりつつあり、そして確実に数倍の時間がかかりそうでもあり……各国語のPDFでも作って(表示をローカライズした30言語分)、それらのPDFで差分検出チェックでもしてるんじゃないかと、、、

Posted in AppleScript Application on Xcode | Tagged 10.14savvy | Leave a comment

Continuity Camera AS

Posted on 12月 12, 2019 by Takaaki Naganoya

Xcode上でCocoa AppleScriptアプリケーションを作成し、macOS 10.14から搭載された「Continuity Camera」の機能を利用して、iOSデバイス上で撮影した写真をその場でMacに転送・保存してみました。

–> ContinityCameraAS(Xcode 11 Project)

Continuity Cameraをサポートする部分のObjective-CのコードはThomas Zoechling氏のBlog上のものを利用させていただいております。

本当は通常のスクリプトでdisplay dialog的なダイアログを表示して、その上に作成したNSImageViewでContinuity Cameraを呼び出せるとよかったのですが、なかなかそこまで噛み砕いて解釈できなかったので、Xcode上のアプリそのままです。

Continuity CameraのプロジェクトをXcode上でビルド&実行すると、なにもないっぽいWindowが表示されますが、下地にNSImageViewを敷いてあるような気がします。このウィンドウの真ん中の方でControl-クリックあるいはマウスの右ボタンをクリックすると、コンテクストメニューが表示され、そこでカメラから画像取り込みを行うデバイスを選択し、それらの周辺デバイスで撮影した写真をそのまま取り込めます。

Continuity Camera機能は、同じiCloud IDで関連づけたiOSデバイスのカメラを無線LANのネットワークごしにMacから利用するものと理解しています(Bluetoothもオンにする必要があるかもしれない)。

ウィンドウ上の「Save Image」ボタンをクリックすると、その内容をデスクトップにPNG画像で保存します。

AppleScriptアプリケーションでもContinuity Cameraを利用できることがわかったので、このプログラムにAppleScript用語辞書(sdef)をつけてScriptableなアプリケーションに仕立て上げれば、通常のAppleScriptからcapture cameraといったコマンドで取り込めてよいのではないでしょうか。

コンテクストメニューの先にある機能に直接アクセスするためには、もう少し調べる必要がありそうではあります。

AppleScript名:AppDelegate.applescript
—
— AppDelegate.applescript
— continityCameraAS
—
— Created by Takaaki Naganoya on 2019/10/21.
— Copyright © 2019 Takaaki Naganoya. All rights reserved.
—

script AppDelegate
  property parent : class "NSObject"
  
  
— IBOutlets
  
property theWindow : missing value
  
property theImageV : missing value
  
  
on applicationWillFinishLaunching:aNotification
    — Insert code here to initialize your application before any files are opened
  end applicationWillFinishLaunching:
  
  
  
on applicationShouldTerminate:sender
    — Insert code here to do any housekeeping before your application quits
    
return current application’s NSTerminateNow
  end applicationShouldTerminate:
  
  
  
on clicked:aSender
    set imgRes to theImageV’s image()
    
set dtPath to POSIX path of (path to desktop)
    
log {"dtPath", dtPath}
    
set fRes to retUUIDfilePath(dtPath, "png") of me
    
log {"fRes", fRes}
    
set sRes to saveNSImageAtPathAsPNG(imgRes, fRes) of me
  end clicked:
  
  
  
–NSImageを指定パスにPNG形式で保存
  
on saveNSImageAtPathAsPNG(anImage, outPath)
    set imageRep to anImage’s TIFFRepresentation()
    
set aRawimg to current application’s NSBitmapImageRep’s imageRepWithData:imageRep
    
set pathString to current application’s NSString’s stringWithString:outPath
    
set newPath to pathString’s stringByExpandingTildeInPath()
    
set myNewImageData to (aRawimg’s representationUsingType:(current application’s NSPNGFileType) |properties|:(missing value))
    
set aRes to (myNewImageData’s writeToFile:newPath atomically:true) as boolean
    
return aRes –true/false
  end saveNSImageAtPathAsPNG
  
  
  
on retUUIDfilePath(aPath, aEXT)
    set aUUIDstr to (current application’s NSUUID’s UUID()’s UUIDString()) as string
    
set aPath to ((current application’s NSString’s stringWithString:aPath)’s stringByAppendingPathComponent:aUUIDstr)’s stringByAppendingPathExtension:aEXT
    
return aPath
  end retUUIDfilePath
  
end script

★Click Here to Open This Script 

Posted in AppleScript Application on Xcode Image | Tagged 10.14savvy 10.15savvy | Leave a comment

Double PDF v2.0完成に近づく

Posted on 11月 29, 2019 by Takaaki Naganoya

Mac App Storeで販売したはいいものの、途中(macOS 10.13)でド派手なバグをOS(PDFView)に作られ、AppleのDevelopper Supportに正式に連絡してもなしのつぶてでそのままMac App Storeに置かれている「Double PDF」。さすがに現状のままだとまずすぎるので、macOS 10.14/10.15上で動作するように改修作業を行なっている今日このごろ(macOS 10.13.xでは、動くことは動くんですがOS自体の未修正バグが多すぎて動作保証いたしかねます)。

# OSをアップデートすると機能が落ちるとは何事だろう?

PDFViewのド派手なバグ(currentPageを取得できない)を回避するために、自前でAppleScriptでいろいろ回避コードを走らせているので、ページめくりのスピードが落ちています(個人的にこれのために作ったので、テンションが落ちるところです)。

初版では画像処理にGPUImage.frameworkを同梱して利用していましたが、GPUImage1だとOpenGL経由でGPUの機能にアクセスしており、OpenGL自体が最新のmacOS 10.15では非推奨となっており、Mac App Storeでリジェクトされる危険性があります(より新しい代替APIであるMetalを使わないと因縁を付けられる気が、、、)。

そこで、GPUImageに依存しているコードをすべて書き換え、GPUImageを完全に取り外しました。これには、よくよく調べたら、PDFの各ページをグレースケール画像に変換する箇所でしか利用していなかったことが大きいです。これで、名実ともに「すべてAppleScriptで記述したアプリケーション」に。

GPUImageの除去は使い勝手には一切影響しません。若干の前向きな機能追加も行なっておきましょう。

これまでに意見として寄せられていないものの、どうもグレースケール画像で比較を行うことに不満を持っていたユーザーが一定数いるものとにらんでいたので、カラーのまま比較する機能を追加しました。

正直なところ、「カラー比較モード」は個人的には不要と思っている(文字主体の書籍の校正用に作った)のですが、念のためです。

Double PDFはデータ上のささいな違いを「見逃す」ように作ってあります。これは、Adobe AcrobatのPDF比較機能が、見た目には影響を及ぼさないデータ上の些細な違いばかりピックアップして実用性がまったくないことから思いついたものです。見た目に影響のない差異を見逃して、見た目や文字で差が発生している箇所を指摘するツールという味付けになっています。

画像サイズを小さくした上でグレースケール化して比較するのはそのための重要な機能です。ただ、間違って色が変わったことを検出したいような用途もあることでしょう。

あとは、PDFからテキスト抽出をしたときに、PDF書き出し時の環境(OSバージョン)によってはNo Width Spaceが検出されるものがあるため、No Width Spaceの削除機能を追加しました。

細かい箇所でまだ不具合点(右側のビューワーのノンブルが表示されないことがある)がありますが、とりあえず出してみてもよさそうな気配はしています。

地味なところで画像素材をDark Mode対応させました。Credits.rtfのダークモード対応など、地味に工数が増えるのは勘弁してほしいです。あとは、外部アプリケーション操作要求を行うためのInfo.plistのエントリ追加などもあります。これを追加しないと外部アプリケーションへの操作要求のダイアログ自体が出ない=一切操作できないので要注意点です。

ほかにも、現行のXcodeでCocoa AppleScriptアプリケーションのプロジェクトを作ると、デフォルトではソースコード開示状態のビルドセッティングになってしまうので、これも要チェック点でしょう。まさかと思ってこの設定を再確認してみたら、execute onlyになっていませんでした。怖すぎ、、、

Posted in AppleScript Application on Xcode Image PDF | Tagged 10.12savvy 10.13savvy 10.14savvy 10.15savvy | Leave a comment

Appleがいまだに直さないPDFViewのバグを回避する

Posted on 4月 10, 2019 by Takaaki Naganoya

PDFViewからcurrentPage()が取れないという、最低最悪レベルのバグが放置されたOSがリリースされ続けて2年。Devlopper Supportに報告しても返事の1つもない今日このごろです。

Apple Developper Connectionのインシデントを消費して質問しても返答がないので、本当に頭にきています。

この、macOS 10.13のBetaでは存在しなかったのにRelease版で作られた画期的なバグを回避するために、いろいろ工夫をしてみました。

テストしてみたところ、Objective-CやSwiftでは発生していないため、Scripting Bridgeのみで発生しているらしきバグのようです。こんな基本的な箇所でバグを作って直さない連中の気が知れません。

AppleのDevelopper Supportが役立たずで仕事をしないのは今日にはじまった話ではないので(Mailing Listが落ちた状態で、報告しても1か月放置した事件など)、仕方なく回避策を検討してみました。

(1)PDFViewまわりのWrapping ClassをObjective-Cで書いて使う
(2)Objective-Cでユーティリティを書いて、パラメータとして与えたPDFViewからObjective-CでcurrentPageを取得する
(3)今後もAppleがバグを作り続けることが予想されるため、サードパーティのPSPDFKitを導入する

といった対策を検討していたのですが、最も手短なものとして、

(4)表示中のページを自前で管理して、PDFViewに指定ページの内容を随時切り出して表示する

という対処を行ってみました。

PDFをオープンしてPDFViewで表示させ、左右の矢印キーでページをめくることができます。なお、macOS 10.14.5beta+Xcode 10.2上でビルドと確認を行いましたが、内容的にはXcodeのバージョンは関係ありません。

–> Download Xcode Project Archive (pdfTestZ)

AppleScript名:AppDelegate.applescript
—
— AppDelegate.applescript
— pdfTestZ
—
— Created by Takaaki Naganoya on 2019/04/09.
— Copyright © 2019 Piyomaru Software. All rights reserved.
—

script AppDelegate
  property parent : class "NSObject"
  
  
— IBOutlets
  
property theWindow : missing value
  
property aView : missing value
  
property maxPageNum : 0
  
property curPageIndex : 0
  
property aPDFDoc : missing value
  
property pLabelField : missing value
  
  
  
on applicationWillFinishLaunching:aNotification
  
end applicationWillFinishLaunching:
  
  
on applicationShouldTerminate:sender
    return current application’s NSTerminateNow
  end applicationShouldTerminate:
  
  
  
on clicked:aSender
    set aTag to (tag of aSender) as integer
    
    
if aTag = 100 then
      set aPath to choose file of type {"com.adobe.pdf"}
      
      
set pPath to POSIX path of aPath
      
set aURL to current application’s |NSURL|’s fileURLWithPath:pPath
      
set my aPDFDoc to current application’s PDFDocument’s alloc()’s initWithURL:aURL
      
      
set myFileName to (current application’s NSString’s stringWithString:pPath)’s lastPathComponent()
      
theWindow’s setTitle:myFileName
      
      
set maxPageNum to ((aPDFDoc’s pageCount()) as integer) – 1
      
set curPageIndex to 0
      
      
log {"maxPageNum", maxPageNum}
      
      
aView’s setAutoScales:true
      
aView’s setDisplaysPageBreaks:true
      
      
my dispCurPageDoc()
      
set tmpStr to ((maxPageNum + 1) as string) & "/" & ((curPageIndex + 1) as string)
      
pLabelField’s setStringValue:tmpStr
      
    else if aTag = 200 then
      
      
set tmpPage to my (aPDFDoc’s pageAtIndex:(curPageIndex))
      
set curPageLabel to tmpPage’s label()
      
      
tell current application
        display dialog (curPageLabel as string)
      end tell
      
    else if aTag = 1000 then
      my decPage()
      
my dispCurPageDoc()
      
    else if aTag = 1010 then
      my incPage()
      
my dispCurPageDoc()
      
    end if
    
  end clicked:
  
  
on dispCurPageDoc()
    set tmpPage to my (aPDFDoc’s pageAtIndex:(curPageIndex))
    
set tmpDoc to (current application’s PDFDocument’s alloc()’s initWithData:(tmpPage’s dataRepresentation()))
    
aView’s setDocument:tmpDoc
    
    
set tmpStr to ((maxPageNum + 1) as string) & "/" & ((curPageIndex + 1) as string)
    
pLabelField’s setStringValue:tmpStr
  end dispCurPageDoc
  
  
  
on incPage()
    if curPageIndex = maxPageNum then
      –何もしない
    else if curPageIndex < maxPageNum then
      set curPageIndex to curPageIndex + 1
    end if
  end incPage
  
  
on decPage()
    if curPageIndex = 0 then
      –何もしない
    else if curPageIndex > 0 then
      set curPageIndex to curPageIndex – 1
    end if
  end decPage
end script

★Click Here to Open This Script 

Posted in AppleScript Application on Xcode PDF | Tagged 10.13savvy 10.14savvy NSString NSURL PDFDocument PDFPage | 1 Comment

macOS 10.14のバグ? アクセシビリティ認証

Posted on 2月 10, 2019 by Takaaki Naganoya

macOS 10.14.4Betaを使っていて遭遇したトラブルというかバグのような挙動なのですが、「システム環境設定」の「セキュリティーとプライバシー」>「プライバシー」>「アクセシビリティ」の項目。これは、Scripterにはおなじみの「GUI Scriptingの許可」を行う設定項目です。

# 本件については、最新のmacOS 10.14.6+同OSで利用可能な最新のXcode 11.3.1の組み合わせで、後述のように回避できるようになったことを確認しています

ここに、同一名称で異なるバージョン(バージョン番号の大きいもの=新バージョン)のアプリケーションが登録されない、という不具合です。

たとえば、v1.0のappletを登録しておいて、v2.0のappletを登録しようとしても、すでにv1.0が登録されているので追加登録できないし、いったん登録したものを削除できなかったという状況でした。

この問題のどこが困るかといえば、Xcode上でAppleScriptによるアプリケーションを開発していて、その中でGUI Scriptingを利用しているような場合です。Xcode上でAppleScriptアプリケーションをビルドすると、まず最初に動作確認用にdebugビルドを行うことになりますが、これで1つのバイナリができます。テスト実行時にアクセシビリティ認証を取得して、実行。

次いで、実際に単体で実行する(Xcodeのログ表示にlogコマンドによる表示が出ない)Relaseビルドのバイナリをビルドして実行。debugビルドとは別のバイナリができて、実行してみるとOS側からアクセシビリティ認証が許可されず、実行できないという状況でした。いったんこうなると、debugビルドのバイナリのアクセシビリティ認証を解除してもReleaseビルドを登録して認証することもできず、お手上げの状態でした。

以前、macOS 10.10あたりでこの項目で不可解な挙動が見られたことがありましたが、それが復活したような不安定さを感じます。ただ、テスト機はHDDで運用しているため、設定項目の変更がなかなか反映されないといった独特の挙動が発生することもあり、継続調査は必要だと感じていました。まだ、他のユーザーの環境でも同様の問題が発生するか「裏取り」ができていない状況でもありました。

この問題がmacOS 10.14 Beta Relaseの最中に突然発症したので、当時仕事で作成途中のプログラムがGUI Scriptingを一部で利用しており、現状のままでは10.14対応ができないと顧客に報告する必要が出てきました。

本BlogにアクセスしているクライアントのOSバージョンについてWebサーバーのアクセスlogから調査してみたところ、(自分の当時のメイン環境が10.12ということもありますが)10.12が最多。10.9から10.12にほぼ同じぐらいのクライアントが存在しているもようです。鬼っ子10.13や鬼っ子改の10.14については、アクセスlogに形跡が残っていない(Unknown Version?)としか言いようがありません。10.14は多い可能性もあります。

AppleにはmacOS 10.13でバギーなまま使い物にならない状態のOSをリリースしたという「前科」があり、10.14もその延長線上にあるということから、つねに疑問を持って接しています。

# かくして、macOS 10.14が正式リリースされ、開発には利用していましたが、メイン環境は長らく移行しませんでした。macOS 10.14.6が出た段階で再評価を行い、この問題が解決されていたので移行。当時macOS 10.15が出ていたものの、メールが消えるといった致命的な障害報告があったために、移行できない危険なOSだと判断しました。

[追記]2020/3時点での状況

macOS 10.14.x+Xcodeのプロジェクト内でGUI Scriptingを使ったプログラムの認証や開発が行えたなかった件については、Xcode側の対応が改善されたためか、OS側の対処が改善されたためか、現在では解決されています。

OSバージョン:macOS 10.14.6
Xcodeバージョン:11.3.1

この環境で、「File」>「New」>「Project」>「AppleScript App」のプロジェクトを作成し、中で他のアプリケーションをGUI Scripting経由でコントロールする処理を含むプログラムを書いて、アプリケーションとしてビルドし、OS側のセキュリティ機能と折り合いをつけて動作するようにできています。

Xcode Project側で設定すべき点は2つ。

(1)Info.plistに「Privacy – AppleEvents Sending Usage Description」のエントリを作成する(このエントリの内容の文字列が、アプリケーション初回起動時のセキュリティダイアログで表示されます)

(2)Xcode Projectの「TARGETS」でビルドターゲットを選択し、「Signning & Capabilities」>「All」で「Runtime Exceptions」の「Apple Events」にチェックを入れる

これらの設定を行って、Code Signしてあればビルドして実行すると、初回時にOSのセキュリティダイアログが表示され、そののちにGUI Scriptingの認証ダイアログが表示され、認証後、ビルドしたアプリケーションをいったん終了。

再度ビルド&実行するとOS側の「セキュリティ」認証とGUI Scriptingの(アクセシビリティの)認証が通ってアプリケーションの実行ができました。

Posted in AppleScript Application on Xcode Bug GUI Scripting | Leave a comment

セキュリティダイアログに表示するメッセージをローカライズする

Posted on 1月 17, 2019 by Takaaki Naganoya

Xcode上で記述し、他のアプリケーションを操作するAppleScript Cocoaアプリケーションで、セキュリティダイアログに表示する内容(Info.plist内のエントリ)をローカライズする方法について紹介します。

セキュリティダイアログを表示させてユーザーの認証を得る

まず、macOS 10.14, Mojaveではセキュリティ機能が強化され、アプリケーションから他のアプリケーションをAppleEventで操作しようとすると、ユーザーに認証を求めます。この動作は、同一アプリケーションでは初回時のみ行われます。アプリケーションのバージョン・アップ時に再度問い合わされることはありません。

このセキュリティ認証をユーザーに求める動作は、Code Signしてあるアプリケーションであれば初回起動時の初回AppleEvents発行時のみ行われます。最新版のXcode上でアプリケーションを開発する場合にはCode Signできること(=Apple Developper Account年間契約を行っていること)が前提条件となるため、Code Signしない場合については言及しません。

# セキュリティダイアログで「OK」しなかった場合でも、あとからシステム環境設定>セキュリティとプライバシー>プライバシー>オートメーション の項目でチェックを入れれば認証したのと同じことになります。この項目、1年使い続けると項目数がヤバいぐらい増加しそうですが、そのあたりの膨大な数になったときの使い勝手が一切考えられていないバカっぷりが素敵です(項目のしぼりこみぐらいできないとまずい)

そして、ただ漫然とXcode上でAppleScriptアプリケーションのプロジェクトを作成し、AppleScriptアプリケーションを記述しても、実行時にセキュリティダイアログは表示されないという話を昨日書きました。

セキュリティダイアログを表示してユーザーに認証を得るためには、

 (1)Info.plistに「Privacy – AppleEvents Sending Usage Description」(NSAppleEventsUsageDescription)のエントリを作成する必要がある

 (2)AppleScriptアプリケーション内にて、セキュリティダイアログの認証が必要な動作(新規ドキュメントを作成するなど)を、アプリケーション起動中あるいは起動直後のタイミングで行い、セキュリティダイアログでユーザーの認証を得ておく(ことが望ましい)

という状態です。

セキュリティダイアログのメッセージをローカライズする

昨日の段階では、このセキュリティダイアログに表示させる内容がローカライズできないと思っていました。

その後、冗談半分で「Info.plistの内容のローカライズ方法」などと検索エンジンで調べてみたら……さがしてみるもので、すぐに方法が見つかりました。

# 冗談半分で探してみる、というのはけっこう強力なソリューションです

Info.plistの内容のローカライズを行う場合には、InfoPlist.stringsというファイルを作成して、そこに(おなじみの)ローカライズ文字ファイルを、

"key" = "value";

のように記述しておき、InfoPlist.stringsファイルをXcode上でローカライズするのだとか。

Info.plistのエントリのローカライズ

Info.plistに「Privacy – AppleEvents Sending Usage Description」のエントリを作ってある状態から話をすすめます。

このままでは、このエントリのキー名称がよくわからないので、Info.plistをテキスト形式でオープンし直します。

すると、このエントリのキー名称が「NSAppleEventsUsageDescription」だということがわかります。

そこで、Xcodeのプロジェクトに「空のファイル」としてInfoPlist.stringsファイルを追加し、ローカライズします。ここでは、デフォルトで用意されるEnglishのほかにJapaneseを追加しました。

この状態でXcode上でビルド+実行(Command-R)を行うと、

のように、日本語環境にあわせてローカライズしておいたメッセージが表示されることが確認できました。

Posted in AppleScript Application on Xcode | Tagged 10.14savvy | 2 Comments

Xcode 10.1+macOS MojaveでGUIアプリケーションを作成

Posted on 1月 16, 2019 by Takaaki Naganoya

Apple Developper Accountの契約を行い、Xcode上で(他のアプリケーションをコントロールする)AppleScriptアプリケーションを作れるようにしたときに、macOS 10.14+Xcode最新版の10.1だと実際どうなのかをまとめてみました。

Xcode上でこれまでと同様にScriptアプリケーションを記述しただけではダメ

Sandbox対応させると制約事項が増えるため、Sandbox非対応のアプリケーションをビルドしてどこまで行けるかは興味深いところです。

ですが、とりあえず(安全のために)、Code Sign+Sandboxの設定を行ってXcode上でAppleScriptアプリケーションを作成。Keynoteに新規ドキュメントを作成させる程度のお気軽なコードを書き、ビルドして実行。すると、

2019-01-15 99:99:99.999999+0900 1014test[13673:1813575] *** -[AppDelegate applicationWillFinishLaunching:]: Not authorized to send Apple events to Keynote. (error -1743)

などとエラーが出るだけで、AppleScriptからの操作対象アプリケーション(ここではNumbers)は、動かせませんでした。Automationのセキュリティダイアログ自体が表示されない状態です。


▲セキュリティダイアログはこんなやつ

Info.plistにエントリを追加するとSecurityダイアログが表示されるようになる

こういう場合には海外のサイトを調べてみるのが一番手っ取り早いところです。いろいろ調べてみたところ、Info.plistに対して、

Privacy - AppleEvents Sending Usage Description

というエントリを追加する必要があるとのこと。

このInfo.plist上のエントリ、例のMojaveから出るようになったSecurityダイアログにアプリケーション側から出力するカスタムメッセージを定義するエントリのようです。エントリさえ存在すれば、とくに何か気の利いたメッセージを入れる必要はないようです。

英語で書いても、日本語で書いてもそのままダイアログに出力されます。Info.plistの内容自体はローカライズできないので、本エントリの内容は広域に配布するものであれば英語で、特定の日本国内の顧客に向けて納品するものであれば日本語で書けばいいんじゃないでしょうか(一般的なメッセージ同様にローカライズできることが望ましい)。このあたり、ローカライズできないのは仕様的におかしいので、そのうち仕様が変わりそうです、、、、

Securityダイアログを表示させるためには、AppleScriptアプリケーション側から対象のアプリケーションに対して命令を発行する必要があるのですが、これが、activateさせるとかバージョン番号を調べるぐらいのコマンドではそのまま実行されてしまって、セキュリティダイアログは表示されません。

せめて新規ドキュメントを作成(make new document)して破棄(close without saving)するぐらいのことを行わないと、ダメなようです。このあたり、実際に試してみるしかないようです。

■セキュリティダイアログを表示させる程度の意味のない(ウォームアップのための)Scriptサンプル

tell application "Microsoft Excel"
  set aDoc to (make new document)
  
close active workbook without saving
end tell

★Click Here to Open This Script 

tell application "Keynote"
  set aDoc to (make new document)
  
close aDoc without saving
end tell

★Click Here to Open This Script 

tell application "Finder"
  make new Finder window
  
close Finder window 1
end tell

★Click Here to Open This Script 

–Touch Barの有無の検出
on detectTouchBar()
  tell application "System Events"
    set frontApp to first application process whose frontmost is true
    
try
      set touchBar to first UI element of frontApp whose role is "AXFunctionRowTopLevelElement"
    on error errMsg number errNum
      return false
    end try
    
    
set touchBarItems to value of attribute "AXChildren" of touchBar
    
return (touchBarItems is not equal to {})
  end tell
end detectTouchBar

★Click Here to Open This Script 

対象アプリケーションに対してコマンドを実行し、Securityダイアログが表示され、ユーザーによってきちんと認証されれば、tccKitを用いて認証状況を確認して、すべてのアプリケーションの認証完了状態をAppleScriptから知ることができます。

AppleScriptアプリケーションの冒頭(applicationWillFinishLaunchingイベントハンドラなど)でtccKitによって認証状態をチェックし、未認証の状態であれば操作対象のアプリケーションに対して試験的にコマンドを実行するようにすればよいでしょう。

AppleScriptアプリケーションがCode Signされていれば、セキュリティ認証ダイアログでユーザー認証する必要があるのは初回のみです。現在、Xcode上でGUIアプリケーションをビルドするためにはApple Developper Accountが必須となっているため、この点は必然的にクリアされることになります。

なお、この認証フローにおいてアプリケーション自体がSandbox化されている必要はありません(確認ずみ)。

Posted in AppleScript Application on Xcode GUI Security | Tagged 10.14savvy | 2 Comments

Xcode上のAppleScriptObjCでpragma markを使う

Posted on 4月 12, 2018 by Takaaki Naganoya

Xcode上でGUIアプリケーションをAppleScriptObjCで記述できますが、Xcodeの「pragma mark」の機能をAppleScriptで利用する方法についてまとめておきます。

pragma markはXcode上のテキストエディタで現在編集中のソーステキスト内の移動を行いやすくするもので、基本的には「ただのコメント文」です。

Xcodeに編集中のソースの各プロパティやハンドラの一覧を表示するポップアップ・メニューが存在しており、これがソースの長さによっては膨大な量になるため、ポップアップ・メニューに「セパレータ」や「目印(数種類のアイコン指定可能)」をpragma markによって表示させます。長くなるメニューを見やすくする、という役割があります。

pragma markはプログラムの実行には何も影響しません。

Xcode上で編集中のソースコードに「pragma mark」形式のコメントがあると、Xcodeがそれを読み取って、ポップアップ・メニュー上に指定内容を表示します。

ただし、外部エディタ(ASObjC Explorer 4やScript Debugger)を併用しないと、途中からXcodeがまともにpragma markを表示しなくなることは日常茶飯事であることを明記しておきます。

–> Download pragma_mark_test Xcode Project

→ PRAGMA MARKのコメント行の先頭にTABを入れないとまともに表示される模様。

Posted in AppleScript Application on Xcode | Leave a comment

Post navigation

  • Newer posts

電子書籍(PDF)をオンラインストアで販売中!

Google Search

Popular posts

  • 開発機としてM2 Mac miniが来たのでガチレビュー
  • macOS 15, Sequoia
  • 指定のWordファイルをPDFに書き出す
  • Pages本執筆中に、2つの書類モード切り替えに気がついた
  • Numbersで選択範囲のセルの前後の空白を削除
  • メキシカンハットの描画
  • Pixelmator Pro v3.6.4でAppleScriptからの操作時の挙動に違和感が
  • AdobeがInDesign v19.4からPOSIX pathを採用
  • AppleScriptによる並列処理
  • Safariで「プロファイル」機能を使うとAppleScriptの処理に影響
  • Cocoa Scripting Course 続刊計画
  • macOS 14.xでScript Menuの実行速度が大幅に下がるバグ
  • AppleScript入門③AppleScriptを使った「自動化」とは?
  • macOS 15でも変化したText to Speech環境
  • Keynote/Pagesで選択中の表カラムの幅を均等割
  • デフォルトインストールされたフォント名を取得するAppleScript
  • macOS 15 リモートApple Eventsにバグ?
  • AppleScript入門① AppleScriptってなんだろう?
  • macOS 14で変更になったOSバージョン取得APIの返り値
  • Keynoteで2階層のスライドのタイトルをまとめてテキスト化

Tags

10.11savvy (1101) 10.12savvy (1242) 10.13savvy (1391) 10.14savvy (587) 10.15savvy (438) 11.0savvy (283) 12.0savvy (212) 13.0savvy (194) 14.0savvy (147) 15.0savvy (132) CotEditor (66) Finder (51) iTunes (19) Keynote (117) NSAlert (61) NSArray (51) NSBitmapImageRep (20) NSBundle (20) NSButton (34) NSColor (53) NSDictionary (28) NSFileManager (23) NSFont (21) NSImage (41) NSJSONSerialization (21) NSMutableArray (63) NSMutableDictionary (22) NSPredicate (36) NSRunningApplication (56) NSScreen (30) NSScrollView (22) NSString (119) NSURL (98) NSURLRequest (23) NSUTF8StringEncoding (30) NSView (33) NSWorkspace (20) Numbers (76) Pages (55) Safari (44) Script Editor (27) WKUserContentController (21) WKUserScript (20) WKWebView (23) WKWebViewConfiguration (22)

カテゴリー

  • 2D Bin Packing
  • 3D
  • AirDrop
  • AirPlay
  • Animation
  • AppleScript Application on Xcode
  • Beginner
  • Benchmark
  • beta
  • Bluetooth
  • Books
  • boolean
  • bounds
  • Bug
  • Calendar
  • call by reference
  • check sum
  • Clipboard
  • Cocoa-AppleScript Applet
  • Code Sign
  • Color
  • Custom Class
  • date
  • dialog
  • diff
  • drive
  • Droplet
  • exif
  • file
  • File path
  • filter
  • folder
  • Font
  • Font
  • GAME
  • geolocation
  • GUI
  • GUI Scripting
  • Hex
  • History
  • How To
  • iCloud
  • Icon
  • Image
  • Input Method
  • Internet
  • iOS App
  • JavaScript
  • JSON
  • JXA
  • Keychain
  • Keychain
  • Language
  • Library
  • list
  • Locale
  • Localize
  • Machine Learning
  • Map
  • Markdown
  • Menu
  • Metadata
  • MIDI
  • MIME
  • Natural Language Processing
  • Network
  • news
  • Noification
  • Notarization
  • Number
  • Object control
  • OCR
  • OSA
  • parallel processing
  • PDF
  • Peripheral
  • PRODUCTS
  • QR Code
  • Raw AppleEvent Code
  • Record
  • rectangle
  • recursive call
  • regexp
  • Release
  • Remote Control
  • Require Control-Command-R to run
  • REST API
  • Review
  • RTF
  • Sandbox
  • Screen Saver
  • Script Libraries
  • sdef
  • search
  • Security
  • selection
  • shell script
  • Shortcuts Workflow
  • Sort
  • Sound
  • Spellchecker
  • Spotlight
  • SVG
  • System
  • Tag
  • Telephony
  • Text
  • Text to Speech
  • timezone
  • Tools
  • Update
  • URL
  • UTI
  • Web Contents Control
  • WiFi
  • XML
  • XML-RPC
  • イベント(Event)
  • 未分類

アーカイブ

  • 2025年5月
  • 2025年4月
  • 2025年3月
  • 2025年2月
  • 2025年1月
  • 2024年12月
  • 2024年11月
  • 2024年10月
  • 2024年9月
  • 2024年8月
  • 2024年7月
  • 2024年6月
  • 2024年5月
  • 2024年4月
  • 2024年3月
  • 2024年2月
  • 2024年1月
  • 2023年12月
  • 2023年11月
  • 2023年10月
  • 2023年9月
  • 2023年8月
  • 2023年7月
  • 2023年6月
  • 2023年5月
  • 2023年4月
  • 2023年3月
  • 2023年2月
  • 2023年1月
  • 2022年12月
  • 2022年11月
  • 2022年10月
  • 2022年9月
  • 2022年8月
  • 2022年7月
  • 2022年6月
  • 2022年5月
  • 2022年4月
  • 2022年3月
  • 2022年2月
  • 2022年1月
  • 2021年12月
  • 2021年11月
  • 2021年10月
  • 2021年9月
  • 2021年8月
  • 2021年7月
  • 2021年6月
  • 2021年5月
  • 2021年4月
  • 2021年3月
  • 2021年2月
  • 2021年1月
  • 2020年12月
  • 2020年11月
  • 2020年10月
  • 2020年9月
  • 2020年8月
  • 2020年7月
  • 2020年6月
  • 2020年5月
  • 2020年4月
  • 2020年3月
  • 2020年2月
  • 2020年1月
  • 2019年12月
  • 2019年11月
  • 2019年10月
  • 2019年9月
  • 2019年8月
  • 2019年7月
  • 2019年6月
  • 2019年5月
  • 2019年4月
  • 2019年3月
  • 2019年2月
  • 2019年1月
  • 2018年12月
  • 2018年11月
  • 2018年10月
  • 2018年9月
  • 2018年8月
  • 2018年7月
  • 2018年6月
  • 2018年5月
  • 2018年4月
  • 2018年3月
  • 2018年2月

https://piyomarusoft.booth.pm/items/301502

メタ情報

  • ログイン
  • 投稿フィード
  • コメントフィード
  • WordPress.org

Forum Posts

  • 人気のトピック
  • 返信がないトピック

メタ情報

  • ログイン
  • 投稿フィード
  • コメントフィード
  • WordPress.org
Proudly powered by WordPress
Theme: Flint by Star Verte LLC