Inno Setup 6 调用 Windows API 实现DirMove移动大文件夹。
调试版本
[Code] const MOVEFILE_REPLACE_EXISTING = $00000001; MOVEFILE_COPY_ALLOWED = $00000002; // 注意:改用 W 版本,避免 Unicode 路径问题 function MoveFileExW(lpExistingFileName, lpNewFileName: string; dwFlags: Integer): Integer; external 'MoveFileExW@kernel32.dll stdcall'; function MoveDirectory(const SourceDir, DestDir: string; const AllowCrossVolume, Overwrite: Boolean; const ShowError: Boolean): Boolean; var Flags, ErrorCode: Integer; Src, Dst: string; Msg: string; begin // 规范化:去掉尾部反斜杠,避免 API 解析异常 Src := RemoveBackslashUnlessRoot(SourceDir); Dst := RemoveBackslashUnlessRoot(DestDir); // 源必须存在 if not DirExists(Src) then begin if ShowError then MsgBox('源文件夹不存在:' + Src, mbError, MB_OK); Log('MoveDirectory: 源不存在 ' + Src); Result := False; Exit; end; // 目标已存在则直接失败(REPLACE_EXISTING 对目录不可靠) if DirExists(Dst) then begin if ShowError then MsgBox('目标文件夹已存在,拒绝移动:' + Dst, mbError, MB_OK); Log('MoveDirectory: 目标已存在 ' + Dst); Result := False; Exit; end; Flags := 0; if Overwrite then Flags := Flags or MOVEFILE_REPLACE_EXISTING; if AllowCrossVolume then Flags := Flags or MOVEFILE_COPY_ALLOWED; Result := MoveFileExW(Src, Dst, Flags) <> 0; if not Result then begin ErrorCode := DLLGetLastError; Msg := Format('MoveFileExW 失败。'#13#10 + '源: %s'#13#10 + '目标: %s'#13#10 + 'Flags: %d'#13#10 + '错误码: %d'#13#10 + '消息: %s', [Src, Dst, Flags, ErrorCode, SysErrorMessage(ErrorCode)]); Log(Msg); if ShowError then MsgBox(Msg, mbError, MB_OK); end else Log(Format('MoveDirectory 成功: %s -> %s', [Src, Dst])); end;
调用处改成:
if DirExists(CacheSrc) then begin // 打印一下实际路径,便于确认 MsgBox('准备移动:'#13#10 + CacheSrc + #13#10 + '->'#13#10 + CacheTmp, mbInformation, MB_OK); MoveDirectory(CacheSrc, CacheTmp, False, True, True); // 最后一个 True = 弹错误 end;
发布版本
[Code] const MOVEFILE_COPY_ALLOWED = $00000002; // 改用 W 版本,避免 Unicode 路径问题 function MoveFileExW(lpExistingFileName, lpNewFileName: string; dwFlags: Integer): Integer; external 'MoveFileExW@kernel32.dll stdcall'; function MoveDirectory(const SourceDir, DestDir: string; const AllowCrossVolume: Boolean): Boolean; var Flags, ErrorCode: Integer; Src, Dst: string; begin // 规范化:去掉尾部反斜杠,避免 API 解析异常 Src := RemoveBackslashUnlessRoot(SourceDir); Dst := RemoveBackslashUnlessRoot(DestDir); // 源必须存在 if not DirExists(Src) then begin Log('MoveDirectory 失败: 源文件夹不存在 ' + Src); Result := False; Exit; end; // 目标已存在则直接失败(防止意外覆盖数据) if DirExists(Dst) then begin Log('MoveDirectory 失败: 目标文件夹已存在 ' + Dst); Result := False; Exit; end; Flags := 0; if AllowCrossVolume then Flags := Flags or MOVEFILE_COPY_ALLOWED; Result := MoveFileExW(Src, Dst, Flags) <> 0; if not Result then begin ErrorCode := DLLGetLastError; Log(Format('MoveDirectory 失败: API 报错 %d (%s) - %s -> %s', [ErrorCode, SysErrorMessage(ErrorCode), Src, Dst])); end; end;
