Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to uninstall older .net native images generated with ngen without matching IL assemblies?

I have been running "ngen install ..." on an application while it is being developed. But haven't run "ngen uninstall ..." on some of the versions / scenarios (debug etc.) before those assemblies were overwritten. Now I see many *.ni.exe and *.ni.dll in folders of the form "C:\Windows\assembly\NativeImages_v4.0.30319_64\AssemblyName\hashkey". (dlls are also internally developed ones.)

I am using .Net 4.

Is there anyway to uninstall these? I have tried "ngen update" it doesn't seem to touch these orphaned native images. Of course I can delete these manually, but it will upset the ref counts on system dlls on which my assemblies depend, or have worse consequences on .net system.

Apart from taking space, these older assemblies are hurting the startup delay as assembly binder is trying to match the current IL to each of the native assemblies.

Also is there a better way to look what is in the native image cache rather than using command line?

Thanks

like image 337
Aelian Avatar asked Oct 15 '13 14:10

Aelian


2 Answers

While this question already has an answer, there are a few things you need to consider if you want to remove stale (old) ngen'ed assemblies.

  • Make sure to check if NGen considers them installed and use the same NGen (CLR version, 32 bit / 64 bit) when doing ngen display. Using ngen display yourasm.dll won't work (on the filename), but ngen display AssemblyName will (internal assembly name). You can use a partial name.
  • When you use ngen uninstall, uninstall them in the inverse order you installed them. Dependencies won't be uninstalled, but if you manually installed a dependency before you installed the dependent assembly, you need to uninstall the dependent assembly first:

    • If A depends on B and C and B depends on C, and you did:

      ngen install B
      ngen install C
      ngen install A
      

      then you can only ever uninstall them by doing:

      ngen uninstall A  // removes A, if nothing is dependent on it
      ngen uninstall C  // removes C, it has no dependencies now
      ngen uninstall B  // removes B, it has no dependencies now
      
    • If you are unsure of the dependencies, check the output of ngen display asmname, it will list the dependencies under "ROOT". Anything under there must be removed first

    • If another application uses any of your files, you need to uninstall that first
    • If found it helpful to check in the c:\windows\assembly\NativeImages_v4.0.30319_64 (and the *_32 version) with the following command whether it was still installed:

      dir | findstr "AsmName"
      

      Since there are so many files here, it helps seeing what is still there. It also helps in finding out to what version (32 bit, 64 bit, MSIL) they belong. It doesn't seem to help with what profile they were put there.

  • I noticed that the Windows Explorer view of the c:\windows\assembly folder does not show assemblies that are ngen'ed, but not in the GAC. But if your assembly is also in the GAC, you can uninstall it from the GAC and from the NGen cache by right-clicking and then selecting "Uninstall".

In addition to the above, having a lot of stale ngen'ed images there won't hurt performance. The CLR stores the files here based on the assembly name (name, version, public key token) and a few other heuristics (file date, internal creation date, hash). It won't even touch your old ngen'ed images. You can verify this by using Process Monitor (it only ever tries to load the ngen'ed image from one location, based on the hash etc). But I agree, it is nasty to have to keep them around.

like image 93
Abel Avatar answered Nov 15 '22 06:11

Abel


ngen uninstall AssemblyName should work. AssemblyName can be a partial or full assembly name.

like image 33
cremor Avatar answered Nov 15 '22 06:11

cremor