-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSetup.ps1
More file actions
279 lines (224 loc) · 8.81 KB
/
Copy pathSetup.ps1
File metadata and controls
279 lines (224 loc) · 8.81 KB
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
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# Written with assistance of AI for clarity and structure
param(
[ValidateSet("install", "uninstall")]
[string]$Action = "install",
[string]$InstallDir = "C:\xampp",
[string]$NetworkDriveLetter = "W",
[bool]$CreateDesktopShortcut = $false
)
$ErrorActionPreference = "Stop"
# === CONSTANTS & PATHS ===
$ClassroomDir = Join-Path $InstallDir "classroom"
$StartCmdPath = Join-Path $ClassroomDir "start.cmd"
$ResetCmdPath = Join-Path $ClassroomDir "reset-database.cmd"
$CommonDesktopDir = [Environment]::GetFolderPath("CommonDesktopDirectory")
$CommonStartMenuDir = [Environment]::GetFolderPath("CommonStartMenu")
$ProgramShortcutDir = Join-Path $CommonStartMenuDir "\Programs\XAMPP Classroom"
$ShortcutDesktop = Join-Path $CommonDesktopDir "XAMPP Classroom.lnk"
$ShortcutStart = Join-Path $ProgramShortcutDir "XAMPP Classroom.lnk"
$ShortcutReset = Join-Path $ProgramShortcutDir "Reset MySQL Database.lnk"
$XamppIconPath = "C:\xampp\xampp_start.exe"
$PublicDirectorySDDL = "O:BAG:DUD:PAI(A;OICI;0x1e01ff;;;AU)(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;0x1200a9;;;BU)"
$WriteFileNotDeleteSDDL = "O:BAG:DUD:PAI(A;;0x1201bf;;;AU)(A;;FA;;;SY)(A;;FA;;;BA)(A;;0x1200a9;;;BU)"
# === FUNCTIONS ===
function New-Shortcut {
<#
.SYNOPSIS
Creates a Windows shortcut (.lnk)
#>
param (
[string]$Target,
[string]$ShortcutPath,
[string]$WorkingDirectory = "",
[string]$Description = "",
[string]$IconLocation = ""
)
$WshShell = New-Object -ComObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut($ShortcutPath)
$Shortcut.TargetPath = $Target
if ($WorkingDirectory) { $Shortcut.WorkingDirectory = $WorkingDirectory }
if ($Description) { $Shortcut.Description = $Description }
if ($IconLocation) { $Shortcut.IconLocation = $IconLocation }
$Shortcut.Save()
}
function Remove-Shortcut {
<#
.SYNOPSIS
Removes a shortcut file if it exists
#>
param ([string]$ShortcutPath)
if (Test-Path $ShortcutPath) {
Remove-Item $ShortcutPath -Force
Write-Host "Removed: $ShortcutPath"
}
}
function Remove-IfEmpty {
<#
.SYNOPSIS
Removes a directory only if it is empty
#>
param ([string]$Directory)
if ((Test-Path $Directory) -and !(Get-ChildItem $Directory -Recurse -Force | Where-Object { -not $_.PSIsContainer })) {
Remove-Item $Directory -Force -Recurse
Write-Host "Removed empty directory: $Directory"
}
}
function Test-ReparsePoint {
<#
.SYNOPSIS
Checks if a path is a symlink (reparse point)
#>
param([string]$Path)
$file = Get-Item $Path -Force -ErrorAction SilentlyContinue
return [bool]($file.Attributes -band [IO.FileAttributes]::ReparsePoint)
}
function Remove-Symlink {
<#
.SYNOPSIS
Removes a symlink without deleting its target content
#>
param([string]$Path)
if (-not (Test-Path $Path)) {
Write-Host "Path does not exist: $Path"
return
}
$item = Get-Item $Path -Force
if (Test-ReparsePoint $item.FullName) {
try {
$item.Delete()
Write-Host "Removed symlink: $($item.FullName)"
} catch {
Write-Warning "Failed to remove symlink: $($item.FullName) - $_"
}
} else {
Write-Warning "Not a symlink: $($item.FullName) - skipping to avoid deleting real data."
}
}
function Set-SDDLToPath {
param([string]$sddl, [string]$path)
$acl = Get-Acl $path
$acl.SetSecurityDescriptorSddlForm($sddl)
Set-Acl $path $acl
}
function Add-PublicDirectoryAndSymlink {
param([string]$LinkPath, [string]$TargetPath)
New-Item $TargetPath -ItemType Directory -Force | Out-Null
Set-SDDLToPath $PublicDirectorySDDL $TargetPath
Add-Symlink -LinkPath $LinkPath -TargetPath $TargetPath -UsePowerShell $true
}
function Add-PublicDirectory {
param([string]$TargetPath)
New-Item $TargetPath -ItemType Directory -Force | Out-Null
Set-SDDLToPath $PublicDirectorySDDL $TargetPath
}
function AddFileAllowWriteNoDelete {
param([string]$FilePath)
if (-Not(Test-Path $FilePath)) {
New-Item $FilePath -ItemType File | Out-Null
}
Set-SDDLToPath $WriteFileNotDeleteSDDL $FilePath
}
function Add-Symlink {
param(
[string]$LinkPath,
[string]$TargetPath,
[bool]$UsePowerShell = $true
)
if (Test-Path $LinkPath) {
if (Test-ReparsePoint $LinkPath) {
(Get-Item $LinkPath).Delete()
} else {
Remove-Item $LinkPath -Force -Recurse
}
}
if ($UsePowerShell) {
New-Item -ItemType SymbolicLink -Path $LinkPath -Target $TargetPath
} else {
cmd.exe /c mklink /D "$LinkPath" "$TargetPath" | Out-Null
}
}
function Add-PublicDirectoryRoot {
param([string]$Path)
$sddl = "O:BAG:DUD:PAI(A;OICI;0x1200a9;;;AU)(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;0x1200a9;;;BU)"
if (Test-Path $Path) {
Write-Host "Xampp public directory already exists: $Path. Deleting..."
Remove-Item $Path -Recurse -Force
}
New-Item $Path -ItemType Directory -Force | Out-Null
Set-SDDLToPath $sddl $Path
}
# === INSTALL ===
if ($Action -eq "install") {
Write-Host "Installing to $ClassroomDir..." -ForegroundColor Cyan
$SourceDir = Join-Path $PSScriptRoot "src"
$XamppPublicDir = "C:\xampp-public"
$MysqlDataDir = "$InstallDir\mysql\data"
$MysqlTemplateDir = "$InstallDir\mysql\data-template"
New-Item $ClassroomDir -ItemType Directory -Force | Out-Null
Copy-Item "$SourceDir\*" -Destination $ClassroomDir -Recurse -Force
Set-Content $StartCmdPath -Value "@echo off`nPowerShell -ExecutionPolicy Bypass -File `"$ClassroomDir\XamppClassRoomStarter.ps1`" -Action start -NetworkDriveLetter $NetworkDriveLetter" -Encoding ASCII
Set-Content $ResetCmdPath -Value "@echo off`nPowerShell -ExecutionPolicy Bypass -File `"$ClassroomDir\XamppClassRoomStarter.ps1`" -Action reset-database -NetworkDriveLetter $NetworkDriveLetter" -Encoding ASCII
New-Item $ProgramShortcutDir -ItemType Directory -Force | Out-Null
if ($CreateDesktopShortcut) {
New-Shortcut $StartCmdPath $ShortcutDesktop -Description "Start Xampp Classroom" -IconLocation $XamppIconPath
}
New-Shortcut $StartCmdPath $ShortcutStart -Description "Start Xampp Classroom" -IconLocation $XamppIconPath
New-Shortcut $ResetCmdPath $ShortcutReset -Description "Reset the database"
if (-not (Test-Path $InstallDir)) {
Write-Error "XAMPP installation directory not found: $InstallDir"
exit 1
}
Set-SDDLToPath "O:BAG:DUD:PAI(A;OICI;0x1200a9;;;AU)(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;0x1200a9;;;BU)" $InstallDir
Add-PublicDirectoryRoot $XamppPublicDir
Add-PublicDirectoryAndSymlink "$InstallDir\apache\logs" "$XamppPublicDir\apache-logs"
Add-PublicDirectoryAndSymlink "$InstallDir\phpmyadmin\tmp" "$XamppPublicDir\phpmyadmin-tmp"
Add-PublicDirectoryAndSymlink "$InstallDir\tmp" "$XamppPublicDir\tmp"
AddFileAllowWriteNoDelete "$InstallDir\xampp-control.ini"
AddFileAllowWriteNoDelete "$InstallDir\xampp-control.log"
Add-Symlink "$InstallDir\htdocs" "$($NetworkDriveLetter):\htdocs" $false
Add-Symlink "$InstallDir\htdocs" "$($NetworkDriveLetter):\htdocs" $false
if (-not (Test-Path $MysqlTemplateDir)) {
if (-not (Test-ReparsePoint $MysqlDataDir)) {
Move-Item $MysqlDataDir $MysqlTemplateDir
}
}
Add-Symlink "$MysqlDataDir" "$($NetworkDriveLetter):\mysqldata" $false
Write-Host "Installation complete." -ForegroundColor Green
}
# === UNINSTALL ===
elseif ($Action -eq "uninstall") {
Write-Host "Uninstalling..." -ForegroundColor Cyan
foreach ($path in @(
"$InstallDir\htdocs",
"$InstallDir\tmp",
"$InstallDir\mysql\data",
"$InstallDir\apache\logs"
"$InstallDir\phpmyadmin\tmp"
)) {
Remove-Symlink $path
# The uninstaller expects to have the directories we have replaced with an symlink
# We have to create them if they don't exist before the uninstaller can run properbly
if (-Not(Test-Path $path)) {
New-Item -ItemType Directory -Path $path
}
}
foreach ($shortcut in @($ShortcutDesktop, $ShortcutStart, $ShortcutReset)) {
Remove-Shortcut $shortcut
}
foreach ($file in @($StartCmdPath, $ResetCmdPath)) {
if (Test-Path $file) {
Remove-Item $file -Force
Write-Host "Removed: $file"
}
}
if (Test-Path $ClassroomDir) {
try {
Remove-Item $ClassroomDir -Recurse -Force
Write-Host "Removed classroom directory: $ClassroomDir"
} catch {
Write-Warning "Could not remove $ClassroomDir. It may be in use by another process."
}
}
Remove-IfEmpty $ProgramShortcutDir
Write-Host "Uninstallation complete." -ForegroundColor Green
}