0

How can one get the corresponding process name of the installed programs in Windows (10)? For now, I'm using this

string uninstallKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"; 
using (RegistryKey rk = Registry.LocalMachine.OpenSubKey(uninstallKey))
      {
          foreach (string skName in rk.GetSubKeyNames())
          {
              using (RegistryKey sk = rk.OpenSubKey(skName))
              {
                  //returns installed programs
              }
          }
      } 

to return the installed software. Despite not every installed program being shown, how can I get the name of the process, like it would be shown in Task Manager, that the program would start if it was started?

I want to make an application blacklist. If an application gets started it compares its process with the blacklist. If the process matches with an entry in the list, the process gets killed.

E Lon Mask
  • 39
  • 1
  • 8

3 Answers3

0

Use static method GetProcesses of Process class to create component for each running process on the local computer.

You can get their names like this:

var processNames = Process.GetProcesses().Select(x => x.ProcessName).ToList();

More about Process class here: https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.process?view=net-6.0

Repulse3
  • 108
  • 6
  • Does this also list the processes that are currently not running because the program has not been started yet? – E Lon Mask Aug 10 '22 at 14:53
  • @ELonMask if the application about to start and the process began it will return – Repulse3 Aug 10 '22 at 15:00
  • I need to know the processes beforehand as I want to make an application blacklist. So if an application gets startet it compares its process with the blacklist and then kills the process if it was on the list – E Lon Mask Aug 10 '22 at 15:06
  • @ELonMask you can achieve your goal by creating a while loop which will check for blacklist process and kill them. The second way is to block the application via Registry editor but this question doesn't match the topic. – Repulse3 Aug 10 '22 at 15:16
  • Thanks for your help! The killing of the processes works already, for testing purposes I hard coded some process names. But now I want to obtain these processes that should be blocked via the UI where all the installed programs/potentially startable processes are listed. So the user can pick the processes to block from this list so one is not able to start said programs. – E Lon Mask Aug 10 '22 at 16:02
0

You should consider to use the Windows integrated feature to block applications via the registry. You can create such entries programmatically.

However, you can implement your own, but you must know that you can't prevent applications from starting using your approach. You can only kill it after it was started and after it has allocated resources.

  1. Create your blacklist first: collect all installed application paths and let the user pick the application to blacklist (see CreateInstalledApplicationIndex method).
  2. Use WMI to observe any process starts by registering a corresponding event handler.
  3. In the event handler retrieve the started Process and compare its filename to your blacklisted filenames to identify and handle a forbidden process.
private List<FileInfo> InstallationInfos { get; } = new List<FileInfo>();
private List<FileInfo> BlacklistedExecutables { get; } = new List<FileInfo>();

public void ApplyBlacklist()
{
  CreateInstalledApplicationIndex();
  WatchProcessStarts();
}

private void CreateInstalledApplicationIndex()
{
  string uninstallKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
  using RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(uninstallKey);

  foreach (string subKeyName in registryKey.GetSubKeyNames())
  {
    using RegistryKey subKey = registryKey.OpenSubKey(subKeyName);

    var installationPath = subKey.GetValue("InstallLocation") as string;
    if (string.IsNullOrWhiteSpace(installationPath))
    {
      continue;
    }

    IEnumerable<FileInfo> fileInfos = Enumerable.Empty<FileInfo>();
    try
    {
      var installationDirectoryInfo = new DirectoryInfo(installationPath);
      fileInfos = installationDirectoryInfo.EnumerateFiles("*.exe", new EnumerationOptions());
    }
    catch (IOException)
    {
      continue;
    }

    foreach (FileInfo fileInfo in fileInfos)
    {
      this.InstallationInfos.Add(fileInfo);

      // For demo, all executables are blacklisted.
      // TODO::Let user fill Blacklisted collection.
      this.BlacklistedExecutables.Add(fileInfo);
    }
  }
}

private void WatchProcessStarts()
{
  WqlEventQuery query = new WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace");
  ManagementEventWatcher watcher = new ManagementEventWatcher(query);
  watcher.EventArrived += OnProcessStarted;

  // Start listening for process start events
  watcher.Start();
                
  // Stop listening for process start events
  //watcher.Stop();
}

private void OnProcessStarted(object sender, EventArrivedEventArgs e)
{
  uint startedProcessId = (uint)e.NewEvent["ProcessID"];

  // Note: Convert.ToInt32 will throw an OverflowException
  // in case uint does not fit into an int.
  // You must decide whether to handle this particular exception or to let it crash your application.
  // Since it is very very unlikely that a machine runs Int32.MaxValue processes, 
  // I recommend not to handle this exception.
  Process startedProcess = Process.GetProcessById(Convert.ToInt32(startedProcessId));

  bool isProcessBlacklisted = this.BlacklistedExecutables
    .Select(fileInfo => fileInfo.FullName)
    .Contains(startedProcess.MainModule.FileName);

  // TODO::Handle blacklisted process e.g., by killing it
  if (isProcessBlacklisted)
  {
    startedProcess.Kill(entireProcessTree: true);
  }
}

It is possible that you have to run your application as administrator in order to observe process starts and to kill them. In this case ensure to prompt the user to elevate your application's rights by restarting it with administrator permissions.

BionicCode
  • 1
  • 4
  • 28
  • 44
  • Thank you! I already had the code to shut down processes. I just needed to get a reliable source of possible processes that the user could chose from. I tried your code but it didn't give me all the processes unfortunately. So I picked another approach based on [this](https://stackoverflow.com/a/57195200/11068611) which seems to be working – E Lon Mask Aug 11 '22 at 16:58
0

I got a solution which looks like this:

First I get all installed programs based on this

public static void LoadInstalledPrograms() 
{
    var FOLDERID_AppsFolder = new Guid("{1e87508d-89c2-42f0-8a7e-645a0f50ca58}");
    ShellObject appsFolder = (ShellObject)KnownFolderHelper.FromKnownFolderId(FOLDERID_AppsFolder);
    foreach (var app in (IKnownFolder)appsFolder)
    {
        //regular installed programs
        if (app.Properties.System.Link.TargetParsingPath.Value != null)
        {
            AddToInstalledProgramsList(app.Name, app.Properties.System.Link.TargetParsingPath.Value, "reg");
        }
        //Windows apps/Microsoft store apps
        /*else
        {
        AddToInstalledProgramsList(app.Name, app.Properties.GetProperty("System.AppUserModel.PackageInstallPath").ValueAsObject.ToString(), "win");
        }*/
   }
}

and then write them to a dictionary which is observed by a BackgroundWorker who kills every process from the list

static Dictionary<String, String> programs = new Dictionary<String, String>();
public static void AddToInstalledProgramsList(string programName, string programPath, string programType) 
{
    string processName = "";
    if (programType == "reg")
    {
        programPath = programPath.Replace("/", "\\");
        processName = programPath.Split("\\").Last();

        if (!programs.ContainsKey(programName))
        {
            programs.Add(programName, processName);
        }
        else
        {
            AddDuplicateEntry(programName, processName, 1);
        }
    }
    else if (programType == "win")
    {
        //...
    }
    Debug.WriteLine(programName + ": " + processName);
}

If I stumble across problems with this approach I will update this thread.

E Lon Mask
  • 39
  • 1
  • 8