ごった煮

色々な事を書いてます

Windows 環境の PHP でビルトインサーバを使用するときに環境変数をセットする方法

とある事情で PHP を書く必要に迫られたのですが Windows 環境 + ビルトインサーバで環境変数を扱う方法を忘れていたのでメモとして残します

やり方

よくある方法だと以下のような感じですよね

Foo=Bar php localhost:8000 -t パス

コマンドプロンプトPowerShell で Foo=Bar ~ みたいなことは、出来ないですよね ということで普通に set コマンドを使って環境変数を指してあげましょう

SET Foo=Bar
php localhost:8000 -t パス

Set コマンドは、使用したセッション中のみ有効な環境変数を設定してくれるコマンドです 確かに普通に環境変数をセットしてあげれば使えますね

まとめ

意外と忘れがちですよねこういうの

csv 出力時に、Excel で 0 が無視される問題とその解決方法について

DB のデータをダンプしたいといった場合、よくあるパターンだとそのまま csv に吐き出すみたいなことがありますが、電話番号や郵便番号の場合に、先頭の 0 が Excel で開いた場合に表示上消される場合があります。

その解決方法についてメモを残します。

やりたいこと

  • 出力した csv のカラムのうち、先頭が 0 などで Excel に無視される部分をプログラム的に解決したい

解決方法

値を ="" で囲んで出力する

C# などの言語では、モデルをから csv に変換してくれるライブラリがあるので、モデルに渡すタイミングで囲んであげましょう

下のような感じ

var tel = "00011112222";
var model = new CsvObj
{
    Id = 1,
    Tel = $"=\"{tel}"",
    Addr = "東京都千代田区1-1"
};

因みに Excel で 0 落ちを防ぐためによくある最初に ' を付けてあげるパターンは、自分の環境(Version 1908 (Build 11929.203838)) では、うまく動作しませんでした。(Excel で手動で ' を入力した場合は、動作しましたが、出力したものを直接読み込んでもうまく動作しませんでした。)

まとめ

よくあるパターンなので覚えておくと良いかと思います。

ASP.NET Core 2.2 から ASP.NET Core 3.1 へ移行する際に ExpressionMetadataProvider が読み出せなくなった件と解決方法について

手元のプロジェクトを移行していた際に、引っかかったのでメモとして残します。

何が起きたか

2.x系で動いていたコードがバージョンアップとともに実行時エラーが発生した ExpressionMetadataProvider の読み出し時になぜか読み出せなくなった

エラーになるコードは、以下のような感じ

        public static IHtmlContent Sample<T, TProperty>(this IHtmlHelper<T> htmlHelper,
            Expression<Func<T, TProperty>> selector)
        {
            var metadata =
                ExpressionMetadataProvider.FromLambdaExpression(selector, htmlHelper.ViewData,
                    htmlHelper.MetadataProvider);
            var defaultModelMetadata = metadata.Metadata as DefaultModelMetadata;

            return new HtmlString("");
        }

具体的なエラーは、以下のような感じ

TypeLoadException: Could not load type 'Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.ExpressionMetadataProvider' from assembly 'Microsoft.AspNetCore.Mvc.ViewFeatures, Version=3.1.4.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'.

原因

ASP.NET Core 3.0 になったタイミングで、Microsoft.AspNet.*.Internal といった API群が本当の internal に変更された 今までは、public internal (pubternal) な API だったのでアクセスできたが、本当に Internal になったのでアクセスできなくなった。

対処法

HttpContext にアクセスできる場合、HttpContext.RequestServices を使って ModelExpressionProvider にアクセスできるので、以下のようにして対応

        public static IHtmlContent Sample<T, TProperty>(this IHtmlHelper<T> htmlHelper,
            Expression<Func<T, TProperty>> selector)
        {
            var modelExpressionProvider = (ModelExpressionProvider) htmlHelper.ViewContext.HttpContext.RequestServices.GetService(typeof(IModelExpressionProvider));
            var metadata = modelExpressionProvider.CreateModelExpression(htmlHelper.ViewData, selector);
            var defaultModelMetadata = metadata.Metadata as DefaultModelMetadata;

            return new HtmlString("");
        }

まとめ

.NET Core のバージョンアップは、とても辛い

Azure Pipelines の変数を動的に切り替える

Azure Pipelines を使用しているとパラメータを動的に切り替えたい場合が出てくると思います。(例えば、Debugビルド、 Releaseビルドの切り替えなど) Runtime Parameters の機能を使用すると変数を動的に切り替えてパイプラインを実行することが出来ます。

使い方

以下のような YAML を定義します。

# Runtime Parameters demo 
trigger:
- master

parameters:
- name: buildConfig
  displayName: Build Config
  type: string
  default: Release
  values:
  - Release
  - Debug

- name: vmImage
  displayName: VM Image
  type: string
  default: windows-2019
  values:
  - windows-latest
  - windows-2019
  - vs2017-win2016
  - ubuntu-latest
  - ubuntu-18.04
  - ubuntu-16.04
  - macOS-10.14
  - macOS-10.15

- name: boolVal
  displayName: second
  type: boolean
  default: true
  values:
  - true
  - false

- name: numVal
  displayName: number
  type: number
  default: 0
  values:
  - 0
  - 1
  - 2
  - 3
  - 4
  - 5
  - 6
  - 7

jobs:
- job: echo
  displayName: echo
  pool:
    vmImage: ${{ parameters.vmImage }}
  steps:
  - script: echo ${{ parameters.buildConfig }}
    displayName: echo
  - ${{ if eq(parameters.boolVal, true) }}:
    - script: echo ${{ parameters.numVal }}
      displayName: 'echo num'

parameters 以下に書いていきます values に値をセットすると、 Run Pipeline メニューで選択できるようになります。 boolean 型を使用すると、job の実行を切り替えたりといったことも可能です。

このパイプラインをで Run Pipeline メニューを開くと以下のような見た目になります。 displayName がメニューの名前として表示されます。

f:id:papemk2:20200416003136p:plain

これによりプルダウンやチェックボックスで動的に値を切り替えることが出来ます。

まとめ

結構便利なので、ぜひ覚えてみましょう

Azure DevOps の Wiki で画像のリサイズをしたい

Azure DevOps の Wiki を書いているときに、画像のリサイズで困ったのでメモとして残します。

やり方

Azure DevOps の Wiki は、Markdown で記述出来るので Markdown で記述します。

![画像の Alt テキスト](ファイルパス =幅x高さ)

この構文で記述すると以下のような HTML に変換されます。

<img src="変換されたパス" atl="Alt テキスト" width="幅" height="高さ">

Markdown でよくあるパターンだと、img タグを埋め込んでリサイズを行う場合が多いですが、Azure DevOps の Wiki の場合、ファイルパスが GUID のような文字列に変換されてしまうためこの方法を使いましょう。

まとめ

意外と使うので覚えておきましょう

Function App の Blob output binding でファイル名にいい感じに日付を入れたい

日時バッチを Function App で実行する場合、ファイル名に日付を入れたいといったことがあるかと思います。 Blob binding だといい感じに日付を入れられるのでその方法を紹介します。

やってみる

Function App の Blob output binding で、以下のようにします。

[FunctionName("demo")]
public async Task Run(
[TimerTrigger("0 0 0 * * * ")]TimerInfo myTimer,
[Blob("demo/demo_{datetime}.csv", FileAccess.Write)] Stream csv,
ILogger log)
{
        
}

{datetime} とすることで、実行時の日付が UTC で差し込まれます。 デフォルトでは、yyyy-MM-ddThh-mm-ssZ になります。 このようにすると、demo_yyyy-MM-ddThh-mm-ssZ.csv といったようなファイル名でファイルが出力されます。

フォーマット指定したい場合は、 {datetime:yyyy-MM-dd} とします。 すると、demo_yyyy-MM-dd.csv となります。

まとめ

ファイル名が動的でも面倒な処理をせずにファイル名に日付を差し込むことが出来ました。

datetime に入ってくる日付は、デフォルトで UTC なので気を付けましょう。 これを変える場合は、 Function App のタイムゾーン設定を変更する必要があり、一緒にデプロイされているすべての Function に影響を与えるのでタイムゾーンを変更する場合は、慎重に行いましょう。

Azure Logc App で SFTP にファイルを転送したい

C# で SFTP に接続してなんやかんやする場合、いいライブラリが少なかったり実装がややこしかったりで結構面倒だと思っていました。 ですが Logic App には、SFTP へのコネクトがちゃんと用意されているので今回は、それを使ってファイルを転送する方法についてまとめます。

やりたいこと

Blob storage と SFTP サーバの両方にテキストファイルを転送する

サービス

Azure Logic App

やってみる

Blob storage の変化を検知する

Logic App のエディタで、 Azure Blob Storage をトリガーとして選択します。 f:id:papemk2:20200323175149p:plain

選択すると When a blob is added or modified の項目があるので選択します。 初めての場合、ストレージアカウントを選択する画面になるので、ストレージアカウントを選択します。

f:id:papemk2:20200323175651p:plain

トリガーが作成されると監視するコンテナを選択する画面が出るので、適当に設定します。 f:id:papemk2:20200323175856p:plain

Blob に配置されたファイルの中身を取得する

New Step から処理を追加します。 また Azure Blob Storage を選択します。 すると色々 Action が出てくるので、Get blobg content を選択します。

f:id:papemk2:20200323180137p:plain

選択すると、Blob で何をするか設定する画面になります。 Blob の項目を List of Files Path に設定します。

f:id:papemk2:20200323180317p:plain

これで、後続の処理に Blob の中身を渡せるようになります。

SFTP へ接続する

また Action を追加します。 SFTP で検索すると、SFTP 用のアクションがいくつか出てくるので Create file を選択します。 f:id:papemk2:20200323180536p:plain

選択すると、SFTP の設定情報を埋める画面が出るので、適当に埋めます。

f:id:papemk2:20200323180714p:plain

private key は、ppk の中身をべた張りで OK です。

接続設定がおかしい場合は、この段階でエラーになってくれるので設定を見直しましょう。 f:id:papemk2:20200323180855p:plain

SFTP へファイルを転送する

SFTP の接続設定が終わると、ファイル名とファイルの中身をどうするか設定する画面になります。 以下のように File name に List of Files DisplayName, File content に File Content を設定します。 Folder path は、任意のパスで埋めます。

f:id:papemk2:20200323181221p:plain

これで準備完了です。

指定した Blob にファイルをアップロードすると、いい感じに SFTP にファイルをコピーしてくれます。 デフォルトの状態だと、 3分に一度の感覚でポーリングするので、ファイルをアップロードしてから最大3分で処理が行われます。

まとめ

C# だと面倒な処理でも Logic App を組み合わせると簡単にできることがあるので、適材適所で Logic App も使ってみましょう。