退屈なパワーシェル

職場では、定期的に自動テスト用のスクリプトを編集および追加する必要があります。 そして歴史的に、それらはPowershellで書かれていました。 しかし、記事はそれについてではありません。



通常、Powershellはシステム管理者向けの自動化ツールとして説明されています。 そして当然、彼らは彼にほとんど興味を示さない。 したがって、退屈な作業だけでなく使用できることを伝えたいと思います。



画像






実験のために、またさまざまなものとして、スクロールシューティングの仕組みを使って小さなゲームを書くというアイデアがありました。 最初は、コンソールを1つに制限したかったのですが、その後は心が勝ちました。 そのため、グラフィックエンジンでは、Windows.Forms要素を使用することが決定されました。



Add-Type -Assemblyname System.Windows.Forms function Create-Form ([string]$name, $x, $y, $w, $h){ $win = New-Object System.Windows.Forms.Form $win.StartPosition = "Manual" $win.Location = New-Object System.Drawing.Size($x, $y) $win.Width = $w $win.Height = $h $win.Text = $name $win.Topmost = $True $win } function Create-Label ([string]$name, $x, $y){ $label = New-Object System.Windows.Forms.Label $label.Location = New-Object System.Drawing.Point($x, $y) $label.Text = $name $label.AutoSize = $true $label } function Create-Button ([string]$name, $x, $y, $w, $h){ $button = New-Object System.Windows.Forms.Button $button.Location = New-Object System.Drawing.Point($x, $y) $button.Size = New-Object System.Drawing.Size($w, $h) $button.Text = $name $button.Enabled = $false $button } function Start-Scroll (){ $form = Create-Form "Let's GO!" 200 150 300 400 $start = Create-Label "Press SPACE to run" 90 200 $info = Create-Label "<-- AD --> 'Esc' for exit" 80 340 $ship = Create-Label "/|\" 135 400 $form.Controls.Add($start) $form.Controls.Add($info) $form.Controls.Add($ship) $form.ShowDialog() }
      
      





その結果、「開始画面」が表示されました。 しかし、同時に、スクリプトの実行は基本的にブロックされました。 ダイアログボックスを起動した後-このウィンドウからの応答を期待し、それ以上実行されません。 もちろん、マルチスレッドスクリプトを作成することもできますが、この問題に対するより簡単な解決策は、タイマーの追加です。



  $timer = New-Object system.windows.forms.timer $timer.Interval = 100 $timer.add_tick({Check}) $timer.start()
      
      





100ミリ秒ごとに、スクリプト自体で実行される内容に関係なく、タイマーはCheck関数を呼び出します。 時間間隔は目で選択されます。 私の感想によると、ゲームは非常にスムーズに更新されますが、必要に応じて、より頻繁に更新することができます。



後で判明したように、タイマーの「目盛り」に示されているすべての変数は、タイマーがアクティブ化された時点の値を保持し、同じデータセットで毎回Checkが呼び出されます。 したがって、関数が関連データにアクセスできるようにするために、必要なすべての情報がオブジェクトにパックされました。



  $Data = @{run = $false; hide = $false; pos = 135; shot = 0; spawn = 0; usb = 0; score = 0; fires = @(); enemies = @()}
      
      





Start-Scroll機能の外観を完成させるために、ホットキーコントロールとサウンドコントローラーを追加します。



  $form.KeyPreview = $True $form.Add_KeyDown({ if ($_.KeyCode -eq "A") {if ($Data.run -and -not $Data.hide -and $Data.pos -gt 0) {$Data.pos -= 5}} }) $form.Add_KeyDown({ if ($_.KeyCode -eq "D") {if ($Data.run -and -not $Data.hide -and $Data.pos -lt 265) {$Data.pos += 5}} }) $form.Add_KeyDown({ if ($_.KeyCode -eq "Escape") {$timer.stop(); $form.Close()} }) $form.Add_KeyDown({ if ($_.KeyCode -eq "Space") { if ($Data.run) { Set-Hide } else { $start.Text = ""; $Data.run = $true } } }) $sound = new-Object System.Media.SoundPlayer; $sound.SoundLocation = "$env:WINDIR\Media\Windows Information Bar.wav"
      
      





ゲームの合計には、ゲームが実行されているかどうかを示すフラグ$ Data.runがあり、一時停止として機能するフラグ$ Data.hideがあります。プレーヤーの座標(pos)、ポイント数(スコア)、ショット前のタイマー(ショット)と敵(スポーン)を追加する前のタイマー、および発射体と敵のデータをそれぞれ保存する2つの射撃と敵の配列。



コントロールは非常にシンプルであることが判明しました。AとDでキャラクターを移動し、Escで終了し、スペースバーで「スタート」ボタンを置き換え、ゲームを起動または一時停止します。 一時停止中にすべてのゲーム要素を非表示にするには、Set-Hide機能を使用します。



 function Set-Hide (){ if ($Data.hide) { $start.Text = "" $start.Location=New-Object System.Drawing.Point(90, 200) $Data.enemies | foreach {$_.obj.Visible = $true} $Data.fires | foreach {$_.obj.Visible = $true} $info.Visible = $true $ship.Visible = $true } else { $start.Location=New-Object System.Drawing.Point(10, 10) $Data.enemies | foreach {$_.obj.Visible = $false} $Data.fires | foreach {$_.obj.Visible = $false} $info.Visible = $false $ship.Visible = $false } $Data.hide = -not $Data.hide }
      
      





ゲームの基本的なロジックは、チェック機能で説明されています。



機能チェック()
 function Check () { #     -    if (!$Data.run) {return} #   -    if ($Data.hide) { if ($Data.usb -eq 0){ $start.Text = "" gwmi Win32_USBControllerDevice | %{[wmi]($_.Dependent)} | where {$_.DeviceID -notlike '*ROOT_HUB*'} | Sort Description | foreach { $start.Text += $_.Description +"`n" } $Data.usb = 500 } else { $Data.usb -= 1 } return } #    $ship.Location=New-Object System.Drawing.Point($Data.pos, 300) #  ,    if ($Data.shot -eq 0) { $Data.fires += @{ obj = Create-Label "*" ($Data.pos + 5) 290; x = $Data.pos + 5; y = 290 } $form.Controls.Add($Data.fires[$Data.fires.Length - 1].obj) $Data.shot = 4 } else { $Data.shot -= 1 } #  ,    if ($Data.spawn -eq 0) { $hp = Get-Random -minimum 4 -maximum 6 $pos = Get-Random -minimum 0 -maximum 200 $Data.enemies += @{ obj = Create-Button "$hp" $pos -22 30 20; x = $pos; y = -22; health = $hp } $form.Controls.Add($Data.enemies[$Data.enemies.Length - 1].obj) $Data.spawn = 150 * $Data.enemies.Length } else { $Data.spawn -= 1 } #   foreach ($fire in $Data.fires){ #   $fire.obj.Location = New-Object System.Drawing.Point($fire.x, $fire.y) $fire.y -= 5 #    / -    foreach ($enemy in $Data.enemies){ if ($fire.x + 5 -gt $enemy.x -and $fire.x -lt $enemy.x + 25 -and $fire.y -gt $enemy.y -and $fire.y -lt $enemy.y + 20){ $enemy.health -= 1 $enemy.obj.Text = $enemy.health $fire.y = -20 $sound.Play() } } } #         -   if ($Data.fires[0].y -lt -10) { $form.Controls.Remove($Data.fires[0].obj) $Data.fires = $Data.fires[1..($Data.fires.Length - 1)] } #   foreach ($enemy in $Data.enemies){ #   -  if ($enemy.health -gt 0){ $enemy.y += 1 } else { $Data.score += 1 $enemy.health = Get-Random -minimum 4 -maximum 6 $enemy.x = Get-Random -minimum 1 -maximum 200 $enemy.y = -22 $enemy.obj.Text = $enemy.health } #   $enemy.obj.Location = New-Object System.Drawing.Point($enemy.x, $enemy.y) #   -   if ($enemy.y -gt 300) { $Data.run = $false $start.Text = "Total score: " + $Data.score } } }
      
      





もちろん、そのようなゲームは「年間最優秀ゲーム」とは言えません。 しかし、Powershellを使用して、アクセス権を構成し、ローカルネットワークの動作を制御できることを示すことができます。



また、ボーナスとして、一時停止モードでは、接続されたUSBデバイスのリストが表示されます)



PSそして、記事のコードを収集するのが面倒な人は、スクリプトと実行するbat-nicknameでアーカイブをダウンロードできます



All Articles