public override bool Execute()
        {
            if (string.IsNullOrEmpty(LinkName))
            {
                throw new InvalidOperationException("LinkName was not set");
            }
            if (string.IsNullOrEmpty(TargetName))
            {
                throw new InvalidOperationException("TargetName was not set");
            }

            var exists = SymlinkTargetType == SymlinkTargetType.Directory ? Directory.Exists(LinkName) : File.Exists(LinkName);

            if (exists)
            {
                // if this is already a symlink, check if it points to the same target and if not then delete it
                var isSymlink = (File.GetAttributes(LinkName) & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint;
                if (isSymlink)
                {
                    var querySymlinkTask = new QuerySymlink {
                        LinkName = LinkName, TargetName = TargetName, TargetType = TargetType, BuildEngine = BuildEngine
                    };
                    if (!querySymlinkTask.Execute())
                    {
                        return(false);
                    }
                    Log.LogMessage(MessageImportance.Low, $"{SymlinkTargetType} '{LinkName}' is a symlink which points to '{querySymlinkTask.TargetName}'");
                    if (string.Equals(querySymlinkTask.TargetName, TargetName.TrimEnd('\\'), StringComparison.InvariantCultureIgnoreCase))
                    {
                        // the symlink's target matches our target
                        return(true);
                    }
                    Log.LogMessage(MessageImportance.Normal, $"Deleting symlink '{LinkName}' because it points to a different target '{querySymlinkTask.TargetName}'");
                }
                else
                {
                    Log.LogMessage(MessageImportance.Normal, $"{SymlinkTargetType} '{LinkName}' needs to be deleted before converting it to a symlink");
                }
                // if this is reached then delete is needed
                DeleteDirectoryOrFile();
            }

            var createSymlinkTask = new CreateSymlink {
                LinkName = LinkName, TargetName = TargetName, TargetType = TargetType, BuildEngine = BuildEngine
            };

            return(createSymlinkTask.Execute());
        }
Exemple #2
0
        public override bool Execute()
        {
            if (string.IsNullOrEmpty(LinkName))
            {
                throw new InvalidOperationException("LinkName was not set");
            }
            if (string.IsNullOrEmpty(TargetName))
            {
                throw new InvalidOperationException("TargetName was not set");
            }

            var linkParentDirectory = Path.GetDirectoryName(LinkName.TrimEnd('\\'));

            try
            {
                if (linkParentDirectory != null && !Directory.Exists(linkParentDirectory))
                {
                    Directory.CreateDirectory(linkParentDirectory);
                }
            }
            catch (Exception ex)
            {
                Log.LogError($"Error creating symbolic link for {LinkName} <<====>> {TargetName}. Could not create parent directory {linkParentDirectory}: {ex.Message}");
                return(false);
            }

            var result = NativeMethods.CreateSymbolicLink(LinkName.TrimEnd('\\'), TargetName.TrimEnd('\\'), _targetType);

            if (!result)
            {
                const uint requiredPrivilegeError = 0x80070522;
                if ((uint)Marshal.GetHRForLastWin32Error() == requiredPrivilegeError)
                {
                    Log.LogError($"Error creating symbolic link for {LinkName} <<====>> {TargetName}. Try running the build from an elevated process.");
                    return(false);
                }

                var exception = Win32Utils.GetExceptionForLastError();
                Log.LogError($"Error creating symbolic link for {LinkName} <<====>> {TargetName}: {exception.Message}");
                return(false);
            }
            Log.LogMessage(MessageImportance.High, $"Symbolic link created for {LinkName} <<====>> {TargetName}");
            return(true);
        }