VB のたまご

作成日: 2017/08/15, 更新日: 2017/08/15


.NET Core 用ソリューション構成でのプロジェクト作成ツール

  •  プロジェクトのテンプレートを生成してくれる「dotnet new」コマンドですが、ソリューション構成ではなく、 1プロジェクト単位での生成なんですよね。

  •  例えば、コンソールアプリケーションを作成したい時「dotnet new」コマンドで作るとこういう構成になります。
  • ConsoleApplication1
     + Program.vb
     + ConsoleApplication1.vbproj
    

  •  そうではなくて、Windows の Visual Studio と同じように、ソリューションに含んだプロジェクトという構成で作ってほしいんです!
  • ConsoleApplication1             ★←ここと
     + ConsoleApplication1.sln    ★←ここなの
     + ConsoleApplication1
         + Program.vb
         + ConsoleApplication1.vbproj
    

  •  ということで、自作ツールを作成しました。「dotnetsln」というコマンドです。 実体はコンソールアプリケーションで、「dotnet publish」したものですが、 exe 単体(Linux では実行ファイルは「.exe」が付かないものが多い)では動きませんでした(´Д⊂ヽ。

  •  どうやら、「dotnet xxx.dll」で動かす場合は、同じ場所にある json ファイルも必要で、 「dotnet pulish」で作成した実行ファイルを動かす場合は、json ファイルの他に、so ファイルと publish フォルダも同じ場所に無いと動かないみたい?です。

  •  わざわざ環境変数に実行ファイルのパスを通すほどのものでも無いから、作りたいフォルダに実行ファイルをポイっと置いて、 ソース生成できれば楽でいいなぁという運用は、ボツとなりました。

  •  それでは、毎回毎回フォルダ毎コピペして使うの?というと、そんな面倒くさいことはしたくありません。 ここは、シンボリックリンク(ショートカットファイルみたいなやつ)を作成して、それ経由で実行する運用にて落ち着きました。

  • ・環境
  • ・Ubuntu 17.04
  • ・.NET Core 2 Preview 2
  • ・Visual Studio Code 1.15.0

  •  参考
  • dobon.net
    カレントディレクトリ(現在の作業ディレクトリ)を取得、設定する
    https://dobon.net/vb/dotnet/file/currentdirectory.html
    
    dobon.net
    DOSコマンドを実行し出力データを取得する
    https://dobon.net/vb/dotnet/process/standardoutput.html
    
    Qiita
    [.NET Core].NET Coreで実行ファイルを作成する
    http://qiita.com/yaegaki/items/bdf529f07552d72bc6e5
    
    パンジェンシーの「汗だく開発日誌」
    【Ubuntu】フォルダへのショートカット「シンボリックリンク」の作成
    http://pangency.hatenablog.com/entry/2015/06/22/115725
    


準備

  •  コマンド(という名のコンソールアプリケーション)を作成して、実行ファイルの発行までを完成させます。 そしたら、シンボリックリンクを作成します。 後は、シンボリックリンクを任意のフォルダに移動しては、コマンドを実行して、ソリューション構成付きプロジェクトを作成します。

  •  つまり、コマンド用に作成したソースは、消さないでその場所にずっと置いておいてね。という縛りがあります。 シンボリックリンクのリンク先が変更されると、動かなくなっちゃうからですね。

  •  それでは、まずは自作コマンドを作成してみましょう!
  • $ dotnet new Console -o dotnetsln -lang VB
    $ cd dotnetsln/
    $ gedit dotnetsln.vbproj
    

  •  例えば、私の場合は Ubuntu 上で動作させたいため、RuntimeIdentifiers タグに Ubuntuを指定しています。 この設定は「dotnet publish」の時に使うやつです。

  •  dotnetsln.vbproj
  • <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>netcoreapp2.0</TargetFramework>
        <RuntimeIdentifiers>ubuntu.16.10-x64</RuntimeIdentifiers>
      </PropertyGroup>
    
    </Project>
    

    $ code .
    

  •  Program.vb
  • Imports System
    
    Module Program
    
        Sub Main(args As String())
    
            If args.Count = 0 Then
                Console.WriteLine("This is a dotnet Command Extension Program.")
                Console.WriteLine("If you want to create Console or ClassLib, then create with solution structures.")
                Console.WriteLine("")
                Console.WriteLine("usage.")
                Console.WriteLine("./dotnetsln (Console|ClassLib) (-o|--output) <Project-Name> (-lang|--language) <Language-Name>")
                Console.WriteLine("")
                Console.WriteLine("[-lang] is optional argument. default is C#.")
                Console.WriteLine("select one of C#/F#/VB")
                Console.WriteLine("")
                Console.WriteLine("")
                Console.WriteLine("Example.")
                Console.WriteLine("$ ./dotnetsln Console -o ConsoleApplication1")
                Console.WriteLine("")
                Console.WriteLine("Created directory tree here.")
                Console.WriteLine("ConsoleApplication1")
                Console.WriteLine(" + ConsoleApplication1.sln")
                Console.WriteLine(" + ConsoleApplication1")
                Console.WriteLine("    + ConsoleApplication1.csproj")
                Console.WriteLine("    + Program.cs")
                Console.WriteLine("")
                Exit Sub
            End If
    
            If args(0).ToLower() <> "console" AndAlso args(0).ToLower() <> "classlib" Then
                Console.WriteLine("Sorry, dotnetsln is only support [Console or ClassLib] option.")
                Exit Sub
            End If
    
            Dim projectType = args(0)
            Dim projectName = String.Empty
            Dim language = "C#"
    
            For i As Integer = 1 To args.Count - 1
    
                Select Case args(i)
    
                    Case "-o", "--output"
                        i = i + 1
                        projectName = args(i)
                        Continue For
    
                    Case "-lang", "--language"
                        i = i + 1
                        language = args(i)
                        Continue For
    
                End Select
    
            Next
    
            If projectName = String.Empty Then
                Console.WriteLine("Error, no input Project-Name. See -o option.")
                Exit Sub
            End If
    
            Try
    
                Work(projectType, projectName, language)
                Console.WriteLine("create succeeded.")
                Console.WriteLine()
    
            Catch ex As Exception
                Console.WriteLine(ex.ToString())
                Console.WriteLine()
            End Try
    
        End Sub
    
        Private Sub Work(projectType As String, projectName As String, language As String)
    
            'ソリューションを入れるフォルダを作成して、projectName フォルダに入る
            ' [cd projectName] が動かなかった
            DoCommand("mkdir", projectName)
            Environment.CurrentDirectory = $"./{projectName}/"
    
            ' プロジェクトの作成
            ' dotnet new projectType --output projectName
            DoCommand("dotnet", $"new {projectType} --output {projectName} --language {language}")
    
            ' ソリューションファイルの作成
            ' dotnet new sln
            DoCommand("dotnet", "new sln")
    
            ' ソリューションファイルにプロジェクトを登録
            Select Case language.ToLower()
    
                Case "c#"
                    DoCommand("dotnet", $"sln add {projectName}/{projectName}.csproj")
    
                Case "f#"
                    DoCommand("dotnet", $"sln add {projectName}/{projectName}.fsproj")
    
                Case "vb"
                    DoCommand("dotnet", $"sln add {projectName}/{projectName}.vbproj")
    
            End Select
    
            '最初のディレクトリに戻る
            Environment.CurrentDirectory = $"../"
    
        End Sub
    
        Private Sub DoCommand(commandName As String, arguments As String)
    
            Dim p = New Process
            p.StartInfo.FileName = commandName
            p.StartInfo.Arguments = arguments
            p.Start()
            p.WaitForExit()
    
        End Sub
    
    End Module
    

  •  構成(launch.json)とタスクランナー(tasks.json)は両方とも「.NET Core」を指定します。 launch.json のパス記載部分は、テンプレートから実際の実行ファイルパスに書き換えます。
  • "program": "${workspaceRoot}/bin/Debug/netcoreapp2.0/dotnetsln.dll",
    

  •  また、tasks.json の Command キーの値を「dotnet build」に変更します。
  • "command": "dotnet build",
    

  •  デバッグ実行して、ビルドが通ることを確認します。

  •  VSCode は閉じて、プログラムを発行します。
  • $ dotnet restore
    $ dotnet publish -c Release -r ubuntu.16.10-x64
    

  •  出力先のパスを覚えておきます。
  •  プロジェクトフォルダ/bin/Release/netcoreapp2.0/ubuntu.16.10-x64/dotnetsln です。

  •  よく分からない場合は、~省略~/ubuntu.16.10-x64/ までディレクトリを移動して来て、 以下のコマンドを実行して、表示されたパスを覚えておきます。
  • $ pwd
    

  •  シンボリックリンクを作成します。
  •  例えばホームディレクトリに作成する場合は以下を入力します。
  • $ cd ~
    $ ln -s プロジェクトフォルダ/bin/Release/netcoreapp2.0/ubuntu.16.10-x64/dotnetsln dotnetsln
    


使い方

  •  あらかじめ、ソリューションプログラムを作成しようとしているディレクトリに、先程作成したシンボリックリンクを置いておきます。 その後、以下のコマンドを入力します。
  • $ ./dotnetsln Console -o ConsoleApplication1 -lang VB
    

  •  プログラム一式が生成されたら完成です!やった!


まとめ

  •  VB.NET でのコマンド操作とかディレクトリ移動を調べたり、シンボリックリンクを調べたり、今回は事前調査が多めでしたが、 なんとか形にすることができました。

  •  ただ重い腰を上げるのがちょっと大変でした。 現状はこうなっているのか → こうできれば良いのに → そういう機能は無いのか → じゃあ作るか! → あでも面倒くさい(;´Д`)、Linux よく知らないし、っていう思考の重りが肩に乗っかってしまいましたorz。

  •  作り始めたらサクサク進めたんですけどね。入口にたどり着くまでに時間がかかるんですよね~。まぁどうでもいい話でした。 最後まで記事を読んでいただき、ありがとうございました。