Project Dependencies - How to check?

So I’ve created a project that uses the Newtonsoft.JSON package. When I do a build (wether debug or release) the dll file gets put in the output folder.

However I’ve used Microsoft’s Dependency walker to see what other dll’s I need to ship etc and I can not find a trace of the Newtonsoft.JSON dll anywhere in there.

So this leads me to the question, how can I know what dependency files my project needs? In Delphi I could the DWalker to see what bpl files to distribute but I do not know how to do that for a .NET project. Is there some other tool I need to use ?

Regards
Anthoni

Hi,

This is how I do this:

I add the following code to the startup of the application:

 if Debugger.IsAttached then
  begin
    var assemblyList := new List<String>;
    AppDomain.CurrentDomain.ProcessExit += method (sender: Object; e: EventArgs) 
    begin
      assemblyList.Sort();
      File.WriteAllLines('UsedAssemblies.txt', assemblyList);
    end;
    AppDomain.CurrentDomain.AssemblyLoad += method (sender: Object; args2: AssemblyLoadEventArgs) 
    begin
      assemblyList.Add(args2.LoadedAssembly.FullName);
    end;
  end;

This can be added to the Main method (console or winforms) or the App.OnStartup method (WPF)

When starting the app in Visual Studio this code will be activated,
If you then use the software and go through all of the functions, when you close the application a file named “UsedAssemblies.txt” is created in the exe folder.
That file contains all the assemblies that you app has loaded during the previous execution.

I hope that helps…

Best Regards,

Jeroen

Thanks for that. I’ve added it as a class method so that I can use it every program I do.
Is this the only way though? No seperate program to analyse the final exe ?

Regards
Anthoni

Hi Anthoni,

I quickly created this small app:

namespace DependencyChecker;

interface

uses
  System.Collections.Generic,
  System.Linq, 
  System.Reflection;

type
  ConsoleApp = class
  private
    class fUsedAssemblies: HashSet<&Assembly> := new HashSet<&Assembly>;
  public
    class method Main(args: array of String);
    class method ProcessAssembly(aAssembly: &Assembly);
  end;

implementation

uses 
  System.IO;

class method ConsoleApp.Main(args: array of String);
begin
  if args.Length < 1 then exit;
  if not File.Exists(args[0]) then exit;
  var dirName := Path.GetDirectoryName(args[0]);

  AppDomain.CurrentDomain.AssemblyResolve += method (sender2: Object; args2: ResolveEventArgs): &Assembly 
    begin 
      var fn := dirName + Path.DirectorySeparatorChar + args2.Name + '.dll';
      if file.Exists(fn) then
      begin
        exit &Assembly.LoadFile(fn);
      end;
      fn := dirName + Path.DirectorySeparatorChar + args2.Name + '.exe';
      if file.Exists(fn) then
      begin
        exit &Assembly.LoadFile(fn);
      end;
    end;

  var initialAssembly := &Assembly.LoadFile(args[0]);
  ProcessAssembly(initialAssembly);
  for each asm in fUsedAssemblies do
  begin
    Console.WriteLine(asm.ToString());
  end;
  Console.ReadLine();
end;

class method ConsoleApp.ProcessAssembly(aAssembly: System.Reflection.Assembly);
begin
  if aAssembly.FullName.Contains('b77a5c561934e089') then exit;
  if aAssembly.FullName.Contains('b03f5f7f11d50a3a') then exit;
  if aAssembly.FullName.Contains('31bf3856ad364e35') then exit;
  fUsedAssemblies.Add(aAssembly);
  var refAsms := aAssembly.GetReferencedAssemblies();
  for each asmName in refAsms do
  begin
    var asm := &Assembly.LoadWithPartialName(asmName.Name);
    if assigned(asm) then
      if not fUsedAssemblies.Contains(asm) then ProcessAssembly(asm);
  end;
end;

end.

This is a command line app, just pass the path+name of the app as a param to this app and it should give you all the dlls it uses.

My initial tests seems to indicate that it works, but it is a quick and dirty approach…

Let me know what you think…

Best Regards,

Jeroen

Hi Jeroen,

It keeps crashing :expressionless:
First it wanted the full path, so I entered that.
Now it crashes on trying to find PresentationFramework with a file not found exception.

I think for now I will use your other method (the one baked right into the program itself). That works and it gives me the assemblies it uses, I just have to remember to switch it off LOL.

BTW: Why do you dismiss these assemblies ?

if aAssembly.FullName.Contains('b77a5c561934e089') then exit;
if aAssembly.FullName.Contains('b03f5f7f11d50a3a') then exit;
if aAssembly.FullName.Contains('31bf3856ad364e35') then exit;

Regards
Anthoni

Hi,

Yeah like I said, it was something I quickly created yesterday…
Concerning the first way that I suggested, you don’t have to turn it off, because when running outside Visual Studio that code will not be invoked…

I dismissed those assemblies because that are all the framework assemblies. You don’t need to deploy those because they are included in the .NET framework.

Ahh, it’s just that they were not listed in your other listing.
Will update to make sure they are not outputted to the text file and clutter it up :smile:

Regards
Anthoni