PowerShellで設定ファイルの内容をコンソールとファイルに出力するようにしてみた

スクリプトを実行する際に設定ファイルの内容をコンソールで確認出来るようにしたらミスも防げるしいいかなーと思って考えてみた. ついでにtsvで出力出来るようにした.

スクリプト

設定ファイルはこんな感じ. PowerShellでは-Option Constantで定数を宣言できる. 変数の内容は-Descriptionで書く.

Get-Variableで変数の一覧を取得出来るがいらないものまで色々出てきてしまう(気になる人は手元でお試しあれ). そこで-Descriptionの先頭にタグを付けることでユーザー定義の変数かそうでないかを判別するようにした.

あとはFormat-Tableでコンソールに表示して, Export-Csvでファイル出力すれば出来上がり.

Config.ps1

# タグ
Set-Variable -Name UserDefinedVarTag -Value "UserDefinedVars:" -Option Constant
# サンプルフラグ
Set-Variable -Name IsSample -Value $true -Option Constant -Description ("{0}サンプルフラグ" -f $UserDefinedVarTag)
# スクリプトのパス
Set-Variable -Name ConfRoot -Value (Split-Path $MyInvocation.MyCommand.Path -Parent) -Option Constant -Description ("{0}スクリプトのパス" -f $UserDefinedVarTag)
# サンプルディレクトリ
Set-Variable -Name SampleDir -Value ("{0}\Sample" -f $ConfRoot) -Option Constant -Description ("{0}サンプルディレクトリ" -f $UserDefinedVarTag)
# ユーザー名
Set-Variable -Name UserName -Value "TestUser" -Option Constant -Description ("{0}ユーザー名" -f $UserDefinedVarTag)
# ユーザーパスワード
Set-Variable -Name UserPassword -Value "PaSsWoRd" -Option Constant -Description ("{0}パスワード" -f $UserDefinedVarTag)
# 設定ファイルの出力パス
Set-Variable -Name ConfFilePath -Value ("{0}\Config.tsv" -f $ConfRoot) -Option Constant -Description ("{0}設定ファイル内容出力先" -f $UserDefinedVarTag)

function Write-Config(){
    <#
    .SYNOPSIS
    設定内容をコンソールに出力します.
    #>

    $vars = @()
    Get-Variable | ForEach-Object{ if($_.Description -ne $null -and $_.Description.Contains($UserDefinedVarTag)) { $vars += $_ } }
    $vars | ForEach-Object{ $_.Description = $_.Description.Split(":")[1] }
    $vars | Select-Object -Property @{n="変数名"; e={$_.Name}}, @{n="値"; e={$_.Value}}, @{n="詳細"; e={$_.Description}} | Format-Table
    $vars | Select-Object -Property  @{n="変数名"; e={$_.Name}}, @{n="値"; e={$_.Value}}, @{n="詳細"; e={$_.Description}} | Export-Csv -Delimiter "`t" -Encoding default -Path $ConfFilePath -NoTypeInformation
}

設定ファイルを読み込んだスクリプトで関数を呼び出す.

Write-Config.ps1

set-variable -name ScriptRoot -value (Split-Path $MyInvocation.MyCommand.Path -Parent) -option Constant

# 設定ファイル読み込み
. ("{0}\Config.ps1" -f $ScriptRoot)

Write-Config

実行してみるとコンソールに設定内容がきれいに表示される.

PS D:\Sample> .\Write-Config.ps1

変数名       値                                             詳細
------       --                                             ----
ConfFilePath D:\Common\PowerShell\Modules\Sample\Config.tsv 設定ファイル内容出力先
ConfRoot     D:\Common\PowerShell\Modules\Sample            スクリプトのパス
IsSample     True                                           サンプルフラグ
SampleDir    D:\Common\PowerShell\Modules\Sample\Sample     サンプルディレクトリ
UserName     TestUser                                       ユーザー名
UserPassword PaSsWoRd                                       パスワード

ファイルにも出力される.

"変数名"  "値"   "詳細"
"ConfFilePath"  "D:\Common\PowerShell\Modules\Sample\Config.tsv"    "設定ファイル内容出力先"
"ConfRoot"  "D:\Common\PowerShell\Modules\Sample"   "スクリプトのパス"
"IsSample"  "True"  "サンプルフラグ"
"SampleDir" "D:\Common\PowerShell\Modules\Sample\Sample"    "サンプルディレクトリ"
"UserName"  "TestUser"  "ユーザー名"
"UserPassword"  "PaSsWoRd"  "パスワード"

http-serverでサクッとローカルにHTTPサーバをたてる

http-serverでサクッとローカルにHTTPサーバをたてる

ローカルにHTTPサーバたてたいなーと思ったので調べてみたら便利なものがあったので紹介します。

http-server

https://github.com/indexzero/http-server

Node.jsで動くHTTPサーバデス。

http-serverをインストールして起動してみる

HTTPサーバをたてたいところでまずはnpm init。

cd D:\Test\sample
npm init -y

続けてhttp-serverをインストールします。
今回はローカルに。

npm install http-server --save-dev

pakcage.jsonを修正します。

  "scripts": {
    "http-server": "http-server"
  }

これでhttp-serverを起動することが出来るようになりました。

あとはHTTPサーバにコンテンツを置いてブラウザから見てみましょう。

D:\Test\sample配下にPublicフォルダを作成します。
あとはPublicフォルダにコンテンツを置きます。

D:Test\Test\sample
├node_modules
├public
│ ├index.html
│ └sample.md
└pakcage.json

index.html

<DOCTYPE html>
<html>
<head>
  <title>サンプル</title>
  <meta charset="utf-8">
  <style>
    body { font-![slide.png](http://luna.science.nttdata-ccs.co.jp:3000/files/5abb2aa9ad52f21d77615203)
family: 'Droid Serif'; }
    h1, h2, h3 {
      font-family: 'Yanone Kaffeesatz';
      font-weight: normal;
    }
    .remark-code, .remark-inline-code { font-family: 'Ubuntu Mono'; }
  </style>
</head>
<body>
  <!-- Remarkjs -->
  <script src="https://remarkjs.com/downloads/remark-latest.min.js" type="text/javascript"></script>
  <script type="text/javascript">
    var slideshow = remark.create({sourceUrl: "sample.md"});
  </script>
</body>
</html>

sample.md

name: inverse
layout: true
class: center, middle, inverse
---
# 見れた?

では早速http-serverを起動してみましょう。
port番号は適当に10000を指定してます。

npm run http-server -- -p 10000

http://localhost:10000 にアクセスしてみます。

f:id:mt9116:20180328144258p:plain

表示されましたー
たったこれだけでHTTPサーバが使えるなんて便利ですよね。

スタイルシートをバンドルする際は画像パスに注意

またASP.NETのバンドルの話です。

スタイルシートを何も考えずにまとめてバンドルする

とりあえずスタイルシートをまとめてみます。

bundles.Add(new StyleBundle("~/bundles/style").Include(
    "~/lib/bootstrap/css/bootstrap.min.css",
    "~/lib/jquery-ui/jquery-ui.css",
    "~/lib/font-awesome/css/font-awesome.css"
));

こうすると3つのスタイルシートは一つにバンドルされます。

画面でこのスタイルを読み込んでみます。

@using System.Web.Optimization
<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title></title>
    @Scripts.Render("~/bundles/scripts")
    @Styles.Render("~/bundles/styles")
    <script>
        $(function () {
            $("#hoge").dialog();
        })
    </script>
</head>
<body>
    <div id="hoge">閉じるボタンのアイコン見えてる?</div>
</body>
</html>

画面を表示してみます。

f:id:mt9116:20180326150350p:plain

ダイアログのアイコンが表示されていませんね。
コンソールを見てみるとjquery-uiのアイコンが見つからないと怒られています。

f:id:mt9116:20180326150406p:plain

これはスタイルシートが仮想パスにバンドルされ、バンドル先にimagesが無いのが原因です。
そこで、実際にスタイルシートが置いてある場所にバンドルするようにします。

実在パスにあわせてスタイルシートをバンドルする

実際のパスはこんな感じです。 jquery-ui.cssが置かれているフォルダにimagesがあります。

f:id:mt9116:20180326150418p:plain

では、ソースをこのように修正しましょう。
パスに<実在パス>/cssのように指定します。

bundles.Add(new StyleBundle("~/lib/jqueryui/css").Include("~/lib/jqueryui/jquery-ui.css"));
bundles.Add(new StyleBundle("~/lib/bootstrap/css/css").Include("~/lib/bootstrap/css/bootstrap.css"));
bundles.Add(new StyleBundle("~/lib/font-awesome/css/css").Include("~/lib/font-awesome/css/font-awesome.css"));

後はそれを画面から読み込みます。

@using System.Web.Optimization
<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title></title>
    @Scripts.Render("~/bundles/scripts")
    @Styles.Render("~/lib/jqueryui/css")
    @Styles.Render("~/lib/bootstrap/css/css")
    @Styles.Render("~/lib/font-awesome/css/css")
    <script>
        $(function () {
            $("#hoge").dialog();
        })
    </script>
</head>
<body>
    <div id="hoge">閉じるボタンのアイコン見えてる?</div>
</body>
</html>

画面を表示すると、ダイアログのアイコンが表示されていることが確認出来ます。

f:id:mt9116:20180326150432p:plain

コンソールを見てみると画像を上手く参照出来ていることが分かります。

f:id:mt9116:20180326150441p:plain

ASP.NETで画像を含むスタイルシートをバンドルする際は個別にバンドルしましょう。

指定した順序でバンドルする@ASP.NET

ASP.NETスクリプトをバンドル出来ますが、かゆいところに手が届かない部分があるのでまとめておきます。

通常のバンドル

ASP.NETスクリプトをバンドルするとき下記のように書きます。

public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles)
    {
        bundles.Add(new ScriptBundle("~/bundles/scripts").Include(
            "~/Scripts/jquery.js",
            "~/Scripts/jquery-ui.js"
            "~/Scripts/bootstrap.js"));    
    }
}

ただし、スクリプトが読み込まれる順番はランダムなので、jquery読み込んだ後にjquery-ui読み込むといったことがデフォルトでは出来ません。
デフォルトでパス追加した順序で読み込んでくれればいいのに!

指定した順序でバンドル

まず、下記のクラスを用意します。

public class AsIsBundleOrderer : IBundleOrderer
{
    public IEnumerable<BundleFile> OrderFiles(BundleContext context, IEnumerable<BundleFile> files)
    {
        return files;
    }
}

続けて、バンドルに読み込みたい順序でスクリプトのパスを追加し、バンドルの順序を指定します。

public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles)
    {
        var bundle = new ScriptBundle("~/bundles/scripts")
            .Include("~/Scripts/jquery.js")
            .Include("~/Scripts/jquery-ui.js")
            .Include("~/Scripts/bootstrap.js");
        // バンドルの順序をバンドルにファイルを追加した順序にします
        bundle.Orderer = new AsIsBundleOrderer();
        bundles.Add(bundle);
    }
}

後は画面で読み込めば、指定した順序でスクリプトが読み込まれます。

@using System.Web.Optimization

<head>
    @Scripts.Render("~/bundles/scripts")
</head>

DateTimeの罠

いきなりですが、下記コードを実行すると落ちます。

var unixTime = -2208988800000;
// 落ちる
var date = new DateTime(unixTime);

「1900/01/01 00:00:00」のunix timeからDateTimeを作成しようとしたコードです。
理由は「1970/01/01 00:00:00」以降のDateTimeしか作れないからです。
代わりにDateTimeOffsetを使うと上手くいきます。

var unixTime = -2208988800000;
var date = DateTimeOffset.FromUnixTimeMilliseconds(unixTime);

インストールしているツール

PCにインストールしているツールをさらす。

システム

QTTabBar

http://qttabbar-ja.wikidot.com/

エクスプローラーの拡張ツール。
エクスプローラーをタブ表示することが出来る。

7zip

https://sevenzip.osdn.jp/

ファイル圧縮・解凍ソフト。

ConEmu

https://www.fosshub.com/ConEmu.html

コンソールを拡張するツール。
範囲選択でコピペしたりドラッグでウィンドウサイズ変更したり出来る。

DiskInfo

http://www.rakuchinn.jp/diskinfo.html

ドライブのファイルだのファイル容量を棒グラフで表示してくれるツール。
どのフォルダがどのくらい容量をくっているのかが分かりやすい。

PatchCleaner

http://www.homedev.com.au/free/patchcleaner
http://wadachi.hatenablog.com/entry/2018/02/01/070000

「C:\Windows\Installer\」の不要ファイルを削除するツール。

コミュニケーション

IPメッセンジャー

https://ipmsg.org/

同一LAN内でメッセージやファイルをやり取りするツール。

パッケージ/バージョン管理

Anaconda

https://www.anaconda.com/download/#_windows

Pythonディストリビューション
主要なライブラリを一括でインストールすることが出来る。
仮想環境を構築することも出来る。
仮想環境ごとにライブラリのインストールも行える。

nodist

https://github.com/marcelklehr/nodist/releases

Node.jsのバージョン管理ツール。
複数のバージョンを共存させることができ、切り替えることも出来る。
パスワードを更新したら下記コマンドを実行すること。

npm -g config set proxy http://userid:password@proxyaddress:proxyportnumber
npm -g config set https-proxy http://userid:password@proxyaddress:proxyportnumber
npm -g config set registry http://registry.npmjs.org/

Git

SVN

TortoiseSVN

https://tortoisesvn.net/downloads.html

Windows用のSVNクライアントソフト。
日本語化するには日本語化パックをインストールすること。

TortoiseGit

https://gitforwindows.org/

Windows用のGitクライアントソフト。
Git for Windowsもあわせてインストールすること。
日本語化するには日本語化パックをインストールすること。

WinMerge

http://www.geocities.co.jp/SiliconValley-SanJose/8165/winmerge.html

ファイル、フォルダの差分を比較するツール。
これなきゃ開発出来ない。

テキストエディタ

サクラエディタ

http://sakura-editor.sourceforge.net/index.html.ja

軽量なテキストエディタ
これ大好き。
メモ取るときとか、ちょっとしたテキストの正規表現置換とかで使う。

Visual Studio Code

https://code.visualstudio.com/download

高機能なテキストエディタ
プログラミングやMarkdownテキストエディタとしても使える。

ER図

a5mk2

https://a5m2.mmatsubara.com/

ER図作成ツール。
SQLの発行も出来るすぐれもの。

プロキシ

stone

http://www.gcd.org/sengoku/stone/stonexp-2.3e.zip

ローカルプロキシ。
認証プロキシの前に通すことで認証情報を一元化することが出来る。
パスワードを更新したらC:\stone23xp\stone.cfgの認証情報を更新すること。

Burp Suite

https://portswigger.net/burp/

HTTPプロキシ。
リクエストを書き換えるのに使用する。
セキュリティ診断の擬似攻撃を行うのに使った。

キャプチャ/動画

PettyCamera

http://www.rainylain.jp/tools/ss/

キャプチャツール。

AG-デスクトップレコーダー

http://t-ishii.la.coocan.jp/download/AGDRec.html

デスクトップの操作を動画で記録するツール。

PDF

Acrobat Reader DC

https://acrobat.adobe.com/jp/ja/acrobat/pdf-reader.html

PDFビューワー。

CutePDF Writer

http://www.acrosoftware.com/ https://comicmall.jp/wiki.cgi?page=CutePDF http://www.khotta.org/ghost/index.html#disk

印刷時にPDF出力できるようにするツール。
PDF出力に対応していないソフトでも印刷できればPDFに出来る。
CutePdf Writerを使用するにはGhostscriptが必須。

Cube PDF Utility

https://www.cube-soft.jp/cubepdfutility/index.php

PDF編集ツール。
ページ順序の変更や結合、分割等を行える。

バックアップ

EaseUs Todo Backup Free

https://jp.easeus.com/backup-software/free.html

バックアップツール。
HDDからSSDに移行する際に使用した。

ドローツール

GIMP

https://www.gimp.org/downloads/ https://synclogue-navi.com/gimp-install

フリーのドローツール。
アイコンを自作する際に使用する。

地図

QGIS

https://qgis.org/ja/site/forusers/download.html

シェープファイルを表示するツール。