サーバールームの室温監視を行う

はじめに


PowerShell Memonewpops

PowerShell Advent Calendar 2011
12

作成の経緯


3221
30


調


PowerShell

室温監視スクリプトの要件

  • 室温の閾値(許容上限値)を設定できる
  • サーバールームの室温を定期的に取得する
  • 取得した温度をメールのサブジェクトに設定して、管理者に通知する
  • 閾値超過に関係なく必ずメールを送る(スクリプトが稼働している確証が欲しい)
  • 閾値温度を超えている場合は、「警報メール」を管理者に通知する
  • 室温の取得に失敗した場合は「取得失敗メール」を管理者に通知する
  • 室温を定期的にCSVに出力する
  • 設定はファイルで定義できること
  • 動作試験が容易であること

ハードウェア調達


湿調


DLL(USBMeter.dll)
4980

スクリプト作成におけるポイントと解説

本投稿の後方に掲載したスクリプトについて簡単に解説します。

定義ファイルはXML


PowerShellXML
PowerShellXML
$xml = [xml](Get-Content ./config.xml)
$value = $xml.xxx.yyy.zzz

XMLSystem.Xml.XmlDocument
Windows Native DLLへのアクセス

USBMeter.dll.NetDLLC++Windows Native DLL
PowerShellWindows Native DLLUSBMeter.dllVB.NetVBCodeProvider
GetMethodInvoke
2つの起動モード

2


(一)  config.xml

(二)  config_test.xml


SwitchParameter
SwitchParameter-RecurseSwitchParameter
Get-ChildItem -Recurse

SwitchParameter
メールの送信

System.Net.Mail.SmtpClient

SmtpClientCredentials


スクリプト

室温監視スクリプト本体(CheckTemperature.ps1)


1: ###############################################################################
2: # スクリプト名 :CheckTemperature.ps1
3: # 概要 :USB接続型温度計の監視を行う
4: # Powered by Hiroshi Yoshioka
5: ###############################################################################
6: # 詳細
7: #
8: # 以下の2つのモードがあり、モード毎に定義ファイルを分けています。
9: # 1.通常モード → 定義ファイル:config.xml
10: # 2.テストモード → 定義ファイル:config_test.xml
11: # 動作確認を行う場合は、config_test.xmlを修正し、
12: # テストモードで実行してください。
13: #
14: # 使用例
15: # 1.通常モードで起動する
16: # C:\> ./CheckTemperature.ps1
17: #
18: # 2.テストモードで起動する
19: # C:\> ./CheckTemperature.ps1 -Test
20: #
21: ###############################################################################
22:  
23: Param([Switch]$Test)
24:  
25: # 初期定義
26: $CONFIG_DIRNAME = 'config'
27: $CONFIG_FILENAME = 'config.xml'
28: $CONFIG_FILENAME_TEST = 'config_test.xml'
29:  
30: $scriptDir = Split-Path $MyInvocation.MyCommand.Path -Parent
31: $CONFIG_DIR = Join-Path $scriptDir $CONFIG_DIRNAME
32: $CONFIG_PATH = Join-Path $CONFIG_DIR $CONFIG_FILENAME
33: $CONFIG_PATH_TEST = Join-Path $CONFIG_DIR $CONFIG_FILENAME_TEST
34: $CHECK_FAULT = -1
35:  
36: # USBMetr.dllが提供する関数を利用可能にする
37: $provider = New-Object Microsoft.VisualBasic.VBCodeProvider
38: $params = New-Object CodeDom.Compiler.CompilerParameters
39: $params.GenerateInMemory = $True
40: $source = @'
41: Module USBMeter
42:  
43: Public Declare Function GetVers Lib "USBMeter.dll" Alias "_GetVers@4" (ByVal dev As String) As String
44: Public Declare Function FindUSB Lib "USBMeter.dll" Alias "_FindUSB@4" (ByRef index As Integer) As String
45: Public Declare Function GetTempHumid Lib "USBMeter.dll" Alias "_GetTempHumid@12" (ByVal dev As String, ByRef temp As Double, ByRef humid As Double) As Integer
46: Public Declare Function ControlIO Lib "USBMeter.dll" Alias "_ControlIO@12" (ByVal dev As String, ByVal port As Integer, ByVal val_Renamed As Integer) As Integer
47: Public Declare Function SetHeater Lib "USBMeter.dll" Alias "_SetHeater@8" (ByVal dev As String, ByVal val_Renamed As Integer) As Integer
48: Public Declare Function GetTempHumidTrue Lib "USBMeter.dll" Alias "_GetTempHumidTrue@12" (ByVal dev As String, ByRef temp As Double, ByRef humid As Double) As Integer
49:  
50: Public g_temp As Double
51: Public g_humid As Double
52:  
53: Function GetVers_PS(ByVal dev As String) As String
54: GetVers_PS = GetVers(dev)
55: End Function
56:  
57: Function FindUSB_PS(ByRef index As Integer) As String
58: FindUSB_PS = FindUSB(index)
59: End Function
60:  
61: Function GetTempHumid_PS(ByVal dev As String) As Integer
62: GetTempHumid_PS = GetTempHumid(dev, g_temp, g_humid)
63: End Function
64:  
65: Function ControlIO_PS(ByVal dev As String, ByVal port As Integer, ByVal val_Renamed As Integer) As Integer
66: ControlIO_PS = ControlIO(dev, port, val_Renamed)
67: End Function
68:  
69: Function SetHeater_PS(ByVal dev As String, ByVal val_Renamed As Integer) As Integer
70: SetHeater_PS = SetHeater(dev, val_Renamed)
71: End Function
72:  
73: Function GetTempHumidTrue_PS(ByVal dev As String) As Integer
74: GetTempHumidTrue_PS = GetTempHumidTrue(dev, g_temp, g_humid)
75: End Function
76:  
77: End Module
78: '
@
79:  
80: $compilerResults = $provider.CompileAssemblyFromSource($params, $source)
81: $assembly = $compilerResults.CompiledAssembly
82: $USBMeter = $assembly.GetType("USBMeter")
83:  
84: # メソッド
85: $GetVers_PS = $USBMeter.GetMethod("GetVers_PS")
86: $FindUSB_PS = $USBMeter.GetMethod("FindUSB_PS")
87: $GetTempHumid_PS = $USBMeter.GetMethod("GetTempHumid_PS")
88: $ControlIO_PS = $USBMeter.GetMethod("ControlIO_PS")
89: $SetHeater_PS = $USBMeter.GetMethod("SetHeater_PS")
90: $GetTempHumidTrue_PS = $USBMeter.GetMethod("GetTempHumidTrue_PS")
91:  
92: #############################################################
93: # 関数名 Get-Temperature
94: # 概要 温度を取得する
95: # 引数 なし
96: # 戻り値 温度(取得できなかった場合は-1を返す)
97: # 戻り値型 Double
98: #############################################################
99: function Get-Temperature()
100: {
101: $retFault = -1
102:
103: # 温度計のデバイス名を取得する
104: $device = $FindUSB_PS.Invoke($null, @(0))
105:  
106: # デバイス名が空文字の場合は -1 を返す。
107: if ($device -eq ''){return $retFault}
108:  
109: # 温度/湿度を取得する
110: $ret = $GetTempHumidTrue_PS.Invoke($null, @($device))
111:
112: # 取得に失敗した場合は -1 を返す。
113: if ($ret -ne 0){return $retFault}
114:  
115: # 取得に成功した場合の処理
116: $temp = $USBMeter.GetField("g_temp").GetValue($null)
117: return $temp
118: }
119:  
120:  
121: #############################################################
122: # 関数名 Send-Mail
123: # 概要 メールを送信する
124: # 引数 以下のスイッチの中から1つ指定する
125: # -Normal 正常メール
126: # -Alarm 警報メール
127: # -Fault 失敗メール
128: # 戻り値 なし
129: # 戻り値型 なし
130: #############################################################
131: function Send-Mail($tempValue, [Switch]$Normal, [Switch]$Alarm, [Switch]$Fault)
132: {
133: if ($Normal.isPresent)
134: {
135: $mailConfig = $xml.USBMeter.NormalMail
136: }
137: elseif ($Alarm.isPresent)
138: {
139: $mailConfig = $xml.USBMeter.AlarmMail
140: }
141: elseif ($Fault.isPresent)
142: {
143: $mailConfig = $xml.USBMeter.FaultMail
144: }
145:  
146: ## メール設定(共通)
147: $common = $xml.USBMeter.Common
148: $from = $common.Mail.From
149: $smtp = $common.Mail.Smtp
150: ## メール設定(個別)
151: # 送信アドレス
152: $OFS = ','
153: $to = [String]$mailConfig.Address
154: $OFS = ' '
155: # サブジェクト
156: $subject = $mailConfig.Subject
157: $tempStr = "{0,4:##0.0}℃" -F $tempValue
158: $subject = $subject.Replace('[TempValue]', $tempStr)
159: $date = Get-Date -Uformat "%Y/%m/%d"
160: $subject = $subject.Replace('[Date]', $date)
161: $time = Get-Date -Uformat "%H:%M:%S"
162: $subject = $subject.Replace('[Time]', $time)
163:  
164: # メール送信
165: $mailer = New-Object System.Net.Mail.SmtpClient($smtp)
166: $mailer.Send($from, $to, $subject, "")
167:
168: # ログ出力
169: Write-Log $subject
170:  
171: # CSV出力
172: Write-Csv $tempValue
173: }
174:  
175: #############################################################
176: # 関数名 Write-Log
177: # 概要 ログファイルに文字列を書き込む
178: # 引数 書き込む文字列
179: # 戻り値 なし
180: # 戻り値型 なし
181: #############################################################
182: function Write-Log($msg)
183: {
184: $logMonth = Get-Date -Uformat "%Y%m"
185: $logDate = Get-Date -Uformat "%Y%m%d"
186: $now = Get-Date -Uformat "[%Y/%m/%d %H:%M:%S]"
187: $logfilePath = $logfilePathDef.Replace('[LogMonth]', $logMonth)
188: $logfilePath = $logfilePath.Replace('[LogDate]', $logDate)
189:  
190: $logfileDir = Split-Path $logfilePath -Parent
191: if ((Test-Path $logfileDir) -eq $false){[void](md $logfileDir)}
192: $msg = "$now " + $msg
193: Write-Host $msg
194: $msg >> $logfilePath
195: }
196:  
197: #############################################################
198: # 関数名 Write-Csv
199: # 概要 CSVファイルに時刻と温度データを書き込む
200: # 引数 温度
201: # 戻り値 なし
202: # 戻り値型 なし
203: #############################################################
204: function Write-Csv($temp)
205: {
206: $csvfileDir = Split-Path $csvfilePath -Parent
207: if ((Test-Path $csvfileDir) -eq $false){[void](md $csvfileDir)}
208:  
209: $date = Get-Date -Uformat "%Y/%m/%d %H:%M:%S"
210: $data = [String]$date + "," + [String]$temp
211: $data | Out-File $csvfilePath -Append -Encoding Default
212: }
213:  
214: ######################################################################
215: # メイン
216: ######################################################################
217:  
218: # 各種設定を読み込む
219: if ($Test.isPresent)
220: {
221: # テストモードの場合
222: $xml = [xml](Get-Content $CONFIG_PATH_TEST)
223: }
224: else
225: {
226: # 通常モードの場合
227: $xml = [xml](Get-Content $CONFIG_PATH)
228: }
229:  
230: # 温度の閾値
231: $tempThreshold = $xml.USBMeter.Temperature.Threshold
232: # チェック間隔(秒)
233: [int]$checkIntervalSec = $xml.USBMeter.CheckInterval.Second
234: # チェック間隔(分)
235: [String]$checkIntervalMin = "{0,4:0.00}" -F ($checkIntervalSec / 60)
236:  
237: # ログファイルの相対パス
238: $logfilePathDef = Join-Path $scriptDir $xml.USBMeter.Common.Logfile
239: # CSVファイルの相対パス
240: $csvfilePath = Join-Path $scriptDir $xml.USBMeter.Common.Csvfile
241:  
242: Write-Log '========================================='
243: if ($Test.isPresent)
244: {
245: # テストモードの場合
246: Write-Log '◆◆◆テストモードで起動しました◆◆◆'
247: }
248: else
249: {
250: # 通常モードの場合
251: Write-Log '◆◆◆通常モードで起動しました◆◆◆'
252: }
253: Write-Log '========================================='
254: Write-Log '   ■温度チェック:開始■'
255: Write-Log "    閾値:$tempThreshold ℃"
256: Write-Log "    間隔:$checkIntervalSec 秒($checkIntervalMin 分)"
257: Write-Log '========================================='
258:  
259: # 指定されたチェック間隔で、温度のチェックを行う
260: while($true)
261: {
262: # 温度を取得する
263: $temperature = Get-Temperature
264: # 温度の取得に失敗した場合は「失敗メールを送る」
265: if($temperature -eq $CHECK_FAULT)
266: {
267: $temperature = -1
268: Send-Mail $temperature -Fault
269: }
270: # 温度が閾値を超えているかチェックする
271: elseif ($temperature -gt $tempThreshold)
272: {
273: # 閾値を超えている場合は「警報メールを送る」
274: Send-Mail $temperature -Alarm
275: }
276: else
277: {
278: # 閾値を超えていない場合は「正常メールを送る」
279: Send-Mail $temperature -Normal
280: }
281: Start-Sleep -Seconds $checkIntervalSec
282: }

定義ファイル(./config/config.xml


1: <?xml version="1.0" encoding="Shift_JIS"?>
2: <USBMeter>
3: <Temperature>
4: <Threshold>35</Threshold>
5: </Temperature>
6:  
7: <CheckInterval>
8: <Second>900</Second>
9: </CheckInterval>
10:  
11: <Common>
12: <Mail>
13: <From>'室温チェッカー'&lt;admin@xxx.com&gt;</From>
14: <Smtp>xxx.smtp.com</Smtp>
15: </Mail>
16: <Logfile>log/[LogMonth]/Temperature_[LogDate].log</Logfile>
17: <CsvFile>csv/Temperature.csv</CsvFile>
18: </Common>
19:  
20: <NormalMail>
21: <Subject>[温度]OK : [TempValue] : [Date] [Time]</Subject>
22: <Address>admin@xxx.com</Address>
23: <Address>yoshioka@xxx.com</Address>
24: </NormalMail>
25:  
26: <AlarmMail>
27: <Subject>[温度]NG : [TempValue] : [Date] [Time]</Subject>
28: <Address>admin@xxx.com</Address>
29: <Address>yoshioka@xxx.com</Address>
30: </AlarmMail>
31:  
32: <FaultMail>
33: <Subject>[温度]NG : 検出失敗 : [Date] [Time]</Subject>
34: <Address>admin@xxx.com</Address>
35: <Address>yoshioka@xxx.com</Address>
36: </FaultMail>
37: </USBMeter>

久々に書き込み


2


PowerShell

BASIC認証つきHTTPSページへのアクセス

わりと最近作ったものとしては、
BASIC認証つきHTTPSページにあるXMLに定期的にアクセスして、情報を取得するスクリプトですかね。


CA署名のない証明書のサイトへアクセスする際、処理に苦労しました。


Delegateを使わなければ実現できなかったので、
以下のページからDownloadできるNew-Delegate.ps1を利用させてもらいました。
http://www.microsoft.com/japan/windowsserver2008/countdown2008/powershell/default.mspx

オセロゲームを作ろう(8):盤面描画とカーソル移動(3)

盤面描画とカーソル移動










Push-CursorPop-Cursor
カーソル位置のバックアップ


170 : function Push-Cursor()
171 : {
172 : $script:savedCursorPositionX = $rui.CursorPosition.X
173 : $script:savedCursorPositionY = $rui.CursorPosition.Y
174 : }

カーソル位置のリストア


176 : function Pop-Cursor()
177 : {
178 : Move-Cursor $script:savedCursorPositionX $script:savedCursorPositionY
179 : }

オセロゲームを作ろう(7):盤面描画とカーソル移動(2)

盤面描画とカーソル移動

前回紹介した、盤面描画とカーソル移動のサンプルについて解説します。

盤面描画


135 : # オセロ盤の描画
136 : function Draw-Board()
137 : {
138 : Write-Host "┌─┬─┬─┬─┬─┬─┬─┬─┐" -ForegroundColor $boardFgColor -BackgroundColor $boardBgColor
139 : for($i=1; $i -le 7;$i++)
140 : {
141 : Write-Host "│ │ │ │ │ │ │ │ │" -ForegroundColor $boardFgColor -BackgroundColor $boardBgColor
142 : Write-Host "├─┼─┼─┼─┼─┼─┼─┼─┤" -ForegroundColor $boardFgColor -BackgroundColor $boardBgColor
143 : }
144 : Write-Host "│ │ │ │ │ │ │ │ │" -ForegroundColor $boardFgColor -BackgroundColor $boardBgColor
145 : Write-Host "└─┴─┴─┴─┴─┴─┴─┴─┘" -ForegroundColor $boardFgColor -BackgroundColor $boardBgColor
146 : }


Draw-Init3
Draw-Board
139143for使



==================================
OthellobyPowerShell
==================================
┌─┬─┬─┬─┬─┬─┬─┬─┐
│ │ │ │ │ │ │ │ │
├─┼─┼─┼─┼─┼─┼─┼─┤
│ │ │ │ │ │ │ │ │
├─┼─┼─┼─┼─┼─┼─┼─┤
│ │ │ │ │ │ │ │ │
├─┼─┼─┼─┼─┼─┼─┼─┤
│ │ │ │ │ │ │ │ │
├─┼─┼─┼─┼─┼─┼─┼─┤
│ │ │ │ │ │ │ │ │
├─┼─┼─┼─┼─┼─┼─┼─┤
│ │ │ │ │ │ │ │ │
├─┼─┼─┼─┼─┼─┼─┼─┤
│ │ │ │ │ │ │ │ │
├─┼─┼─┼─┼─┼─┼─┼─┤
│ │ │ │ │ │ │ │ │
└─┴─┴─┴─┴─┴─┴─┴─┘


カーソル移動


152 : # 指定した位置にカーソルを移動する
153 : function Move-Cursor([int]$newX, [int]$newY)
154 : {
155 : $coordinate = New-Object System.Management.Automation.Host.Coordinates $newX, $newY
156 : $rui.CursorPosition = $coordinate
157 : }


Move-Cursor
XY
CoordinatesCursorPositionOK


X=2Y=4(53byte)
上下左右キー操作


46 : # 上下左右のキー操作
47 : if($keyCode -eq $keyMap::Up) {Move-CursorByDirection ([String]$keyMap::Up); continue}
48 : if($keyCode -eq $keyMap::Down) {Move-CursorByDirection ([String]$keyMap::Down); continue}
49 : if($keyCode -eq $keyMap::Left) {Move-CursorByDirection ([String]$keyMap::Left); continue}
50 : if($keyCode -eq $keyMap::Right){Move-CursorByDirection ([String]$keyMap::Right);continue}


Get-InputKey
Move-CursorByDirection
String$KeyMap(Keys)


159 : # 上下左右のキーを押した時のカーソル移動
160 : function Move-CursorByDirection([String]$key)
161 : {
162 : ($oldX, $oldY) = ($rui.CursorPosition.X, $rui.CursorPosition.Y)
163 : if($key -eq "Up") {$newX = $oldX; if($oldY -gt 0){$newY = $oldY - 1}}
164 : elseif($key -eq "Down") {$newX = $oldX; $newY = $oldY + 1}
165 : elseif($key -eq "Left") {if($oldX -gt 0){$newX = $oldX - 1}; $newY = $oldY}
166 : elseif($key -eq "Right"){$newX = $oldX + 1; $newY = $oldY}
167 : Move-Cursor $newX $newY
168 : }


Move-CursorByDirection162
163166(Up,Down,Left,Right4)

オセロゲームを作ろう(6):盤面描画とカーソル移動(1)

盤面描画とカーソル移動






1 : ###############################################################################
2 : # 初期処理/定義
3 : ###############################################################################
4 : # アセンブリ読み込み/参照
5 : $rui = $host.UI.RawUI
6 : [void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
7 : $keyMap = [Windows.Forms.Keys]
8 : # 初期化/定義
9 : $boardStartLine = 3
10 : ($startX, $startY) = (2, ($boardStartLine + 1))
11 : ($msgStartLine, $debugMsgStartLine) = (21, 23)
12 : $script:screen = $null
13 : #色定義
14 : ($boardFgColor, $boardBgColor) = ("Black", "White")
15 :
16 : ###############################################################################
17 : # メイン
18 : ###############################################################################
19 : function Start-Game()
20 : {
21 : Backup-ScrBuf
22 : Draw-Init
23 : Get-InputKey
24 : Restore-ScrBuf
25 : }
26 :
27 : ###############################################################################
28 : # キー入力受付関連の関数
29 : ###############################################################################
30 :
31 : # キー入力関数
32 : function Get-InputKey()
33 : {
34 : while($true)
35 : {
36 : # キー取得
37 : $keyInfo = $rui.ReadKey("NoEcho,IncludeKeyDown")
38 : $keyCode = $keyInfo.VirtualKeyCode
39 :
40 : # Enterを入力
41 : if($keyCode -eq $keyMap::Enter){continue}
42 :
43 : # Escを入力→終了
44 : if($keyCode -eq $keyMap::Escape){return}
45 :
46 : # 上下左右のキー操作
47 : if($keyCode -eq $keyMap::Up) {Move-CursorByDirection ([String]$keyMap::Up); continue}
48 : if($keyCode -eq $keyMap::Down) {Move-CursorByDirection ([String]$keyMap::Down); continue}
49 : if($keyCode -eq $keyMap::Left) {Move-CursorByDirection ([String]$keyMap::Left); continue}
50 : if($keyCode -eq $keyMap::Right){Move-CursorByDirection ([String]$keyMap::Right);continue}
51 :
52 : # Aを入力→現在の座標を表示
53 : if($keyCode -eq $keyMap::A)
54 : {
55 : $dX = $rui.CursorPosition.X
56 : $dY = $rui.CursorPosition.Y
57 : $dMsg = "X : " + $dX + " Y : " + $dY
58 : Show-DebugMsg $dMsg
59 : }
60 :
61 : }
62 : }
63 :
64 : ###############################################################################
65 : # メッセージ表示関数
66 : ###############################################################################
67 :
68 : # メッセージ表示
69 : function Show-Msg($msg)
70 : {
71 : Show-MsgInner $msgStartLine $msg $msgFgColor $msgBgColor
72 : }
73 :
74 : function Show-DebugMsg($msg)
75 : {
76 : Show-MsgInner $debugMsgStartLine $msg $boardFgColor $boardBgColor
77 : }
78 :
79 : function Show-MsgInner([int]$pos, [String]$msg, [ConsoleColor]$fg, [ConsoleColor]$bg)
80 : {
81 : Push-Cursor
82 : Move-Cursor 0 $pos
83 : Write-Host -NoNewLine " "
84 : Move-Cursor 0 $pos
85 : Write-Host -NoNewLine $msg -ForegroundColor $fg -BackgroundColor $bg
86 : Pop-Cursor
87 : }
88 :
89 : ###############################################################################
90 : # スクリーン操作関数
91 : ###############################################################################
92 :
93 : # スクリーンバッファのバックアップ
94 : function Backup-ScrBuf()
95 : {
96 : $rect = New-Object System.Management.Automation.Host.Rectangle
97 : $rect.Left = 0
98 : $rect.Top = 0
99 : $rect.Right = $rui.WindowSize.Width
100 : $rect.Bottom = $rui.CursorPosition.Y
101 : $script:screen = $rui.GetBufferContents($rect)
102 : }
103 :
104 : # スクリーンバッファのリストア
105 : function Restore-ScrBuf()
106 : {
107 : Clear-Host
108 : $origin = New-Object System.Management.Automation.Host.Coordinates(0, 0)
109 : $rui.SetBufferContents($origin, $script:screen)
110 : $pos = New-Object System.Management.Automation.Host.Coordinates(0, $script:screen.GetUpperBound(0))
111 : $rui.CursorPosition = $pos
112 : }
113 :
114 : ###############################################################################
115 : # 描画関連の関数
116 : ###############################################################################
117 :
118 : # 初期描画
119 : function Draw-Init
120 : {
121 : # タイトルの描画
122 : Clear-Host
123 : Write-Host "=================================="
124 : Write-Host " OthellobyPowerShell "
125 : Write-Host "=================================="
126 :
127 : # オセロ盤の描画
128 : Move-Cursor 0 $boardStartLine
129 : Draw-Board
130 :
131 : # カーソル位置の初期化
132 : Move-Cursor $startX $startY
133 : }
134 :
135 : # オセロ盤の描画
136 : function Draw-Board()
137 : {
138 : Write-Host "┌─┬─┬─┬─┬─┬─┬─┬─┐" -ForegroundColor $boardFgColor -BackgroundColor $boardBgColor
139 : for($i=1; $i -le 7;$i++)
140 : {
141 : Write-Host "│ │ │ │ │ │ │ │ │" -ForegroundColor $boardFgColor -BackgroundColor $boardBgColor
142 : Write-Host "├─┼─┼─┼─┼─┼─┼─┼─┤" -ForegroundColor $boardFgColor -BackgroundColor $boardBgColor
143 : }
144 : Write-Host "│ │ │ │ │ │ │ │ │" -ForegroundColor $boardFgColor -BackgroundColor $boardBgColor
145 : Write-Host "└─┴─┴─┴─┴─┴─┴─┴─┘" -ForegroundColor $boardFgColor -BackgroundColor $boardBgColor
146 : }
147 :
148 : ###############################################################################
149 : # カーソル操作関数
150 : ###############################################################################
151 :
152 : # 指定した位置にカーソルを移動する
153 : function Move-Cursor([int]$newX, [int]$newY)
154 : {
155 : $coordinate = New-Object System.Management.Automation.Host.Coordinates $newX, $newY
156 : $rui.CursorPosition = $coordinate
157 : }
158 :
159 : # 上下左右のキーを押した時のカーソル移動
160 : function Move-CursorByDirection([String]$key)
161 : {
162 : ($oldX, $oldY) = ($rui.CursorPosition.X, $rui.CursorPosition.Y)
163 : if($key -eq "Up") {$newX = $oldX; if($oldY -gt 0){$newY = $oldY - 1}}
164 : elseif($key -eq "Down") {$newX = $oldX; $newY = $oldY + 1}
165 : elseif($key -eq "Left") {if($oldX -gt 0){$newX = $oldX - 1}; $newY = $oldY}
166 : elseif($key -eq "Right"){$newX = $oldX + 1; $newY = $oldY}
167 : Move-Cursor $newX $newY
168 : }
169 :
170 : function Push-Cursor()
171 : {
172 : $script:savedCursorPositionX = $rui.CursorPosition.X
173 : $script:savedCursorPositionY = $rui.CursorPosition.Y
174 : }
175 :
176 : function Pop-Cursor()
177 : {
178 : Move-Cursor $script:savedCursorPositionX $script:savedCursorPositionY
179 : }
180 :
181 : # 処理スタート
182 : Start-Game



実行直後


上下左右キーを押下すると、キーの方向にカーソルが「1」移動します。
また、Aキーを押下すると現在のカーソル位置を表示します。
#カーソル位置を表示する処理はデバッグ目的で実装しています。

下に移動+カーソル位置表示

1
A










Enter



×



オセロゲームを作ろう(5):スクリーンバッファ操作(3)

スクリーンバッファの操作

前回に引き続き、前々回紹介した、スクリーンバッファ操作のサンプルについて解説します。

スクリーンバッファのリストア


# スクリーンバッファのリストア
function Restore-ScrBuf()
{
Clear-Host
$origin = New-Object System.Management.Automation.Host.Coordinates(0, 0)
$rui.SetBufferContents($origin, $script:screen)
$pos = New-Object System.Management.Automation.Host.Coordinates(0, $script:screen.GetUpperBound(0))
$rui.CursorPosition = $pos
}


Restore-ScrBufBackup-ScrBuf



(一)Clear-Host

(二)Coordinates

(三)SetBufferContents

(四)CursorPosition


Clear-Host
X=0,Y=0Coordinates
SetBufferContents
SetBufferContentsメソッド
System.Void SetBufferContents(Coordinates origin, BufferCell[,] contents)
System.Void SetBufferContents(Rectangle r, BufferCell fill)

SetBufferContents2
CoordinatesBufferCell2



1



オセロゲームを作ろう(4):スクリーンバッファ操作(2)

スクリーンバッファの操作

前回紹介した、スクリーンバッファ操作のサンプルについて解説します。

スクリーンバッファのバックアップ


# スクリーンバッファのバックアップ
function Backup-ScrBuf()
{
$rect = New-Object System.Management.Automation.Host.Rectangle
$rect.Left = 0
$rect.Top = 0
$rect.Right = $rui.WindowSize.Width
$rect.Bottom = $rui.CursorPosition.Y
$script:screen = $rui.GetBufferContents($rect)
}


PowerShell


(一)(Rectangle)

(二)(GetBufferContents)


RectangleLeft,Top,Right,Bottom
RightWindowBottom


GetBufferContents
GetBufferContentsメソッド
System.Management.Automation.Host.BufferCell[,] GetBufferContents(Rectangle r)

RectangleBufferCell2


$script:screen
$script:screen[0,5]  → 1行目の6桁目
$script:screen[1,10] → 2行目の11桁目