■処理の流れ 今回の Powershell スクリプトで行う一連の処理の流れは以下の通りです。 ① LAN 内の各 PC のローカルフォルダからログの CSV ファイルを収集。サーバ側のイベントログ も CSV 出力します。 ② CSV を結合。各ユーザ 1 日毎の初回ログイン、最終ログオフ時刻を抽出。 ③ユーザーごとの CSV ファイルに分割。 ④ ExceI に変換 ⑤ Excel テンプレートから「勤怠管理表」を生成。④で生成した Excel ファイルの値を参照する 参照式を配置します。 -Section 4 ー社内の全 PC の Windows ログオン / ログオフ時刻を集計するはなし ログ集計の流れ テンプレート (xlsx) ログファイル (CSV) サー ⑤生成 ①ファイル収集 ②結合 一時ファイル ( CSV) ③分割 勤怠管理表 (xlsx) 値を参照 ログファイル ( CSV) ④変換 ログファイル ( csv) 参照用ファイル ヨ , ューザー別 (xlsx) [ 図 4 ー 6 ] ログ集計処理の流れ ■「勤怠管理表」テンプレート 今回のスクリプトでは社内資料として使うことを想定した「勤怠管理表」の Excel ファイルを生成 します。このファイルはほかの担当者が適宜、備考欄などを編集するものです。しかし、ログオン / ログオフ時刻欄だけは、ファイルを生成した日以降も自動更新されるようにしなければなりません。 そこで今回は、直接 Excel ファイルに値を格納するのではなく、値格納用の Excel ファイルを別途生 成し、 Excel の参照式により外部参照を行います。外部参照の値は、一旦、全てデータシートに格納し ておけば、あとは通常通りプック内で VLOOKUP 関数などを使うことができます。 18
-Section 4 ー 社内の全 PC の Windows ログオン / ログオフ時刻を集計するはなし 162 1 66 1 69 171 1 73 1 75 176 179 181 182 185 188 189 1 92 1 93 1 94 1 95 196 : 198 1 99 200 epcsv $templ -Append -Encod i ng UTF8 } ¯eq Enab led "TRUE" } 190 → gci $dirPersonaICsv -FiIe ー % { group -AsHashTab 厄 -AsStr i ng -Property "SamAccountName 187 $AdUsers = Get-ADUser —F ilter * -Propert ies * ー sel ect SamAccountName Di spl ayName 186 # ActiveDirectory 上ののユーザ—ID と表示名を一括取得。 184 sp litCsv $temp2 $d i rPersonaI Csv "UserName" 183 # 個人別の CSV ファイルに分割 processCsv $temp2 180 # 「 temp2. csv 」から必要項目を抽出・加工し、上書きします。 sort —Un i que -Descend i ng ー Out-F ⅱ e $temp2 -Encod i ng UTF8 —Append 1 78 type $templ ー 177 # 重複を削除し、一時ファイル「 temp2. csv 」に出力 gCl -r $dirLog -FiIe ー % { ipcsv $_FuIIName 174 # ログ CSV を結合し、一時ファイル「 templ. csv 」に出力 Name $d i rLogRemote $d i rLog 1 72 co Ⅱ ectPcLog $computers. $computers = Get-ADComputer -FiIter * ー ? { $ 170 # 各 PC のログを収集 1 68 epEventLogFil e $d i rLog 8 167 # サーバ上のログを取得し、指定のフォルダに出力 1 64 # # # # # # メイン処理 # # # # # # # CSV の内容をそのまま Exc 引出力します。この Exc 引ファイル上の値を「勤怠管理表」から参照します。 —repl ace 十 BaseName $d i rKi ntai ( ($AdUsers [ $ ー BaseName] Di splayName) epK i nta i F Ⅱ es $ ー # 苗字と名前の間にスペースがあったりなかったりするので、スペースを除去しています。 # 「勤怠管理表」を Exc 引出力します。ファイル名は AD の表示名 ( 日本語の氏名 ) です。 BaseName convertTOXI sx $ ー Fu llName ()d i rRef + $ ー [ 図 4- 川「ログオン・ログオフ集計 . psl 」メイン処理部分 イル入出力が多いと処理時間が増えるので、実運用に乗せる段階では入出力を極力省いたほうがよい ように工程ごとに CSV を出力するようにしておいたほうが、デバッグしやすいです。 ( もちろん、ファ CSV ファイル「 ( ユーザー名 ). csv 」を作成します。 PowersheII で CSV ファイルを加工する際は、この 処理の途中、一時ファイルとして「 temp\templ. csv 」「 temp\temp2. csv 」およびユーザー名ごとの 各処理を行っている関数につきましては次へージ以降で解説します。ちなみに、このスクリプトは 収集した csv ファイル→ [ 結合 ] →「 templ. csv 」→ [ 重複排除 ] →「 temp2. csv 」 CSV 加工の流れは以下の通りです。 です ) 。 21 として整理しておいてもよいかもしれません。 CSV ファイルを扱う上で、 CSV 同士の結合や分割はよく行う処理なので、汎用性のあるモジュール → [ 分割 ] →「 ( ューザー名 ). csv 」
社内の全 PC の Windows ログオン / ログオフ時刻を集計するはなし -Section 4 ー 108 109 # 参照先 Exc 引ファイルを生成。 110 funct ion convertTOXl sx ($src, $dst) { # c sedXML の Exc 引ワークプックオブジェクトです。 $wb = new-object ClosedXML. Excel. XLWorkb00k $ws $wb Worksheets Add ("data") $ ⅱ nes = @(Get-Content $src -Encod i ng Defau は $array = @() $lines ー % { $array + = # 配列をシートにペーストします。 1 20 $ws. CeII ( 1. I)TnsertData( $array ) 1 22 # Exc 引ブックを保存します。 1 23 $wb. SaveAs ($dst) 1 24 125 } select -Skip 1 ) —repl ace [ 図 4 ー 18 ] 「ログオン・ログオフ集計 . p 引」参照用 Excel ファイル生成部分 [ 図 4 ー 1 印は加工した CSV を ExceI ファイルにする関数です。新規作成した ClosedXML のワークシー トに値を貼り付けます。 CSV ファイルを一旦、配列として読み込み、カンマで分割しながら 1 行ずつべー ストしています。 ( もっとシンプルな方法がありそうな気もします ) 126 127 128 # 社内資料用の Exc 引ファイルを生成。 129 # 値は convertToXlsx で生成した Excel を外部参照します。 130 # こちらももっと良い方法があるはず ( 131 funct i on epKi ntai F Ⅱ es ($name, $dst, $Di spIayName) 132 ヨ # 引 osedXML の Exc 引ワークプックオブジェクトです。 133 $wb = new-object 例 osedXML. Exce に XLWorkb00k ( $ 幻 Templ ate) : 134 135 # ActiveDirectory の表示名 ( 日本語の氏名 ) をシートで使えるよう、 136 # ワークシート " data " 上に値を格納します。 137 $ws $wb Worksheet ("data") 138 $ws CeIl ( 2 2 ) . VaIue = $D i spl ayName 139 140 # ワークシート " data2 " 上に参照式を設置します。 141 $ws2 $wb Worksheet ("data2") 142 i pcsv ()d i rPersonal Csv + $name + $data ー 143 144 145 146 147 148 149 150 152 153 154 156 158 159 1 60 } . csv") -Encod i ng Defau は + $name 十 $ commo n $data ー % { # 外部 E = 0 引 0 ーイルの値を参照する参照式です : $common 十 $ws2 CeII ($i, 1 ) FormulaAI $common 十 $ws2. CeIl ()i . 2 ) . FormuIaA1 $common 十 $ws2. Ce Ⅱ ( $ i , 3 ) . Formul aA1 . 幻 sx]data + $dirRef + 十 1 # ファイル名 ( 日本語氏名 +. 幻 sx ) で保存します。 $fil eName = $dst + $D i spl ayName + $wb. SaveAs ()f Ⅱ eName) . X ー SX [ 図 4-19 ] 「ログオン・ログオフ集計 . psl 」勤怠管理表 ExceI ファイル生成部分 ー図 4 ー 19 ] は社内資料「勤怠管理表」用の Excel ファイルを生成する関数です。こちらでも ClosedXML を使用します。テンプレートファイルを読み込み、ワークシート「 data 」上にユーザー名 ( 日 25
2 . ログを収集・加工する ここからは、ログ情報を集計し Excel ファイルを作成する実際のスクリプトを解説します。あくま で一例ですので、実際には要件によって変わってくる部分も多いと思いますが、参考にしていただけ ればと思います。 ■ログ集計スクリプト ではさっそく見ていきましよう一図 4- IOIO まずは DLL の読み込み、作業ディレクトリや Excel テン プレートファイルのパスの宣言です。 1 # DLL の読み込み 2 -CRef lect ion. AssembI ⅵ : LoadFiI e ( 3 "C:%Program Fil es (x86)YOpen XML SDKW2. 5 Ⅵ i bVDocumentFormat. 0penXmI. dll") 4 •CRef lect ion. AssembI y] : LoadFiI e ( 5 "C:%Iog_testVCIosedXML. dll " ) 6 7 8 # ファイル出力用フォルダと一時フォルダのパスです。 9 $d i r "C:%log—testV" 10 $dirLog = $dir + 勹0g\ 11 $dirTemp = $dir + 'temp% 1 2 $templ= $d i rTemp + 'templ. csv 1 3 $temp2= $d i rTemp + 'temp2. csv 14 $dirPersonalCsv = $dirTemp + personalCsvV" 15 $dirRef = $dir + "referral%" 1 6 $d i rK i nta i = $d i r + " 幻 sxV 1 8 # ExceI テンプレートファイル 1 9 $xITempIate = $d i r + "templ ateYtemplate-2017. 幻 sx' 20 21 # 各 PC のログ保管フォルダ 22 $d i rLogRemote "c$%l og-csv%" 23 24 # 該当フォルダがない場合は作成します。 26 27 # 前回実行時に生成したファイルを削除します。 28 rm $d i rK i nta i * $d i rRef* $d i rTemp* -Recurse -Force 29 -Section4- 社内の全 PC の Windows ログオン / ログオフ時刻を集計するはなし 25 $dirLog, $dirTemp, $dirRef, $dirKintail ? い (Test-Path $ - ) } ー % { mkdir $ ー } [ 図 4-10 ] 「ログオン・ログオフ集計 . psl 」宣言部分 そして、つぎの [ 図 4 ー 11 ] がメイン処理部分です。 20
-Section 4 ー社内の全 PC の Windows ログオン / ログオフ時刻を集計するはなし epcsv $Fu llName -Encod i ng UTF8 4 # イベントログに出力する文字列。ログオフスクリプトでは " がログオフしました。 [System. Secur i ty. Pr i nc ipal. Wi ndowsldent i ty] : GetCurrent ( ) $user i nfO 1 # ログインユーザー情報を取得。 2 3 6 9 24 25 十 " がログオンしました。 -EventId 8 -EntryType lnformat ion -ComputerName server01 1 2 Wr i te-EventLog -LogName App licat ion -Source App ⅱ cat ion 11 # ログをサーバに記録 —EventId 8 -EntryType lnformat ion -Message $msg 8 Wr ite-EventLog -LogName App ⅱ cat ion -Source App ⅱ cat ion 7 # ログを PC 本体に記録 $user i nfO. Name 5 $msg "yyyyMMdd-HHmss" 1 6 $j i kan = Get-Date -Format 1 5 $hostname = $Env:COMPUTERNAME —Message $msg 1 7 $d i r ー 'C:%Iog—csvV 19 # CSV 出力用フォルダが無い場合は新規作成 20 i f (' (Test-Path $d i r) ) {md $d i r} 22 # CSV ファイルバス 23 $Fu llName [str i ng] ()d i r + $hostname + # 過去のイベントログを取得し、 CSV 出力 + $j i kan 十 . CSV") 26 Get-EventLog App ⅱ cat i on Event I D ¯eq 今回登録するスクリプトは [ 図 4 図の通りです。 [ 図 4-2 ] 「ログオンイベントを記録 . psl 」 ■イベントログを CSV 出力→加工→ Excel 書式に取り込む カルのフォルダにログを出力した CSV ファイルが溜まってゆきます。 登録完了し、ポリシーが適用されると、徐々にイベントログが記録されてゆきます。同時に、各 PC のロー ClosedXML は GitHub ページからダウンロードできます。 「 CIosed 」というネーミングですが、ちゃんとオープンソース ( MIT ライセンス ) のライプラリです。 でも使用できるという利点があります。ちなみに「 CIosedXML 」は後述の「 OpenXML 」の反対 ( ? ) の かし、 ClosedXML のほうが動作も安定し、高速です。また、 ExceI がインストールされていない環境 lnterop. Excel.Application) を使うという手段もあります ( 筆者は VB script でよく使ってました ) 。し PowersheII から ExceI ファイルを扱う方法としては、 ExceI の COM オプジェクト (Microsoft. Office. PowersheII で ExceI ファイルを扱うために、今回は CIosedXML というライプラリを使用します。 ■ Powershell で Excel ファイルを扱う 集計も自動化し、そのまま社内資料に使える ExceI ファイルを出力できるようにしましよう。 提出する必要があります。かといって、毎回手作業でテータ集計するのは面倒です。せつかくなので、 情報として生かすのであれば、データを集計し、それらしい書式に整えた上で人事部などの担当者へ ただイベントログを集めて眺めているだけでは、情報を活用できているとは言えません。勤怠管理 https: 〃github.com/ClosedXML/ClosedXML/reIeases マ CIosedXML ダウンロード 16
zip 形式のリリースファイルを展開すると、中に「 ClosedXML. dll 」があります。こちらを Powershell でロードして使います。 CIosedXML は内部で OpenXML を使用しますので、 CIosedXML. dll の利用には OpenXML の DLL も必要です。下記ページから OpenXML SDK のインストーラ (. msi 形式 ) をダウンロードし、 インストールを行いましよう。 VOpenXML ダウンロード https: 〃 www.microsoft.com/en-us/download/details.aspx?id=30425 。 Op 印 1XMLOK2.5fo 「 M に「 09ft0 幵に e Select lnstallatlon FO に e 「 -Section 4 ー社内の全 PC の Windows ログオン / ログオフ時刻を集計するはなし X ロ ロー口 llb ホーム共有表示 ロ ファイル 0 罰 b の検 更新日時 アプリケーション拡 12 / / 01224 XML ドキュメント 却 12 / / 01 2 加 “ V25 ) lib ← 名前 Docu mentFormatOpenXmLdIl Docu ntFom t. 0 nX . x T 式餠 wil ーロ p ”刈 SDK2.5 M ロ os O に猷猷 IO 10 旧 d 餠 T01n ~ 旧 d 餠 . cli 改 e ! To ⅵ訓 toa 回日旧 d 釚 e 印 ow い Eo 「 0 一 2 *Prcgam Files X86 ) \ Op XML SDK*V2.5¥ 町お e. く改ー 2 個の項目 1 個の項目を選択 5. MB [ 図 4 ー 4 ] 「 DocumentFormat. OpenXml.dllJ [ 図 4 ー 3 ] rOpenXM 凵のインストール インストール先のフォルダの中に「 DocumentFormat. OpenXmI. dll 」がありますので、 こちら も先程の「 ClosedXML. dll 」と併せてロードしてください。 ■作業フォルタ 目蔓 ← 名前 更新日時 ファイルフォルダー 2017 / 10 / 11 11 : 31 ↓ ファイルフォルダー 2017 / 10 / 10 19 : template ログオン・ログオフ集計 . 1 2017 / 10 / 11 15 : 01 Windows Powe に .. ClosedXML. dll アプ丿ケーション拡弴 2017 / 10 / 05 10 : 15 [ 図 4-5 ] 作業フォルダ [ 図 4 ー司は今回の処理で使用する作業フォルダです。 Excel テンプレートは「 template 」フォ ルダに。収集したログの CSV ファイルは「 log 」フォルダに蓄積します。 《ローカルデ .. log_test ト サイズ 6 KB 788 KB 17
本語氏名 ) を格納。そして、ワークシート「 data2 」上には先程の参照用 Excel の値を参照する関数式 -Section4- 社内の全 PC の Windows ログオン / ログオフ時刻を集計するはなし を設置してゆきます。外部 ExceI ファイル内の値は、 ■定時実行で自動運用 イルに対する読み取りアクセス権が必要です ) 。 = ℃ :\hogehoge\[f00.xIsx]bar'!AI のようにフォルダバス、ファイル名、シート名、セルを指定することで参照できます ( 当然、そのファ にお声掛けください ( ^ ^ ) / ので、「こんな業務の自動化をやってみたよ ! 」「もっと良い書き方があるよ ! 」という方はぜひ気軽 個人的にも今後は一層 PowerShe Ⅱを使った業務自動化に地道に取り組んでいきたいと思っています えずは一つの例として頭の隅にでも置いていただければと思います。 イルのみを保存するよう改良が必要です。 Excel の処理の部分も改良する必要がありますので、とりあ ル数が徐々に増えて処理時間が長くなってしまいます。安定的に運用するためには、重複排除したファ 今回のスクリプトは実行する度にログファイルを新規に生成してそのまま溜めてしまうので、ファイ するようにしておけば、ログの集計と ExceI ファイルへの転記を全自動で行うことができます。尤も、 この「ログオン・ログオフ集計 . psl 」をタスクスケジューラに登録し、日中 1 時間に 1 回程度実行 て生じたいかなる損害に対しても、著者は責任を負いかねます。ご了承ください。 本書に掲載しております情報に基づいて行った機器の分解・改造、サンプルコードの実行等によっ ■こ注思 【スクリプト検証環境】 WindowsServer 2012 R2 Windows 10 Pro Creators Update 64bit PowerShell 5.1 奥付 発行日 : 2017 年 10 月 22 日 「 Gijutsu-san-saku 2017 Autamn 」 URL : http: 〃 clear-mint. net : clear-mint 印刷 : グラフィック 26 発行
社内の全 PC の Windows ログオン / ログオフ時刻を集計するはなし -Section 4 ー G26 A LastOff 1 Date FirstOn UserName 2 2017 / 10 / 11 a. tanaka 09 : 03 : 03 3 2017 / 10 / 10 a. tanaka 08 : 58 : 42 18 : 01 : 30 4 2017 / 10 / a. tanaka 08 : 57 : 58 18 : 11 : 45 5 2017 / 10 / 05 a. tanaka 08 : 52 : 22 18 : 27 : 30 6 2017 / 10 / a. tanaka 18 : OO : 55 08 : 55 : 08 7 2017 / 10 / 03 a. tanaka 18 : : 07 8 9 第 十 [ 図 4-14]CSV から加工・抽出した情報 抽出・加工後の状態が [ 図 4 ー 14 ] です。各ユーザーの 1 日ごとの初回ログオン時刻と最終ログオフ時 刻の一覧です。 さらにこの情報を業務用の「勤怠管理表」の書式に合わせたのが [ 図 4 ー 1 司の Excel ファイルです。 先述の通り、このファイルには値を保持せず、 [ 図 4 ー 1 引の Excel ファイル上の値を参照するようにし ています。 AH32 I J L 忖 0 P Q 只 S T LI V W X Y Z AB ACAD AE AF AGAHAI △ A B C D E F G H 1 勤怠管理表 「り CO ~ OO 2 0 1 7 年 1 0 月 田中 A 子 PO ロク時剣 開始時則 氏名 眈業時則 眈業時間 開始時刻終了時刻実爾時間残業時間 備考 日 日日日日日日日日 務 ワー一ワリ 4 ・ l-n CD 「ーー 終了時刻 1 8 : 圓 : 55 1 8 : 2 7 : 30 1 8 : 1 1 : 45 囲 : 5 5 : 08 囲 : 5 2 : 2 2 囲 : 5 7 : 5 8 data data 2 10 月 ト イ 塰備完了 [ 図 4 ー 15 ] 「勤怠管理表」 ExceI 23
■ログファイルの収集 38 { 49 { -Section 4 ー社内の全 PC の Windows ログオン / ログオフ時刻を集計するはなし ,"20141ハ橋1","SYStem. Byte , " 201310 01 " , " System. B 員 e ,"201511鴨10","SYStem. Byte , " 201311 11 " , " Sys 土 em. Byte , " 201502 お 10 " , "System. Byte , " 201506VW1 " , "System. Byte , " 201506 Ⅷ 01 " , "System. Byte , " 201506VW1 " , System. Byte , " 201506V 1 " , "System. Byte 30 32 39 40 42 43 44 } 45 46 50 53 54 } param ($hostnames, $d i rLogRemote, $dst) workf low coll ectPcLog 36 # workflow で foreach ー para Ⅱ引を使い実行すると、終了を待たず並列的に実行します。 35 # function だとシーケンシャルに処理されるので時間が掛かりますが、 34 # 各 PC からのログファイル収集を行うワークフロー cp $src $dst -Force + $dirLog 十 *. CSV + $hostname 十 $src foreach -para Ⅱ引 ($hostname i n $hostnames) { 48 funct ion epEventLogF Ⅱ e ()d i r, $ i d) 47 # ログを取得し、指定のフォルダに出力する関数 [ 図 4 ー 12 ] 「ログオン・ログオフ集計 . psl 」ログ CSV の出力・収集部分 EventID -eq $ i d } epcsv $Fu Ⅱ Name -Encod i ng UTF8 Get—EventLog App ⅱ cat ion . CSV") [string] ($dir + $jikan + $Fu llName yyyyMMdd-HHmmss" $j i kan = Get-Date -Format CSV 形式で保存します。ファイル名は現在時刻です。実際に出力した CSV は [ 図 4 ー 13 ] のようなもの グを CSV 出力する関数です。イベントログ ( アプリケーション ) の中から、 ID が 8 のものを抽出し、 その下 ( 48 行目 ~ ) の関数「 epEventLogFiIe 」はスクリプトを実行しているサーバ上のイベントロ に短縮できます。 理完了を待たずにどんどん実行するというだけで、マルチスレッドではないですが ) 、処理時間を大幅 ンシャルに実行されますが、ワークフローの「 foreach -parallel 」の場合、並列的に処理するので ( 処 Workflow Foundation) で処理します。通常の関数で「 foreach 」処理した場合、対象 1 件ずつ、シーケ この処理は 1 件ごとにそれなりの待ち時間が発生しますので、関数ではなくワークフロー (Windows ザーが各フォルダに対し読み取りアクセス権を持っていることが前提です。 ) です。各 PC の C ドライプ上の所定フォルダから CSV ファイルを収集します。 ( スクリプトの実行ユー [ 図 4 ー 12 ] の「 coIIectPcLog 」 ( 37 行目 ~ ) は LAN 内の PC からログファイルを収集するワークフロー となります。ここから必要な情報を抽出してゆきます。 20171011-113109. csv - メモ帳 方イル旧編集 ( 印書式 ( 0 ) 表示 ( Y ) しプ凹 科 System. Diagnost ics. EventLogEnt 「 y # 如司 icat ion/AppIicat ion / 8 ID", " chi 「 " , "Data" "lndex", "Category", "CategoryN1-rnbe 「 ", "EntryType Message , 」「 ce " , " R 印 c 印土 St 「 ings , "lnstanceld", "Tin•r , " 79153 " , , " 79151 , " 79145 " , " デバイス " , " 79146 " , " デバイス " , " 79147 , " デバイス " , " 79148 " , " デバイス " " , " 79149 " , " デバイス " , , " 79150 " , " デバイス " , , " デバイス " , , " 79152 " , " デバイス " デバイス " lnformat ion " , " ソース lnformat ion , lnformat i01 lnformat ion lnformat ion lnformat ion AppIication' のイベント田 ' 8 ' の説明が " ソース 'Application' のイベント ' 8 ' の説明が " ソース 'Application' のイベント ID ' 8 ' の明が " ソース 'AppIication' のイベント ID ' 8 ' の説明が のイベント ID ' 8 ' の説明が " ソース 'Application' のイベント ID ' 8 ' の説明が " ソース 'Application' lnfo 「士 ion " , " ソース 'Application' のイベント ID ' 8 ' の説明か lnformation , " ソース 'Application' のイベント ID ' 8 ' の説明が lnformation" " ソース 'Åpplication' のイベント ID ' 8 ' の説明が つかりません。必 つかりません。 つかりません。 つかりません。必 つかりません。必 つかりません。必 ! つかりません。必 つかりません。必 つかりません。 ロ [ 図 4 ー 13 ] ログを CSV に出力したもの 22
-Section 4 ー 60 { 社内の全 PC の Windows ログオン / ログオフ時刻を集計するはなし 56 64 65 68 69 70 71 72 76 84 88 89 90 93 } 94 sel ect group UserName Date 83 $data ー " は削除します。 82 # 初期値 " 99 : 99 : 99 " と " 81 # 1 日ごとの初回ログオン、最終ログオフ時刻を抽出します。 0ffT ime= (CDateT ime] $ ー T imeGenerated) . ToStr i ng ("HH:m: ss") UserName = $matches [ 1 ] , " \ \ (. * ) がログオフ " ) { i f ( $ ー Message -match OnT ime= ([DateT ime] $ ー T imeGenerated) . ToStr i ng("HH:m ・ ss") UserName = $matches [ 1 ] , " \ \ (. * ) がログオン " ) { if ( $ ー Message -match # 正規表現でユーザー ID 部分を抽出します。 Date (CDateTime] $ ー T imeGenerated) . TOStr i ng ("yyyy/MM/dd") ; Last0ff 0ffT i me F i rst0n = " 99 : 99 : 99 " ・ Date 0nTime ー " 99 : 99 : 99 " ・ # 後の工程を考慮した初期値を入れておきます。 $data ー Add-Member -NotePropertyMembers @{ ipcsv $src $data 59 funct ion processCsv ($src) 58 # 必要な情報のみを抽出し、 CSV を上書きします 57 # CSV の成型加工を行う関数 @{Name="Date" Express ion- { ( $ ー group @{Name="F i rstOn" ・ Expression={(( $ ー group @{Name-"LastOff" Expression-{(( $ ー group @{Name="UserName ・・ Expression-{( $ group epcsv $src -Encod i ng UTF8 measure —max Date ) . Max imum) } measure —min OnTime ) M i n i mum) " 99 : 99 : 99 —replace —replace measure —max UserName ) . Max imum} } measure -max OffT ime ) . Max imum) [ 図 4-16 ] 「ログオン・ログオフ集計 . p 引」 CSV 加工処理部分 CSV 加工を行う関数が「 processCsv 」一図 4 ー 16 Ⅱ 59 行目 ~ ) です。まず最初に 1 日ごとの初回 ログオン、最終ログオフ時刻を格納する「 FirstOn 」「 LastO 列を追加しています。この際のデフォ ルト値ですが、 83 行目以降で「 FirstOn 」の最小値、「 LastOff 」の最大値を選ぶ際にデフォルト値 が選ばれてはいけないので、それぞれ、「 99 : 99 : 99 」「一一 . ー」としています。 9 96 # 特定の列の値 ( 今回は UserName ) を基準に CSV を分割する関数 97 functi on sp ⅱ tCsv ($src, $dst, $key) 98 { 99 100 102 103 104 105 106 } # 保存先ディレクトリが存在しない場合は作成 i f ( ! (Test-Path $dst) ) { mkd i r $dst } # CSV を読込み、分割 # 1 行すっ追ファイルに記するという頭の悪い方法なので速度は遅いです C ipcsv $src ー epcsv ( $dst + . csv" ) -Append -Encod i ng UTF8 } [ 図 4-1 刀「ロクオン・ログオフ集計 . psl 」 CSV 分割処理部分 ー図 4 ー 1 刀は CSV を分割する関数です。特定の列の値を基準に分割します。 1 行ずつファイル に追記する方法なので速度は遅いですが、ワンライナーで済むので筆者は多用しています。 24