初めてのC# 備忘録
Back
Alt+HOME
最近言語に関する興味が結構あきらめ悪く続く。以前から気にはなっていたC#を試してみたくなっておもむろに始めてしまった。
先日までPythonでTLMForwarderを1.0.16までアップしてきたが、何か違う言語でないと無理なのかと言う局面に立ち至った。GUIであるという点が重荷なのかも知れない。(とにかく初めてだったので)どうせ初めてついでにと、全く同じ仕様のアプリをC#で作ってみることにした。
これで結果OKという、備忘録として逐次追加していきます。何の脈略も有りません。
Visual Basic 6の後、2010年前後に一時期 Visual Basic 2008/2010をかじった事が有って、何か?懐かしい感じがする。
当時重~く感じたIDEもSSDのお陰も有ってか快適。馴染むまで暫くやってみよう!!
FormMainの立ち上げ時に、設定値をFormConfigに書き込む
public partial class FormMain : Form
{
private readonly string filePath = @"Config.ini";
private readonly FormConfig formConfig = new(); // ここでインスタンスだけ作って表示はしない
public FormMain()
{
InitializeComponent();
}
private void FormMain_Load(object sender, EventArgs e) // メインフォームのロードイベント
{
/* 設定ファイルよりデータを読みConfigフォームに表示する関数呼び出し */
ReadSettingsFromfile();
}
private void ReadSettingsFromfile()
{
// ファイルが存在するか確認
if (File.Exists(filePath))
{
// ファイルからすべての行を読み込む
string[] lines = File.ReadAllLines(filePath); // 設定ファイルからの行データを取得
//各行を処理する
foreach (string line in lines)
{
// セパレータ'='で分割
string[] parts = line.Split('=');
if (parts.Length == 2)
{
//項目名をテキストボックス名として取得
string textBoxName = parts[0].Trim(); // keyとテキストボックス名を同じにしてある
string textBoxText = parts[1].Trim(); // セパレータ'='の左と右
// インスタンスの対応するテキストボックスに設定値を代入
if (formConfig.Controls.ContainsKey(textBoxName))
{
TextBox textBox = (TextBox)frmSettings.Controls[textBoxName];
textBox.Text = textBoxText;
}
}
}
}
}
/* 設定パネルを表示(データはメインフォーム立ち上げ時代入済み */
private void BtnConfig_Click(object sender, EventArgs e)
{
formConfig.ShowDialog(); // インスタンスの表示のみ
}
別フォームのインスタンスをクラス宣言の直下で定義しておくことで、そのフォームを立ち上げずとも、有るべきコントロールを利用することが出来る。
つまり、そのインスタンスに属するテキストボックスにテキストを保存したり、string str = formConfig.Name.Text; のようにして保存しているデータを読み出すことが出来る。
複数のテキストボックスが Typedefのように使えることになる。
もちろん、ボタンイベントでも新たにインスタンスは定義せず単に ShowDialog() するだけですでに記載済みの設定ページが開く。
Pythonのprint,Cのprintfのようにデバッグ出力したい
// satと言う配列の中身を item として一つずつ、IDEの出力に表示する。
foreach (string item in sat)
{
Debug.WriteLine(item);
}
[
ツール] → [
オプション] → [
デバッグ] → [
全般]で、「
出力ウィンドウの文字をすべてイミディエイトウィンドウにリダイレクトする」
にチェックしていると余分な出力が省かれて見易い。
リストを使い回すには慣れるまでグローバルにするのが簡単
public partial class FrmMain : Form
{
private readonly List MyList = new(); // グローバルスコープでのリスト宣言
private void MakeMyList()
{
// リストするデータitemの抽出・構成などの処理
MyList.Add(item);
}
// 一例としてComboBoxのクリックイベントで利用
private void ComboBox_SelectionIndexChanged(object sender, EventArgs e)
{
foreach (string[] line in MyList)
{
if (line[0] == ComboBox.Text)
{
Label.Text = line[1];
}
}
}
}
private List
MakeMyList()のように関数内でリストの宣言・作成をして、return MyList で他の関数に渡すのが推奨されているが、
グローバルを多用せず、コードの可読性を損なわなければ理解しやすい。
C#で作ったDLLを動的に切り替えて、選択した衛星毎に処理を変える
/* DLLファイルのパスを作成 */
string dllFilePath = "./dll/" + LblNoradID.Text + ".dll"; // カレントディレクトリー/dll/53106.dll
/* dllが供給されているかチェック */
if (File.Exists(dllFilePath))
{
/* DLLをロードする */
Assembly assembly = Assembly.LoadFrom(dllFilePath);
/* 利用するクラスの完全修飾名(名前空間を含む"namespace.class")を指定 */
string className = "_53106._53106";
/* クラスのTypeを取得する */
Type classType = assembly.GetType(className);
/* クラスのインスタンスを生成する */
object classInstance = Activator.CreateInstance(classType);
/* メソッドの名前を指定して呼び出す */
MethodInfo method = classType.GetMethod("ReceiveDataFormat");
method.Invoke(classInstance, null);
}
else
{ /* ファイルが無い旨を知らせる */
MessageBox.Show("Not exists " + dllFilePath + " for " + CmbSatName.Text);
}
アプリケーション運用ログの作成
using Serilog;
public static void CreateLogFile()
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information() // Information以上に重要なもののみ
.MinimumLevel.Override("Microsoft", Serilog.Events.LogEventLevel.Warning) // MicrosoftからのWarning以上も
.Enrich.FromLogContext()
.WriteTo.File(
@".\\syslog\\TLMForwarder-.log",
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}",
rollingInterval: RollingInterval.Day,
retainedFileCountLimit: 10
)
.CreateLogger(); // 上記設定でLoggerインスタンスを作成
try
{
Log.Information("Starting Application and Logger...");
}
catch (Exception ex)
{
Log.Fatal(ex, "The Application has closed.");
}
// 終了時には必ず Log.CloseAndFlush(); を実行する (quitボタンなど)
}
/*-------------------------------------------------------------------------------------*/
using Serilog;
praivate void SomeThing()
{
// 何らかの処理関数
Log.Information("処理に関する情報・結果など");
Log.Warning("注意など");
Log.Error("エラーメッセージ");
Log.Debug("デバッグに必要なコメントなど");
}
JSONファイルで設定の別ファイル化や複数のログファイルに対応できる。
その他のファイル作成とネーミング
private readonly FrmSettings frmSettings = new();
string directory = frmSettings.TxtDirectory.Text;
try
{
char lastChar = directory[^1];
if (lastChar != '\\') // D:\sample\data のように最後が \ でない
{
directory += "\\"; // D:\sample\data\ にする
}
}
catch (IndexOutOfRangeException)
{
MessageBox.Show("Settingsでフォルダを指定してください。");
return;
}
/* フォルダが存在しない時は作成する */
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
/* ファイル名を作成する */
string timeStamp = DateTime.UtcNow.ToString("s").Replace(":", ""); // UTCを使用している
string fileName = "ファイル名" + "_" + timeStamp + "_" + ".txt"; // filename_2023-09-22T003032.txt
string filePath = Path.Combine(directory, fileName); // D:\sample\data\filename_2023-09-22T003032.txt
/* ファイルパスを使ってファイルを作成 */
File.Create(filePath).Close(); // この時フォルダが存在しない場合フォルダも作成する。
なお、ToString("s").Replace(":", "") の意味は "s" で 2023-09-22T00:30:32 となり ':' が挿入される。
これはファイル名として使えない文字でなので .Replace(":", "") で ':' を取り除いている。
フォルダ内の特定ファイルを削除
/* 特定フォルダ内の空のファイルが有れ削除する */
string[] files = Directory.GetFiles(directory);
foreach (string file in files)
{
FileInfo fileInfo = new(file);
if (fileInfo.Length == 0) // サイズゼロの空ファイル
{
File.Delete(file);
}
}
/* フォルダ内にサブフォルダがある場合 */
string[] files = Directory.GetFiles(directory, "*", SearchOption.AllDirectories);
Back
Alt+HOME

この 作品 は
クリエイティブ・コモンズ 表示 - 非営利 - 改変禁止 4.0 国際 ライセンス
の下に提供されています。
English
Powered by