PowerShellでCSVを読み取るとき

 PowerShellでCSVを読み取るときの注意点は2つです。
 (ハマってしまいました)
 
 先に結論。
 
 ・PowerShellのCSV読み取りは、「Get-Content sample.csv | ConvertFrom-Csv」を用いる。
 ・CSVのヘッダー情報はCSVファイル1行目に書くか、ConvertFrom-Csvの-Headerで指定する。

 
 以下、詳細です。
 PowerShellでは、
 
 Import-Csv sample.csv
 
 というふうにImport-Csvコマンドレットを使うだけでCSVファイルを読み取ることができます。いや違った。読み取ることができるように見えます
 しかし、2つのトラップがあります。
 
 1.CSVファイルのヘッダー
 
 プログラミングをしていて、以下のようなエラーに悩まされました。
 
 PS C:\Users\USER> Import-Csv sample.csv
 Import-Csv : 引数 “name” の値が無効なため、引数を処理できません。引数 “name” の値を変更し、操作を実行し直してください。

 よくわからないエラーですよね。調べたところ、Import-Csvは-Headerオプションをつけないと、CSVファイルの1行目をヘッダーとして理解するということがわかりました。sample.csvは以下のようなファイルだったのです。
 
 1000,
 2000,あいう
 3000,
 4000,えお

 
 PowerShellは1行目をヘッダーとして理解しますが、ヌル値があります。ヌルはヘッダー情報としては無効となるので、エラーになってしまうのです。
 
 Import-Csv sample.csv -Header “ID”,”Name”
 
 というようにヘッダーを指定する。あるいは、
 
 ID,Name
 1000,
 2000,あいう
 3000,
 4000,えお

 
 というようにCSVファイル1行目にヘッダーを書けばOKです。
 
 2.文字コード
 
 CSVを表示させようとして、
 
 Import-Csv sample.csv -Header “ID”,”Name”
 
 として実行すると、文字化けします。
 
 ID Name
 – —-
 1000
 2000 ������
 3000
 4000 ����

 
 Unicodeにしなければならないそうです。しかし、Import-Csvには-Encodingが無い(おいおい)。そこで、
 
 Get-Content sample.csv > sample2.csv
 
 とするとsample2.csvはUnicodeになるので、これを読み取って処理していたのですが、うーん微妙。
 調べたところ、Get-Contentを使うべきらしい。
 
 Get-Content sample.csv | ConvertFrom-Csv -Header “ID”,”Name”
 
 ID Name
 – —-
 1000
 2000 あいう
 3000
 4000 えお

 
 ふむふむ。これでいいね。
 
 おまけ。1のCSVファイルのヘッダーについてですが、ConvertFrom-Csvは動きが異なります。エラーにならず、ヌルがある列がデータとして認識されなくなります。
 
 Get-Content sample.csv | ConvertFrom-Csv 
 
 1000
 —-
 2000
 3000
 4000

 
 となります。1行目の「1000,」がヘッダーとして認識され、ヘッダーのうちの「1000」の列のみが読み込まれます。
 
 わかりにくいなー。
 PowerShellのわかりにくさは今に始まったことではないけど。

Continue reading “PowerShellでCSVを読み取るとき”

五十嵐貴之『Windows自動処理のためのWSHプログラミングガイド』

 五十嵐貴之『Windows自動処理のためのWSHプログラミングガイド』を読みました。
 
 
 
 サンプルが豊富。
 何がいいって「共通モジュール」が掲載されていること。ダウンロードも出来ます。
 「共有モジュール」を使えば、いろいろと簡単にスクリプティングできます。
 さっそくフォルダバックアップと、Outlookメール送信と、いくつかのアプリを自動起動するスクリプトを作ってみました。会社で使ってみよう。
 
 しかし、VBScriptなので、Excel VBAとの親和性も高い。Windowsのシェル環境は、今後はPowerShellが中心になるのでしょうが、PowerShellはいまいち分かりにくい。WSH(VBScript)でいいような気がします。.Netの機能を使いたい場合のみPowerShellかなあ。
 
 今年66冊目。

Continue reading “五十嵐貴之『Windows自動処理のためのWSHプログラミングガイド』”

Windows PowerShellでメール送信

 Windows PowerShellでメール送信するスクリプトを書いてみました。
 @ITの「[運用]Windows PowerShellコマンド&スクリプティング入門(後編)」を参考にしました。
 
 .NET Frameworkのクラスを用いているのですが、そもそも私プログラマしていたのは10年以上前で、なおかつWindows系のプログラミングはほぼやったことがない。Googleで色々と調べたりしましたが、クラスライブラリの説明はMSDNにあります。ここをまず確認するべきでした。
 
 以下、スクリプトです。
 「★★★」のところには適切な値を入れてください。
 
# --------------------------------------------------
# 各種設定
# --------------------------------------------------
 
# メール情報。宛先は;で複数記載することが可能となる。
$smtp = “★★★” #SMTPサーバ(必須項目)
$targets = @(“★★★”,”★★★”) #送信先(必須項目・複数指定可能)
$from = “★★★” #送信元(必須項目)
$replyTo = “★★★” #ReplyTo先(オプション項目。一つだけ設定。NullでもOK)
$bcc = “★★★” #BCC先(オプション項目。一つだけ設定。NullでもOK)
 
# メールサブジェクトと本文。
$subject = “★★★”
# 本文はヒアドキュメントで記載。
$body = @”
★★★
★★★
★★★
“@
 
# --------------------------------------------------
# メール送信処理
# --------------------------------------------------
 
# New-Opjectコマンドレットで.NETクラスをインスタンス化。
$mail = New-Object Net.Mail.MailMessage
$mail.From = $from
$mail.ReplyTo = $replyTo
$mail.Subject = $subject
$mail.Body = $body
 
# エンコーディング。System.Text.Encodingの静的メンバにアクセスするため::を用いている。
$mail.SubjectEncoding = [Text.Encoding]::GetEncoding(“ISO-2022-JP”)
$mail.BodyEncoding = [Text.Encoding]::GetEncoding(“ISO-2022-JP”)
 
# To設定。複数設定可能。
foreach($to in $targets){ $mail.To.Add($to) }
 
# Bcc設定。設定なしも可。
if($bcc -ne “”){ $mail.BCC.Add($bcc) }
 
# ReplyTo設定。設定なしも可。
if($replyTo -ne “”){ $mail.ReplyTo = $replyTo }
 
# New-Opjectコマンドレットで.NETクラスをインスタンス化。
$sc = New-Object Net.Mail.SmtpClient($smtp)
# 送信。
$sc.Send($mail)
$mail.Dispose()

Continue reading “Windows PowerShellでメール送信”