Link to home
Start Free TrialLog in
Avatar of Buckofive
BuckofiveFlag for United States of America

asked on

How to determine if .NET is being actively used?

I've been tasked with removing old/outdated versions of .NET from some of our servers that we've found to have multiple versions of .NET installed. Prior to removing the older versions of .NET - I want to verify that they are not actually being utilized by anything running on the server.


I understand that I can use the Get-ChildItem IIS:\AppPools PS command to get a view of any application running under the .NET application pools, but is this the best/only way to validate that nothing else on these servers is running under .NET?

ASKER CERTIFIED SOLUTION
Avatar of ste5an
ste5an
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial

If you're not 100% sure of every application that runs, then it complicates things. Your main concern is going to be any programs that do not run all the time. Maybe they're scheduled or maybe they are triggered by some activity and they do some task and finish within milliseconds so any kind of polling task manager is likely to miss them unless it's very lucky.


Personally, I'd approach this by dumping a list of every .exe and every .dll in the filesystem to a file. Then run ildasm.exe (.NET decompiler that is part of the .NET SDK) against every file in the list to dump the headers.


ildasm.exe /text file.exe /noil /headers >> c:\temp\ildasm.log


In the output you should see a version string that indicates the targeted .NET framework.


It's pretty rare to find any .NET 3.x or earlier assemblies, so you might not find any at all.


Once you have a list of the old assemblies, load up procmon (Microsoft Process Monitor) and filter it down to only entries that touch those old assemblies and check the option to drop filtered rows, then let it run for the day. You should be able to see if anything accessed those files in any way.

Avatar of dfke
dfke

Hi,

In general use Get-Process to list the processes with this powershell script:

$processes = Get-Process | Where-Object {$_.Modules -match "mscor"}
foreach ($process in $processes)
{
    Write-Host "Process Name: $($process.ProcessName)"
    Write-Host "PID: $($process.Id)"
    Write-Host "File Path: $($process.Path)"
    Write-Host " "
}

Open in new window


This will get you a list of all running processes, and then filters that list by processes that have a module loaded with "mscor" in the name, which is an indicator that the process is using .NET. For each process that meets this criteria, the script will output the process name, process ID, and file path.


As for the application pools you can run this script:

$appPools = Get-ChildItem IIS:\AppPools | Select-Object -Property Name, ManagedRuntimeVersion
foreach ($appPool in $appPools)
{
    Write-Host "Application Pool Name: $($appPool.Name)"
    Write-Host "Used .NET Version: $($appPool.ManagedRuntimeVersion)"
    Write-Host " "
}

Open in new window


It uses the Get-ChildItem cmdlet to get a list of all application pools in IIS, and filters that list by application pools with names that contain ".NET" and displays the .NET version being used.



Cheers

@dfke - some issues with that approach:


1. Getting the current process list is fine, but that won't capture any programs that DO run but might not be running at the time that you check the process list. There may be applications that do polling so they only run every X minutes or hours or something. Or there may be integration points that execute some script / application under certain circumstances. 


2. .NET applications can have a mixed-mode execution where the executing assembly is using .NET 4.8 but is referencing an assembly that utilizes .NET 3 (and worse, it might not load up the assembly until it needs to use it), so the managed or image runtime version can be misleading.


There are a bunch of edge cases here.

There are a bunch of edge cases here.
This is one reason for choosing a declarative way.
Avatar of Buckofive

ASKER

I was worried that I was going to find that there is no quick and easy way to accomplish this, and it sounds like that is indeed the case. Appreciate all of the feedback.
Hi,

Try C#, this uses WMI to get a list of all the running processes, including the .NET runtime version for each process. This will give you a comprehensive list of all the running applications, regardless of whether they are running continuously or just executing on demand.

using System;
using System.Management;

namespace GetProcessesAndRuntime
{
    class Program
    {
        static void Main(string[] args)
        {
            ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Process");
            foreach (ManagementObject obj in searcher.Get())
            {
                string[] args1 = { string.Empty, string.Empty };
                int returnVal = Convert.ToInt32(obj.InvokeMethod("GetOwner", args1));
                if (returnVal == 0)
                {
                    Console.WriteLine("Process: " + obj["Name"]);
                    Console.WriteLine("Owner: " + args1[0]);
                    Console.WriteLine(".NET runtime version: " + obj["ExecutablePath"]);
                }
            }
        }
    }
}

Open in new window



Cheers