Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
LuSlower authored Jun 27, 2024
1 parent 66960c4 commit d862696
Showing 1 changed file with 344 additions and 0 deletions.
344 changes: 344 additions & 0 deletions WinBCD.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,344 @@
# Chequear privilegios de administrador
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
$delay = 2
if (-not $isAdmin) {
[System.Windows.Forms.MessageBox]::Show("Run the script as an administrator", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
Start-Sleep -Seconds $delay
Exit
}

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

function Console {
param (
[Switch]$Show,
[Switch]$Hide,
[string]$Text
)

if (-not ("Console.Window" -as [type])) {
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);
'
}

if ($Show) {
$consolePtr = [Console.Window]::GetConsoleWindow()
$null = [Console.Window]::ShowWindow($consolePtr, 5)
}

if ($Hide) {
$consolePtr = [Console.Window]::GetConsoleWindow()
$null = [Console.Window]::ShowWindow($consolePtr, 0)
}

if ($Text) {
$syncHash.TextBoxOutPut.AppendText("$Text`r`n")
}
}

# Funcion para mostrar un dialogo desplegable
function Show-SelectionDialog {
param (
[string]$title,
[string]$prompt,
[array]$options
)

$form = New-Object System.Windows.Forms.Form
$form.Text = $title
$form.Size = New-Object System.Drawing.Size(410, 290)
$form.StartPosition = 'CenterScreen'
$form.MaximizeBox = $false
$form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedSingle

$label = New-Object System.Windows.Forms.Label
$label.Text = $prompt
$label.AutoSize = $true
$label.Location = New-Object System.Drawing.Point(10, 20)
$form.Controls.Add($label)

$listBox = New-Object System.Windows.Forms.ListBox
$listBox.Size = New-Object System.Drawing.Size(360, 150)
$listBox.Location = New-Object System.Drawing.Point(10, 50)
$listBox.Items.AddRange($options)
$form.Controls.Add($listBox)

$okButton = New-Object System.Windows.Forms.Button
$okButton.Text = 'OK'
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$okButton.Location = New-Object System.Drawing.Point(310, 220)
$form.Controls.Add($okButton)
$form.AcceptButton = $okButton

$cancelButton = New-Object System.Windows.Forms.Button
$cancelButton.Text = 'Cancel'
$cancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$cancelButton.Location = New-Object System.Drawing.Point(220, 220)
$form.Controls.Add($cancelButton)
$form.CancelButton = $cancelButton

$form.Add_Shown({$form.Activate()})
[void]$form.ShowDialog()

if ($form.DialogResult -eq [System.Windows.Forms.DialogResult]::OK -and $listBox.SelectedItem -ne $null) {
return $listBox.SelectedItem
}

return $null
}

# Funcion para refrescar los nombres de las particiones
function Refresh-Partitions {
$comboBox.Items.Clear()
$drives = Get-WmiObject -Class Win32_LogicalDisk | Where-Object { $_.DriveType -eq 3 -or $_.DriveType -eq 5 -and $_.DeviceID -ne "$env:SystemDrive" }
foreach ($drive in $drives) {
$label = $drive.VolumeName
if ([string]::IsNullOrWhiteSpace($label)) {
$label = "Drive " + $drive.DeviceID
}
$comboBox.Items.Add("$($drive.DeviceID) - $label")
}
if ($comboBox.Items.Count -gt 0) {
$comboBox.SelectedIndex = 0
}
}


# Funcion para crear la particion a partir del nombre la iso
function Create-Partition {
param (
[string]$filePath
)

# Verificar si existe la particion
$volumeName = [System.IO.Path]::GetFileNameWithoutExtension($filePath)
$checkpartition = Get-WMIObject Win32_Volume | Where-Object { $_.Label -eq $volumeName}

if ($checkpartition) {
[System.Windows.Forms.MessageBox]::Show("The partition already exists", "Info", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
return
}

# calcular el valor en GB, redondear para estar más seguro, verificar en que disco se encuentra
$fileSizeGB = [math]::Ceiling((Get-Item $filePath).Length / 1GB)
$systemDrive = $env:SystemDrive.TrimEnd(':')
$disk = Get-Partition -DriveLetter $systemDrive | Get-Disk

if ($disk -ne $null) {
# reducir el tamaño de la particion principal,
$systemPartition = Get-Partition -DriveLetter $systemDrive
Resize-Partition -InputObject $systemPartition -Size ($systemPartition.Size - ($fileSizeGB * 3GB))

# Crear la nueva particion
$partition = New-Partition -DiskNumber $disk.Number -Size ($partitionSizeGB * 3GB) -AssignDriveLetter

if ($partition -ne $null) {
$driveLetter = $partition.DriveLetter

# Determinar el sistema de archivos, obtener el nombre de la iso
$fileSystem = if ($fileSizeGB -lt 4) { "FAT32" } else { "NTFS" }

# formatear
Format-Volume -DriveLetter $driveLetter -FileSystem $fileSystem -NewFileSystemLabel $volumeName

[System.Windows.Forms.MessageBox]::Show("Partition created and formatted successfully", "Info", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)

# refrescar
Refresh-Partitions

} else {
[System.Windows.Forms.MessageBox]::Show("Failed to create partition", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
}
} else {
[System.Windows.Forms.MessageBox]::Show("Failed to find the system disk", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
}
}

# Crear form, ocultar consola
Console -Hide
[System.Windows.Forms.Application]::EnableVisualStyles();
$form = New-Object System.Windows.Forms.Form
$form.Text = "WinBCD"
$form.Size = New-Object System.Drawing.Size(330, 135)
$form.StartPosition = "CenterScreen"
$form.MaximizeBox = $false
$form.AllowDrop = $true
$form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedSingle

# ComboBox para enumerar particiones
$comboBox = New-Object System.Windows.Forms.ComboBox
$comboBox.Location = New-Object System.Drawing.Point(10, 10)
$comboBox.Size = New-Object System.Drawing.Size(250, 20)
$comboBox.DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList


# TextBox para mostrar el nombre de la imagen
$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Point(10, 40)
$textBox.Size = New-Object System.Drawing.Size(250, 20)
$textBox.Enabled = $false

# OpenFileDialog para seleccionar la imagen
$openFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$openFileDialog.Filter = "ISO Files (*.iso)|*.iso|WIM Files (*.wim)|*.wim|ESD Files (*.esd)|*.esd"

# Boton para mostrar el OpenFileDialog
$buttonSelectFile = New-Object System.Windows.Forms.Button
$buttonSelectFile.Location = New-Object System.Drawing.Point(270, 40)
$buttonSelectFile.Size = New-Object System.Drawing.Size(25, 20)
$buttonSelectFile.Text = "..."
$buttonSelectFile.Add_Click({
if ($openFileDialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
$textBox.Text = $openFileDialog.FileName
$buttonCreatePartition.Enabled = $true
}
})

# Boton para instalar la image en la particion seleccionada
$buttonInstall = New-Object System.Windows.Forms.Button
$buttonInstall.Location = New-Object System.Drawing.Point(10, 70)
$buttonInstall.Size = New-Object System.Drawing.Size(75, 23)
$buttonInstall.Text = "Install"
$buttonInstall.Add_Click({

# Obtener la ruta de la imagen
$filePath = $textBox.Text
if ([string]::IsNullOrEmpty($filePath)) {
[System.Windows.Forms.MessageBox]::Show("An error occurred while trying to mount the ISO.", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
return
}

# Step 1: Confirmar montaje de la imagen
$driveLetter = ($comboBox.SelectedItem.ToString() -split ' ')[0]
$warningMessage = "Mounting the image ($filePath) will erase all files on drive $driveLetter. Do you want to continue?"
$confirmation = [System.Windows.Forms.MessageBox]::Show($warningMessage, "Warning", [System.Windows.Forms.MessageBoxButtons]::YesNo, [System.Windows.Forms.MessageBoxIcon]::Warning)

if ($confirmation -eq [System.Windows.Forms.DialogResult]::Yes) {
# Verificar si la imagen es .iso
if ([System.IO.Path]::GetExtension($filePath) -eq ".iso") {
try {
Mount-DiskImage -ImagePath "$filePath" | Out-Null
} catch {
Write-Host "An error occurred while trying to mount the ISO.`nError: $($_.Exception.Message)`n" -ForegroundColor Red
[System.Windows.Forms.MessageBox]::Show("An error occurred while trying to mount the ISO.", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
return
}

$mountedDrive = (Get-DiskImage -ImagePath "$filePath" | Get-Volume).DriveLetter

$esdPath = "$mountedDrive`:\sources\install.esd"
$wimPath = "$mountedDrive`:\sources\install.wim"

if (Test-Path $esdPath) {
$imgPath = $esdPath
} elseif (Test-Path $wimPath) {
$imgPath = $wimPath
} else {
[System.Windows.Forms.MessageBox]::Show("The selected ISO does not appear to be a Windows ISO. The ISO must contain either install.esd or install.wim in the 'sources' folder.", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
Dismount-DiskImage -ImagePath "$filePath"
return
}
} else {
$imgPath = $filePath
}

# Step 2: Seleccionar la edicion
$windowsEditions = Get-WindowsImage -ImagePath $imgPath
$editionsList = $windowsEditions | ForEach-Object { $_.ImageName }
$selectedEdition = Show-SelectionDialog -title "Select a Windows edition" -prompt "Available editions:" -options $editionsList

if (-not $selectedEdition -or $selectedEdition -eq "Cancel") {
Write-Host "Edition selection canceled." -ForegroundColor Yellow
Dismount-DiskImage -ImagePath "$filePath"
return
}

$selectedIndex = $windowsEditions | Where-Object { $_.ImageName -eq $selectedEdition } | Select-Object -ExpandProperty ImageIndex

# Step 3: Aplicar la imagen
# Formatear, extraer imagen en la particion
Write-Host "Applying image (installing/extracting Windows)..." -ForegroundColor Yellow
Expand-WindowsImage -ImagePath "$imgPath" -ApplyPath "$driveLetter\" -Index $selectedIndex -LogLevel 2

# Step 7: Aplicar autounattend por si existe
if (Test-Path "$driveLetter\autounattend.xml") {
Write-Host "Applying unattend answer files..." -ForegroundColor Yellow
Use-WindowsUnattend -Path "$driveLetter\" -UnattendPath "$driveLetter\autounattend.xml"
if (Test-Path "$mountedDrive\sources\$OEM$\$$\Setup\Scripts") {
Copy-Item "$mountedDrive\sources\$OEM$\$$\Setup\Scripts\*" -Destination "$driveLetter\Windows\Setup\Scripts" -Recurse
}
Copy-Item "$mountedDrive\autounattend.xml*" -Destination "$driveLetter\Windows\Setup\Scripts" -Recurse
}

# Step 8: añadir la instalacion de windows al bootmgr
Write-Host "Adding new Windows installation to boot loader..." -ForegroundColor Yellow
bcdboot "$driveLetter\Windows" | Out-Null

Write-Host "Installation completed!" -ForegroundColor Green
$confirm = [System.Windows.Forms.MessageBox]::Show("Installation completed!`ndo you wish to reboot now?", "Info", [System.Windows.Forms.MessageBoxButtons]::YesNo, [System.Windows.Forms.MessageBoxIcon]::Information)
if ($confirm -eq [System.Windows.Forms.DialogResult]::Yes) {
Restart-Computer -Force
}
Dismount-DiskImage -ImagePath "$filePath"
} else {
Write-Host "Mounting canceled." -ForegroundColor Yellow
return
}
})


$buttonRefresh = New-Object System.Windows.Forms.Button
$buttonRefresh.Location = New-Object System.Drawing.Point(100, 70)
$buttonRefresh.Size = New-Object System.Drawing.Size(75, 23)
$buttonRefresh.Text = "Refresh"
$buttonRefresh.Add_Click({
Refresh-Partitions
})

$buttonCreatePartition = New-Object System.Windows.Forms.Button
$buttonCreatePartition.Location = New-Object System.Drawing.Point(190, 70)
$buttonCreatePartition.Size = New-Object System.Drawing.Size(120, 23)
$buttonCreatePartition.Text = "Create Partition"
$buttonCreatePartition.Enabled = $false
$buttonCreatePartition.Add_Click({
Create-Partition -filePath $textBox.Text
})

# añadir Controles
$form.Controls.Add($comboBox)
$form.Controls.Add($textBox)
$form.Controls.Add($buttonSelectFile)
$form.Controls.Add($buttonInstall)
$form.Controls.Add($buttonRefresh)
$form.Controls.Add($buttonCreatePartition)

# Drag & Drop
$form.Add_DragEnter({
if ($_.Data.GetDataPresent([Windows.Forms.DataFormats]::FileDrop)) {
$_.Effect = [Windows.Forms.DragDropEffects]::Copy
}
})

$form.Add_DragDrop({
$files = $_.Data.GetData([Windows.Forms.DataFormats]::FileDrop)
if ($files.Count -eq 1) {
$filePath = $files[0]
$extension = [System.IO.Path]::GetExtension($filePath).ToLower()
if ($extension -eq ".iso" -or $extension -eq ".wim" -or $extension -eq ".esd") {
$textBox.Text = $filePath
$buttonCreatePartition.Enabled = $true
} else {
[System.Windows.Forms.MessageBox]::Show("Unsupported file format.`nPlease drag and drop an ISO, WIM, or ESD file.", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
}
}
})


Refresh-Partitions

[void]$form.ShowDialog()

0 comments on commit d862696

Please sign in to comment.