GUI/OSDPad.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#================================================
# Window Functions
# Minimize Command and PowerShell Windows
#================================================
$Script:showWindowAsync = Add-Type -MemberDefinition @"
[DllImport("user32.dll")]
public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
"@
 -Name "Win32ShowWindowAsync" -Namespace Win32Functions -PassThru
function Hide-CmdWindow() {
    $CMDProcess = Get-Process -Name cmd -ErrorAction Ignore
    foreach ($Item in $CMDProcess) {
        $null = $showWindowAsync::ShowWindowAsync((Get-Process -Id $Item.id).MainWindowHandle, 2)
    }
}
function Hide-PowershellWindow() {
    $null = $showWindowAsync::ShowWindowAsync((Get-Process -Id $pid).MainWindowHandle, 2)
}
function Show-PowershellWindow() {
    $null = $showWindowAsync::ShowWindowAsync((Get-Process -Id $pid).MainWindowHandle, 10)
}
Hide-CmdWindow
Hide-PowershellWindow
#================================================
# Get MyScriptDir
#================================================
$Global:MyScriptDir = [System.IO.Path]::GetDirectoryName($myInvocation.MyCommand.Definition)
#================================================
# Load Assemblies
#================================================
[System.Reflection.Assembly]::LoadWithPartialName("presentationframework") | Out-Null
[System.Reflection.Assembly]::LoadFrom("$Global:MyScriptDir\assembly\System.Windows.Interactivity.dll") | Out-Null
#================================================
# Set PowerShell Window Title
#================================================
#$host.ui.RawUI.WindowTitle = "OSDPad"
#================================================
# Test-InWinPE
#================================================
function Test-InWinPE {
    return Test-Path -Path Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlset\Control\MiniNT
}
#================================================
# LoadForm
#================================================
function LoadForm {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $False, Position = 1)]
        [string]$XamlPath
    )
    
    # Import the XAML code
    [xml]$Global:XamlCode = Get-Content -Path $XamlPath

    # Add WPF and Windows Forms assemblies
    try {
        Add-Type -AssemblyName PresentationCore,PresentationFramework,WindowsBase,system.windows.forms
    } 
    catch {
        throw "Failed to load Windows Presentation Framework assemblies."
    }

    #Create the XAML reader using a new XML node reader
    $Global:XamlWindow = [Windows.Markup.XamlReader]::Load((New-Object System.Xml.XmlNodeReader $Global:XamlCode))

    #Create hooks to each named object in the XAML
    $Global:XamlCode.SelectNodes("//*[@Name]") | ForEach-Object {
        Set-Variable -Name ($_.Name) -Value $Global:XamlWindow.FindName($_.Name) -Scope Global
    }
}
#================================================
# LoadForm
#================================================
LoadForm -XamlPath (Join-Path $Global:MyScriptDir 'OSDPad.xaml')
#================================================
# Initialize Script Selection
#================================================
if ($Global:OSDPad) {
    $Global:OSDPad | ForEach-Object {
        $ScriptSelectionControl.Items.Add($_.Path) | Out-Null
        New-Variable -Name $_.Guid -Value $($_.ContentRAW) -Force -Scope Global

        if ($_.Path -like "*Readme.md") {
            $ScriptSelectionControl.SelectedValue = $_.Path
        }
        if ($Global:OSDPadBranding.Title -eq 'OSDPad') {
            $Global:OSDPadBranding.Title = "github.com/$RepoOwner/$RepoName/"
        }
    }
}
#================================================
# Initialize Empty Script
#================================================
$ScriptSelectionControl.Items.Add('New PowerShell Script.ps1') | Out-Null

if (-NOT (Get-Variable -Name 'New PowerShell Script.ps1' -Scope Global -ErrorAction Ignore)) {
    New-Variable -Name 'New PowerShell Script.ps1' -Value '#Paint on your blank canvas' -Scope Global -Force -ErrorAction Stop
}
Write-Host -ForegroundColor DarkGray "================================================"
#================================================
# Set-OSDPadContent
#================================================
function Set-OSDPadContent {
    if ($ScriptSelectionControl.SelectedValue -eq 'New PowerShell Script.ps1') {
        Write-Host -ForegroundColor Cyan 'New PowerShell Script.ps1'
        $ScriptTextControl.Foreground = 'Blue'
        $ScriptTextControl.IsReadOnly = $false
        $ScriptTextControl.Text = (Get-Variable -Name 'New PowerShell Script.ps1' -Scope Global).Value
        $StartButtonControl.Visibility = "Visible"
        $BrandingTitleControl.Content = 'OSDPad'
        #$BrandingTitleControl.Visibility = "Collapsed"
    }
    else {
        #$BrandingTitleControl.Visibility = "Visible"
        $Global:WorkingScript = $Global:OSDPad | Where-Object {$_.Path -eq $ScriptSelectionControl.SelectedValue} | Select-Object -First 1
        Write-Host -ForegroundColor Cyan $Global:WorkingScript.Path
        Write-Host -ForegroundColor DarkGray $Global:WorkingScript.Git
        Write-Host -ForegroundColor DarkGray $Global:WorkingScript.Download
        #Write-Host -ForegroundColor DarkCyan "Get-Variable -Name $($Global:WorkingScript.Guid)"

        $ScriptTextControl.Text = (Get-Variable -Name $Global:WorkingScript.Guid).Value

        if ($Global:WorkingScript.Name -like "*.md") {
            $ScriptTextControl.Foreground = 'Black'
            $ScriptTextControl.IsReadOnly = $true
            $StartButtonControl.Visibility = "Collapsed"
        }
        else {
            $ScriptTextControl.Foreground = 'Blue'
            $ScriptTextControl.IsReadOnly = $false
            $StartButtonControl.Visibility = "Visible"
        }
        $BrandingTitleControl.Content = $Global:OSDPadBranding.Title
    }
    foreach ($Item in $Hide) {
        if ($Item -eq 'Branding') {$BrandingTitleControl.Visibility = "Collapsed"}
        if ($Item -eq 'Script') {
            $Global:XamlWindow.Height="140"
            $ScriptTextControl.Visibility = "Collapsed"
        }
    }
    Write-Host -ForegroundColor DarkGray "================================================"
}

Set-OSDPadContent
#================================================
# Change Selection
#================================================
<# $ScriptSelectionControl.add_SelectionChanged({
    Set-OSDPadContent
}) #>

$ScriptSelectionControl.add_SelectionChanged({
    Set-OSDPadContent
})
$ScriptTextControl.add_TextChanged({
    if ($ScriptSelectionControl.SelectedValue -eq 'New PowerShell Script.ps1') {
        Set-Variable -Name 'New PowerShell Script.ps1' -Value $($ScriptTextControl.Text) -Scope Global -Force
    }
    else {
        Set-Variable -Name $($Global:WorkingScript.Guid) -Value $($ScriptTextControl.Text) -Scope Global -Force
    }
})
#================================================
# GO
#================================================
$StartButtonControl.add_Click({
    Write-Host -ForegroundColor Cyan "Start-Process"
    $Global:OSDPadScriptBlock = [scriptblock]::Create($ScriptTextControl.Text)

    if ($Global:OSDPadScriptBlock) {
        if ($ScriptSelectionControl.SelectedValue -eq 'New PowerShell Script.ps1') {
            $ScriptFile = 'New PowerShell Script.ps1'
        }
        else {
            $ScriptFile = $Global:WorkingScript.Name
        }
        if (!(Test-Path "$env:Temp\OSDPad")) {New-Item "$env:Temp\OSDPad" -ItemType Directory}
        
        $ScriptPath = "$env:Temp\OSDPad\$ScriptFile"
        Write-Host -ForegroundColor DarkGray "Saving contents of `$Global:OSDPadScriptBlock` to $ScriptPath"
        $Global:OSDPadScriptBlock | Out-File $ScriptPath -Encoding utf8 -Width 2000 -Force

        #$Global:XamlWindow.Close()
        #Invoke-Command $Global:OSDPadScriptBlock
        #Start-Process PowerShell.exe -ArgumentList "-NoExit Invoke-Command -ScriptBlock {$Global:OSDPadScriptBlock}"

        Write-Host -ForegroundColor DarkCyan "Start-Process -WorkingDirectory `"$env:Temp\OSDPad`" -FilePath PowerShell.exe -ArgumentList '-NoLogo -NoExit',`"-File `"$ScriptFile`"`""
        Start-Process -WorkingDirectory "$env:Temp\OSDPad" -FilePath PowerShell.exe -ArgumentList '-NoLogo -NoExit',"-File `"$ScriptFile`""
    }
    #Write-Host -ForegroundColor DarkGray "================================================"
})
#================================================
# Customizations
#================================================
[string]$ModuleVersion = Get-Module -Name OSD | Sort-Object -Property Version | Select-Object -ExpandProperty Version -Last 1
$Global:XamlWindow.Title = "$ModuleVersion OSDPad"
#================================================
# Branding
#================================================
if ($Global:OSDPadBranding) {
    $BrandingTitleControl.Content = $Global:OSDPadBranding.Title
    $BrandingTitleControl.Foreground = $Global:OSDPadBranding.Color
}
#================================================
# Launch
#================================================
$Global:XamlWindow.ShowDialog() | Out-Null
#================================================