Search This Blog

Monday, June 6, 2022

PowerShell: Custom profile

A custom profile allows you to set certain attributes, load some of your own self-made functions in advance and make your prompt a bit cooler.


Basically you place a .ps1 file named "Microsoft.PowerShell_profile.ps1" in your PowerShell folder.

This applies to Windows PowerShell ISE:

\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1

It applies to regular Windows PowerShell:

\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

It applies to PowerShell 7 (cross-platform):

\PowerShell\Microsoft.PowerShell_profile.ps1 

Being in admin mode doesn't seem to change the profile path. To find the profile path on your computer enter $profile and hit enter.

The code is basically a bunch of settings put together. You can customize it to your needs. In order to change the prompt, which is the bit of text to the left of what you enter, customize a function called prompt. First part sets your window title to the current version of PowerShell installed. It beeps a few times at startup. A custom theme of colors is applied. A few functions are placed in the $profile script to illustrate that you can preload some of them in advance. If you want to get rid of the text popping up at the top of PowerShell at startup, use the command line switch -nologo in your shortcut.


$ErrorView = "ConciseView"
$ErrorActionPreference = "Stop"

$Major = $psversiontable | select-object -ExpandProperty psversion | Select-Object -ExpandProperty major
$Minor = $psversiontable | select-object -ExpandProperty psversion | Select-Object -ExpandProperty minor
$Patch = $psversiontable | select-object -ExpandProperty psversion | Select-Object -ExpandProperty patch

$host.UI.RawUI.WindowTitle = (
    "PowerShell $Major.$Minor.$Patch"
)


# Beeps three times at startup
1..3 | foreach-object {[console]::beep(400,100)};

$host.ui.RawUI.BackgroundColor = "Black"
$host.ui.RawUI.ForegroundColor = "Yellow"
$host.ui.RawUI.CursorSize = 10 # 1-100

<#
$host.PrivateData.ErrorForegroundColor = "Green"
$host.PrivateData.ErrorBackgroundColor = "Red"
$host.PrivateData.ErrorAccentColor = "Blue"
$host.PrivateData.WarningBackgroundColor = "Yellow"
$host.PrivateData.WarningForegroundColor = "Red"
$host.PrivateData.FormatAccentColor = "Cyan"
#>


Set-PSReadLineOption -BellStyle None
# The following are hex colors
Set-PSReadLineOption -Colors @{
    "Command" = "#D2691E" # Chocolate
    "Comment" = "#A0A0A0" # Gray
    "ContinuationPrompt" = "#FA8072" # Salmon, The >> that shows up at linebreak
    "Default" = "#6B8E23" # Olive, like pipeline etc
    "Emphasis" = "#FFCCE5"
    "Error" = "#FF9999"
    "Keyword" = "#FFA500" # Orange, keywords such as -or/-and
    "Member" = "#9999FF" # When you ().member
    "Number" = "#E0E0E0" # gray
    "Operator" = "#FFE4C4" # bisque
    "Parameter" = "#FFC0CB" # Pinkish
    "Selection" = "#CCFFCC"
    "String" = "#CCFF99"
    "Type" = "#99CCFF" # Lightblue when you [cast]
    "Variable" = "#7FFF00" # Clear greenish
}

Set-Location D:\Temp\
function prompt
{
    $colors = "DarkGreen", "DarkCyan", "DarkRed", "DarkMagenta", "DarkYellow", "Gray", "DarkGray", "Green", "Cyan", "Red", "Magenta", "Yellow", "White"; #no Black, DarkBlue or Blue
        [console]::CursorVisible = 0;
        $Location = Get-Location;
        $Date = Get-Date -Format "HH:mm:ss";
    (write-host "|" -ForegroundColor "magenta" -nonewline);
    (write-host ">" -ForegroundColor "white" -BackgroundColor "darkmagenta" -NoNewline);
    (write-host "_" -ForegroundColor "White" -BackgroundColor "darkcyan" -NoNewline);
    (write-host "|" -ForegroundColor "cyan" -nonewline);
    (write-host "$Date " -foregroundcolor ($colors | get-random) -nonewline);
    (write-host "| " -foregroundcolor ($colors | get-random) -nonewline);
    (write-host "$location" -foregroundcolor ($colors | get-random) -nonewline);
    (write-host " > " -foregroundcolor ($colors | get-random) -nonewline);
        " ";
      }   

function Start-WoW {start-process "D:\BattleNet\World of Warcraft\_retail_\wow.exe"}


function Start-Blinking {1..50 | foreach-object {$host.ui.RawUI.BackgroundColor = ($colors = "DarkGreen", "DarkCyan", "DarkRed", "DarkMagenta", "DarkYellow", "Gray", "DarkGray", "Green", "Cyan", "Red", "Magenta", "Yellow", "White", "Black", "DarkBlue", "Blue" | get-random); start-sleep -milliseconds 100; Clear-Host}}


function Start-Nightsky {1..100 | ForEach-Object {start-sleep -milliseconds 100; write-host ("x").PadLeft((1..200 | get-random)) -ForegroundColor ("yellow","white","red","cyan","blue" | get-random)}}

PowerShell: Making a game

Using regular PowerShell code I managed to put together a concept of a game.


Quick description of the game style:

Fighting game in which you and the computer takes turn attacking each other. When the player uses an ability this triggers a function that runs an enemy attack while your actions are blocked. The enemy action also has a bit of delay built in to make the experience a bit smoother.

Every time you deal damage, you subtract and update the health bar of the enemy while your mana is reduced as a cost of your attack. You can instead spend your turn on healing yourself or restoring mana.

Just to prove a point I put in a background image and two placeholder images from online. The player images has to be png:s with built in transparency.

The game uses classes, functions and Windows Forms. I wrote the code with PowerShell ISE, but as you can see it runs perfectly in PowerShell 7.2.4.

The following is the code I used, note that I am no programmer or skilled scripter - this was an exercise in creativity. The script uses images placed in the same folder as the game-file itself.

[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
class Player {

    [string]$name;
    [int]$age;
    [int]$hp;
    [int]$mana;
    [int]$dmg;

    [void]AddAge([int]$years){
    $this.age += $years
    }
    [void]RestoreHP(){
    $this.hp = 5;
    Write-Host "Health back to 100%"
    }
    [void]RestoreMana(){
    $this.mana = 5;
    Write-Host "Mana back to 100%"
    }
    [void]Attack(){
    $this.dmg = 1;
    Write-Host "Dealing 1 dmg"
    }

    #Player () {} # Gets overloaded by the next line of code

    Player ([string]$name,[int]$age,[int]$hp,[int]$mana,[int]$dmg){
    $this.name = $name; $this.age = $age; $this.hp = $hp; $this.mana = $mana; $this.dmg = $dmg;
    }
}

<# Create players #>
$Player1 = [Player]::New("Player1", 20, 5, 5, 1);
$Player1;

$Player2 = [Player]::New("Player2", 60, 5, 5, 1);
$Player2;

<# Create the UI#>
$MainWindow = New-Object System.Windows.Forms.Form
    $MainWindow.text = "Battle Game"
    $MainWindow.size = New-Object system.drawing.size(800,600)
    $MainWindow.FormBorderStyle = "FixedDialog"
    $MainWindow.TopMost = $True
    $MainWindow.MaximizeBox = $True
    $MainWindow.MinimizeBox = $True
    $MainWindow.ControlBox = $True
    $MainWindow.StartPosition = "CenterScreen"
    $MainWindow.font = "Arial"
    $MainWindow.TopLevel = $True
    $MainWindow.Opacity = 1
    $Image = [system.drawing.image]::FromFile("$PSScriptRoot\map.jpg")
    $MainWindow.BackgroundImageLayout = "Stretch"
    $MainWindow.BackgroundImage = $Image
    $MainWindow.BackColor = [System.Drawing.ColorTranslator]::FromHtml("#F0E68C");

$FontFace = New-Object System.Drawing.Font("Garamond",20,[System.Drawing.FontStyle]::Bold)

$Lbl_Game = New-Object System.Windows.Forms.Label
    $Lbl_Game.location = New-Object System.Drawing.Size(150,10)
    $Lbl_Game.Autosize = $true
    $Lbl_Game.ForeColor = "Red"
    $Lbl_Game.BackColor = "Black" # "Transparent"
    $Lbl_Game.Text = "Highscore Heroes - A quest for riches"
    $Lbl_Game.font = $FontFace
    $MainWindow.Controls.Add($Lbl_Game)

    
$Lbl_Player = New-Object System.Windows.Forms.Label
    $Lbl_Player.Location = New-Object System.Drawing.Size(210,200)
    $Lbl_Player.Size = New-Object System.Drawing.Size (140,20)
    $Lbl_Player.BackColor = "Black"
    $Lbl_Player.ForeColor = "Lightblue"
    $Lbl_Player.Text = "Player 1"
    $Lbl_Player.textalign = "MiddleCenter"
    $MainWindow.Controls.Add($Lbl_Player)

$Lbl_Enemy = New-Object System.Windows.Forms.Label
    $Lbl_Enemy.Location = New-Object System.Drawing.Size(410,200)
    $Lbl_Enemy.Size = New-Object System.Drawing.Size (140,20)
    $Lbl_Enemy.BackColor = "Black"
    $Lbl_Enemy.ForeColor = "Orange"
    $Lbl_Enemy.Text = "Player 2"
    $Lbl_Enemy.textalign = "MiddleCenter"
    $MainWindow.Controls.Add($Lbl_Enemy)

$Txt_Health = New-Object System.Windows.Forms.TextBox
    $Txt_Health.Location = New-Object System.Drawing.Size(210,250)
    $Txt_Health.Size = New-Object System.Drawing.Size (140,20)
    $Txt_Health.BackColor = "Black"
    $Txt_Health.ForeColor = "LightGreen"
    $Txt_Health.Text = "#" * $player1.hp
    $Txt_Health.ReadOnly = $True
    $MainWindow.Controls.Add($Txt_Health)

$Txt_Mana = New-Object System.Windows.Forms.TextBox
    $Txt_Mana.Location = New-Object System.Drawing.Size(210,270)
    $Txt_Mana.Size = New-Object System.Drawing.Size (140,20)
    $Txt_Mana.BackColor = "Black"
    $Txt_Mana.ForeColor = "Cyan"
    $Txt_Mana.Text = "#" * $player1.hp
    $Txt_Mana.ReadOnly = $True
    $MainWindow.Controls.Add($Txt_Mana)

$Txt_EnemyHealth = New-Object System.Windows.Forms.TextBox
    $Txt_EnemyHealth.Location = New-Object System.Drawing.Size(410,250)
    $Txt_EnemyHealth.Size = New-Object System.Drawing.Size (140,20)
    $Txt_EnemyHealth.BackColor = "Black"
    $Txt_EnemyHealth.ForeColor = "LightGreen"
    $Txt_EnemyHealth.Text = "#" * $player2.hp
    $Txt_EnemyHealth.ReadOnly = $True
    $MainWindow.Controls.Add($Txt_EnemyHealth)

$Txt_EnemyMana = New-Object System.Windows.Forms.TextBox
    $Txt_EnemyMana.Location = New-Object System.Drawing.Size(410,270)
    $Txt_EnemyMana.Size = New-Object System.Drawing.Size (140,20)
    $Txt_EnemyMana.BackColor = "Black"
    $Txt_EnemyMana.ForeColor = "Cyan"
    $Txt_EnemyMana.Text = "#" * $player2.hp
    $Txt_EnemyMana.ReadOnly = $True
    $MainWindow.Controls.Add($Txt_EnemyMana)

Function player2_action {
if ($Player2.hp -gt 0) {
$Btn_RestoreHP.Enabled = $False; $Btn_RestoreMana.Enabled = $False; $Btn_Attack.Enabled = $False;
Start-Sleep -Seconds 1
$player1.hp -= 1
$Txt_Health.Text = "#" * $player1.hp
write-host "Player 2 does 1 dmg to player 1"
$player2.mana -= 1
Start-sleep -Seconds 1
$Btn_RestoreHP.Enabled = $True; $Btn_RestoreMana.Enabled = $True; $Btn_Attack.Enabled = $True;
} else {Write-Host "no action taken"}
}

$Btn_RestoreHP = New-Object System.Windows.Forms.Button
    $Btn_RestoreHP.Location = New-Object System.Drawing.Size(150,530)
    $Btn_RestoreHP.Size = New-Object System.Drawing.Size(140,20)
    $Btn_RestoreHP.TextAlign = "MiddleCenter"
    $Btn_RestoreHP.Text = "Restore health"
    $Btn_RestoreHP.Enabled = $False
    $Btn_RestoreHP.BackColor = [System.Drawing.ColorTranslator]::FromHtml("#BCB88A")
    $Btn_RestoreHP.Add_Click({
        $player1.RestoreHP()
        $Txt_Health.text = "#" * $player1.hp
    })
    $MainWindow.Controls.Add($Btn_RestoreHP)

        $Btn_RestoreMana = New-Object System.Windows.Forms.Button
    $Btn_RestoreMana.Location = New-Object System.Drawing.Size(290,530)
    $Btn_RestoreMana.Size = New-Object System.Drawing.Size(140,20)
    $Btn_RestoreMana.TextAlign = "MiddleCenter"
    $Btn_RestoreMana.Text = "Restore mana"
    $Btn_RestoreMana.Enabled = $False
    $Btn_RestoreMana.BackColor = [System.Drawing.ColorTranslator]::FromHtml("#BCB88A")
    $Btn_RestoreMana.Add_Click({
        $player1.RestoreMana()
        $Txt_Mana.text = "#" * $player1.mana
    })
    $MainWindow.Controls.Add($Btn_RestoreMana)

        $Btn_Attack = New-Object System.Windows.Forms.Button
    $Btn_Attack.Location = New-Object System.Drawing.Size(430,530)
    $Btn_Attack.Size = New-Object System.Drawing.Size(140,20)
    $Btn_Attack.TextAlign = "MiddleCenter"
    $Btn_Attack.Text = "Attack"
    $Btn_Attack.Enabled = $False
    $Btn_Attack.BackColor = [System.Drawing.ColorTranslator]::FromHtml("#BCB88A")
    $Btn_Attack.Add_Click({
        if ($player2.hp -gt 0) {
        $player1.Attack()
        $player2.hp -= 1
        $Txt_EnemyHealth.Text = "#" * $player2.hp
        $player1.mana -= 1
        $Txt_Mana.text = "#" * $player1.mana
        player2_action
        } else {
        $Btn_RestoreHP.Enabled = $False; $Btn_RestoreMana.Enabled = $False; $Btn_Attack.Enabled = $False;
        Write-Host "Enemy is dead, start a new game!"
        }
    })
    $MainWindow.Controls.Add($Btn_Attack)

    $Btn_NewGame = New-Object System.Windows.Forms.Button
    $Btn_NewGame.Location = New-Object System.Drawing.Size(10,10)
    $Btn_NewGame.Size = New-Object System.Drawing.Size(100,20)
    $Btn_NewGame.TextAlign = "MiddleCenter"
    $Btn_NewGame.Text = "New Game"
    $Btn_NewGame.BackColor = [System.Drawing.ColorTranslator]::FromHtml("#BCB88A")
    $Btn_NewGame.Add_Click({

        $Btn_RestoreHP.Enabled = $True; $Btn_RestoreMana.Enabled = $True; $Btn_Attack.Enabled = $True;
        $player1.hp = 5; $player1.mana = 5;
        $player2.hp = 5; $player2.mana = 5;
        $Txt_Health.text = "#" * $player1.hp
        $Txt_Mana.text = "#" * $player1.mana
        $Txt_EnemyHealth.text = "#" * $player2.hp
        $Txt_EnemyMana.text = "#" * $player2.mana
    })
    $MainWindow.Controls.Add($Btn_NewGame)

    <# Player Image #>
    $PlayerImg = New-Object System.Windows.Forms.PictureBox;
    $PlayerImg.Width = 140;
    $PlayerImg.Height = 200;
    $PlayerImg.BackColor = [System.Drawing.Color]::Transparent
    $PlayerImg.Location = New-Object system.drawing.point(210,300)
    $PlayerImg_file = (Split-Path -Parent $PSCommandPath) + "\hero.png";
    $PlayerImg.ImageLocation = $PlayerImg_file
    $PlayerImg.BorderStyle = 0;
    $PlayerImg.Background
    $PlayerImg.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::StretchImage;
    $MainWindow.controls.Add($PlayerImg)

    <# Enemy Image #>
    $EnemyImg = New-Object System.Windows.Forms.PictureBox;
    $EnemyImg.Width = 140;
    $EnemyImg.Height = 200;
    $EnemyImg.BackColor = [System.Drawing.Color]::Transparent
    $EnemyImg.Location = New-Object system.drawing.point(410,300)
    $EnemyImg_file = (Split-Path -Parent $PSCommandPath) + "\enemy.png";
    $EnemyImg.ImageLocation = $EnemyImg_file
    $EnemyImg.BorderStyle = 0;
    $EnemyImg.Background
    $EnemyImg.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::StretchImage;
    $MainWindow.controls.Add($EnemyImg)

    <# Show the game#>
    $MainWindow.add_shown({$MainWindow.activate()})
[void] $MainWindow.ShowDialog()