LoginSignup
8
6

More than 5 years have passed since last update.

コンソールアプリケーションとしても振る舞えるXamarin.Macアプリケーションの作り方

Last updated at Posted at 2017-12-14

Problem

GUIアプリケーションとして通常のフローで立ち上げることができる。
しかしターミナルなどから引数を与えて立ち上げたときはそのまま標準出力に結果を返して終了する。
そういうことをmacOSアプリでやりたくなったときに参考にしてください。
方法論としてXamarin特有というわけではありませんが,ここではXamarin.Macを使って解説します。

TL;DR

エントリポイント Main.cs で分岐します。

Prerequisites

  • Visual Studio for Mac Version 7.3 (build 799)
  • Xamarin.Mac 4.0.0.214

ここで作ったサンプルは GitHub:xamarin-mac-console-sample に公開してあります。

Solution

プロジェクトを作る

Xamarin.Macプロジェクトを適当に作ります。詳しい手順は割愛しますが,ウィンドウが立ち上がるようにしておいてください。
Screen Shot 2017-12-14 at 15.14.41.png

Main.csで引数をパースする

Main.cs はたいてい次のようになっているはずです。

Main.cs
using AppKit;

namespace ConsoleSample
{
    static class MainClass
    {
        static void Main(string[] args)
        {
            NSApplication.Init();
            NSApplication.Main(args);
        }
    }
}

NSApplication.Init を呼ぶと,NSNotificationCenter.DefaultCenterやら,NSFileManager.DefaultManagerなどNS*系の静的インスタンスが確保され使えるようになります。つまり呼ばないとNS*系のなにがしかは使えたり使えなかったりします。だいたい使えません。

NSApplication.Main を呼ぶとアプリケーションの起動シーケンスに入り,AppDelegateへ制御が移っていきます。その前に引数をパースして処理を分岐するのが本稿の目的とするところです。ということで適当にコマンドラインパーサーをNuGet経由で入れるなり,自前でパースするなりしましょう。ここではdotnet-corefxlabリポジトリで提供されているSystem.CommandLineを使います。雑ですがおおよそ次のようになるでしょう。

Main.cs
using System;
using System.CommandLine;
using AppKit;

namespace ConsoleSample
{
    static class MainClass
    {
        static void Main(string[] args)
        {
            var input = string.Empty;

            ArgumentSyntax.Parse(args, syntax =>
            {
                syntax.DefineOption("i|input", ref input, true, "Something interesting.");

                syntax.ErrorOnUnexpectedArguments = false;
            });

            if (string.IsNullOrEmpty(input))
            {
                NSApplication.Init();
                NSApplication.Main(args);
            }
            else
            {
                Console.WriteLine($"{input.Length} - {input}");
            }
        }
    }
}

プロジェクトの設定から引数を指定してデバッグする,ターミナルから引数を与えて起動するなどで動作を確認できます。ターミナルから起動したい場合は app/Contents/MacOS/ にエントリポイントがあります。
Screen Shot 2017-12-14 at 15.27.56.png
Screen Shot 2017-12-14 at 15.28.16.png

% ./ConsoleSample.app/Contents/MacOS/ConsoleSample -i Hello
5 - Hello

当然ながら,何も引数を与えなければウィンドウが立ち上がり,通常のアプリとして振る舞います。

Conclusion

Main.cs で起動前になんでもできることがわかりました。
ネイティブライブラリを読み込んでおいたり集約例外ハンドラを設置したりと,それなりのアプリケーションを作る際にはこの辺でいろいろ介入が必要になってくると思います。ぜひ覚えておいてください。

8
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6