C#でbash上で動く(具体的にはMacやUbuntuで動く)コマンドラインツールが書きたい!そんな動機から最近.NET Core3.0周りを調べております.
前回の記事:.NET Core3.0でPublishSingleFile
前回の検証で,.NET Core3.0を使えば単独の実行ファイルが作れることがわかり,しめしめとコーディングを始めたわけですが,設定ファイルを作ったところで大きな落とし穴が・・・・
私はいつもC#でコーディングするときに,以下のコードで実行ファイルのディレクトリパスを取得しています
using System.IO;
using System.Reflection;
Directory.GetParentPath(Assembly.GetExecutingAssenbly().Location);
Windowsではうまく行くものの,Linuxではうまく行かない!何故かtmpディレクトリが指定される!?となりました1.これでは話にならないと,Environment.CommandLineも試したけどこちらもtmpディレクトリ配下.これは困った.これでは設定ファイルからの読み込みなんかできたもんじゃない.
そういうわけで,とりあえずじゃぁどこまで環境情報が取得できるのか,やってみることにしました.実行は以下のコードで.えぇ,全部手書き.とってもダルい.誰かクラスのメンバを全部表示するライブラリとか作ってくれないかなぁ.ありそうなもんだけど.
using System;
namespace ConsoleApp1 {
class Program {
static void Main(string[] args) {
Console.WriteLine($"CommandLine: {Environment.CommandLine}");
Console.WriteLine($"CurrentDirectory: {Environment.CurrentDirectory}");
Console.WriteLine($"CurrentManagedThreadId: {Environment.CurrentManagedThreadId}");
Console.WriteLine($"ExitCode: {Environment.ExitCode}");
Console.WriteLine($"HasShutdownStarted: {Environment.HasShutdownStarted}");
Console.WriteLine($"Is64BitOperationSystem: {Environment.Is64BitOperatingSystem}");
Console.WriteLine($"Is64BitProcess: {Environment.Is64BitProcess}");
Console.WriteLine($"MachineName: {Environment.MachineName}");
Console.WriteLine($"NewLine: {Environment.NewLine}");
Console.WriteLine($"OSVersion: {Environment.OSVersion}");
Console.WriteLine($"ProcessorCount: {Environment.ProcessorCount}");
Console.WriteLine($"StackTrace: {Environment.StackTrace}");
Console.WriteLine($"SystemDirectory: {Environment.SystemDirectory}");
Console.WriteLine($"SystemPageSize: {Environment.SystemPageSize}");
Console.WriteLine($"UserDomainName: {Environment.UserDomainName}");
Console.WriteLine($"UserInteractive: {Environment.UserInteractive}");
Console.WriteLine($"UserName: {Environment.UserName}");
Console.WriteLine($"Version: {Environment.Version}");
Console.WriteLine($"WorkingSet: {Environment.WorkingSet}");
}
}
}
で,とりあえずWindows側で動作検証
CommandLine: A:\ConsoleApp1\ConsoleApp1\bin\Debug\netcoreapp3.0\win10-x64\ConsoleApp1.dll
CurrentDirectory: A:\ConsoleApp1\ConsoleApp1\bin\Debug\netcoreapp3.0\win10-x64
CurrentManagedThreadId: 1
ExitCode: 0
HasShutdownStarted: False
Is64BitOperationSystem: True
Is64BitProcess: True
MachineName: *******
NewLine:
OSVersion: Microsoft Windows NT 6.2.9200.0
ProcessorCount: 16
StackTrace: at System.Environment.get_StackTrace()
at ConsoleApp1.Program.Main(String[] args) in A:\ConsoleApp1\ConsoleApp1\Program.cs:line 17
SystemDirectory: C:\Windows\system32
SystemPageSize: 4096
UserDomainName: *******
UserInteractive: True
UserName: *******
Version: 3.0.0
WorkingSet: 21168128
まぁそうなるよね.って感じ.NewLineの所は改行されてんじゃねぇかよってなりますが,実際問題改行をしたい時以外使われないので,むしろ改行されているという事実が大事なわけでそのまま放っておいてあります.
じゃぁつぎは問題のLinux側.今回もUbuntu18.04 on Win10でWSL上での検証です.
CommandLine: /var/tmp/.net/ConsoleApp1/oljoqwbr.lyi/ConsoleApp1.dll
CurrentDirectory: /home/*******
CurrentManagedThreadId: 1
ExitCode: 0
HasShutdownStarted: False
Is64BitOperationSystem: True
Is64BitProcess: True
MachineName: *******
NewLine:
OSVersion: Unix 4.4.0.18362
ProcessorCount: 16
StackTrace: at System.Environment.get_StackTrace()
at ConsoleApp1.Program.Main(String[] args)
SystemDirectory:
SystemPageSize: 4096
UserDomainName: *******
UserInteractive: True
UserName: ******
Version: 3.0.0
WorkingSet: 20955136
なるほどなるほど.
ってなってた所で気付きました.2行目に.
/home/******* って書いてあるやないかい(/home/*******配下で実行した)
と言うわけで,今回全然意図しなかったところから欲しい答えが見つかりました.これで心置きなくPublishSingleFileを使いながら設定ファイルに書き出せる・・・
(2019/6/21追記 後で気がつきましたが,CurrentDirectoryを叩くとショートカットやエイリアス経由で起動した場合にディレクトリが変わってしまうことに気がつきました・・・どうすりゃええねん)
-
PublishSingleFileで単独の実行ファイルを生成した場合,ランタイムがtmp以下に展開され,その中でプログラムが実行される仕組みのようです.そのため,Assemblyの位置がtmp以下を指し示すようです. ↩