diff --git a/scripts/build-msi.ps1 b/scripts/build-msi.ps1
new file mode 100644
index 000000000..af7f3c7ce
--- /dev/null
+++ b/scripts/build-msi.ps1
@@ -0,0 +1,279 @@
+# OpenRGB MSI Builder for Windows
+# PowerShell conversion of build-msi.sh
+
+# Add Wix to path
+$env:Path += ";C:\Program Files (x86)\WiX Toolset v3.14\bin"
+
+# Add Qt to path
+$env:Path += ";C:\Qt\6.8.3\msvc2022_64\bin"
+
+# Function to generate random UUID v4
+function Generate-UUIDv4
+{
+ return [guid]::NewGuid().ToString().ToUpper()
+}
+
+# Function to generate namespace-based UUID (SHA1)
+function Generate-NamespaceUUID
+{
+ param
+ (
+ [guid]$Namespace,
+ [string]$Name
+ )
+
+ $nameBytes = [System.Text.Encoding]::UTF8.GetBytes($Name)
+ $combined = $Namespace.ToByteArray() + $nameBytes
+ $hash = [System.Security.Cryptography.SHA1]::Create().ComputeHash($combined)
+
+ # Set version to 5 (SHA1-based namespace UUID)
+ $hash[6] = ($hash[6] -band 0x0f) -bor 0x50
+ $hash[8] = ($hash[8] -band 0x3f) -bor 0x80
+
+ $uuidBytes = [byte[]]($hash[0..15])
+ $uuid = [guid]$uuidBytes
+
+ return $uuid.ToString().ToUpper()
+}
+
+# Configuration
+$PRODUCTNAME = "OpenRGB"
+$VENDOR = $PRODUCTNAME
+
+$TLD = "org"
+$WEBSITE = "https://$($PRODUCTNAME.ToLower()).$TLD"
+
+# URL namespace UUID (RFC 4122, version 4 namespace)
+$URLNamespace = [guid]'6ba7b810-9dad-11d1-80b4-00c04fd430c8'
+$NAMESPACE = Generate-NamespaceUUID $URLNamespace $WEBSITE
+
+$VENDOR_ID = "$TLD.$VENDOR"
+$APP_ID = "$VENDOR_ID.$($PRODUCTNAME.ToLower())"
+
+$GITURL = "https://gitlab.com/CalcProgrammer1/OpenRGB/-"
+$GITPARAM = "?inline=false"
+$ICONFILE = "qt/OpenRGB.ico"
+$LICENSEFILE = "scripts/License.rtf"
+$BANNERIMAGE = "scripts/banner.bmp"
+$DIALOGBACKGROUND = "scripts/dialog_background.bmp"
+$PROJECT_FILE = "OpenRGB.pro"
+$XMLOUTFILE = "$($PRODUCTNAME.ToLower()).wxs"
+
+# Extract version from project file
+$VERSION = & qmake $PROJECT_FILE 2>&1 | Select-String 'VERSION_WIX' | Select-Object -First 1 | ForEach-Object {
+ $_.Line -split ':' | Select-Object -Last 1 | ForEach-Object { $_.Trim() }
+}
+
+# Check for suffix to determine channel
+$CHANNEL = ""
+$SUFFIX = Select-String -Path $PROJECT_FILE -Pattern 'SUFFIX\s' | ForEach-Object {
+ $_.Line -split '=' | Select-Object -Last 1 | ForEach-Object { $_.Trim() }
+}
+
+if($SUFFIX)
+{
+ $CHANNEL = "-git"
+}
+
+# Calculate upgrade code
+$UPGRADECODE = Generate-NamespaceUUID ([guid]$NAMESPACE) $APP_ID
+
+$PRODUCTCOMMENT = "Open source RGB lighting control that doesn't depend on manufacturer software."
+
+# Print Metadata to the log
+Write-Host "Icon URL:`t" $GITURL$ICONFILE
+Write-Host "License URL:`t" $GITURL$LICENSEFILE
+Write-Host "AppID - Channel:`t" $APP_ID " - " $CHANNEL
+Write-Host "Upgrade UUID:`t" $UPGRADECODE
+Write-Host "Product Name:`t" $PRODUCTNAME
+Write-Host "Vendor - VendorID:`t`t" $VENDOR " - " $VENDOR_ID
+Write-Host "Version:`t" $VERSION
+
+# Copy build directory to working path
+$BUILT_PATH = "OpenRGB Windows 64-bit\*"
+$WORKING_PATH = "OpenRGB Windows MSI Installer\"
+
+if(Test-Path $BUILT_PATH)
+{
+ Copy-Item -Path $BUILT_PATH -Destination $WORKING_PATH -Recurse -Force
+}
+
+$count = 1
+$EXE_FILE = ""
+$SVC_FILE = ""
+$FILES = ""
+$COMPONENTS = ""
+$DIRECTORIES = ""
+
+# Build file list for files in the working path
+Get-ChildItem -Path $WORKING_PATH -Force | ForEach-Object {
+ $file = $_
+ $filename = $_.Name
+
+ if($filename -eq "$PRODUCTNAME.exe")
+ {
+ # If this is the executable, treat as special case
+ $script:EXE_ID = "$($PRODUCTNAME)00"
+ $script:SVC_ID = "$($PRODUCTNAME)00_SVC"
+ $script:EXE_FILE = " `r`n"
+ $script:SVC_FILE = " `r`n"
+ }
+ elseif($_.PSIsContainer)
+ {
+ # If this is a directory, add another component
+ $script:COMPONENTS += " `r`n"
+ $guid = Generate-UUIDv4
+ $TEMP = " `r`n"
+ $TEMP += " `r`n"
+
+ Get-ChildItem -Path $file.FullName -Force | ForEach-Object {
+ $filename2 = $_.Name
+ $TEMP += " `r`n"
+ $script:count++
+ }
+
+ $TEMP += " `r`n `r`n"
+ $script:DIRECTORIES += $TEMP
+ }
+ else
+ {
+ # Any other file to files list
+ $script:FILES += " `r`n"
+ $script:count++
+ }
+}
+
+# Create the Wix XML file
+$XML_FILE = ""
+
+$XML_FILE += "`r`n"
+$XML_FILE += "`r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += " VersionNT64`r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += "`r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += "`r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += "`r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += "`r`n"
+$XML_FILE += " WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID=`"1`"`r`n"
+$XML_FILE += " 1`r`n"
+$XML_FILE += " 1`r`n"
+$XML_FILE += " 1`r`n"
+$XML_FILE += " 1`r`n"
+$XML_FILE += " 1`r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += "`r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+
+$guid1 = Generate-UUIDv4
+$XML_FILE += " `r`n"
+$XML_FILE += $EXE_FILE
+$XML_FILE += $FILES
+$XML_FILE += " `r`n"
+
+$guid2 = Generate-UUIDv4
+$XML_FILE += " `r`n"
+$XML_FILE += $SVC_FILE
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += $DIRECTORIES
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += $COMPONENTS
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += " `r`n"
+$XML_FILE += ""
+
+# Write XML file
+$XML_FILE | Out-File -FilePath $XMLOUTFILE -Encoding UTF8
+
+# Print the XML for debugging
+Write-Host (Get-Content $XMLOUTFILE)
+
+# Build the MSI package
+Write-Host "`nBuilding MSI package..."
+
+$wixObjFile = "$($PRODUCTNAME.ToLower()).wixobj"
+$msiFile = "$($PRODUCTNAME)_Windows_64.msi"
+
+& candle -arch x64 $XMLOUTFILE
+& light -sval -ext WixUIExtension $wixObjFile -out $msiFile
diff --git a/scripts/build-msi.sh b/scripts/build-msi.sh
index c0979e5b8..24f1d79ef 100755
--- a/scripts/build-msi.sh
+++ b/scripts/build-msi.sh
@@ -115,6 +115,23 @@ XML_FILE+=" \r\n"
XML_FILE+=" \r\n"
XML_FILE+=" \r\n"
XML_FILE+="\r\n"
+XML_FILE+=" \r\n"
+XML_FILE+="\r\n"
XML_FILE+=" \r\n"
XML_FILE+="\r\n"
-XML_FILE+=" WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID=\"1\"\r\n"
+XML_FILE+=" WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID=\"1\"\r\n"
XML_FILE+=" 1\r\n"
+XML_FILE+=" 1\r\n"
+XML_FILE+=" 1\r\n"
XML_FILE+=" 1\r\n"
-XML_FILE+=" 1\r\n"
+XML_FILE+=" 1\r\n"
XML_FILE+=" \r\n"
XML_FILE+="\r\n"
XML_FILE+=" \r\n"