### MAC Address Lookup API Using PowerShell

Meet macvendors.com! I’ve used this website quite a bit in the past and recently saw that they have an API. This means I can query MAC address vendors using PowerShell instead of loading the site every time.

So I quickly threw together a small test to see if this would work using Invoke-WebRequest. You can see this below:

$mac_example = "3C-07-71-75-BC-32" Invoke-WebRequest -Uri "https://api.macvendors.com/$mac_example"

This returns the following information:

StatusCode        : 200
StatusDescription : OK
Content           : Sony Corporation
RawContent        : HTTP/1.1 200 OK
Connection: keep-alive
x-request-id: lhgjrrs7mf0desm40sifji9reoehi08b
Content-Length: 16
Cache-Control: max-age=0, private, must-revalidate
Content-Type: text/plain; charset=utf-8...
Forms             : {}
Headers           : {[Connection, keep-alive], [x-request-id, lhgjrrs7mf0desm40sifji9reoehi08b], [Content-Length, 16],
[Cache-Control, max-age=0, private, must-revalidate]...}
Images            : {}
InputFields       : {}
ParsedHtml        : mshtml.HTMLDocumentClass
RawContentLength  : 16

This provides with a lot of useless information. All I really want is the content field which contains the manufacturer information. So what I’m going to do is wrap the Invoke-WebRequest in brackets and select the content field as shown below:

(Invoke-WebRequest -Uri "https://api.macvendors.com/$mac_example").content Which simple returns “Sony Corporation”. Perfect. Enjoy! ### SharePoint Group Membership WinForm This is a little WinForm I created that would output the group membership for a domain user or FBA (Forms-Based Authentication) user on SharePoint. This is what the form looks like, it gives the option for a domain or FBA user and also checked if the user exists before trying to get the relevant information: The form first checks if CredSSP is configured on your machine to delegate your credentials to the SharePoint server. The form then loads, waits for your input, validates your input and finally collects the group information for your input. And finally, this is the code for the Winform. I’ve removed some details as they need to be filled in by you. Enjoy! #CHECKING CREDSSP SETTINGS if ((Get-Item WSMan:\localhost\Client\Auth\CredSSP).value -eq$false){
#CREDSSP NOT CONFIGURED, EXITING
Write-Host @"

CredSSP is not configured!

Please open an elavated PowerShell prompt and run:

Enable-WSManCredSSP -Role client -DelegateComputer sandsharepointf

"@
Exit
}else{}

[System.Windows.Forms.Application]::EnableVisualStyles()

#ICON FOR THE FORM
[string]$icon64=@" #base64data "@ #CONVERTING BASE 64 ICON INTO GRAPHIC$iconstream = [System.IO.MemoryStream][System.Convert]::FromBase64String($icon64)$iconbmp = [System.Drawing.Bitmap][System.Drawing.Image]::FromStream($iconstream)$iconhandle = $iconbmp.GetHicon()$icon = [System.Drawing.Icon]::FromHandle($iconhandle) #FORM$SharePoint_Membership_Form                 = New-Object system.Windows.Forms.Form
$SharePoint_Membership_Form.ClientSize = '400,278'$SharePoint_Membership_Form.text            = "SharePoint Membership"
$SharePoint_Membership_Form.TopMost =$false
$SharePoint_Membership_Form.StartPosition = "centerscreen"$SharePoint_Membership_Form.Icon            = $icon$SharePoint_Membership_Form.FormBorderStyle = "Fixed3D"

$Username_Label = New-Object system.Windows.Forms.Label$Username_Label.text             = "Enter a username:"
$Username_Label.AutoSize =$true
$Username_Label.width = 25$Username_Label.height           = 10
$Username_Label.location = New-Object System.Drawing.Point(146,12) #USERNAME TEXTBOX$Username_Textbox                = New-Object system.Windows.Forms.TextBox
$Username_Textbox.multiline =$false
$Username_Textbox.width = 175$Username_Textbox.height         = 20
$Username_Textbox.location = New-Object System.Drawing.Point(115,33) #VARIABLE FOR KEYDOWN$Username_Textbox_keydown = {}

#KEYDOWN ASSIGNED
$Username_Textbox_keydown = [System.Windows.Forms.KeyEventHandler]{ if ($_.keycode -eq 'Enter'){
$Search_Button.PerformClick() } } #REGISTER KEYDOWN HANDLER TO USERNAME TEXTBOX$Username_Textbox.add_keydown($Username_Textbox_keydown) #DOMAIN RADIO BUTTON$Domain_User_RB                  = New-Object system.Windows.Forms.RadioButton
$Domain_User_RB.text = "Domain User"$Domain_User_RB.AutoSize         = $true$Domain_User_RB.width            = 104
$Domain_User_RB.height = 20$Domain_User_RB.location         = New-Object System.Drawing.Point(120,64)
$Domain_User_RB.Checked =$true

$FBA_User_RB = New-Object system.Windows.Forms.RadioButton$FBA_User_RB.text                = "FBA User"
$FBA_User_RB.AutoSize =$true
$FBA_User_RB.width = 104$FBA_User_RB.height              = 20
$FBA_User_RB.location = New-Object System.Drawing.Point(215,64) #SEARCH BUTTON$Search_Button                  = New-Object system.Windows.Forms.Button
$Search_Button.text = "Search"$Search_Button.width            = 60
$Search_Button.height = 30$Search_Button.location         = New-Object System.Drawing.Point(171,89)

#SEPERATOR LINE
$Seperator_Label = New-Object system.Windows.Forms.Label$Seperator_Label.text            = ""
$Seperator_Label.AutoSize =$false
$Seperator_Label.BorderStyle = "Fixed3D"$Seperator_Label.width           = 390
$Seperator_Label.height = 2$Seperator_Label.location        = New-Object System.Drawing.Point(5,124)

#OUTPUT TEXTBOX
$Output_Textbox = New-Object System.Windows.Forms.TextBox$Output_Textbox.Multiline       = $true$Output_Textbox.Width           = 390
$Output_Textbox.Height = 142$Output_Textbox.Location        = New-Object System.Drawing.Point(5,131)
$Output_Textbox.ReadOnly =$true
$Output_Textbox.ScrollBars = "vertical" #ADDING CONTROLS TO FORM$SharePoint_Membership_Form.controls.AddRange(@($Domain_User_RB,$FBA_User_RB,$Seperator_Label,$Username_Label,$Username_Textbox,$Search_Button,$Output_Textbox))$Search_Button.add_click({

$Output_Textbox.Text = "" #DATE FOR OUTPUT$date = Get-Date
$username_value =$Username_Textbox.Text
$Username_Prefix =$null
$location = #base location #SETTING SEARCH VALUES BACK TO FALSE$Search_On_AD_User = $false$Search_On_FBA_User = $false #CHECKING IF USERNAME TEXTBOX IS EMPTY if ($Username_Textbox.Text.Length -le 0){
#IF EMPTY, VARIABLE IS FALSE
$Output_Textbox.AppendText("$date - $Username cannot be empty! n")$Username_Not_Empty = $false }else{$Username_Not_Empty = $true$Output_Textbox.Text = ""
}

#RUNS IF DOMAIN USER RADIO BUTTON IS CHECKED
if ($Domain_User_RB.Checked -and$Username_Not_Empty){
try{
$Output_Textbox.AppendText("$date - Searching for $username_value n") Get-ADUser -Identity$username_value

$Output_Textbox.AppendText("$date - Found user! n")

$Search_On_AD_User =$true
$Search_On_FBA_User =$false

$Username_Found =$true

}catch{
$Output_Textbox.AppendText("$date - Cannot find domain user n")
$Username_Found =$false
}
}

#RUNS IF FBA USER RADIO BUTTON IS CHECKED
if ($FBA_User_RB.Checked -and$Username_Not_Empty){

$SPAdmin = "sharepoint_admin_user"$credential = New-Object System.Management.Automation.PSCredential $SPAdmin, (Get-Content "$location\sharepoint_admin_user_encrypted_password.txt" | ConvertTo-SecureString )

$sb = {$username = $args[0] Add-PSSnapin microsoft.sharepoint.PowerShell$user = Get-SPUser -Limit All -Web http://SHAREPOINTSERVER |
Where-Object {$_.loginname -like "i:0#.f|fbamembershipprovider|$username"}

return $user }$Output_Textbox.AppendText("$date - Trying to find$username_value... n")

$invokeoutputfbasearch = Invoke-Command -ScriptBlock$sb -ComputerName SHAREPOINTSERVER -Authentication Credssp -Credential $credential -ArgumentList$username_value

if ($invokeoutputfbasearch){ #FOUND USER$Username_Found = $true$Search_On_FBA_User = $true$Search_On_AD_User = $false$Output_Textbox.AppendText("$date - Found FBA user!n") }else{ #NOT FOUND USER$Username_Found = $false$Output_Textbox.AppendText("$date - Cannot find FBA user n") } } #ONLY RUNS IF BELOW CONDITIONS ARE MET if ($Username_Found -and $Username_Not_Empty){ #ASSIGNING THE RIGHT USERNAME FORMAT if ($Search_On_AD_User){
$Username_Prefix = "*|DOMAIN_NAME\" }else{$Username_Prefix = "i:0#.f|fbamembershipprovider|"
}

$SPAdmin = "sharepoint_admin_user"$credential = New-Object System.Management.Automation.PSCredential $SPAdmin, (Get-Content "$location\sharepoint_admin_user_encrypted_password.txt" | ConvertTo-SecureString )

$sb = {$groups = $null$prefix = $args[0]$username = $args[1] Add-PSSnapin Microsoft.SharePoint.PowerShell$user = get-SPUser -limit all -web http://SHAREPOINTSERVER |
Where-Object { $_.loginname -like "$prefix$username" }$SPGroups = get-spsite -limit all |
Select-Object -ExpandProperty rootweb |
Select-Object -ExpandProperty siteusers |
Where-Object { $user.userlogin -eq$_.loginname } |
Select-Object -ExpandProperty groups |
Select-Object -ExpandProperty name
foreach ($i in$SPGroups){
$groups =$groups + "     - $i rn" } return$groups
}

$Output_Textbox.AppendText("$date - Collecting group info on $username_value... n")$InvokeOutputfinal = Invoke-Command -ScriptBlock $sb -ComputerName SHAREPOINTSERVER -Authentication Credssp -Credential$credential -ArgumentList $Username_Prefix,$username_value

$Output_Textbox.AppendText("n")$Output_Textbox.AppendText("$InvokeOutputfinal") }else{#THIS SERVES ONLY AS A TRAP TO STOP ANYTHING RUNNING } }) #DISPLAYING FORM [void]$SharePoint_Membership_Form.ShowDialog()

### Using DinoPass in PowerShell

This is a nice little trick I learnt whilst automating domain user creation with PowerShell, I found generating passwords in PowerShell was always ugly. Just see the example below from a previous post I’d made:

[string]$initialpassword = ([char[]](Get-Random -input$(47..57 + 65..90 +97..122) -count 8)) + (Get-Random -minimum 0 -maximum 10)

$passwordwithspacesremoved =$initialpassword.Replace(' ','')

$convertedpassword = ConvertTo-SecureString -AsPlainText$passwordwithspacesremoved -Force

This would generate a password like “cDUtxlvM5” which is just about as ugly as the code used to create it.

So I decided to use DinoPass instead since it created better looking passwords without the faff of generating them in PowerShell. This is a the code I used:

Invoke-WebRequest -Uri https://www.dinopass.com/password/strong | Select-Object -ExpandProperty content

Which would give me a much nicer, but still secure, password like “poorJump62”. Then to use it when automating domain user creation, I would use the below and put the whole thing into a variable that I would set the password to:

$super_secure_password = Invoke-WebRequest -Uri https://www.dinopass.com/password/strong | Select-Object -ExpandProperty content | ConvertTo-SecureString -AsPlainText -Force Enjoy! ### Blackjack in PowerShell This is a little function that mimics a simplified version of blackjack. I have wrapped it in a function for cleanliness and so that it can be called again. The rules are below: • Get a higher total than the dealer • Keep your total under 21 or you will be bust • That’s it Here is the code for you to try this out yourself, hope you enjoy! function blackjack{ #CHANGING NAME OF WINDOW$pshost = Get-Host
$pswindow =$pshost.UI.RawUI
$pswindow.WindowTitle = "Blackjack" #RESETTING GAME OVER VARIABLE$blackjack_game_over = $false #GENERATING A RANDOM TOTAL FOR THE DEALER$blackjack_dealer_total = Get-Random -Minimum 14 -Maximum 22

#CREATING AN ARRAY FOR THE USERS CARD NUMBERS
$blackjack_user_card_array = [System.Collections.ArrayList]::new("") #GENERATING A RANDOM NUMBER FOR THE USERS FIRST CARD$blackjack_user_first_card = Get-Random -Minimum 1 -Maximum 11

#ADDING USERS FIRST CARD TO ARRAY
$blackjack_user_card_array.Add($blackjack_user_first_card)

#CREATING A VARIABLE TO COUNT USERS TOTAL
$blackjack_user_total =$blackjack_user_first_card

Clear-Host

Write-Host "Your first card is $blackjack_user_first_card" #DO THIS (PLAY GAME) UNTIL THE GAMEOVER VARIABLE IS TRUE do { #GET USER INPUT do {$blackjack_input = Read-Host "Take another card? (Y or N)"}while (("y","n") -notcontains $blackjack_input) #IF USER INPUT IS VALID AND ISN'T BUST AND WANTS ANOTHER CARD if ($blackjack_input -eq "y" -and $blackjack_user_total -le 21){ #GENERATE A NEW CARD FOR THE USER$blackjack_user_new_card = Get-Random -Minimum 1 -Maximum 11

#ADD NEW CARD TO CARD ARRAY
$blackjack_user_card_array.Add($blackjack_user_new_card)

#ADD NEW CARD TO CARD TOTAL
$blackjack_user_total =$blackjack_user_total + $blackjack_user_new_card Clear-Host Write-Host "You have$blackjack_user_card_array"

#IF THE USER IS BUST
if ($blackjack_user_total -gt 21){ Write-Host "You went bust! The dealer won with " -ForegroundColor Red -NoNewline Write-Host$blackjack_dealer_total
$blackjack_game_over =$true
}

#IF THE USER DOESNT WANT ANOTHER CARD
}else{

Clear-Host

#OUTPUTTING THE FINAL SCORE
#Write-Host "You had $blackjack_user_total and the dealer had$blackjack_dealer_total"

#SWITCH TO SEE WHO WON
switch ($blackjack_user_total){ {$_ -gt 21}{Write-Host "You went bust! The dealer won with " -ForegroundColor Red -NoNewline; Write-Host $blackjack_dealer_total;$blackjack_game_over = $true; break} {$_ -eq $blackjack_dealer_total}{Write-Host "It's a draw, the dealer also had$blackjack_dealer_total"; $blackjack_game_over =$true; break}
{$_ -gt$blackjack_dealer_total}{Write-Host "You win! The dealer only had " -ForegroundColor Green -NoNewline; Write-Host $blackjack_dealer_total;$blackjack_game_over = $true; break} {$_ -lt $blackjack_dealer_total}{Write-Host "You lose! The dealer won with " -ForegroundColor Red -NoNewline; Write-Host$blackjack_dealer_total; $blackjack_game_over =$true; break}
default {Write-Host "Something happeneds that wasn't accounted for!" -ForegroundColor Red; break}
}
}
}until ($blackjack_game_over) #ASK USER IF THEY WANT TO REPLAY UNTIL INPUT IS A Y OR N do {$blackjack_play_again = Read-Host "Do you want to play again? Y or N"} while (("y","n") -notcontains $blackjack_play_again) #SWITCH TO EITHER PLAY AGAIN OR GO TO MAIN MENU switch ($blackjack_play_again){
"y" {blackjack}
"n" {exit}
default {exit}
}
}

### Enumerating PowerShell Options

This is quite a handy trick that I use when designing or just fiddling around with what I can do with PowerShell WinForms. The last time I used this was to get all the possible colours I could use for my form background, and also check the possible options for my border on a panel.

So if I wanted to find all the possible colours available for my forms background, I would use the following:

[enum]::GetValues([System.ConsoleColor])

Black
DarkBlue
DarkGreen
DarkCyan
DarkRed
DarkMagenta
DarkYellow
Gray
DarkGray
Blue
Green
Cyan
Red
Magenta
Yellow
White

or if I wanted to find out all the possible borders for my panel as I stated above, I would use the following:

[enum]::GetValues([System.Windows.Forms.BorderStyle])

None
FixedSingle
Fixed3D

Hope this helps, I know this is usually helpful for me. Enjoy!

### LAPS Winform

*UPDATE*

I have created the *final* iteration of this WPF form which can be found here

*UPDATE*

I didn’t like having to remote desktop into my domain controller and couldn’t figure out if there was a LAPS tool included in RSAT tools so I decided just to make my own and to add some extra features.

I wanted the GUI to look pretty much identity to the actual LAPS GUI. You can see the difference below:

You might be able to see that I  changed the “Set” button to say “Set and Update”. This was because I wanted the form to also attempt to update the group policy settings on the computer so that it would get a new password a lot quicker than the original GUI.

There’s not much else I can say, I will leave the entire script below for you to copy and paste. You will need to add the domain controller for your environment in the $domaincontroller variable at the top of the script. I have converted this to an EXE and run whenever I need it, never skips a beat. Let me know how you get on with it. Enjoy! #ADDING FORM ASSEMBLY Add-Type -AssemblyName system.windows.forms #ENTER DOMAIN CONTROLLER BELOW$domaincontroller = ""

#BASE 64 ICON
[string]$icon64 = "iVBORw0KGgoAAAANSUhEUgAAAEEAAAA5CAYAAABphkbpAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAB5kSURBVGhDpXt5cFXHne7j/TN/vKr33lRsa7lXV9KV7r3S1b1akcCAQWKXQEK7hAQICSTATjI1M37UeItdFY8dO2MncVyVpTLjmedZY7ABLYCIoTLl2PFCbLzFjrFjs9gGHmDQvn7v+37nHFkEucr2NPTtc0736e7f17+1++i/YXYaHeHPlJuBCeZJu2KaZtbNOLOqdT/FH5VeZpqcdt61ujH2MMn7KeVJNpni6xNeU7cPjjMxZc003jifaRhrM9O/+pxi/RTG7H3nHtNq6V67eXpKvXxx/RTrx6ZHeU1CxodZAteCMDHICXCo6TEONMFm+uXjKZdyTUoFidJEpt1BJidV2pXz3M0aUE91PW7Td/5Nqk6kijjLbDY7CxGVHggTzvh6U0BMTrv9zozv1Hv3M+N+Qb3lEQIwLDCuA2GI1XpBaI9rmpa9Z5rQNCdo8+OvSu/aS5qABtNERbwIdqG0fPzF5/F///5n+Nt77sQ9t/8VHn/oQez5x3/Eh2//ntUczSV8etopLXtgMHmc5hCkJOKskXNnAHxxvXEKuZLsBwzOxQljY2qlnmYGdQp1wJfcZ6pWGuPkNJSyjaPxVXrZ3pvCieMv4a927sDNkSyUpAaxNBxBWTQbpdGok8NRFAbSsLSkGN+57x6cPnfWuhofJ/juWEaTsu5nj/F1M0UQw1rc60Dg0JNs4czdaWzJe/B5EhDiWs1rXB0qqf04n5gOoPwOXsFt7W1YEIlgRXYOqmMFqApF0VJQiOUpATTk52NNRgYaeb8yFMaaggIsyM5GUSwb3/vufeyPq6hBvL49EJR1/3Wyl9TvoHTgdSBwFDX804HcB96tsqcHvFL1kxPiJHHMON5//TWsKMjHKq70yrR0bMyJozYliM2ZWajx+dCWnYW6QACt2RGsZ7klLxcbkgPYnBXH+tQMlKYH0VSxBuMjV9k3tYH1zfHGPY7UnL56aXO3C97PqRMEgpLaK3sU242j1dVCV6b8bJWcPGXKx5gY7756HEXBANbHYqhIC6KVhG9Ky8StJLCVhN6aE0NtQgK6cnJQ5/ehnaJRn5yMb0Vi2Jqcjq5QHFUEYnUsimXFBZgYFhDOIkgnONPSuF+ndGgw3TA2lzi4WngmXwOAFKU0tEOqVelnRmkJiFEMXr6AhVz9SrJ2eUoaOqL5aPGlojMjjJakFOyIRLExOQWdWVHUUyTayREt/hTcSnHZmJCMbcEQmnwBbI3GUZ6WgbWxXNRVrGXvk7QvjooWEUbI1yi9bCI7NKirPwVhlA1mgWDJAUErrDp15qyF049AmNG+RLdl3TqsicWxKiUV7Tn5aEpMwS4qPhG4iyvemOxDVzjbIZSKsoFAbM8ModWXgp3UHa28N4AI2NZoHlb607AoEjYdMU4u0Ez+lKCvmi1JrEbmFAeBMCvNvEkCTdbde8NFU/EmRHBGh3Bs716UZoSwLhBEB5Vg7U1+7BQAPj+2Z2WiwX8T2iMZBIAcwZVu1MqHs7CZOmM7dUNt0o3YGRNn+AhMBM3+VGxlPyvY36LMTAxcujCzDE5W+oqlR8M47+f2E8bZVC3c5L1gICi797Ig/D9BeysPUE6MlOHG0jKs5ITbIrloTErFruw4mpKS0RmlEky+CTvjESu3R7IpEoEZgDoiIdT6EtCZE0Yjyx1ZEXsujhFHtJGjykNZuHf37RzW8T8saS52/RWzCsnVwJzWQZ7irKSbax44yXvsKCmyKD3Kk2+eQGkogpZYPglNx04qwYYkH7ZlZVH2/QZEU1IiWZ4AJAawKxJHc2IyuiKZaExJNABUvyPLUZJSmvWslw5p9QVRT9NaWjIfI1PyPB0OtDQzP1Jm3DqLY62lsnNr3qa1441AGHbqrgWBciI9N5NmXXuX9j6Jd8RA3ODoil88/iMso2yvSyFrZ+WhOSGFhMRQRwCk/OqSkrCLsr4x0U/CYqYrbqVP0JKcaKJinJIdRXMSOYNlrY8cREAE1K5QDFXstzgrhJdPHL8eBJucltcl2pusPVN2kt6x94wI5oE5dYIImpVm3Vzz3E3iA4mC0N2ysYEmLY6NuQVkYa40RaGOLL0lHMLGAK0BZb4xMQldtAI11AnbCVBLog87MjKxKcWpr3frG/3UIQTI4YwIGhKSsJn9CoSf/+InHNUjziXavddsnH+ziFX2mntZz+Tgze02fwkQdOGygXSCeEKTaqiiVcjLp05I48pTF5DQrSRAfsD2LJpHlbQGum/LiZJDqByp/DaTwB3hMJUggaGoNBC4bXSrm1N8tCbSDRQNAlNBc7s4noO77v4bDi5KRKqWk1n6ymbiRZpOrc3VI9pp4t7zZ5xcoCCK6TpxmCFWadbNzKXXIUeZMY3sdH1ZKcqLCtBQWIBKeoBbtZIkVAA0+pKwjcqvSUqQZnIDCWyjjthEf+E2OlIbpTtoJRoJhEShWf5DmNYk4UZyQgg1NyVgc14hlsbjuOOO3ZyC5iky3ezNiT9aEHeNmFTvAnVN5vMpgjD4Ga+/DghKGlCZDz1XuWblCqzOjWN5Wio2cbIbSLhYXKzeHqLy4/2uKJUdlV47PcHqZN5T+7fRX9hOR6oxmdZAniRXvk3mNIX1OSE0J9NaRGOoZOB1C+t3m4VwiHWI1CI4c1Hhyb1TL4Il98py9pxg3N6jT4TRuZyl0Tmsg5tmP9e1OUo2qlAdR0dzPcrzqAcIRGWAKy6WT0owpdfkdxwlKTlp/wYC0iVrQVHYGaJypA6R31BPR0ou9AaayW2xCN9LoDINm4fZkp2LpdQ5P/7BozML4Fw4RDn6gBJt2bUCSmznaC6HQ5QtyeUf/QJx+DLWQR1ZO8vORB649w6U0tytSQ1Q5mO24ttyyOI0fxIJKblb5TLTSojFmwiQrIVc6a5wDs2plCNBpM7oYBRZlXSDtWtlsLU9MxsV9BwX0tz2Hz7o0G406keE/D/m027+kPmkm3WvugFO9fP9kRkihoZ099UVo/e+3bsBlCz3s0cPYSktQT1Zt5aOUCedmwbK/nYSJFHoouvbSvPXRc9PZlH+gRwp+QHN5IQuU6YB8yvq/EnoIAcJMPXTyOizPicPiyhmly6RKC25gUB2n/yY5SvA1acw/O4DOP/it3Duhe0YeO0vgI++zyaHWf8e213UC/LsnXdVjujnv8AJdu8+HGWv2owrK8jDGgZA26MF5hG2hcKOdaBOaCFnyFGSjtiZzeeJN1o02SLC6TnWJfiwk+F2A4ERYM3UGWrfwH42EaAV9EE2N9RySE2cxE9c5kS42uf24d3DnXhrzwqcfHohzhwoxNkD2fhoXw5O7inCez1VOPvyd/jOcb7zKQEgAm4XGJwLhC/pJ+ha2QtrHXU6hcceeciCnaqUDGyjgyOXV8quhUrvNnKIRKSNWr+Osi4P0mIKmsmNNH/bIznGGRZEkWO+mR1zgFQQxbC6kGL2ysvPcwGkzK6QiBMYevNevLd/GU7tL8K5nhgudIdx4UA6rh4M4PwBHy73hvHx/mx8uC+O9w9uIPsf4WTPcuIkXiAM6edrguBstLpA2BMvTWAhFWMVXedKsnBHNNchkNq/IYG6IUZHiSLSwSCpPkXBEwGg0pN/0OynSIgDEhPNajQl+AlYHOvSQlhJALdtbGLQp30FsvXE6xj/4+N485clONcbwbkDAZzbn4zhwwSg17m+0BvCR3sK8P4v83F2XxSnuktw4ul6Tvg3JIAiNcK4Yc4A6suaSBMqisCE015Z13r864N9iGUGUb1wASroGu9kMLUxkGoeYj1FYStd6FpfIh2qzx0kOVYCRFZEVkOAbCeQAmBdvBA3890rF8jKZuo+IAH/irf2leFUTx7OHQrhwtFMnDvsrP757iAJzsXp/mqKyi/JNL0YeuXbeL+7DO8+swgfHWtjH68TDIrT0Nf2E8gFDGImJ5wzCj3XWYHVj/GXrPHDxx5BdkYANfmFWEel1yFZlwtN3WAOlFxkioZFk3SMOqg7BICCKCnFzQRqTUqqAVBCZ+qV559ngCsrQBCm3yAhDTjdG8XZ7gyCkMmSq38wFZcoBp/0ZuGDvjVs28OVfp/zOcd3nsPIm7fjwwP5eGffQuDSXnbFuhFZjj8F4Uv5CVxunUPQQZLtHaG6lXpxLaUBoe3uR3/0MGJZGVhbmIv1lPHbqNwsPKbrLH9BSrGOfkIHdYBc5B0UkeqkG9HGck2aD5VUskVUhkcP9buDcwAdmoy9SA5Yaqt+sT8Tl8gJAwcycWV/KgaeDeDkgTAG376T7V5i+wFmznWKpnK8Fx/2lFCHkEte+y6fv016ZUKv4wTqBLnCGnQWANckqyO19LjGJ52wdlTzU52AUGaSZ9ZzpBs3F8VQwZWuIotvysqhy5yGLXSMVG6Kk+VTU9ESZ5uAD03xbKzOSGE0moqqpQtw+gOaNvVlKDNPDWDy1B6cfCqOyz034HyPD58dzMDAM+kY6U7Hxb4EfNATxsXjf8nGL/MdrrSAwClagr34YF8uzhzMw6v9HXxGszryEcvrFKNcYFIhM+JqfiPOJsAfu1FSPWfGFdcjSYE3z8lJcoLrP0zSP5+cGMZD37kbywvzUUSXuiyeh7K8ApTm5mNF4XwsLyjC0rw83EJvsygjHZVLFuHpJ37KjujITNP3U6fK6nLsLAb/8FN8QLYWwVf6/KYIr3az7E7GZ31J+LQ3g/WL6Tf8nH1I9rniOIyPf7MJn/Tk4OPePLze18Bn/0kQCA7TdZxgpzMCwc4OnfFnLtw8s8usUve8k5UYmXDecX7cNoTH8eOncLT/CHb/9e2or69F2YrlWL1yDVaUrURjYyPuv/9+/Pa3v3XeEQu7/r4iVRM15ekzGHr/J2T5AlzsTcZAXwCDBOFKTwo+6/URlAAu9QVxpieK033LMXSc/sF7j+DU0Wp8eLgYp55JxaeH5+O1nlp2RhCGzrD8KpwwO2tCLgDK01SoKr0zQC8Pjw6Z3pA/MaadbLVnkgs7QS6ZOR1z2Ui3AlNe/qS5YM6ZqFUYEh9j5PQ/4eQzxbi4n4T3pFP5B6281JuOC33pVJDpOEMgzvZm0zQW4AxF4HRPCGcOpeHcr4I42VuAE4doIaYoDkOyOHOCwFIDupNS1rSkK2weeqDSimnnsNNEQ3kclz49gyef+AWqaypx7/33GVFePx5uo1PDfE5fXvfKLgijLHWpd3TVVFuJHVtbcfDp/WQzOUnU9BPP4o/7b8ElOkUXe9Isf9aTgUvMF/oy8OmhdJzvZ0muuNKbZtzyafcNuNTvMwvyXncxTr94N2l9g9aDZpLpenHwZszsXWpl7IBzVp0mOsiJSjVOUWv/55FetJHwJbkx5FHDx3KjePjvvu+oklnvjJJyL6TVvZdFvPLnSnYC326qo5JMZ0ySjcU0m3d8azPOvvYTrnQZvcFMAkD2pzgMsrxKgi+TA8QNAuKT3lRrM3AwaKJzmebz3N4APthLffHpUxyUlmGAnifT3CB4AQQLu7VpurNjYWqD12L1f/nnJ1BanIebM9Owivb/Fk66rLgQuYwgn3zySfVi70jDewTbHqUtv9OlNIBCYO2Ce8ZJZ5rfbmpAGZVlfVEJlmf6UZo1D//24FL6BosdggmAgBjopnlkFiAX+lJx/lAQ58gVF3rYhj7E1YOO6Jzfl0//oolo/44D0nLM6TGOOg+dHSNdOMXMOol/x4QCcOhAD5aXFGMJo8J16enYTLNXHUhHS14hlgUzuXI5ONzd63AB2yv//t138NOf/wxnznzsKFcBQZ/jpVdexhP/9A8YHLhsz3W8qffuvetuWpJclPlTUZf55zj2wxW4eGQViQ1TEZJgEnmRq/1ZdwiX6SlqxS8eJNv3EJB+xhHkCpnRq4eSaE2y8M6e1cD5/+CYtApjdL7mjiJdP8FLs0GQxpbOGBxCZ0sLikl8VVERVsnFzYrZGaPi/hp/Ou39fCwJhnGsT2EsE/t56bnnECdY+XyvY0u707cUAr3PYvoJsVAGlpTkY/gq5ZR14ph7vnMfFrCulrkhcx6e+34YA/059BFSmP2mDC/3RUh8DrkiYpwgtr/URze6m+JyOEyxCDOizMa7Ty8DzvyC4/2emb6DDo9GxINzKUYmj3axva2iVmxyBH988WWszM3FEvr9VbT7cnTaGdw0JzMMpgvcmkgX2IKeCBanh/Dq8y+wrylcHbiExdQV6whMTVYuVt1cik8ucNXZ9cD5T7FYgM4vws2xGJpqapwxmR5//DGUxCNYFk5AbWwejj2SjMFnM8nelPcDfnIAc18InxwqwJVfLyZ3ZGOAgdOVA4wn9kdw6uko3npqAT44+k26ygdJx4fsm0GYwBdto3OB4HKCcarubbWYR4fxu18dQimjvNK0NDQWFGA1Xd1tnLSCoM5wyLbT5RprQ6UxJx9LGSK/9/YbpGcMDQ1VKKWy1CFrrT8DCxgm9/U/a3rgSG8vlqYHsTqYgfV0nOaHQnj04Yc4j0n85Mc/xM3xAFZH5+FXj5Vh6LlSnO9LsSjxKll9iKZv6NAC7LsvGT/e+T9x5AcxnOldT/O4Huf66zF8nMR/8jOOQkug6HOcFsajSUAPfcEJlJLaTLhHbWp87g+/x7KsTJQy2JGrq42OnXSBdbi6lUGRzhW0i1zr92NzLJcApWEZAfvw/bfxo8cfQn40HVXFBahmtLglJw8LyTUPfO9B0zQPfe9+LM+Koo7vrQ0EUFtUiGhmGK++9jr+jaZ2eex/4Xub/geGj67AJwei9AiDuHwoFRcZPI0dXoL+O4KMTuehMfYNLI39b2xYHeYq/4HzPsn5y+1WfPAZF9YJ+PSR2AwIc265zwJBqsF8H7JFfelSlDIqbI7H7eDk1kgOtiT6HQ5g9LctK4wGRodtBKKKQDXF4ihnSPzoXbuxKBbG+uJ8AujDZr6v6HAJOeiFF35DTpjCiy++gALqCnFYWywH6wLJWD0/hvJbYrh9SymeuHMRho+tpQkki1MBXuxjbMBy4mgpjtyZgXbqiltjaVhL5bmqqBgF8VzcufsuI0I0iBaRIYukayUrBcbYXNZBJpJJ/r8lFn179mIZlVZ9LBvVFgZHTQdo11hhsfYEG3w+JxzWuQLrBUQDOaE6PQNbyTmVvgA25+q4PgUrs0K445u3OZPkEDK1f3P7/+Eq6oCFUSXZvzJjHu6q9+PoDxbgnX8tpAhEufq0/c8k0zWOYuJQGY7sDmJr+jx0ZFJfJNxAUSNwqeS4ghLkZkbxx5PkAMk9s3SbQxH9GoqEufHyigfm3G12QPDSJA13ZVkZqkhARUqynSjpg4ouEirCBchGsnA7Q15POWqLbFtOFI18rg8umhMImEWNqahh+LwqNwcnT7zKiX0+1u9eehHFkUzUM4iqTPkz3FuVhKv9bXR2FuLKQa68bL8cokPZGDq4BM9/Nw9tgXnYlZNiGzC7yHk665SOWhtIw/LcAuz+9l87IIjtiYBodnnCKRkBz20d5CfwBXGCXnrrjTdRkp1NVk7BVilBbX5yxXXavEMDUyQ6Ilm2M7QjmmNbaDv15UmyTp9DtlusQ9bqZL/pgoq0DOysqDRF67jbHHOMJe/XFOTZV2yVMR9+0EVnp7+cfkCMTk6qRYoDPRF6f4vxwsOF5MB52BlPQ03CN4wD9R2D5qPt/dZoJpZzAVbn57N/eqXMTgDH5AJiIEjW5z6VnuUnsHjg7nuwjGzarI+q7HA0ZLvGIrze9Q+kJPVliYDRWaM2SLqkLBMTsCvscE4b66sCQdSEY+gqryLK7qQkl3IlR67iluwAKuI+VObMwyPb/zsuPbvYYoHPulMwdCCMib5b8NuH8tASpAhk+ezQt5PA2+EtdZR2rrRNX5eaZPsTyzKDONbfQ2ZwXHTTCPov7jBx4LhznkqPSzF6E5zElrVrUUVO2GBni96HFtm2jb7NjtREuD64kIg4R2x2mkwgOgVAog+3EihxTFuswL5iaxcniAuFtVmgCQ41iNL5N+HY42vx0b8vxqk9cbJ/GFcOMwjaH8B03xKceLAIreSArmgiOTLBrJOdWFE36QxTgOheBz+rA6n2neS9d+4m+eP852zUG2nKNrbAn0sc3C9V1AbDQ1hCrV1Oh0gd69uizlwCkniDmUMRrDNC74sS+QmdUZo6f5JtojZQJGzbXOcJWXSpaTY3kGXbK8kJHH9aeJvHeIkX76CmdB5O71+CEXqAg/3ZtABBC5Mn+hfi9UeKsdlPEYgm2UGOtuWle+xDjhS/c2DDe51g1VA0mvPysZp1tWtXiigDwEAQYbNBoPerdB0nqF75rVeO25endZx4dUqQiFO5udvmOiCxs0VxAr29zQRIE6tPcj65qfclcMXCBIAiJKWZ5DftvSo9FVvXrqEe4ACcjCOrJ/GHX3fizK+WUAdkMwZg3H+AcUF3GGMHb8YbPy5BE63FlmxaAf+N6IxR9AjwjhznTFN+Ssus7x/EoToVby6ej5JQkIPoOyyJhADncELDA2FoTuswZgpVjlL3L/cyOArZ9wZtOQWU9SC2UfYkg/qCRN8NyE+QstwRznLODOUv+BNs07Q+6SbsonJsJWA6YKmjddhA32FXFTlB4SL/S1KBt/F293KceYbxAGP/y4z6FBCN9i/DG48tRGvaPHQWUFekJNhhrZ1oiWD6J/rWSePp0FffP2geWpitFM1yLsyi9ABOvXlChFH9uIpYQ6qU6LsB47UgUGMLKAHx6N8+gLJwmFFhARrTQqZ8mijj0vbyFE0J2rkBS660zg0EUEc0Qs+QE6NfIYC0u9zECUmkxAlb1jKSo0UYY6gshtAB6tljW8wSXKElGDyQjqnuBXjv8SU0v1SCFIHq5D9nf9qmT3TPKqkLqKNmf/+gBdHJlR3cJOrzvzhWZ2TiuWeeJtoiltQb8fzxOGFwrqP5yVFbHXlXf9G5HVX08Mq54u1SQonJjvmjzMtPkF2Wn9Ci7xXp5jrfF1AO2X4bAdABi9rpXEEcVENltYH3XVVUjNTMAtos1OQZTL/zIE49tQiDhxYxHrgFp362DG2mBJPNFRfLN9OR0ja9xhHL14jDqIRb2L/3/YP3Qag82np/mn0M+uRDDxN0x2U24r38hZwwJm9KdnUCW6qrUBFMpQxSu5PgLq5Eo59KMZzunDLLGhAYzzrsohKUrtDEnK/VKLvUCfowQ4et7TmOy9xZXs6VobJyT68wzcDm3F68+c/12HNHHL/+u3XYSBHoCH+DBN5ost9KANu4qvqOQZ/81ukQV9aAOkCcKNEQ54lTTFRljUJZqKQ4P3K7nCbnI1XPMtvA4oQ5QRgfZr2YdBxrF5VgIz0/EabDUzki7RFqXsqmBpJfICDkKNkXqhQV3cuTlGcpVlU7Pfe0dgM5amfFOgNBE7ENrEkdrr6OKsYA1cx1BKAtK9UIco7vE+xTniZ/un3HoEPaTvknSSlmJmWdJBo1/kQ745So6Li/gYBXc/y/bG7iQLJ6MpReIhqmGOe0DtKWfIHIlS8soTJKtZVuJPKyw/ryRCujFZB5lP0XgfUs9X2BSrUTq2qlpAvaqSvkULXn5GJ9IB27yis4hGOGbVKK7oY/RnM+nSkqOemcJrL0bSS0OSHJPuSoS9TK59q4M/WROFpuEus7oqlPgPSJkEo5ThqvnCF613qCru+TJOgWEUosKIxfyAljQ2QZV4lwtapjefat0JaCYvv8vpXmsoKEbaEdXseyhfXrg/QOyepqp8/sKmieWvLyzL9opihVBYNoZRC1kh7mhtx8bC1fzwlwBCJgf8WiDZvBAZSR3Rui7M+voKsIVT5ZJXIQ+20mQXK5NzG2WCcXnv2p3vYnVE/C1wQDaCxkkJYWwEbNMy2ICuoQixRJ/Chd8xnkNa64cU4TSS0qeyq8RvUHIGo4QvEYYtbeop7J11ccLmWjgEsKRqVQ1Wdxytq/0zH6BEtpZh2D69xBKyGibQR5iqyX6dIYMpvjaqf33T6VNY49U998T1ljqY2e6Y/XVK+xtIC61jPtGhkNRJyEG9fxZ1z7+roxENiO6VoQ2LnUlao4hLU1FtKF3fDHrjlhgqU4w2mjFdWFBpTed5SryhnOYhphO0mm/tBsalKjcKKqc16xts7X0nbLGrXWt0aOw2PjaRxLfM/d/1OQ5CyeezSg+Yh4NZlw5qiW9qp+FLMIhDl3m4c5MTbSC9r/l7lU5/YeX7ROlHTBPIOJe//5SF7BTpR4o8mImdTEnttRGxPrHBdaN854aiMQxrkcExhmKSdOIKhG77JQdieg8XWrd1QqeXsiYhw9d/pz6zUtVczJCQJBCGq2ai3W1QxV2sYjS7HnKJ/pXoiqQ2/Wo7ywkvVaDYXLaqc/uNJz5imxvp6LlfWesmanTK6bpl4yNla/xkVeZgOJmvrzxjd2Z6m+rR/+2Htu9voxWpj1js2L2cRc/QL/H9J7FoQajQSGAAAAAElFTkSuQmCC" #CONVERTING BASE 64 ICON TO SOMETHING USEFUL$iconstream = [System.IO.MemoryStream][System.Convert]::FromBase64String($icon64)$iconbmp = [System.Drawing.Bitmap][System.Drawing.Image]::FromStream($iconstream)$iconhandle = $iconbmp.GetHicon()$icon = [System.Drawing.Icon]::FromHandle($iconhandle) #LAPS UI FORM$lapsform = New-Object system.windows.forms.form
$lapsform.Size = New-Object System.Drawing.Size(400,320)$lapsform.Text = "                                     LAPS UI         "
$lapsform.StartPosition = "centerscreen"$lapsform.FormBorderStyle = "fixed3d"
$lapsform.Icon =$icon

#LAPS TEXTBOX LABEL
$lapsform_computername_textbox_label = New-Object System.Windows.Forms.Label$lapsform_computername_textbox_label.Location = New-Object System.Drawing.Point(20,20)
$lapsform_computername_textbox_label.Size = New-Object System.Drawing.Size(100,15)$lapsform_computername_textbox_label.Text = "ComputerName"
$lapsform.Controls.Add($lapsform_computername_textbox_label)

#LAPS TEXTBOX
$lapsform_computername_textbox = New-Object System.Windows.Forms.TextBox$lapsform_computername_textbox.Location = New-Object System.Drawing.Point(21,40)
$lapsform_computername_textbox.Size = New-Object System.Drawing.Size(250,15)$lapsform.Controls.Add($lapsform_computername_textbox) #VARIABLE FOR KEYDOWN$lapsform_computername_textbox_keydown = {}

#KEYDOWN ASSIGNED
$lapsform_computername_textbox_keydown = [System.Windows.Forms.KeyEventHandler]{ if ($_.keycode -eq 'Enter'){
$lapsform_search_button.PerformClick() } } #REGISTER KEYDOWN HANDLER TO COMPUTER TEXTBOX$lapsform_computername_textbox.add_keydown($lapsform_computername_textbox_keydown) #LAPS SEARCH BUTTON$lapsform_search_button = New-Object System.Windows.Forms.Button
$lapsform_search_button.Location = New-Object System.Drawing.Point(290,40)$lapsform_search_button.Size = New-Object System.Drawing.Size(60,20)
$lapsform_search_button.Text = "Search"$lapsform.Controls.Add($lapsform_search_button) #LAPS SEARCH BUTTON LOGIC$lapsform_search_button.add_click({
if ($lapsform_computername_textbox.Text.Length -le 0){$lapsform_output_label.Text = "You must enter a computer name"
}else{
try{
#getting text from textbox
$computernametext =$lapsform_computername_textbox.Text

#checking if computer is in AD
$checkad = Get-ADComputer -Identity$computernametext

#invoking admpwdpassword command on $domaincontroller$invokegetadmpwd = Invoke-Command -ComputerName $domaincontroller -ScriptBlock {get-admpwdpassword -ComputerName$args[0] } -ArgumentList $computernametext | Select-Object Password, expirationtimestamp #getting password and password expiration date$lapsform_password_textbox.Text = $invokegetadmpwd | Select-Object -ExpandProperty password$lapsform_password_expires_textbox.Text = $invokegetadmpwd | Select-Object -ExpandProperty expirationtimestamp$lapsform_output_label.text = ""
}catch{

if (!$checkad){$lapsform_output_label.Text = "Computer not found"
}
$lapsform_password_textbox.Text = ""$lapsform_password_expires_textbox.Text = ""
}
}
})

$lapsform_password_textbox_label = New-Object System.Windows.Forms.Label$lapsform_password_textbox_label.Location = New-Object System.Drawing.Point(20, 90)
$lapsform_password_textbox_label.Size = New-Object System.Drawing.Size(100,20)$lapsform_password_textbox_label.Text = "Password"
$lapsform.Controls.Add($lapsform_password_textbox_label)

$lapsform_password_textbox = New-Object System.Windows.Forms.TextBox$lapsform_password_textbox.Location = New-Object System.Drawing.Point(21,110)
$lapsform_password_textbox.Size = New-Object System.Drawing.Size(250,15)$lapsform_password_textbox.ReadOnly = $true$lapsform_password_textbox.Font = New-Object System.Drawing.Font("courier",12,[System.Drawing.FontStyle]::Regular)
$lapsform.Controls.Add($lapsform_password_textbox)

$lapsform_password_expires_textbox_label = New-Object System.Windows.Forms.Label$lapsform_password_expires_textbox_label.Location = New-Object System.Drawing.Point(20,145)
$lapsform_password_expires_textbox_label.Size = New-Object System.Drawing.Size(100,20)$lapsform_password_expires_textbox_label.Text = "Password Expires"
$lapsform.Controls.Add($lapsform_password_expires_textbox_label)

$lapsform_password_expires_textbox = New-Object System.Windows.Forms.TextBox$lapsform_password_expires_textbox.Location = New-Object System.Drawing.Point(21,165)
$lapsform_password_expires_textbox.Size = New-Object System.Drawing.Size(250,15)$lapsform_password_expires_textbox.ReadOnly = $true$lapsform.Controls.Add($lapsform_password_expires_textbox) #DATETIME PICKER LABEL$lapsform_datetime_picker_label = New-Object System.Windows.Forms.Label
$lapsform_datetime_picker_label.Location = New-Object System.Drawing.Point(20,200)$lapsform_datetime_picker_label.Size = New-Object System.Drawing.Size(150,20)
$lapsform_datetime_picker_label.Text = "New Expiration Time"$lapsform.Controls.Add($lapsform_datetime_picker_label) #DATETIME PICKER$lapsform_datetime_picker = New-Object System.Windows.Forms.DateTimePicker
$lapsform_datetime_picker.Location = New-Object System.Drawing.Point(21,220)$lapsform_datetime_picker.Size = New-Object System.Drawing.Size(250,15)
$lapsform_datetime_picker.Format = "custom"$lapsform_datetime_picker.CustomFormat = "dd MMMM yyyy"
$lapsform.Controls.Add($lapsform_datetime_picker)

#DATETIME PICKER SET BUTTON
$lapsform_datetime_set_button = New-Object System.Windows.Forms.Button$lapsform_datetime_set_button.Location = New-Object System.Drawing.Point(285,220)
$lapsform_datetime_set_button.Size = New-Object System.Drawing.Size(91,20)$lapsform_datetime_set_button.Text = "Set and Update"
$lapsform.Controls.Add($lapsform_datetime_set_button)

$lapsform_datetime_set_button.add_click({ if ($lapsform_computername_textbox.Text.Length -le 0){
$lapsform_output_label.Text = "You must enter a computer name" }else{ try{$datetimepickervalue = $lapsform_datetime_picker.value.ToString("MM dd yyyy") #getting text from textbox$computernametext = $lapsform_computername_textbox.Text #checking if computer is in AD$checkad = Get-ADComputer -Identity $computernametext #invoking admpwdpassword command on$domaincontroller
Invoke-Command -ComputerName $domaincontroller -ScriptBlock {reset-admpwdpassword -ComputerName$args[0] -wheneffective $args[1] } -ArgumentList$computernametext, $datetimepickervalue #setting value of output label$lapsform_output_label.Text = "Password reset request was successful - GP updating - PLEASE WAIT"

Invoke-GPUpdate -Computer $computernametext -ErrorAction SilentlyContinue$lapsform_output_label.Text = "Finished"
}catch{
#checking if computer is in AD
if (!$checkad){$lapsform_output_label.Text = "Computer not found"
}else{
write-host "Another issue - WinRM probably isn't allowed..."
}

}

}
})

#OUTPUT TEXTBOX
$lapsform_output_label = New-Object System.Windows.Forms.Label$lapsform_output_label.Location = New-Object System.Drawing.Point(1,265)
$lapsform_output_label.Size = New-Object System.Drawing.Size(385,20)$lapsform_output_label.BackColor = "white"
$lapsform_output_label.BorderStyle = "fixedsingle"$lapsform.Controls.Add($lapsform_output_label) #LAPS UI FORM DIALOG [void]$lapsform.ShowDialog()

### Unix Permissions Winform

In this post, I will show case a winform application that I have just finished building which will tell you the correct command when given the required permissions. For example, a read permission is identified as a 4 in Unix environments.

I have created a small table below:

 Permission Level Permission Bit Read 4 Write 2 Execute 1

Since you need to define permissions for: the owner; owner group and others, you need to supply 3 permission bits per command. Plus one more for special permissions at the beginning but we can ignore that for now.

So if we wanted to give the below permissions:

Special – ignore

Owner – read (4), write(2) and execute(1)

Owner group – read(4) and write(2)

we would use the following command: chmod 0764 <path-to-file>

Now we can get on with the actual winform… I created this to tell me what permissions I needed to assigned. Below is a screenshot of the winform:

This also keeps a short history of the permissions in the history textbox which is flushed after so long to stop the textbox from overflowing. Here is a download for the project, in the zip folder is both a ps1 file and an exe file. Enjoy!

### Server Reboot Script

Running a little low on content this last few months, plus I’ve been busy with other work stuff.

I had the requirement to create a PowerShell script that would get the uptime of a server and then decide whether or not the server needed rebooting.

I also wanted the script to randomize the reboot of the servers, that way if there are multiple servers that need rebooting at once, they don’t cause a power spike or resource issues on the hosts. I did this by creating a random number between 1 and 5 and then if the number equals 5, the server is rebooted. If not then the server isn’t rebooted.

This is the script that I ended up with and what is currently being tested:

$loglocation = "C:\scripts\reboot\log"$dateforfile = Get-Date

#GETS UPTIME IN DAYS
$lastbootuptime = Get-WmiObject win32_operatingsystem$uptime = (Get-Date) - ($lastbootuptime.converttodatetime($lastbootuptime.lastbootuptime))
$uptimeindays =$uptime.days

#GETS RANDOM NUMBER
$randomnumber = Get-Random -Minimum 1 -Maximum 6 if ($uptimeindays -ge "14"){

Add-Content -Path "$loglocation\$env:COMPUTERNAME.txt" -Value @"
=====================================================================================
Server restarted at:
$dateforfile This was an immediate shutdown as the server had been up for$uptimeindays days
"@

Restart-Computer -Force

}elseif ($uptimeindays -lt "14" -and$uptimeindays -ge "7"){

if ($randomnumber -eq "5"){ Add-Content -Path "$loglocation\$env:COMPUTERNAME.txt" -Value @" ===================================================================================== Server restarted at :$dateforfile
This was a random restart as uptime was only $uptimeindays days "@ Restart-Computer -Force }else{ Add-Content -Path "$loglocation\$env:COMPUTERNAME.txt" -Value @" ===================================================================================== Server NOT restarted$dateforfile
This was not randomly restarted. Uptime is currently $uptimeindays days. Random number was$randomnumber
"@
}
}else{

Add-Content -Path "loglocation\$env:COMPUTERNAME.txt" -Value @" ===================================================================================== No restart required$dateforfile
No restart required since uptime is only $uptimeindays days "@ } The first time I created this script and set it up as a scheduled task, nothing happened. Turns out that I needed the -Force parameter in order for the server to be rebooted. This will later be used in a group policy without the log creating as that is only necessary in the testing stage. Enjoy! ### 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!