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

Decompile multiple projects under single solution and use ProjectReference's #2875

Open
gerneio opened this issue Dec 23, 2022 · 0 comments
Open
Labels

Comments

@gerneio
Copy link

gerneio commented Dec 23, 2022

Steps to reproduce

  1. Use either a) the ILSpy WPF desktop app, or b) ILSpyCmd w/ 8.0 prev 1 (CLI requires Cli support for generating solution for multiple projects #2364 to support multiple assemblies)
  2. Make sure you have at least two DLL's where one of them has a dependency on the other (i.e. First.dll depends on Second.dll)
  3. Using CLI in terminal, execute command: ilspycmd First.dll Second.dll -p -o TEMP
  4. Open the newly generated solution in VS from the TEMP directory
  5. Notice in project First how the reference to Second is a DLL reference, NOT a project reference.

Expectation

  • First should see Second as a project reference

Details

The main culprit of this issue is in ICSharpCode.Decompiler.Solution.SolutionCreator with the use of ProjectFileNamespace which is coded for how this would work with the old project file structure.

private static readonly XNamespace ProjectFileNamespace = XNamespace.Get("http://schemas.microsoft.com/developer/msbuild/2003");

var referencesItemGroups = projectDoc.Root
.Elements(ProjectFileNamespace + "ItemGroup")
.Where(e => e.Elements(ProjectFileNamespace + "Reference").Any());

private static void FixProjectReferences(string projectFilePath, XElement itemGroup, IDictionary<string, ProjectItem> projects)
{
foreach (var item in itemGroup.Elements(ProjectFileNamespace + "Reference").ToList())
{
var assemblyName = item.Attribute("Include")?.Value;
if (assemblyName != null && projects.TryGetValue(assemblyName, out var referencedProject))
{
item.Remove();
var projectReference = new XElement(ProjectFileNamespace + "ProjectReference",
new XElement(ProjectFileNamespace + "Project", referencedProject.Guid.ToString("B").ToUpperInvariant()),
new XElement(ProjectFileNamespace + "Name", referencedProject.ProjectName));
projectReference.SetAttributeValue("Include", GetRelativePath(projectFilePath, referencedProject.FilePath));
itemGroup.Add(projectReference);
}
}
}

Since the new SDK style is used by default (from CLI or UI), our only option is to manually correct this after decompilation, which is a ton of work. From some quick testing, simply using string.Empty in replace of the XML namespace works just fine for the expected behavior to work. However, the correct solution would probably involve finding a way to pull in ICSharpCode.Decompiler.DecompilerSettings into SolutionCreator somehow so that we can reference the UseSdkStyleProjectFormat boolean.

public bool UseSdkStyleProjectFormat {

The only public method of that class is one of the WriteSolutionFile overloads...

public static void WriteSolutionFile(string targetFile, IEnumerable<ProjectItem> projects)

...which seems to be referenced in two different areas: ICSharpCode.ILSpyCmd.ILSpyCmdProgram.OnExecute & ICSharpCode.ILSpy.SolutionWriter.CreateSolution.

SolutionCreator.WriteSolutionFile(Path.Combine(outputDirectory, Path.GetFileNameWithoutExtension(outputDirectory) + ".sln"), projects);

await Task.Run(() => SolutionCreator.WriteSolutionFile(solutionFilePath, projects))

Workaround

  • I don't see any workarounds at the momment, so I think this will ultimately require a code fix.
@gerneio gerneio added the Bug label Dec 23, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant