WIX安装器执行BackupDatabase2014.bat时抛出0x80070001错误求助
问题:WIX Bootstrapper执行SQL Server备份BAT脚本失败
场景与配置
使用WIX Bootstrapper制作应用安装包,预期执行流程:
- 备份SQL Server 2014数据库
- 移除SQL Server 2014实例
- 删除相关注册表项
- 安装SQL Server 2022实例
- 将2014备份恢复到2022实例
Bundle.wxs中的Chain配置:
<Chain> <ExePackage SourceFile="..\prerequisites\BackupDatabase2014.bat" DisplayName="Backing up 2014 Database.." Compressed ="yes" Vital ="no" Permanent ="yes" /> <ExePackage SourceFile="..\prerequisites\RemoveDatabase2014.bat" DisplayName="Uninstalling 2014 database.." Compressed ="yes" Vital ="no" Permanent ="yes" /> <ExePackage SourceFile="..\prerequisites\RemoveFiles.bat" DisplayName="Removing Existing Database Keys.." Compressed ="yes" Vital ="no" Permanent ="yes" /> <PackageGroupRef Id="Sql2022Express"/> <ExePackage SourceFile="..\prerequisites\RestoreDatabase2014.bat" DisplayName="Restoring 2014 Database records.." Compressed ="yes" Vital ="no" Permanent ="yes" /> </Chain>
问题现象
单独运行BackupDatabase2014.bat可成功备份数据库,但通过WIX生成的EXE执行时返回错误:
Applying execute package: BackupDatabase2014.bat, action: Install, path: C:\ProgramData\Package Cache\812A85A2036657975578443EC126F48F631CEC9E\BackupDatabase2014.bat, arguments: '"C:\ProgramData\Package Cache\812A85A2036657975578443EC126F48F631CEC9E\BackupDatabase2014.bat"' Error 0x80070001: Process returned error: 0x1 Error 0x80070001: Failed to execute EXE package. Error 0x80070001: Failed to configure per-machine EXE package.
备份脚本内容
BackupDatabase2014.bat完整代码:
@echo off SETLOCAL EnableExtensions rem Check if the script is running with administrative privileges net session >nul 2>&1 if %errorLevel% neq 0 ( echo This script requires administrative privileges. Please run it as an administrator. exit /b 1 ) echo Checking for SQL Server instance XYZInstance... reg query "HKLM\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL" /v XYZINSTANCE | findstr /i "MSSQL12.XYZINSTANCE" > nul 2>&1 if %errorlevel% neq 0 ( echo XYZInstance instance not found in the registry. Exiting... exit /b 1 ) echo Setting backup folder path... set "BackupFolderPath=C:\Database2014Backup" echo Checking if the backup folder exists... if not exist "%BackupFolderPath%" ( echo Creating backup folder... mkdir "%BackupFolderPath%" if %errorlevel% neq 0 ( echo Failed to create the backup folder. Exiting... exit /b 1 ) ) echo Granting permissions... icacls "%BackupFolderPath%" /grant "NT AUTHORITY\SYSTEM":(OI)(CI)F if %errorlevel% neq 0 ( echo Failed to grant permissions to the backup folder. Exiting... exit /b 1 ) echo Setting variables for backup... set "ServerName=%COMPUTERNAME%\XYZInstance" set "DatabaseName=XYZInstance" set "BackupFileName=%DatabaseName%_Backup_%date:~4,2%-%date:~7,2%-%date:~10,4%.bak" set "BackupFilePath=%BackupFolderPath%\%BackupFileName%" echo Checking if the database exists... sqlcmd -S %ServerName% -Q "IF EXISTS(SELECT 1 FROM sys.databases WHERE name = '%DatabaseName%') SELECT 1 ELSE SELECT 0;" -h-1 -s" " -W > nul if %ERRORLEVEL% EQU 0 ( echo Performing database backup... sqlcmd -S %ServerName% -Q "BACKUP DATABASE [%DatabaseName%] TO DISK='%BackupFilePath%'" if %errorlevel% neq 0 ( echo Database backup failed. Exiting... exit /b 1 ) echo Checking if the backup was successful... if exist "%BackupFilePath%" ( echo Database backup completed successfully. ) else ( echo Database backup failed. Backup file does not exist. exit /b 1 ) ) else ( echo Database %DatabaseName% does not exist. Skipping backup. ) exit /b 0
解决方案
1. 修改WIX ExePackage配置,确保脚本在标准命令行环境运行
WIX直接调用BAT时可能缺失系统环境变量,改用cmd /c启动脚本,并指定64位执行上下文(针对64位系统):
<ExePackage SourceFile="..\prerequisites\BackupDatabase2014.bat" DisplayName="Backing up 2014 Database.." Compressed="yes" Vital="no" Permanent="yes" InstallCommand="cmd /c "[SourceFile]"" Platform="x64" />
InstallCommand:强制通过cmd.exe执行脚本,确保加载完整环境变量Platform="x64":避免32位进程注册表重定向,确保能正确读取SQL Server的64位注册表项
2. 优化BAT脚本的兼容性与错误排查
移除冗余的管理员权限检查
WIX安装包已以管理员权限运行,net session在WIX的执行上下文可能返回异常,直接删除以下代码块:
rem Check if the script is running with administrative privileges net session >nul 2>&1 if %errorLevel% neq 0 ( echo This script requires administrative privileges. Please run it as an administrator. exit /b 1 )
固定sqlcmd路径,避免环境变量缺失
SQL Server 2014的sqlcmd默认路径为C:\Program Files\Microsoft SQL Server\120\Tools\Binn\sqlcmd.exe,在脚本开头添加路径定义,并替换所有sqlcmd调用:
set "SqlCmdPath=C:\Program Files\Microsoft SQL Server\120\Tools\Binn\sqlcmd.exe"
修改后的数据库检查与备份命令:
echo Checking if the database exists... "%SqlCmdPath%" -S %ServerName% -Q "IF EXISTS(SELECT 1 FROM sys.databases WHERE name = '%DatabaseName%') SELECT 1 ELSE SELECT 0;" -h-1 -s" " -W > nul if %ERRORLEVEL% EQU 0 ( echo Performing database backup... "%SqlCmdPath%" -S %ServerName% -Q "BACKUP DATABASE [%DatabaseName%] TO DISK='%BackupFilePath%'" if %errorlevel% neq 0 ( echo Database backup failed. Exiting... exit /b 1 )
替换日期格式为系统兼容方式
%date%的格式依赖系统区域设置,可能生成非法文件名,改用wmic生成统一格式的日期:
for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a" set "BackupFileName=%DatabaseName%_Backup_%dt:~4,2%-%dt:~6,2%-%dt:~0,4%.bak"
添加日志记录,方便排查错误
在脚本开头添加日志文件定义,将所有输出写入日志:
set "LogFolder=C:\Database2014Backup" if not exist "%LogFolder%" mkdir "%LogFolder%" for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a" set "LogFile=%LogFolder%\BackupLog_%dt:~0,8%_%dt:~8,4%.txt" echo Starting backup at %date% %time% >> "%LogFile%"
然后将所有echo命令修改为追加到日志,例如:
echo Checking for SQL Server instance XYZInstance... >> "%LogFile%"
3. 调整脚本错误处理逻辑
将部分严格的exit /b 1改为警告并继续执行(根据实际需求),例如注册表检查失败时,允许脚本跳过备份而非直接退出:
echo Checking for SQL Server instance XYZInstance... >> "%LogFile%" reg query "HKLM\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL" /v XYZINSTANCE | findstr /i "MSSQL12.XYZINSTANCE" > nul 2>&1 if %errorlevel% neq 0 ( echo XYZInstance instance not found in the registry. Skipping backup... >> "%LogFile%" exit /b 0 )
内容的提问来源于stack exchange,提问作者Suman jha
相关产品推荐
相关产品推荐

