Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ComponentIDs for files change depending on folder that source is built from. #1561

Closed
cameron-moore opened this issue Jun 18, 2024 · 5 comments

Comments

@cameron-moore
Copy link

cameron-moore commented Jun 18, 2024

Hi,

I'm using WixSharp 1.25.3 to build an installer and noticed that the component Ids of files included in the install package changed depending on where the VS solution that includes the WixSharp project was located. For example, if the solution was in a folder under C:\projects" the wxs file would have one set of ComponentIDs generated. If the solution was built on the build server, in a different location, it'd have a different set of component IDs. This led to issues where files are unexpected deleted on an upgrade because there are multiple component IDs for the same installed file.

Absolute paths are being used to define the source for the files to include and I'm using the default component ID generation algorithm that creates a hash from the destination folder and filename.

What I noticed is that the GetTargetPathOf method in Project uses the full file name, including any path, to generate the target path. For example, if file xyx.txt was being installed to the folder %ProgramFiles%\My Company\My Product from source folder C:\sourceFiles the GetTargetPath method would return a target path of %ProgramFiles%\My Company\My Product\C:\sourceFiles\xyz.txt for that file.

If the GetTargetPathOf method is meant to get the target path of the file then I believe it should be stripping any path information from the source filename before using it to construct the target path of the file. When this is done the hash and component ID generated for each file is consistent regardless of what path the source file is located in.

Below is an updated version of GetTargetPathOf that does strips path information from the source file and just combines the source filename with the destination folders.

 public string GetTargetPathOf(File file)
 {
     var filename = file?.Name.Split(System.IO.Path.DirectorySeparatorChar).LastOrDefault() ?? string.Empty;
     var dir = this.AllDirs.FirstOrDefault(d => d.Files.Contains(file));
     var path = new List<string> { filename };

     while (dir != null)
     {
         path.Insert(0, dir.Name);
         dir = this.AllDirs.FirstOrDefault(d => d.Dirs.Contains(dir));
     }
     return path.JoinBy($"{System.IO.Path.DirectorySeparatorChar}");
 }

Hope this helps and thanks for a great library!

Cameron.

@oleg-shilo
Copy link
Owner

Yes, indeed the component ID generation is based on the path and in the case of an absolute path it can lead to unintended id changes. Even though still valid msi.

I will process your suggestion and integrate it if it does not cause any implications.

Thank you for sharing.

@cameron-moore
Copy link
Author

Thanks @oleg-shilo. Much appreciated.
Cameron.

@oleg-shilo
Copy link
Owner

oleg-shilo commented Jun 28, 2024

Hi Cameron,

May I ask you why you did not use GetFileName? Is there a reason? Am I missing something?

var filename = file?.Name.Path.PathGetFileName() ?? string.Empty;
// instead of 
var filename = file?.Name.Split(System.IO.Path.DirectorySeparatorChar).LastOrDefault() ?? string.Empty;

oleg-shilo added a commit that referenced this issue Jun 28, 2024
- Issue #1561: ComponentIDs for files change depending on folder that source is built from.
oleg-shilo added a commit that referenced this issue Jun 28, 2024
- Issue #1561: ComponentIDs for files change depending on folder that source is built from.
@cameron-moore
Copy link
Author

Hi Cameron,

May I ask you why you did not use GetFileName? Is there a reason? Am I missing something?

var filename = file?.Name.Path.PathGetFileName() ?? string.Empty;
// instead of 
var filename = file?.Name.Split(System.IO.Path.DirectorySeparatorChar).LastOrDefault() ?? string.Empty;

Hi @oleg-shilo,
Path.GetFileName() would definitely be fine to use. There wasn't any reason why I didn't use that & you're not missing anything. I just didn't think of that at the time.

Thanks,
Cameron.

@oleg-shilo
Copy link
Owner

Perfect. Then we are fine.

oleg-shilo added a commit that referenced this issue Sep 21, 2024
- #1638: Simplify Custom UI - removed Caliburn.Micro
- #1641: How to set or use Launchcondition Action in Wix#
- #1613: Hidden child features in FeaturesDialog.UserSelectedItems
- #1613: Hidden child features in FeaturesDialog.UserSelectedItems
- #1604: Some strings in Dialogs from .wxl are not replaced in Custom WPF UI
- Issue #1561: ComponentIDs for files change depending on folder that source is built from.
- fixed problem with `SetShellSize` not setting the top level window size
- Added `CommonTasks.MapAsDeferredProperty` extension method
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants