winutil/winutil-test.ps1
DeveloperDurp b670968731
upload example (#12)
Co-authored-by: Chris Titus <dfm.titus@gmail.com>
2022-05-17 10:59:06 -05:00

256 lines
9.4 KiB
PowerShell

<#
.NOTES
Author : @DeveloperDurp
GitHub : https://github.com/DeveloperDurp
Version 0.0.1
#>
#region Header
#region Load .Net framwork
[Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName PresentationFramework
[System.Windows.Forms.Application]::EnableVisualStyles()
#endregion Load .Net framework
#Hiding Console Window
<#
Add-Type -Name Window -Namespace Console -MemberDefinition '
[DllImport("Kernel32.dll")]
public static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
'
$consolePtr = [Console.Window]::GetConsoleWindow()
[Console.Window]::ShowWindow($consolePtr, 0) > $Null
#>
#endregion Header
#region Functions
#Instead of running the whole form in a run space I like to have it call the additional runspaces as
#I have found additional complexity when running forms outside of the main thread
function Invoke-Button {
Param ([string]$Button)
Switch -Wildcard ($Button){
"*InstallProgram_Button*"{Invoke-Runspace $InstallScript}
}
}
#You can call this function and pass a "powershell" script so that it can execute it inside a runspace.
#Anything executed with this function will be able to interact with the $global:sync variable
#Another neat feature you can do with this method is updating the form itself assuming you created the form objects inside the $sync variable
function Invoke-Runspace {
Param ([string]$commands)
$Script = [PowerShell]::Create().AddScript($commands)
$runspace = [RunspaceFactory]::CreateRunspace()
$runspace.ApartmentState = "STA"
$runspace.ThreadOptions = "ReuseThread"
$runspace.Open()
$runspace.SessionStateProxy.SetVariable("sync", $global:sync)
$Script.Runspace = $runspace
$Script.BeginInvoke()
}
#The prowershell gui scripts I build tend to be very daynamic in nature so I don't like to have a predefined layout like you do.
#This is one way for me to make sure things don't go too far down
Function Check-Space {
Param ([string]$cords)
[int]$xint = ($cords -split ";")[0]
[int]$yint = ($cords -split ";")[1]
[int]$increment = ($cords -split ";")[2]
if($yint -gt 650){Write-output "$($xint + 225)";10}
if($yint -le 650){Write-output "$xint;$($yint + $increment)"}
}
#endregion functions
#region Scripts
#This is what you pass to the Invoke-Runspace function. This can interact with the $sync variable and even make changes that the main form will pickup.
#IE I could say $global:sync["InstallProgram_Browsers-LibreWolf_Checkbox"].text = "LibreWolf Installed"
$InstallScript = {
$programstoinstall = @()
$global:sync.keys | Where-Object {$_ -like "InstallProgram_*_Checkbox"} | ForEach-Object {
if($global:sync["$_"].checked -eq $true){
$program = (($_ -split "_")[1] -split "-")[1]
$programstoinstall += $program
}
}
[System.Windows.MessageBox]::Show("I will install the following programs $programstoinstall",'Install Programs Button',"OK","Info")
}
#endregion Scripts
$version = "0.0.1"
$ToolName = "winutil"
$formwidth = 1170
$formHeight = 800
$InstallPrograms = @(
"Browsers;Brave,Google Chrome,Un-Googled Chromium, Firefox,LibreWolf,Vivaldi"
"Communications;Discord,Hexchat,Matrix,Signal,Skype,Slack,Microsoft Teams,Zoom Video Conference"
"Development;Atom,Github Desktop,OpenJDK Java 8,OpenJDK Java 16,Oracle Java 18,Jetbrains Toolbox,NodeJS,NodeJS LTS,Python3,Sublime,Visual Studio Code 2022 Community,VS Code,VS Codium"
"Document;Adobe Reader DV,LibreOffice,Notepad++,Obsidian,Sumatra PDF"
"Games;Epic Games Launcher,GOG Galaxy,Steam"
"Pro Tools;Advanced IP Scanner,mRemoteNG,Putty,WinSCP,WireShark"
"Multimedia Tools; Audacity,Blander (3D Graphics),Eartumpet (Audio),Flameshot (Screenshots),Foobar2000 (Music Player),Gimp (Image Editor),Greenshot (Screenshots),HandBrake,ImageGlass (Image Viewer),Inkscape,Media Player Classic (Video Player),OBS Studio,ShareX (Screenshots),Spotify,VLC (Video Player),Voicemeeter (Audio)"
"Utilities;7-Zip,AnyDesk,AutoHotkey,Bitwarden,CPU-Z,Etcher USB Creator,Everything Search,GPU-Z,HWInfo,KeePassXC,MalwareBytes,NVCleanstall,Microsoft Powertoys,RevoUninstaller,Rufus Imager,TeamViewer,Translucent Taskbar,TreeSizeFree,WinDirStat,Windows Terminal"
)
$tabs = @(
"Install"
"Tweaks"
"Config"
"Updates"
"Help"
)
$global:sync = [Hashtable]::Synchronized(@{})
#region Form
$Form = New-Object system.Windows.Forms.Form
$Form.text = "$toolname $Version"
$form.AutoScroll = $True
$form.width = $formwidth
$form.Height = $formHeight
$Form.FormBorderStyle = 'Fixed3D'
$Form.MaximizeBox = $false
$Form.Add_FormClosing({
Get-Process -Id $pid | Stop-Process
})
#For adding in an icon image
#$iconBase64 = ''
#$iconBytes = [Convert]::FromBase64String($iconBase64)
#$stream = New-Object IO.MemoryStream($iconBytes, 0, $iconBytes.Length)
#$stream.Write($iconBytes, 0, $iconBytes.Length);
#$Form.Icon = [System.Drawing.Icon]::FromHandle((New-Object System.Drawing.Bitmap -Argument $stream).GetHIcon())
#endregion Form
#region Tab Control
$tabcontrol = New-Object 'System.Windows.Forms.TabControl'
$tabcontrol.Alignment = 'Top'
$tabcontrol.Location = '0,0'
$tabcontrol.Multiline = $True
$tabcontrol.Name = 'tabcontrol'
$tabcontrol.SelectedIndex = 0
$tabcontrol.width = $formwidth
$tabcontrol.Height = $($formHeight-35)
$tabcontrol.Anchor = [System.Windows.Forms.AnchorStyles]::Bottom -bor [System.Windows.Forms.AnchorStyles]::Right -bor [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left
$tabcontrol.TabIndex = 0
$Form.Controls.Add($tabcontrol)
#endregion Tab Control
#region Main Page
foreach ($tab in $tabs){
$page = New-Object 'System.Windows.Forms.TabPage'
$page.name = "$tab"
$page.text = "$tab"
$tabcontrol.Controls.Add($page)
}
#Since I don't use an xaml file to create the gui (not sure how compatable that method is with this script as I have never used it) I create a loop to build everything.
#You could do the same for the rest of the tabs in a similar fashion to this one.
#region Install Tab
$x = 5
$y = 10
foreach($InstallProgram in $InstallPrograms){
$group = ($InstallProgram -split ";")[0]
$programs = ($InstallProgram -split ";")[1] -split ","
$Label = New-Object Windows.Forms.Label
$Label.Name = "$group"
$Label.Location = New-Object System.Drawing.Point($x,$y)
$Label.Font = 'Microsoft Sans Serif,15'
$Label.Text = "$group"
$Label.AutoSize = $true
$tabcontrol.controls["Install"].Controls.Add($Label)
$space = (Check-Space "$x;$y;40") -split ";"
$x = $space[0]
$y = $space[1]
foreach($program in $programs){
#The key here is adding the object to the $sync variable, this what allows powershell to interact with it while inside a runspace.
#IE $tabcontrol.controls["Install"] is not modifiable but $global:sync["InstallProgram_Browsers-LibreWolf_Checkbox"] is
$object = New-Object Windows.Forms.Checkbox
$object.Name = "InstallProgram_$group-$($program -replace " ","_")_Checkbox"
$object.Font = 'Microsoft Sans Serif,8'
$object.Location = New-Object System.Drawing.Point($x,$y)
$object.Size = "225,20"
$object.text = "$program"
$object.checked = $false
$global:sync["$($object.name)"] = $object
$tabcontrol.Controls["Install"].Controls.Add($global:sync["$($object.name)"])
$space = (Check-Space "$x;$y;20") -split ";"
$x = $space[0]
$y = $space[1]
}
$y = [int]$y + 10
}
$space = (Check-Space "$x;9000;20") -split ";"
$x = $space[0]
$y = $space[1]
$object = New-Object 'System.Windows.Forms.Button'
$object.name = "InstallProgram_Button"
$object.Location = New-Object System.Drawing.Point($x,$y)
$object.Font = 'Microsoft Sans Serif,10'
$object.Size = "200,25"
$object.TextAlign = 'MiddleCenter'
$object.text = "Install Programs"
$object.Add_Click({
#This took me a long time to figure out as my other scripts would create buttons dynamically. This will get the name of the button that you clicked
#then pass it to the Invoke-Button function above.
[System.Object]$Sender = $args[0]
Invoke-Button $Sender.name
})
$tabcontrol.controls["Install"].Controls.Add($object)
#endregion Install Tab
#region Help Page
$Label = New-Object Windows.Forms.Label
$Label.Name = "Help_Page_Label"
$Label.Location = New-Object System.Drawing.Point(5,10)
$Label.Font = 'Microsoft Sans Serif,15'
$Label.Text = "Welcome to the Help Page"
$Label.AutoSize = $true
$tabcontrol.controls["help"].Controls.Add($Label)
#endregion Help Page
#endregion Main Page
[Windows.Forms.Application]::Run($form)