none
変数内の代入するTextの改行方法について RRS feed

  • 質問

  • いつもお世話になっております。

    PowerShell初心者です。
    下記のような自動でメールを送信するスクリプトを作成しました。
    メール本文(Body)には"AAA", "BBB", "CCC"というテキストをそれぞれ次にライン(改行)に代入したいのですが
    どうすれば良いでしょうか?

    - 現在の結果:
    AAABBBCCC

    - 実現したい結果:
    AAA
    BBB
    CCC

    基本的な事で申し訳ないのですが、宜しくお願い致します。


    - - - スクリプト - - -
    $Body = "AAA"
    $Body = $Body + "BBB"
    $Body = $Body + "CCC"
    $oSender = @("AAAAAA <AAAA@aaa.aaa>") # For Testing Purpose
    $oFrom = "BBBBBB <BBB@aaa.aaa>"
    $oSubject = "Subject"

    $oSMTP = "Mail Relay Server"send-mailmessage -to $oSender -from $oFrom -subject $oSubject -smtpServer $oSMTP -body $Body -Attachments $oFile

    2014年12月2日 5:27

回答

すべての返信

  • http://www.atmarkit.co.jp/ait/articles/0709/20/news125_2.html

    // メールはCR+LFが普通でしたっけ?

    2014年12月2日 5:41
  • チャブーンです。

    単純に$Bodyに複数行のテキストを置きたい、のであれば、配列変数として定義すればよいのではないでしょうか?
    したのような感じです。

    ----
    $Body=@()
    $Body+="AAA"
    $Body+="BBB"
    $Body+="CCC"
    $oSender = ...

    追記:here stringを使う手もありますね。

    ----
    $Body=@"
    AAA
    BBB
    CCC
    "@

    追記の追記:英語フォーラムで実際にsend-mailmessageで複数行の本文を送った例が出ていますね。

    単純に""で囲むだけ、ですね。ちなみにPowerShellの改行コードはCRLFで、メールの改行コードといっしょですね。

    $Body="
    AAA
    BBB
    CCC
    "

    https://social.technet.microsoft.com/Forums/windowsserver/en-US/b5ef3955-51de-445e-a132-9928af8a962a/cant-send-a-smtp-email-with-a-multi-line-string-in-the-content?forum=winserverpowershell


    2014年12月2日 5:48
  • Hongliang様、チャプーン様

    返信ありがとうございます。早速下記のスクリプトでテストしたのですが、改行されませんでした。
    メール本文の結果:AAABBBCCC

    - - - Script - - -
    $Body = @()
    $Body = "AAA"
    $Body+= "BBB"
    $Body+= "CCC"

    $oSender = @("AAA <AAA@aaa.aaa>") # For Testing Purpose
    $oFrom = "BBB<bbb@bbb>"
    $oSubject = "TEST"
    $oSMTP = "MailRelay"
    send-mailmessage -to $oSender -from $oFrom -subject $oSubject -smtpServer $oSMTP -body $Body

    - - -  -


    here stringの場合ですが、実際のスクリプトは繰り返し処理で、$Bodyに順次値を代入している為現在方法を考えております。
    Chr(10) + Chr(13)などは使えないでしょうか?

    $Body = "AAA" + Chr(10) + Chr(13)
    *)残念ながら動きませんでしたが。。。

    2014年12月2日 6:53
  • チャブーンです。

    なるほど。ではエスケープシーケンスをつかってみてはどうでしょうか?

    http://news.mynavi.jp/column/powershell/014/

    ----
    $Body+="AAA`r`n"
    $Body+="BBB`r`n"
    $Body+="CCC"


    #配列変数は必要ありません
    2014年12月2日 7:01
  • チャプーン様

    ありがとうございます!!
    エスケープシーケンス"`r`n"で動きました!!

    ただ度々すいません。。。
    実際のスクリプトの$Bodyに関する記述が下記のようにテキストと変数を結合しております。

    $Body = "Scipt Started : " + $SciptRun + "-" + $SciptEnd

    下記のように単純にエスケープシーケンスを追加するとうごきません。。。
    Foreach (A in B)
    {
    $SciptRun = "2014/12/01"
    $SciptEnd = "2014/12/02"
    $Body = "Scipt Started : " + $SciptRun + "-" + $SciptEnd + "`r`n"
    }

    変数との結合の場合にはどのように結合すれば良いか分かりますでしょうか?
    質問ばかりで申し訳ありません。。。

    宜しくお願い致します。


    • 編集済み YNaka_1 2014年12月2日 7:54
    2014年12月2日 7:54
  • 結合相手が変数だろうがリテラルだろうが別に何も変わりません。

    $Bodyが+=じゃなくて=になっていて毎回上書きされてるとかその辺りの問題ではないですか?

    2014年12月2日 8:16
  • チャプーン様

    ありがとうございました。
    確かに、下記のように記載した場合には動きました。
    ただ、やはり実際のスクリプトで実行すると、改行が入りません。
    ちょっと調べさせてください。基本動くはずだと思います。
    大変ありがとうございました。

    $SciptRun = "2014/12/01"
    $SciptEnd = "2014/12/02"

    $Body+= "Scipt Started : " + $SciptRun + "-" + $SciptEnd + "`r`n"
    $Body+= "Scipt Started : " + $SciptRun + "-" + $SciptEnd + "`r`n"

    $oSender = @("AAA <AAA@aaa.aaa>") # For Testing Purpose
    $oFrom = "BBB <BBB@aaa.aaa>"
    $oSubject = "TEST"
    $oSMTP = "MailRelayServer"
    send-mailmessage -to $oSender -from $oFrom -subject $oSubject -smtpServer $oSMTP -body $Body

    2014年12月2日 9:09
  • チャブーンです。

    予期しないところでバグ(不具合というより予期しない動作)が出ているのかもしれないですね。このような場合ですが、Powershell ISEを使ってデバッグすると、とても分かりやすくなります。

    ISEでスクリプトをステップ実行(ブレークポイントを作って段階的にスクリプトを進める)すると、変数の値がどのように変化するかオンデマンドでわかりますので、どの行で問題が顕在化するのかといった、切り分けが可能になります。したのページを見てもらうとISEの使い方はわかると思います。

    http://codezine.jp/article/detail/4350


    2014年12月2日 9:18
  • チャプーン様

    まずは返信が遅くなり申し訳ありませんでした。
    ISEの情報ありがとうございます。色々といじってみました。スクリプトの各ラインの実行結果も見れて非常に便利でした。
    もう少し勉強しようと思ってります。

    改行の件ですが、私の実現したいコードでテストするとやはり改行が入りませんでした。
    $Bodyに代入している値にDateTime型(Get-Dateで取得)とString型と混在していたので、Get-Dateに「-Fromat」や「ToString」等を使って幾つかテストしたのですが、どれも駄目でした。。。
    単純に"日付"を$Bodyに代入すると動きます。

    取り急ぎ、下記のようにスクリプトを変更したので、掲載いたします。
    完全ではないのですがどなたかの参考になれば幸いです。

    スクリプト内容:
    複数のサーバーのWindows Event Viewerから「Error, Critical」のレコードだけをCSVに抽出し、管理者にメールで送付。メールは各サーバーに付き一件。
    *)サーバー上のスケジュールタスクで一日1回実行予定。

    抽出条件:
    1. 期間:スクリプト実行の前の日の8:00から実行日の8:00(24H)
    2. イベントタイプ:System, Application
    3. $oExceptionsで不要なイベントIDを削除
    *1) サーバーは$oComputersに追加・削除するだけでOKです。
    *2)除外したいイベントIDは$oExceptionsに追加・削除頂ければOKです。

    問題点:
    1. 下記コマンド、Get-WinEventでレコードを取得していますが、対象のレコードが無い場合に、エラーがでます。
    スクリプトはそのまま実行されるので、要件は満たしているので今後の課題にしたいと思っております。

    イベントの取得コード:
    $oWinEvents = Get-WinEvent -Computer $oComputer -FilterHashtable @{LogName=$lognames;StartTime=$oStartDateTime;EndTime=$oEndDateTime;level=1,2}

    エラーメッセージ:
    Get-WinEvent : No events were found that match the specified selection criteria

    エラーメッセージの参考資料:今後の課題にしよう
    http://stackoverflow.com/questions/26247652/powershell-get-winevent-no-events-were-found-that-match-the-specified-selection

    2. $oExceptionsで不要なイベントIDを抽出結果から抜いているのですが、抽出結果が1件の場合になぜか1の値が入りません。(結果がブランクになります。)
    2件以上は正常に代入されるようです。この件数はメールのSubjectにException後のレコード件数 / エラーの総件数で表示されるようにしています。
    件数代入コード:
    $ErrorNum =  $oWinEvents.count

    ***留意点:***
    1. もし、参考にする方がいれば幸いなのですが、スクリプトの動作保障はありません。自己責任でお願い致します。
    2. 素人の作ったスクリプトです。。。改善・もしくはよりよいスクリプトがあれば情報共有頂ければ幸いです。
    (結果を添付ファイルではなく、本文に直接挿入したかったのですが、今回は諦めました。今後の課題にします。)

    - - - スクリプト - - -
    $oComputers = @("ServerName1","ServerName2","ServerName3","ServerName4","ServerName5","ServerName6","ServerName7","ServerName8","ServerName9","ServerName10","ServerName11","ServerName12")
    # $oComputers = @("ServerName1") # Testing Purpose
    $Path = "D:\Eventlog\"
    $lognames = "system","application"
    $oEventType = @(1,2) # Level : 1=Critical, 2=Error
    $oExceptions = @("1111", "222")
    $i = $oExceptions.count


    $oStartTime = "08:00:00"
    $oStartDate = (Get-Date).AddDays(-1)
    $oStartDateTime = $oStartDate.ToString('yyyy/MM/dd') + " " + $oStartTime
    $oStartDateTime = Get-Date $oStartDateTime

    $oEndTime = "08:00:00"
    $oEndDate = (Get-Date)
    $oEndDateTime = $oEndDate.ToString('yyyy/MM/dd') + " " + $oEndTime
    $oEndDateTime = Get-Date $oEndDateTime

    # Check File Export Directory and create if it is not exist.
    If (-Not(Test-Path -path $Path))
    {
       # Create Folder if the Log folder does not exists.
       New-Item $Path -type directory
     }Else{}  

    # Collect Number of error records
    $ErrorNum = 0
    $ErrorNumExt = 0

    Foreach ($oComputer in $oComputers)
    {
    $SciptRun = Get-Date -Format "HH:mm:ss"
    $oWinEvents = Get-WinEvent -Computer $oComputer -FilterHashtable @{LogName=$lognames;StartTime=$oStartDateTime;EndTime=$oEndDateTime;level=1,2}
    $ErrorNum =  $oWinEvents.count
    $Body = ""
    $j = 0

        # - - - Check and remove Exception IDs - - -
        Do
        {
            $oWinEvents = $oWinEvents | Where-object {$_.id -notmatch $oExceptions[$j]}
            $j = $j + 1
        }until ($j -eq $i)

    $File = $Path + $oComputer + ".csv"
    $ErrorNumExt = $oWinEvents.Count
    $oWinEvents | Select TimeCreated, ID, LevelDisplayName, Message | Export-Csv –Path $File -notype –Encoding Default
    $SciptEnd = Get-Date -Format "HH:mm:ss"

    # - - - Send Mail - - -
    $oSender = @("AAA <AAA@aaa.aaa>")
    $oFrom = "BBB <BBB@aaa.aaa>"
    $oSMTP = "MailRelayServer"
    $oSubject = $oComputer + ":"+ "windows event Log" + "("+$ErrorNumExt +"/"+ $ErrorNum + ")"
    $Body+= "Server Name : " + $oComputer + "`r`n"
    $Body+= "Scipt Started : " + $SciptRun + "`r`n"
    $Body+= "Scipt End : " + $SciptEnd + "`r`n"
    send-mailmessage -to $oSender -from $oFrom -subject $oSubject -smtpServer $oSMTP -body $Body -Attachments $File
    }

    チャプーン様、最後になりましたが色々と勉強になりました。
    これから更に勉強したいと考えております。

    ご教授誠にありがとうございました。
    また、今後とも宜しくお願い致します。



    • 編集済み YNaka_1 2014年12月3日 6:17
    2014年12月3日 6:15
  • 以前投稿したスクリプトの問題点で、Objectの件数をチェックしたコードで、件数が1件しかない場合に値が入らないとの件で、問題が解決したので、情報まで記載致します。

    問題点:
    2. $oExceptionsで不要なイベントIDを抽出結果から抜いているのですが、抽出結果が1件の場合になぜか1の値が入りません。(結果がブランクになります。)
    2件以上は正常に代入されるようです。この件数はメールのSubjectにException後のレコード件数 / エラーの総件数で表示されるようにしています。
    件数代入コード:
    $ErrorNum =  $oWinEvents.count

    解決方法:
    上記でも記載していますが、これまで単純に「$oWinEvents.count」の記述方法で件数を取得しておりましたが、Objectの型や件数が0や1件の場合には上記の方法ではだめなようです。。。
    そこで、このように記述を変更し現在は正常に1件の件数も取得できるようになりました。「@($oWinEvents).count」

    参考URL:
    http://tech.guitarrapc.com/entry/2015/01/17/071137

    お役に立てれば幸いです。
    また、今後とも宜しくお願い致します。

    2015年5月15日 0:54