### Creating a Logon Script To Cleanup User Directories

In this post, I’ll discuss how I created a PowerShell script that runs when a user logs out of a terminal server and cleans up a directory in their home folder that was filling up with space due to application crashes.

This is the script I created:

$username =$ENV:USERPROFILENAME

$testpath = Test-Path -Path "$username\AppData\Local\Microsoft\Windows\ApplicationFolder"

if ($testpath -eq$true){

$items = Get-ChildItem - Path "$username\AppData\Local\Microsoft\Windows\ApplicationFolder"

foreach($i in$items){

Remove-Item -Path "$username\AppData\Local\Microsoft\Windows\ApplicationFolder\$i" -Recurse -Confirm:$FALSE } }else{} This code will get the users profile root path and then check if the application folder exists, if it doesn’t then the script ends. If it does exist, the script will cycle through each entry and remove it. The -Confirm:$FALSE parameter was added because the script kept asking for confirmation when deleting each item. This stops this behaviors and deletes each item without a confirmation prompt.

Now that I have the script and it is working as expected, I create a local group policy that will use:

Name – “powershell.exe”

Parameters – “-F “C:\path\to\file.ps1”

You can see this in the screenshot below:

This group policy was added under:

User Configuration – Windows Settings – Scripts (Logon/Logoff) – Logoff

Hopefully you can replicate what I have done and don’t experience any issue. Note that you might need to change the script execution policy on the machine before this works properly. Just something to keep in mind if the group policy isn’t working. Enjoy!

### Creating a Dynamically Changing WinForm

This is a fairly simple thing, if you know what you’re doing or if you have done it before. But if, like me, you are at a complete lost and sick of searching only to find half complete or even completely contradictory answers, then this is the guide for you.

My goals for this GUI was to have the form resize IF a tick box was $true (ticked) First I started off created a blank form with a single checkbox item, you can see this below: $form = New-Object System.Windows.Forms.Form
$form.Text = "New User Form"$form.Size = New-Object System.Drawing.Size(500,540)
$form.StartPosition = "CenterScreen"$form.FormBorderStyle = "Fixed3D"
$form.MaximizeBox =$false
$form.MinimizeBox =$false

$OKButton = New-Object System.Windows.Forms.Button$OKButton.Location = New-Object System.Drawing.Point(165,470)
$OKButton.Size = New-Object System.Drawing.Size(75,23)$OKButton.Text = "OK"
$OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK$form.AcceptButton = $OKButton$form.Controls.Add($OKButton)$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Point(245,470)$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Cancel"$CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton =$CancelButton
$form.Controls.Add($CancelButton)

$checkbox = New-Object System.Windows.Forms.CheckBox$checkbox.Location = New-Object System.Drawing.Point(100,100)
$checkbox.Size = New-Object System.Drawing.Size(100,25)$checkbox.Text = "Test Checkbox"
$form.controls.Add($checkbox)

$result =$form.ShowDialog()

That will create an empty form like the one below:

Now I will add the following code after all the objects but before the end $result variable which displays the form: $checkbox.add_checkstatechanged({

if ($checkbox.Checked -eq$True){

$form.size = new-object system.drawing.size(800,540) }else{$form.size = new-object system.drawing.size(500,540)

}

})

this is the part that will make the form larger if the checkbox is checked and return it to the original size if it isn’t checked. You can do SO many other things as well. For example, having a textbox enabled or disabled, changing the forms title, changing the colour of the form and to be honest just about anything you can think of.

This is the complete script you will need:

$form = New-Object System.Windows.Forms.Form$form.Text = "New User Form"
$form.Size = New-Object System.Drawing.Size(500,540)$form.StartPosition = "CenterScreen"
$form.FormBorderStyle = "Fixed3D"$form.MaximizeBox = $false$form.MinimizeBox = $false$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Point(165,470)$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"$OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton =$OKButton
$form.Controls.Add($OKButton)
$CancelButton = New-Object System.Windows.Forms.Button$CancelButton.Location = New-Object System.Drawing.Point(245,470)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)$CancelButton.Text = "Cancel"
$CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel$form.CancelButton = $CancelButton$form.Controls.Add($CancelButton)$checkbox = New-Object System.Windows.Forms.CheckBox
$checkbox.Location = New-Object System.Drawing.Point(100,100)$checkbox.Size = New-Object System.Drawing.Size(100,25)
$checkbox.Text = "Test Checkbox"$form.controls.Add($checkbox)$checkbox.add_checkstatechanged({
if ($checkbox.Checked -eq$true){
$form.Size = New-Object System.Drawing.Size(800,540) }else{$form.Size = New-Object System.Drawing.Size(500,540)
}
})

$result =$form.ShowDialog()

This script will create a form like in the screenshots below. In this screenshot the checkbox is not ticked:

And in this screenshot the checkbox has been ticked, making the form size noticeably wider:

Hope this helps someone struggling with getting started with some of the more complex WinForm tricks. Enjoy and comment if you need any help!

### Better Credentials Checking in PowerShell

This is something that I have recently created so that when a script asks for a credentials and there is an error, it doesn’t display a big, ugly and often intimidating error message for any poor soul trying to run my scripts.

That’s why I have recently (as in yesterday) “created” a “fool proof” way of entering and validating credentials against a domain.

This was a problem because whenever someone ran my script and did ANYTHING other than enter perfectly correct credentials, it would throw and error and exit the script. Or even carry on with the script WITHOUT THE CREDENTIALS, which obviously wouldn’t work. I know, I know. Amateur hour! But it was a crap system I must admit.

That’d why I spent and hour or so creating this beauty! It captures any errors, such as null credentials and incorrect credentials and only continues if a user exists with the same samaccountname as the one entered at the credentials prompt and if the user is in the domain admins group. Just for added “security”. Really I just want the appropriate people to be using the script.

This is the code I use!

#PROMPTING FOR CREDENTIALS
$cred =$host.UI.PromptForCredential("Need credentials", "Please enter your username and password.", "", "")
if ($cred -ne$null -and $cred -ne ''){ #CHECKING IF THE CREDENTIAL USERNAME EXISTS$check = $(try {Get-ADUser -Identity$cred.UserName} catch {$null}) if ($check -ne $null){ #GETTING CREDENTIAL USERNAME GROUPMEMBERSHIP$checkadmin = Get-ADPrincipalGroupMembership -Identity $cred.UserName$checkadminrefined = $checkadmin.SamAccountName #PUTTING GROUP MEMBERSHIP INTO AN ARRAY$array = $checkadminrefined #CHECKING IF USER GROUP LIST CONTAINS DOMAIN ADMINS if ($array -contains "Domain Admins"){
Write-Host "Credentials are GOOD! - Continuing with script" -ForegroundColor Green
Start-Sleep -Seconds 1
}else{
#RESULT IF USER IS NOT DOMAIN ADMINS
Clear-Host
Write-Host "Credentials are not a domain admin! - Close and start again" -ForegroundColor Red ;
$x =$host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
Exit
}
}else{
#RESULT IF NO USER CAN BE FOUND FROM CREDENTIAL USERNAME
Clear-Host
Write-Host "Check is empty - No user found matching credentials supplied! - Close and start again" -ForegroundColor Red
$x =$host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
Exit
}
}else{
#RESULT IF PROMPT IS CLOSED / NO CREDENTIALS SUPPLIED
Clear-Host
write-host "No credentials supplied - Close and start again" -ForegroundColor Red
$x =$host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
Exit
}

You should be able to read the script and see which each part does. I left comments in the script which I don’t normally do since it might be easier for you to see what its doing with pointers at each stage.

Enjoy!

### Create, Store & Use Encrypted Passwords With PowerShell

This is just a neat little “tactic” I use when I need to connect to the same machine over and over again but don’t want to drive myself insane with having to constantly enter the same username and password. For example, when testing a script.

First you need to enter your password, in plain text, into this script so that it can get the password. This a perfectly safe as it will only be at this point where the password is in plain text.

$password = "PUT PASSWORD HERE" | ConvertTo-SecureString -AsPlainText -Force This gets the password that you just entered and encrypts it and also puts it into the variable “password” Now you need to convert the password to an encrypted string of characters using the below command: $Password2 = $password | ConvertFrom-SecureString | Out-File "PATH TO TEXT FILE TO STORE PASSWORD" This puts the encrypted password into the text file for later use. Now, whenever you need to connect to a machine, you can put this into a variable along with the username. Then put them together into a credential and away you go: $Username = "DOMAIN\username"

$EcryptedPassword = Get-Content "LOCATION TO TEXT FILE" | ConvertTo-SecureString$Credential = New-Object System.Management.Automation.PSCredential($Username,$EncryptedPassword)

This builds the credential which you can now use with something similar to below:

Invoke-Command -Credential $Credential -ScriptBlock {echo "test"} -ComputerName "COMPNAME" -Authentication CredCSSP Enjoy! ### Linux New Users Form Following on from my recent upload on Linux scripting, I have yet again created a BASH script to make my Linux’ing life easier. This is also my second script created in BASH so I guess i’ve accomplished something by not running for the hills… What I needed was a script to make creating FTP users easier on my CentOS box. Below is a list of things I needed the script to accomplish: • Get a username from a user prompt • Get a Description from a user prompt • Create the new user • Change the users password • Add the username to /etc/vsftpd.userlist • Add the username to /etc/vsftpd/chroot_list • Make a directory in the home folder of the user called “ftp” • Change the permissions and ownership on this directory • Make a directory in the “ftp” folder called “files” • Change the permissions and ownership on this directory • Ask the user to create a share or not • Get a share name from user prompt • Make a directory in the users “files” folder with the same name as the share name • Mount the share to the “files” directory • Ask if the new user is the owner of the share • if so then change the ownershipa and permissions on the share • if not then just change the permissions on the share • Finish Here is my script for achieving these goals: #!/bin/bash #Creating new FTP users ##Gathering Variables echo "Enter a username" read Username echo "Enter a description" read Description useradd -m -c "$Description" -s /bin/bash $Username passwd$Username

echo "$Username" | tee -a /etc/vsftpd.userlist echo "$Username" | tee -a /etc/vsftpd/chroot_list

mkdir /home/$Username/ftp chown nobody:nobody /home/$Username/ftp
chmod a-w /home/$Username/ftp mkdir /home/$Username/ftp/files
chown $Username:$Username /home/$Username/ftp/files chmod 0700 /home/$Username/ftp/files

read -p "Create a share? [yn]: " CreateShare
if [[ $CreateShare = y ]] ; then read -p "Enter a share name: " ShareName mkdir /home/$Username/ftp/files/$ShareName mkdir /home/shares/$ShareName
mount --bind /home/shares/$ShareName /home/$Username/ftp/files/$ShareName elif [[$CreateShare = n ]] ; then
read -p "Enter the pre-existing share name: " ShareName
mkdir /home/$Username/ftp/files/$ShareName
if [ -d /home/shares/$ShareName ] ; then echo "Mounting share" mount --bind /home/shares/$ShareName /home/$Username/ftp/files/$ShareName
else
echo "Cannot find the share name : $ShareName" fi else echo "Not a y or n" fi read -p "Is$Username the owner of this share? [yn]: " ShareOwner
if [[ $ShareOwner = y ]] ; then chown$Username:$Username /home/shares/$ShareName
chmod 0775 /home/shares/$ShareName else echo "$Username is not the owner of $ShareName" chmod 0775 /home/shares/$ShareName
fi

echo "Finished creating user : $Username" * Insert your code here  Hopefully somebody gains something from this, probably not though. Enjoy! ### Linux Mounting Script Recently I have set up a VSFTPD CentOS 7 server and chrooted all the local users to their home directory. *If you know what that means$YourPoints = $YourPoints + 5* But when ever the system was rebooted or for any other reason that I don’t fully understand yet, the mounts from the shares to the users home directory would get lost. Because the users were chrooted into their home directories, I couldn’t use symbolic or hard links. Instead I had to use the: mount --bind option to make the mount accessible to the chrooted users. But since the mount kepts getting lost and I had grown tired of the users complaining that they couldn’t access the share. Plus it was taking too long manually remounting all the shares, let alone finding out which ones had become disconnected before the users started to complain. So I created a script to check and ask me if I wanted to mount the share. Just so you know, this is my first time scripting in BASH and I only did it because of my short lived love with Linux. Below is an example of the code in my script, I basically created one of these functions for each user: #TESTING USER3 if mountpoint -q /home/user3/ftp/files/share then echo "user3 is mounted" else echo "user3 is not mounted" read -p "Do you want to mount share? (y or n):" REPLY if [[$REPLY = y ]]
then
mount --bind /home/shares/share/ /home/user3/ftp/files/share
fi
fi

This way all I have to do is run this script and it will mount all of the shares for me. Let me know if there is an easier way to do this or if im missing something obviouse. Enjoy!

### Windows Favourites Folder Spelt “Favorites”

Something a little off topic today. Windows naming is weird… that’s it. I found this when trying to run a RoboCopy script to back-up my favourites “Internet Explorer” (Award winning, grama nominated, amazing browser).

This is what my script for RoboCopy used to look like:

robocopy C:\Users\harwoodm\Favourites d:\robocopy\Favourites /MIR /R:1 /W:5 /FFT /LOG:"C:\users\harwoodm\robocopy logs\favourites.txt" /TEE /NP /NFL /NDL

Little did I know that, even though in the Explorer it’s spelt “Favourites” the path has it as “Favorites”

EVIDENCE!!!

Does this make any sense to you, doesn’t to me…

Anway, hope this helped. Enjoy!

### Rock, Paper, Scissors In PowerShell

Another game today, I’ll be adding this to my big Games Project soon. Just need to implement it into the script.

First I started off by making the PowerShell window the correct size. I did this by adding:

$pshost = get-host$pswindow = $pshost.ui.rawui$newsize = $pswindow.buffersize$newsize.height = 500
$newsize.width = 500$pswindow.buffersize = $newsize$newsize = $pswindow.windowsize$newsize.height = 22
$newsize.width = 85$pswindow.windowsize = $newsize$pswindow.WindowTitle = "Rock, Paper, Scissors"

to the start of the function.

Next I created the meat of the game, here its just a simple do statement until either the score of the user or the score of the computer has reached or exceeded 3. Best of three sort of thing. Heres that part:

do {
$options = @("Rock","Paper","Scissors")$option = $options | Get-Random -Count 1 Clear-Host Write-Host "Your Score -$score" -ForegroundColor Green
Write-Host "Computer's Score - $computerscore" -ForegroundColor Red do {$selection = Read-Host "Selection"}while (("Rock","Paper","Scissors") -notcontains $selection) if ($selection -eq "rock" -and $option -eq "paper"){ Write-Host "You lose, the computer chose$option";
Start-Sleep -Seconds 1
$computerscore =$computerscore + 1
}elseif($selection -eq "paper" -and$option -eq "scissors"){
Write-Host "You lose, the computer chose $option" Start-Sleep -Seconds 1$computerscore = $computerscore + 1 }elseif($selection -eq "scissors" -and $option -eq "rock"){ write-host "You lose, the computer chose$option"
Start-Sleep -Seconds 1
$computerscore =$computerscore + 1
}elseif ($selection -eq$option){
Write-Host "Its a draw"
Start-Sleep -Seconds 1
}else{
Write-Host "You won, the computer chose $option" Start-Sleep -Seconds 1$score = $score + 1 } }until (($score -eq 3) -or ($computerscore -eq 3)) if ($computerscore -gt $score){ Clear-Host Write-Host "You lost, the computer scored$computerscore points whilst you only scored $score points" -ForegroundColor Red }else{ Clear-Host Write-Host "You won, you got$score points. More than the computer's $computerscore" -ForegroundColor Green } } Finally, I ended the code of by showing the user who won and giving then the option to exit the game or play again. Here is the code for that: do {$playagain = Read-Host "Do you want to play again? Y or N"} while (("Y","N") -notcontains $playagain) if ($playagain -eq "y"){
RPS
}elseif ($playagain -eq "n"){ exit } =================================================================================================== Hopefully you can see how this all comes together. Here is the entire script for the game: function RPS{$pshost = get-host
$pswindow =$pshost.ui.rawui
$newsize =$pswindow.buffersize
$newsize.height = 500$newsize.width = 500
$pswindow.buffersize =$newsize
$newsize =$pswindow.windowsize
$newsize.height = 22$newsize.width = 85
$pswindow.windowsize =$newsize
$pswindow.WindowTitle = "Rock, Paper, Scissors" [int]$score = 0
[int]$computerscore = 0 do {$options = @("Rock","Paper","Scissors")
$option =$options | Get-Random -Count 1
Clear-Host
Write-Host "Your Score - $score" -ForegroundColor Green Write-Host "Computer's Score -$computerscore" -ForegroundColor Red
do {$selection = Read-Host "Selection"}while (("Rock","Paper","Scissors") -notcontains$selection)
if ($selection -eq "rock" -and$option -eq "paper"){
Write-Host "You lose, the computer chose $option"; Start-Sleep -Seconds 1$computerscore = $computerscore + 1 }elseif($selection -eq "paper" -and $option -eq "scissors"){ Write-Host "You lose, the computer chose$option"
Start-Sleep -Seconds 1
$computerscore =$computerscore + 1
}elseif($selection -eq "scissors" -and$option -eq "rock"){
write-host "You lose, the computer chose $option" Start-Sleep -Seconds 1$computerscore = $computerscore + 1 }elseif ($selection -eq $option){ Write-Host "Its a draw" Start-Sleep -Seconds 1 }else{ Write-Host "You won, the computer chose$option"
Start-Sleep -Seconds 1
$score =$score + 1
}
}until (($score -eq 3) -or ($computerscore -eq 3))
if ($computerscore -gt$score){
Clear-Host
Write-Host "You lost, the computer scored $computerscore points whilst you only scored$score points" -ForegroundColor Red
}else{
Clear-Host
Write-Host "You won, you got $score points. More than the computer's$computerscore" -ForegroundColor Green
}

do {$playagain = Read-Host "Do you want to play again? Y or N"} while (("Y","N") -notcontains$playagain)
if ($playagain -eq "y"){ RPS }elseif ($playagain -eq "n"){
exit
}
}

I was quite surprised at how short I got the script to be, I think I may try to make the Blackjake game shorter as, lets me honest. Its barbaric in its construction.

### Headline News Reporter in PowerShell

Daft one today. Been a little  busy and lacking ideas as to what to do next, so don’t expect anything special in this post. That that you ever should with me…

Basically what this does is that it looks at the technology page the BBC news site and gives me the current 10 stories. Stupid right? I know, I know.

I might add this to a start-up script so that I can automatically get the latest tech news when ever I logon to my computer. Anyway, my code is below if you want to waste some hard drive space…

$result = Invoke-WebRequest -Uri http://www.bbc.co.uk/news/technology$path = "C:\Scripts\testing.txt"
$result.Links | Select innertext | Select-String "full article *" | Out-File -FilePath$path

(Get-Content "\$path") -replace "@{innerText=Full article" -replace "}","" | select -First 11

Enjoy!

### Games In PowerShell – Version 4

Quite a large update to my Games in PowerShell project, adding a new game, changing some of the styling of the game and changing the loading screen of the game.

You’ll be pleased and proud to know that the games code is now over a thousand lines long…At least fake being proud then.

As mentioned earlier, I have added a new game. This one is different from my other games because it is a text based adventure game about a dino that needs capturing. The player only successfully completes the game once they have captured the dino and also not been killed by it. Tall order, I know.

I also changed how the Quick Fire Character Counting game works. It now starts by giving the player a full second to see the word and guess how many characters it contains, then, each time the user gets a correct answer reduces the viewing time of the word by 30 miliseconds. That way the game gradually gets more difficult instead of being stuck at the same length, which is boring.

Here is the link to my code for the game

I will be updating my project page with this update as well. Enjoy!