インスタンスが既に実行されているかどうかを Swift アプリで検出しようとしています。実行されている場合は、ユーザーが別のインスタンスを起動しないようにします。このような動作を検出するために NSRunningApplication クラスを使用していますが、正しく動作させるのに問題があります。私はいくつかの古い投稿を読み、 flock() がそれを検出するための低レベルの方法であることを知っていますが、可能であれば「Swiftの方法で行う」ことを好みます。コードのスニペットを次に示します。
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Check if app has already been launched. If so, alert user and terminate the new session
let bundleID = Bundle.main.bundleIdentifier!
if NSRunningApplication.runningApplications(withBundleIdentifier: bundleID).count > 1 {
// warn and terminate
NSApp.terminate(nil)
}
// keep going and finish launching the app
...
}
開こうとしているセッションの数に関係なく、返されるカウントの値は常に 1 のようです。何がうまくいかないのか、またはこのチェックを適切な場所で呼び出していませんか?
さらに、私のアプリでは、ユーザーが定義済みのファイル拡張子を持つファイルをダブルクリックしてアプリを起動することもできます。上記を機能させることができれば、このシナリオでも機能するはずだと思いますか?
アップデート:
アクティビティ モニターを使用してアプリの起動動作を確認した後、観察された動作の原因を特定できたと思います。
完全な開示、私のアプリはコンソールアプリを起動する新しいプロセスを作成し、このプロセスが完了して終了するまで待機します。以下の更新されたコード スニペット:
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Check if app has already been launched. If so, alert user and terminate the new session
let bundleID = Bundle.main.bundleIdentifier!
let num_instances = NSRunningApplication.runningApplications(withBundleIdentifier: bundleID).count
// Debug dialog box to see instances count
let alert = NSAlert()
alert.messageText = "msg"
alert.informativeText = "num instances running: \(num_instances)"
alert.alertStyle = NSAlert.Style.critical
alert.addButton(withTitle: "OK")
alert.runModal()
if num_instances > 1 {
// warn and terminate
NSApp.terminate(nil)
}
// keep going and finish launching the app
let task = Process()
task.launchPath = "myConsoleApp"
task.launch()
task.waitUntilExit()
let status = task.terminationStatus
if status == 0 {
// Done with the console app, exit
...
} else {
// something's wrong; report to user
...
}
}
これで、アプリが最初に起動されると、最初に mySwiftApp と myConsoleApp という 2 つのプロセスが作成されます。ただし、デバッグ ダイアログ ボックスがあると、myConsoleApp の起動後に mySwiftApp プロセスが終了します。その結果、mySwiftApp のインスタンス数は 0 になりました。したがって、mySwiftApp のその後の起動は成功し、システム上で 2 つの myConsoleApp プロセスが実行されます。アラート ボックスの存在によって mySwiftApp プロセスが終了する理由は明確ではありませんが、アプリに終了信号が送信され、終了ステータスが変更されると思われます。
デバッグ ダイアログ ボックスが表示されない場合は、waitUnitlExit() のセットアップが原因で、2 番目のインスタンスを起動しようとしても表示されず、実質的に失敗に終わります。2 番目のインスタンスを起動できないため、これは「望ましい」動作ですが、ユーザーに通知する方法があると便利です。
そうするための最良の方法は何ですか?