Last active
June 22, 2017 19:55
-
-
Save pinecones-sx/6b1f6f89014afc7f2e9e8134d06a4915 to your computer and use it in GitHub Desktop.
uses an OU in active directory to find raffle winners. prevents users from winning multiple times.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Required scripts -- this just loats the AD snapin or calls it remotely from a DC | |
.'\\ps1\functions\Import-AD.ps1' | |
$env:winnerListUNC = '\\DomainName.local\filestore\winnerList.txt' | |
$env:userOUSearchBase = 'OU=TheUsers,DC=DomainName,DC=local' | |
function global:Get-Winner { | |
param( | |
$ExcludedUsers, | |
$WinnerListPath, | |
[switch]$DoNotSaveWinner, | |
[switch]$VerboseReturn | |
) | |
# Normalize parameters | |
If ($WinnerListPath){$env:winnerListUNC = $WinnerListPath} | |
If (-not (Test-Path $env:winnerListUNC)){ | |
$null = ( | |
$ExcludedUsers | | |
ForEach {Get-ADUser -Filter "Name -eq '$_'" -SearchBase $env:userOUSearchBase -ErrorAction Stop} | |
) | |
[array]$ExcludedUsers = $ExcludedUsers | |
} | |
Else {[array]$ExcludedUsers = Get-Content -Path $env:winnerListUNC -ErrorAction Ignore} | |
# Get current non-winners | |
$nonWinners = ( | |
Get-ADUser -Filter * -SearchBase $env:userOUSearchBase | | |
select -ExpandProperty Name | | |
Where {$ExcludedUsers -notcontains $_} | |
) | |
# Get new winner | |
$newWinner = Get-Random -InputObject $nonWinners | |
# Update winners list | |
[array]$winnerList = $excludedUsers + $newWinner | |
# Update winners file | |
If (-not $DoNotSaveWinner){ | |
$null = ( | |
$winnerList | | |
Out-File -FilePath $env:winnerListUNC | |
) | |
} | |
# Return results | |
If ($VerboseReturn){ | |
$returnObj = [ordered]@{ | |
'Winner' = $newWinner | |
'NewLosers' = ($nonWinners | Where {$_ -ne $newWinner}) | |
'OldLosers' = $nonWinners | |
'NewWinners' = $winnerList | |
'OldWinners' = $ExcludedUsers | |
} | |
Return (New-Object -TypeName PSObject -Property $returnObj) | |
} | |
Else{ | |
Return $newWinner | |
} | |
} | |
# this is the basic form creation code from the original example. | |
# It assumes that the windows forms assemblies are already loaded... | |
# Set reused colors | |
$dBackColor = [System.Drawing.Color]::FromArgb(52,113,90) | |
$dForeColor = [System.Drawing.Color]::FromArgb(242,242,242) | |
# R,G,B in 255 integer format, min 0,0,0 max 255,255,255 | |
# Create form & inheritables | |
$formMinHeight = 450 | |
$formMinWidth = 500 | |
$dForm = New-Object System.Windows.Forms.Form | |
$dForm.MinimumSize = New-Object System.Drawing.Size @($formMinWidth,$formMinHeight) | |
$dForm.Size = New-Object System.Drawing.Size @(($formMinWidth + 100),$formMinHeight) | |
$dForm.Text = "RAFFLE" | |
$dForm.BackColor = $dBackColor | |
$dForm.ForeColor = $dForeColor | |
# Config form font | |
$fontName = 'Calibri' | |
$fontSize = ($dForm.Height / 8) | |
$fontStyle = [System.Drawing.FontStyle]::Bold | |
$fontSizeType = [System.Drawing.GraphicsUnit]::Pixel | |
$dFont = New-Object System.Drawing.Font($fontName,$fontSize,$fontStyle,$fontSizeType) | |
# 'font name',[int]size,[System.Drawing.FontStyle]::Style,[System.Drawing.GraphicsUnit]::SizeType | |
# Font styles are: Regular, Bold, Italic, Underline, Strikeout | |
# Font size types are: Point,Pixel,Inch,Millimeter,Display,Document,World -- defaults to Point if left off | |
# Config label control | |
$dLabel = New-Object System.Windows.Forms.Label | |
$dLabel.Text = 'Initialized.' | |
$dLabel.Font = $dFont | |
#$dLabel.AutoSize = $True | |
$dLabel.Height = $dLabel.Font.Height + 2 | |
$dLabel.Width = $dForm.Width | |
$dLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter | |
$dLabelStartLeft = 0 | |
$dLabelStartTop = ($dForm.Height / 2) - ($dLabel.Height / 2) | |
$dLabel.Location = New-Object System.Drawing.Point @($dLabelStartLeft,$dLabelStartTop) | |
$dForm.Controls.Add($dLabel) | |
$dLabelWinner = New-Object System.Windows.Forms.Label | |
$dLabelWinner.Text = '' | |
$dLabelWinner.Font = $dFont | |
#$dLabelWinner.AutoSize = $True | |
$dLabelWinner.Height = $dLabelWinner.Font.Height + 2 | |
$dLabelWinner.Width = $dForm.Width | |
$dLabelWinner.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter | |
$dLabelWinnerStartLeft = 0 | |
$dLabelWinnerStartTop = ($dForm.Height / 2) - ($dLabelWinner.Height / 2) - $dLabel.Height | |
$dLabelWinner.Location = New-Object System.Drawing.Point @($dLabelWinnerStartLeft,$dLabelWinnerStartTop) | |
$dForm.Controls.Add($dLabelWinner) | |
# Config button control | |
# https://social.technet.microsoft.com/wiki/contents/articles/25911.how-to-add-a-powershell-gui-event-handler-part-1.aspx | |
$dButton = New-Object System.Windows.Forms.Button | |
$dButton.Size = New-Object System.Drawing.Size @(150,50) | |
#$dButton.AutoSize = $true | |
#$dButton.Dock = [System.Windows.Forms.DockStyle]::Bottom | |
#$dButton.Anchor = [System.Windows.Forms.AnchorStyles]::Right | |
$dButton.Text = 'PULL!' | |
$dButtonStartLeft = ($dForm.Width / 2) - ($dButton.Width / 2) | |
$dButtonStartTop = $dForm.Height - $dButton.Height - 50 | |
$dButton.Location = New-Object System.Drawing.Point @($dButtonStartLeft,$dButtonStartTop) | |
$dButton.Add_Click({$env:dButtonPressed = $true}) | |
$dForm.Controls.Add($dButton) | |
<# Config text control | |
$dText = New-Object System.Windows.Forms.TextBox | |
#$dText.ScrollBars = [System.Windows.Forms.ScrollBars]::both | |
$dText.Dock = [System.Windows.Forms.DockStyle]::fill | |
$dText.Multiline = $true | |
$dText.Parent = $dForm | |
$dText.ReadOnly = $true | |
#> | |
$dForm.Add_Shown({$dform.Activate()}) | |
# now we need to create a separate runspace so that the form can run on | |
# a separate thread... | |
$rs = [Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace() | |
$rs.Open() | |
# create a variable in the new runspace that also points at the form object. | |
# We'll use the same name for simplicity... | |
$rs.SessionStateProxy.SetVariable("dForm", $dForm) | |
# now create a pipeline in the new runspace that will cause | |
# the form to be shown then close the input stream to the pipe since we don't | |
# need it and it will cause the pipeline to block | |
$p = $rs.CreatePipeline( { [void] $dForm.ShowDialog() } ) | |
$p.Input.Close() | |
# Now start the pipeline running asynchronously | |
$p.InvokeAsync() | |
# At this point, the window should appear and we can start Writing stuff | |
# into the text box... | |
#$dText.AppendText("This is the first line we wrote!`n") | |
#$dLabel.AppendText("This is the first line we wrote!`n") # does not work | |
# magical variables | |
$dLabel.Text = '' | |
$dLabelWinner.Text = '' | |
$vUpdate = 'Clear' | |
$env:dButtonPressed = $false | |
$leverPulled = $false | |
$timeBeforeAutoClose = 60 | |
$timeStart = Get-Date | |
$timeStop = $timeStart.AddSeconds($timeBeforeAutoClose) | |
$baseTextDelay = 225 | |
$baseBlankDelay = 70 | |
$scrollAcceleration = 1 | |
$scrollSequence = ( | |
1.5,1,.9,.9,.8,.8,.7,.7,.6,.5,.4,.3,.2,.1,.1,.09,.09,.08,.08,.07,.07,.07,.07,.07,.07,.07, | |
.07,.07,.07,.07,.07,.07,.07,.07,.07,.07,.07,.07,.07,.07,.07,.07,.07,.07,.07,.07,.07,.07, | |
.07,.1,.2,.3,.5,.7,.8,.9,1,1.1,1.5,1.75,4 | |
) | |
$scrollState = 0 | |
# Main loop | |
$running = $true | |
While ($running){ | |
# Update positions | |
# Label (text) | |
$fontSize = ($dForm.Height / 10) | |
$dFont = New-Object System.Drawing.Font($fontName,$fontSize,$fontStyle,$fontSizeType) | |
$dLabel.Font = $dFont | |
$dLabel.Height = ($fontSize + 8) | |
$dLabelWinner.Font = $dFont | |
$dLabelWinner.Height = ($fontSize + 8) | |
$dLabel.Width = $dForm.Width | |
$dLabelWinner.Width = $dForm.Width | |
$dLabelStartTop = ($dForm.Height / 2) - ($dLabel.Height / 2) | |
$dLabel.Location = New-Object System.Drawing.Point @($dLabelStartLeft,$dLabelStartTop) | |
$dLabelWinnerStartTop = ($dForm.Height / 2) - ($dLabelWinner.Height / 2) - $dLabel.Height | |
$dLabelWinner.Location = New-Object System.Drawing.Point @($dLabelWinnerStartLeft,$dLabelWinnerStartTop) | |
# Button | |
$dButtonStartLeft = ($dForm.Width / 2) - ($dButton.Width / 2) | |
$dButtonStartTop = $dForm.Height - $dButton.Height - 50 | |
$dButton.Location = New-Object System.Drawing.Point @($dButtonStartLeft,$dButtonStartTop) | |
# Deal with button | |
$buttonReady = (($env:dButtonPressed -eq $true) -and ($leverPulled -eq $false)) | |
If ($env:dButtonPressed){ | |
If ($buttonReady){ | |
$leverPulled = $true | |
$raffleResults = Get-Winner -VerboseReturn -DoNotSaveWinner | |
Write-Verbose 'Button works.' | |
} | |
$env:dButtonPressed = $false | |
} | |
# Change Text | |
$vTakeAction = (Get-Date) -ge $actionTime | |
If ($leverPulled -and $vTakeAction -and $vUpdate){ | |
Switch ($vUpdate){ | |
'Show' { | |
$scrollSequenceFinished = ($scrollState -eq $scrollSequence.Length) | |
If (-not $scrollSequenceFinished){ | |
$vUpdate = 'Clear' | |
$dLabel.Text = Get-Random $raffleResults.OldLosers | |
$scrollAcceleration = $scrollSequence[$scrollState] | |
$actionTime = (Get-Date).AddMilliseconds(($baseTextDelay * $scrollAcceleration)) | |
$scrollState++ | |
} | |
Else{ | |
$vUpdate = 'Clear' | |
$dLabel.Text = $raffleResults.Winner | |
$dLabelWinner.Text = '!! WINNER !!' | |
$scrollState = 0 | |
$scrollAcceleration = $scrollSequence[$scrollState] | |
$actionTime = (Get-Date).AddMilliseconds(($baseTextDelay * $scrollAcceleration)) | |
$leverPulled = $false | |
} | |
} | |
'Clear' { | |
$vUpdate = 'Show' | |
$dLabel.Text = '' | |
$dLabelWinner.Text = '' | |
$scrollAcceleration = $scrollSequence[$scrollState] | |
$actionTime = (Get-Date).AddMilliseconds(($baseBlankDelay * $scrollAcceleration)) | |
} | |
default {} | |
} | |
} | |
# Validate things and attempt to escape | |
$timeExpired = ((Get-Date) -ge $timeStop) | |
If ($timeExpired -and $lastTextTrue){$running = $false} | |
If (-not $dForm.Visible){$running = $false} | |
} | |
# and finally close everything down - first the form and then the runspace... | |
$dForm.Close() | |
$rs.Close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment