public void Execute() { List <string> destinationFiles = new List <string>(); foreach (FileTransfer fileTransfer in this.FileTransfers) { string fileSource = this.ResolveFile(fileTransfer.Source, fileTransfer.Type, fileTransfer.SourceLineNumbers, BindStage.Normal); // If the source and destination are identical, then there's nothing to do here if (0 == String.Compare(fileSource, fileTransfer.Destination, StringComparison.OrdinalIgnoreCase)) { fileTransfer.Redundant = true; continue; } bool retry = false; do { try { if (fileTransfer.Move) { Messaging.Instance.OnMessage(WixVerboses.MoveFile(fileSource, fileTransfer.Destination)); this.TransferFile(true, fileSource, fileTransfer.Destination); } else { Messaging.Instance.OnMessage(WixVerboses.CopyFile(fileSource, fileTransfer.Destination)); this.TransferFile(false, fileSource, fileTransfer.Destination); } retry = false; destinationFiles.Add(fileTransfer.Destination); } catch (FileNotFoundException e) { throw new WixFileNotFoundException(e.FileName); } catch (DirectoryNotFoundException) { // if we already retried, give up if (retry) { throw; } string directory = Path.GetDirectoryName(fileTransfer.Destination); Messaging.Instance.OnMessage(WixVerboses.CreateDirectory(directory)); Directory.CreateDirectory(directory); retry = true; } catch (UnauthorizedAccessException) { // if we already retried, give up if (retry) { throw; } if (File.Exists(fileTransfer.Destination)) { Messaging.Instance.OnMessage(WixVerboses.RemoveDestinationFile(fileTransfer.Destination)); // try to ensure the file is not read-only FileAttributes attributes = File.GetAttributes(fileTransfer.Destination); try { File.SetAttributes(fileTransfer.Destination, attributes & ~FileAttributes.ReadOnly); } catch (ArgumentException) // thrown for unauthorized access errors { throw new WixException(WixErrors.UnauthorizedAccess(fileTransfer.Destination)); } // try to delete the file try { File.Delete(fileTransfer.Destination); } catch (IOException) { throw new WixException(WixErrors.FileInUse(null, fileTransfer.Destination)); } retry = true; } else // no idea what just happened, bail { throw; } } catch (IOException) { // if we already retried, give up if (retry) { throw; } if (File.Exists(fileTransfer.Destination)) { Messaging.Instance.OnMessage(WixVerboses.RemoveDestinationFile(fileTransfer.Destination)); // ensure the file is not read-only, then delete it FileAttributes attributes = File.GetAttributes(fileTransfer.Destination); File.SetAttributes(fileTransfer.Destination, attributes & ~FileAttributes.ReadOnly); try { File.Delete(fileTransfer.Destination); } catch (IOException) { throw new WixException(WixErrors.FileInUse(null, fileTransfer.Destination)); } retry = true; } else // no idea what just happened, bail { throw; } } } while (retry); } // Finally, if there were any files remove the ACL that may have been added to // during the file transfer process. if (0 < destinationFiles.Count && !this.SuppressAclReset) { var aclReset = new FileSecurity(); aclReset.SetAccessRuleProtection(false, false); try { //WixToolset.Core.Native.NativeMethods.ResetAcls(destinationFiles.ToArray(), (uint)destinationFiles.Count); foreach (var file in destinationFiles) { new FileInfo(file).SetAccessControl(aclReset); } } catch { Messaging.Instance.OnMessage(WixWarnings.UnableToResetAcls()); } } }
/// <summary> /// Final step in binding that transfers (moves/copies) all files generated into the appropriate /// location in the source image /// </summary> /// <param name="fileTransfers">Array of files to transfer.</param> /// <param name="fileTransfers">Array of directories to transfer.</param> /// <param name="suppressAclReset">Suppress removing ACLs added during file transfer process.</param> protected void LayoutMedia(ArrayList fileTransfers, bool suppressAclReset) { if (this.core.EncounteredError) { return; } ArrayList destinationFiles = new ArrayList(); for (int i = 0; i < fileTransfers.Count; ++i) { FileTransfer fileTransfer = (FileTransfer)fileTransfers[i]; string fileSource = fileManager.ResolveFile(fileTransfer.Source, fileTransfer.Type, fileTransfer.SourceLineNumbers, BindStage.Normal); // If the source and destination are identical, then there's nothing to do here if (0 == String.Compare(fileSource, fileTransfer.Destination, StringComparison.OrdinalIgnoreCase)) { fileTransfer.Redundant = true; continue; } bool retry = false; do { try { if (fileTransfer.Move) { this.core.OnMessage(WixVerboses.MoveFile(fileSource, fileTransfer.Destination)); this.FileManager.MoveFile(fileSource, fileTransfer.Destination); } else { this.core.OnMessage(WixVerboses.CopyFile(fileSource, fileTransfer.Destination)); this.FileManager.CopyFile(fileSource, fileTransfer.Destination, true); } retry = false; destinationFiles.Add(fileTransfer.Destination); } catch (FileNotFoundException e) { throw new WixFileNotFoundException(e.FileName); } catch (DirectoryNotFoundException) { // if we already retried, give up if (retry) { throw; } string directory = Path.GetDirectoryName(fileTransfer.Destination); this.core.OnMessage(WixVerboses.CreateDirectory(directory)); Directory.CreateDirectory(directory); retry = true; } catch (UnauthorizedAccessException) { // if we already retried, give up if (retry) { throw; } if (File.Exists(fileTransfer.Destination)) { this.core.OnMessage(WixVerboses.RemoveDestinationFile(fileTransfer.Destination)); // try to ensure the file is not read-only FileAttributes attributes = File.GetAttributes(fileTransfer.Destination); try { File.SetAttributes(fileTransfer.Destination, attributes & ~FileAttributes.ReadOnly); } catch (ArgumentException) // thrown for unauthorized access errors { throw new WixException(WixErrors.UnauthorizedAccess(fileTransfer.Destination)); } // try to delete the file try { File.Delete(fileTransfer.Destination); } catch (IOException) { throw new WixException(WixErrors.FileInUse(null, fileTransfer.Destination)); } retry = true; } else // no idea what just happened, bail { throw; } } catch (IOException) { // if we already retried, give up if (retry) { throw; } if (File.Exists(fileTransfer.Destination)) { this.core.OnMessage(WixVerboses.RemoveDestinationFile(fileTransfer.Destination)); // ensure the file is not read-only, then delete it FileAttributes attributes = File.GetAttributes(fileTransfer.Destination); File.SetAttributes(fileTransfer.Destination, attributes & ~FileAttributes.ReadOnly); try { File.Delete(fileTransfer.Destination); } catch (IOException) { throw new WixException(WixErrors.FileInUse(null, fileTransfer.Destination)); } retry = true; } else // no idea what just happened, bail { throw; } } } while (retry); } // finally, if there were any files remove the ACL that may have been added to // during the file transfer process if (0 < destinationFiles.Count && !suppressAclReset) { try { WixToolset.Cab.Interop.NativeMethods.ResetAcls((string[])destinationFiles.ToArray(typeof(string)), (uint)destinationFiles.Count); } catch { this.core.OnMessage(WixWarnings.UnableToResetAcls()); } } }