20200222のC#に関する記事は8件です。

KeyVault のシークレット情報をマネージドIDを利用して取得する

どうしてこんなにわかりにくいのだろうか。。
ここを見たけどうまくいかず
https://docs.microsoft.com/ja-jp/azure/key-vault/tutorial-net-create-vault-azure-web-app

これに挑戦してようやく
https://news.mynavi.jp/article/zeroazure-23/

はじめに

KeyVaultにServiceBusの接続情報をシークレットという形式で格納することで、Functionsにハードコーディングせずに済むという話。KeyVaultにFunctionsがシークレット情報ください、と問い合わせるわけだが、当然誰彼構わずわたすわけではなく。特定の認証された人にだけ渡すようになっている。これがマネージドID。

大まかな流れ

1.KeyVault(キーコンテナ)を作成
2.作成したキーコンテナにシークレット情報を格納
⇒この時シークレット識別子というのがアサインされるので、これをメモしておく。
image.png
3.VisualStadioでキーコンテナからシークレット情報を参照するコーディングを行う
(VSの新規プロジェクト>ASP.Core Web アプリケーションのテンプレートを指定)

Program.cs
// キーコンテナーのDNS名を設定する
var keyVaultEndpoint = "https://keyvault-je-001.vault.azure.net/";

// Azure Key Vaultに接続するための追加の設定を記述する
// 1.アプリをAzureに認証するためのアクセストークン取得プロバイダーのインスタンス化
var azureServiceTokenProvider = new AzureServiceTokenProvider();

// 2.Azure Key Vaultに接続するためのクライアントのインスタンス化
var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));

// 3.Azure Key Vault(キーコンテナー)からシークレットにアクセスするための設定をbuilderに追加
builder.AddAzureKeyVault(keyVaultEndpoint, keyVaultClient, new DefaultKeyVaultSecretManager());

4.デプロイして、テスト!してもつながりません。(500系エラー)

5.デプロイしたWebAppsのIDを選択し、こんな感じでオンに切り替えて保存
image.png

6.キーコンテナ>アクセスポリシーから「+アクセスポリシーの追加」を選択

7.さっきWebAppsでオンに切り替えたときに作成されたIDが選択可能になっているはずなので、選択してシークレットの一覧、参照を有効にして保存。
image.png

8.もう一回VSからデプロイして、打鍵テスト。正常に表示!
image.png

後記

Azure Key Vault を使用してサーバー アプリのシークレットを管理する

.NET Core の公式の Key Vault クライアントは、Microsoft.Azure.KeyVault NuGet パッケージの KeyVaultClient クラスです。 これを直接使用する必要はありませんが、— と ASP.NET Core の AddAzureKeyVault メソッドを使用すると、起動時にコンテナーのすべてのシークレットを Configuration API に読み込むことができます。 この手法では、残りの構成で使用するものと同じ IConfiguration インターフェイスを使用して、すべてのシークレットに名前を指定してアクセスできます。 AddAzureKeyVault を使用するアプリには、コンテナーに対する Get と List の両方のアクセス許可が必要です。

マイナビのサイトもMSのLearningでも実装方法はほぼ同じなことに気づきました。
MSのLearningだとProgram.cs内でわずかにこれだけ。キーコンテナを丸ごと読み込んで、必要なものだけアプリ内で抽出して(SeacretNameとの一致するものだけ)利用してるんですね。

Program.cs
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;

namespace KeyVaultDemoApp
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((context, config) =>
                {
                    // Build the current set of configuration to load values from
                    // JSON files and environment variables, including VaultName.
                    var builtConfig = config.Build();

                    // Use VaultName from the configuration to create the full vault URL.
                    var vaultUrl = $"https://{builtConfig["VaultName"]}.vault.azure.net/";

                    // Load all secrets from the vault into configuration. This will automatically
                    // authenticate to the vault using a managed identity. If a managed identity
                    // is not available, it will check if Visual Studio and/or the Azure CLI are
                    // installed locally and see if they are configured with credentials that can
                    // access the vault.
                    config.AddAzureKeyVault(vaultUrl);
                })
                .UseStartup<Startup>();
    }
}
SecretTestController.cs
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;

namespace KeyVaultDemoApp.Controllers
{
    [Route("api/[controller]")]
    public class SecretTestController : ControllerBase
    {
        private readonly IConfiguration _configuration;

        public SecretTestController(IConfiguration configuration)
        {
            _configuration = configuration; // ★ごそっと一括で取得
        }

        [HttpGet]
        public IActionResult Get()
        {
            // Get the secret value from configuration. This can be done anywhere
            // we have access to IConfiguration. This does not call the Key Vault
            // API, because the secrets were loaded at startup.
            var secretName = "SecretPassword";
            var secretValue = _configuration[secretName]; // ★配列みたいなもので一致しているものだけとっている?

            if (secretValue == null)
            {
                return StatusCode(
                    StatusCodes.Status500InternalServerError,
                    $"Error: No secret named {secretName} was found...");
            }
            else {
                return Content($"Secret value: {secretValue}" +
                    Environment.NewLine + Environment.NewLine +
                    "This is for testing only! Never output a secret " +
                    "to a response or anywhere else in a real app!");
            }
        }
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AtCoder Beginner Contest 156 参戦記

AtCoder Beginner Contest 156 参戦記

ABC156A - Beginner

4分で突破. 書くだけ.

N, R = map(int, input().split())

if N >= 10:
    print(R)
else:
    print(R - 100 * (10 - N))

ABC156B - Digits

2分で突破. 書くだけ. K進数の 10 は K で、100 は K2 だと分かっていれば、K で何回割れるか調べるだけと分かるはず.

N, K = map(int, input().split())

result = 0
while N != 0:
    result += 1
    N //= K
print(result)

ABC156C - Rally

3分半で突破. 書くだけ……なのは、この計算をしなれてるからなんですが. (Xi−P)2 が最小になる P は重心. 減色の K-means で3次元のこの計算をしてます…….

N = int(input())
X = list(map(int, input().split()))

P = int(sum(X) / N + 0.5)
print(sum((x - P) * (x - P) for x in X))

ABC156D - Bouquet

70分半で突破. まず nC0+nC1+...+nCn = 2n を知っていないといけない. 私は知りませんでした orz. パスカルの三角形の Wikipedia 見てたら書いてあって知りました. これで過去に書いた mpow と mcomb を貼って終わりかと思ったら n! を求める部分があって 2≤n≤109 に殺される. a, b はたかだか 105 であることに気づき、nCk を求める別の式に組み替えてようやく解けた. 良問!

def mpow(x, n):
    result = 1
    while n != 0:
        if n & 1 == 1:
            result *= x
            result %= 1000000007
        x *= x
        x %= 1000000007
        n >>= 1
    return result


def mcomb(n, k):
    a = 1
    b = 1
    for i in range(k):
        a *= n - i
        a %= 1000000007
        b *= i + 1
        b %= 1000000007
    return a * mpow(b, 1000000005) % 1000000007


n, a, b = map(int, input().split())

result = mpow(2, n) - 1
result -= mcomb(n, a)
result + 1000000007
result %= 1000000007
result -= mcomb(n, b)
result + 1000000007
result %= 1000000007
print(result)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Service Bus(トピック)への書き込み処理

全然参考となる資料が見つからなくて苦戦。。
結局公式ドキュメントにあったんだけどこれを見つけるのに時間がかかった。

解決していない事柄

Functionsから受け取った情報をSerivce Busに書き込むこと
Service Busの接続文字列をキーコンテナから取得すること

解決までの流れ

1.Service Busのデプロイ(Service Busの名前空間)
2.Service Busのトピック作成
⇒Service Bus 名前空間の共有アクセスポリシー(RootManageSharedAccessKey)からプライマリ接続文字列は入手可能

3.チュートリアルのprivatemessagesenderをコピペで関数アプリ(Functions)を作成するも動かず。

4.Service Bus キューの使用を発見し、Visual Stadio 2019(以降VSと表記)を導入して、無事解決。
(Visual Stadio 2019導入は割愛)

4-1.プロジェクトを作成し、パッケージの追加を実施

Service Bus NuGet パッケージの追加
新しく作成したプロジェクトを右クリックし、 [NuGet パッケージの管理] を選択します。
[参照] を選択します。 [Microsoft.Azure.ServiceBus] を検索して選択します。
[インストール] を選択し、インストールが完了したら、NuGet パッケージ マネージャーを閉じます。

4-2.サンプルコードをコピペ※以下の箇所だけ作成したServiceBusに合わせて更新

Program.cs
const string ServiceBusConnectionString = "Endpoint=sb://***********.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=***********";
const string QueueName = "samplequeue";

4-3.VS上で実行 ⇒ Service Bus キューの概要からアクティブなメッセージ数が増えていることを確認
image.png

4-4.プロジェクトを選択し、右クリック>発行
AppServicePlanなどが自動で作成されるのでしばらく待つ。
再度発行ボタンを押すと、Azure 側へデプロイされる。

image.png

4-5.Azureへのデプロイが完了したら、該当リソース(App Service)のWebジョブをクリック
4-6.ジョブを選択して、実行を押下 ⇒ Service Bus キューの概要からアクティブなメッセージ数が増えていることを確認
image.png

4-7.あれ、、増えてない。。ジョブがアベンドしている?!

4-8.ソースコード見てみると、Enter待ちになってる箇所あり。コメントアウトして、再度デプロイ

Program.cs
// Console.ReadKey();

4-9.Azureへのデプロイが完了したら、該当リソース(App Service)のWebジョブをクリック
4-10.ジョブを選択して、実行を押下 ⇒ Service Bus キューの概要からアクティブなメッセージ数が増えていることを確認

終了!

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

今更ながらWPFに置き換えてみる(2)

WPFをターゲットにしてプロジェクトを作成し、とりあえず側だけ作ってみる。
こんな感じになる予定。ボケてない。

コメント 2020-02-22 120606.png

ここまででよくわからない点
FORMSではコントロールとしてデザイナ上で配置できてた以下のものたちはどうなるの?
・タイマー
・CMSメニュー
・NotifyIcon
・PictureBox(これはImageコントロールっぽい)
・リストビューの背景設定

それと、SETTINGSのエリアは、VBでは動的に表示非表示の切り替えと、画面サイズの変更を自前で行っていたが、なんかEXPANDER?っていうコントロールで置き換えたほうがスマートな感じがする。

画面変遷.png

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

C# 6.0 の記述方法

C# 6.0 の新機能

読み取り専用の自動プロパティ (Read-only auto-properties)

自動実装プロパティで読み取り専用を記述できるようになった。

class Person
{
    public DateTime Birth { get; } = new DateTime(1999, 12, 31);
}

以前の書き方

フィールドを用意する必要があった。
class Person
{
    private DateTime birth = new DateTime(1999, 12, 31);
    public DateTime Birth 
    {
        get { return this.birth; }
    }
}

自動プロパティ初期化子 (Auto-property initializers)

自動実装プロパティの初期値を指定できるようになった。

class Person
{
    public DateTime Birth { get; set; } = new DateTime(1999, 12, 31);
}

以前の書き方

コンストラクタで初期化する必要があった。
class Person
{
    public Person()
    {
        this.Birth = new DateTime(1999, 12, 31);
    }

    public DateTime Birth { get; set; }
}

ラムダ式によるメソッドとプロパティ (Expression-bodied function members)

メソッド (Methods)

簡単なメソッドを1行で書けるようになった。

class Person
{
    private DateTime birth = new DateTime(1999, 12, 31);
    public int GetAge() => DateTime.Today.Year - this.birth.Year + 1; // 数え年
}

以前の書き方

1行で書けなかった。
class Person
{
    private DateTime birth = new DateTime(1999, 12, 31);
    public int GetAge()
    {
        return DateTime.Today.Year - this.birth.Year + 1; // 数え年
    }
}

using static

static クラスのメソッド呼び出し等に、クラス名が省略可能になった。

using static System.Math;

static class Util
{
    public static int Range(int value, int lower, int upper)
    {
        return Max(Min(value, lower), upper);
    }
}

Null 条件演算子 (Null-conditional operators)

イベント発生等を簡潔に書けるようになった。

class Person
{
    private string name;
    public string Name
    {
        get { return this.name; }
        set
        {
            this.name = value;
            this.NameChanged?.Invoke(this, EventArgs.Empty);
        }
    }

    public event EventHandler NameChanged;
}

以前の書き方

null チェックの必要があった。
class Person
{
    private string name;
    public string Name
    {
        get { return this.name; }
        set
        {
            this.name = value;
            var handler = this.NameChanged;
            if (handler != null) handler(this, EventArgs.Empty);
        }
    }

    public event EventHandler NameChanged;
}

文字列補間 (String interpolation)

文字列の書式化が簡単になった。

var message = $"ファイル {path} が存在しません。";

以前の書き方

string.Format を使う必要があった。
var message = string.Format("ファイル {0} が存在しません。", path);

例外フィルター (Exception filters)

nameof 式 (The nameof expression)

変数などの名前を文字列として取得できるようになった。

if (path == null) throw new ArgumentNullException(nameof(path));

以前の書き方

文字列で指定する必要があったため、リファクターの対象にならなかった。
if (path == null) throw new ArgumentNullException("path");

Catch ブロックと Finally ブロックでの Await (Await in Catch and Finally blocks)

インデクサーを使用して関連コレクションを初期化する (Initialize associative collections using indexers)

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

[WPF] データに応じてリストの表示形式を切り替える

はじめに

ListBox に代表される ItemsControl コントロールを使って、色々な形式のデータを表示する方法をまとめました。

対応方法

表示する元データ

今回は "データ形式" と "値" を個別に管理するクラスを用意しました。

class MyData
{
    public enum ItemType { Bool, Int, String };
    public ItemType Type { get; }

    public bool BoolValue { get; set; }
    public int IntValue { get; set; }
    public string StringValue { get; set; }

    /* コンストラクタ省略 */
}

表示する元リスト

enum型の ItemType に応じて表示形式を切り替えます。

public static List<MyData> Items => new List<MyData>()
{
    new MyData(false),
    new MyData(true),
    new MyData(123),
    new MyData("Hello"),
    new MyData(null),
    new MyData(4321),
    new MyData("こんにちわ"),
    new MyData(false),
    new MyData(0),
};

表示1:データ種別に応じて表示形式を切り替える

ItemsControl.ItemContainerStyleSelector を使い、データ種別に応じて Style を切り替えます。

WpfContainerStyleSelector.png

表示2:データ種別に応じてグルーピングする

ItemsControl.GroupStyle.HeaderTemplateSelector を使い、データ種別に応じて DataTemplate を切り替えます。

WpfDataTemplateSelector.png

表示3:グルーピングしてデータ種別に応じて表示形式を切り替える

ItemsControl.GroupStyle.ContainerStyleSelector を使い、データ種別に応じて Style を切り替えます。

WpfGroupContainerStyleSelector.png

まとめ

説明は冒頭で力尽きてしまいましたが、ソースコードは以下に置いてあります。

WpfListTemplateSwitch

参考にさせて頂いたページ

ItemsControl 攻略 ~ 外観のカスタマイズ

How to make WPF Listview works same as Photoshop layer

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

C#から鬼雲(bregonig.dll)を使って正規表現を処理する

目的

grepなど大規模な正規表現検索をしようとすると、C#の System.Text.RegularExpressions.Regexだと処理速度が物足りない。
C#だから遅いのかは判っていませんが、ネイティブなライブラリを使えば多少速くなるのではと思い、サクラエディタとかで採用されている鬼雲(bregonig.dll)をC#から使えないかと調べてみた。
既に実現されている方がいたので、たどり着けるようにメモを残しておきます。

速度はまだ比較できてませんが、鬼雲の正規表現の機能はC#標準クラスの正規表現よりも充実しているらしいです。

参考サイト

https://hnx8.hatenablog.com/entry/2018/11/25/153251
https://github.com/hnx8/BregonigDotNet

Visual Studioでコンパイルする場合

プロジェクトファイルが上記のGitHubサイトに一緒に入っているので、たぶんそれを使えばできるはず。

Visual Studio無しでコンパイルする場合

※下記は私が勝手にやってみた手順なので、上記の参考サイト様には下記内容について問い合わせしないようお願いします。

bregonig.dllをサクラエディタのフォルダからコピーするなりダウンロードし、
上記のGitHubサイトから一式ダウンロードして、
BregonigRegex.cs と Program.cs と bregonig.dllを同じフォルダにおき、

csc BregonigRegex.cs Program.cs

でコンパイルすると、Program.exeが出来上がるので、これを実行します。
下記のエラー

pattern:「(03|045)-(\d{3,4})-(\d{4})」
間違ったフォーマットのプログラムを読み込もうとしました。 (HRESULT からの例外:0x8007000B)
dllの32bit/64bitが妥当ではない可能性もあります。正しいbregonig.dllを実行フォルダに配置してください。

が出る場合は、exeとdllのbitが整合していないと思われますので、

csc /platform:x86 BregonigRegex.cs Program.cs

もしくは

csc /platform:x64 BregonigRegex.cs Program.cs

でコンパイルしたProgram.exeのいずれかがうまく動作するはずです。
Program.exeを実行して下記のようなログがとれれば、うまく動作しているものと思います。

pattern:「(03|045)-(\d{3,4})-(\d{4})」
input:「 Yokohama 045-222-1111  Osaka 06-5555-6666  Tokyo 03-1111-9999 」
 ->found:「045-222-1111」(start=10, length=12)
 ->found:「03-1111-9999」(start=50, length=12)
:
(中略)
:
pattern:「[a-f]」
input:「 置換パターンにエラーがある場合0123456789abcdef 」
replacement:(null)
 ->error:「invalid reg parameter」

処理速度の比較(まだ)

ファイル読み込む処理とか対象のファイルとかの準備ができていない。。。
Regexクラスもオプション指定でキャッシュとかコンパイルとかすると多少速くなるようなので、それらも比較したい。

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

オーバーウォッチのマッチング通知

オーバーウォッチのマッチング長すぎん....?

Overwatchというゲームが僕は大好きですが,ここ最近異様にマッチングが長いです
10分越えなんてざらです
マッチング長いし洗濯でもしてるか...
なんてことすると,いつの間にか強制退出くらってます

ということでマッチングしたらスマホに通知をもらおう

まず,おおまかな仕組みはこんな感じです
Untitled Diagram (4).png
ミソはマッチの検出とお知らせ方法です

マッチ検出

おばっちはマッチが始まるとかっこいいBGMと相手味方のメンバーが表示されます
おばっちから直接データをいただくことはできないので(パッケージ化させているので)
このBGMか画面の違いを取得することでマッチ検出を行おうと思います

BGM

音声認識使おうか?
でもcloud speechは無料で一時間までしか使えんしなぁ
やめた

画面遷移

マッチ後の画面学習させてYOLOかなんかで認識しようかなぁ
でも学習させるのめんどいし(マッチング画面はマップによって異なる)
認識率が心配....
ん?
マップによらず共通なのはマッチ前の画面の文字だけだよな?

[検索中....]←これ

これ認識させて検出できなかったらマッチ始まったってことでいいんじゃね?

マッチ検出実装

文字の認識にはOCRを使いました
画像から文字を取り出してくれます
C# OCRとググれば先人たちが輝かしいソースを残してくれているのでこれを使いましょう

Microsoft.VisualBasic.Interaction.AppActivate("Overwatch");
SendKeys.SendWait("{PRTSC}");

#ここに先人のコードを入れる→pageという名の変数で帰ってくる

if(page.GetText().Contains("検索中")) {
   処理
}

お知らせ方法

IFTTTです
iPhoneで受け取ろうと思います
1.スマホでiftttのアプリを入れましょう
2.Webhooksからurlで送信できるトリガーを取得しましょう
3.スマホの通知を選択しましょう
4.取得したurlを使ってプログラムを編集しましょう

DateTime dt = DateTime.Now;
string result = dt.ToString("yyyy/MM/dd HH:mm:ss");
string lnk = "https://maker.ifttt.com/trigger/match/with/key/#########/?value1=" + result;
System.Diagnostics.Process.Start(lnk);

こんな感じです
日時を含めているのはtwitterでもつぶやこうと思ったので
同じ内容の送信をブロックする機能の対策として追加してます

でげだ!

ツイッターでつぶやかせました
aaaa.png

今のところ
検出の誤作動は,ないです
100発100中です
おかげさまでお風呂に入りながらでも,ダッシュで駆けつけることができるようになりました

おしまい

追記

なんかぐぐったらDiscordの機能かなんかで同じようなのあって草
ちなみにコードは大事なとこ以外かなり端折ってます

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