2

I am able to get the process name using the below code but how do I get the application name that an end user is familiar with i.e. instead of getting WinWord I would like to display Word 2013 as shown in the start menu.

foreach (var p in Process.GetProcesses())
{
   try
   {
     if (!String.IsNullOrEmpty(p.MainWindowTitle))
       {
         Console.WriteLine(String.Format("Process Name: " + p.ProcessName.ToString()));
       }
     }
   catch
   {
   }
}
jmgibbo
  • 97
  • 1
  • 10

1 Answers1

2

I couldn't find the "start menu" name anywhere in the executable file description. For example, the file WINWORD.EXE has Product Name "Microsoft Office 2016" and File Description "Microsoft Word", when viewing the executable details in the file explorer.

This leads me to think that in order to find the "start menu" name, we should actually look at the start menu. We can do it by enumerating all the lnk files in it, and keeping a mapping between the "start menu" name (which is simply the file name of the lnk file) and the executable it links to.

One we have this mapping, we can query it for the processes we get from GetProcesses().

Example code (add Windows Script Host Object Model as a COM reference):

public static string GetShortcutTargetFile(string shortcutFilename)
{
    if (File.Exists(shortcutFilename))
    {
        var shell = new WshShell();
        var link = (IWshShortcut)shell.CreateShortcut(shortcutFilename);

        return link.TargetPath;
    }

    return string.Empty;
}

public static Dictionary<string, string> CreateDictionary(string path)
{
    var dictionary = new Dictionary<string, string>();

    foreach (var filePath in Directory.EnumerateFiles(path, "*.lnk", SearchOption.AllDirectories))
    {
        var lnkPath = GetShortcutTargetFile(filePath);
        if (lnkPath.Length > 0 && !dictionary.ContainsKey(lnkPath))
        {
            dictionary.Add(lnkPath, Path.GetFileNameWithoutExtension(filePath));
        }
    }

    return dictionary;
}

static void Main()
{
    var startMenuLocation = Environment.GetFolderPath(Environment.SpecialFolder.CommonStartMenu);
    var dictionary = CreateDictionary(startMenuLocation);

    foreach (var p in Process.GetProcesses())
    {
        try
        {
            if (!string.IsNullOrEmpty(p.MainWindowTitle))
            {
                var pair = dictionary.FirstOrDefault(entry => entry.Key.Contains(p.ProcessName));
                var prettyName = pair.Value;
                Console.WriteLine(string.Format("Process Name: " + prettyName));
            }
        }
        catch
        {
        }
    }
}

As ReneA pointed out in the comments, the code only enumerates the shared start menu folder. One might want to enumerate the users' start menu folders as well.

This code is not thoroughly tested or guarded against corner cases. Use at your own risk.

Community
  • 1
  • 1
Tomer
  • 1,606
  • 12
  • 18
  • Thanks @Tomer for the suggestion, this is working for some applications but not all. I would also mentioned for people that are not familiar with WshShell that this is using IWshRuntimeLibrary that can be added as a COM reference called Windows Script Host Object Model. – jmgibbo Jan 16 '17 at 06:25
  • 1
    It's interesting to see what applications are not covered. Perhaps there's another way to query the dictionary which will include them as well. The problem, as far as I understand, is that the information you require is only available through the start menu links. – Tomer Jan 16 '17 at 07:07
  • @jmgibbo, Note that the example only enumerates over the shared start menu (SpecialFolder.CommonStartMenu). Maybe the missing applications are only installed for the current user `SpecialFolder.StartMenu`? And I'm sure you've seen the Process.MainWindowTitle property. – ReneA Jan 16 '17 at 15:20