public DesktopAppInfo(int processId, bool trackProcess) { _processId = processId; var handle = Kernel32.OpenProcess(Kernel32.ProcessFlags.PROCESS_QUERY_LIMITED_INFORMATION | Kernel32.ProcessFlags.SYNCHRONIZE, false, processId); if (handle != IntPtr.Zero) { try { ZombieProcessException.ThrowIfZombie(processId, handle); var fileNameBuilder = new StringBuilder(260); uint bufferLength = (uint)fileNameBuilder.Capacity; if (Kernel32.QueryFullProcessImageName(handle, 0, fileNameBuilder, ref bufferLength) != 0) { if (fileNameBuilder.Length > 0) { var processFullPath = fileNameBuilder.ToString(); ExeName = Path.GetFileNameWithoutExtension(processFullPath); SmallLogoPath = processFullPath; PackageInstallPath = processFullPath; } } } finally { Kernel32.CloseHandle(handle); } } else { trackProcess = false; if (TryGetExecutableNameViaNtByPid(processId, out var imageName)) { ExeName = Path.GetFileNameWithoutExtension(imageName); SmallLogoPath = imageName; PackageInstallPath = imageName; } else { throw new ZombieProcessException(processId); } } // Display Name priority: // - AppsFolder // - A window caption // - Exe Name try { var appResolver = (IApplicationResolver) new ApplicationResolver(); appResolver.GetAppIDForProcess((uint)processId, out string appId, out _, out _, out _); Marshal.ReleaseComObject(appResolver); var shellItem = Shell32.SHCreateItemInKnownFolder(FolderIds.AppsFolder, Shell32.KF_FLAG_DONT_VERIFY, appId, typeof(IShellItem2).GUID); DisplayName = shellItem.GetString(ref PropertyKeys.PKEY_ItemNameDisplay); } catch (COMException ex) { Trace.WriteLine($"DesktopAppInfo DisplayName read failed {ExeName} 0x{((uint)ex.HResult).ToString("x")}"); } catch (Exception ex) { Trace.WriteLine($"DesktopAppInfo DisplayName read failed {ExeName} {ex}"); } if (string.IsNullOrWhiteSpace(DisplayName)) { try { using (var proc = Process.GetProcessById(_processId)) { DisplayName = proc.MainWindowTitle; } } catch (Exception ex) { Trace.WriteLine(ex); } } if (trackProcess) { ProcessWatcherService.WatchProcess(processId, (pid) => Stopped?.Invoke(this)); } }
private static string GetAppUserModelIdByPid(int processId) { string appUserModelId = string.Empty; var processHandle = Kernel32.OpenProcess(Kernel32.ProcessFlags.PROCESS_QUERY_LIMITED_INFORMATION | Kernel32.ProcessFlags.SYNCHRONIZE, false, processId); if (processHandle != IntPtr.Zero) { try { ZombieProcessException.ThrowIfZombie(processId, processHandle); int amuidBufferLength = Kernel32.MAX_AUMID_LEN; var amuidBuffer = new StringBuilder(amuidBufferLength); Kernel32.GetApplicationUserModelId(processHandle, ref amuidBufferLength, amuidBuffer); appUserModelId = amuidBuffer.ToString(); } finally { Kernel32.CloseHandle(processHandle); } // We may receive an AUMID for an app in a package that doesn't have // the metadata we need (e.g. Skype). If the AUMID doesn't resolve to // an app, we need to bust open the package, find the main app, and // retrieve the metadata we need. if (!CanResolveAppByApplicationUserModelId(appUserModelId)) { int packageFamilyNameLength = Kernel32.PACKAGE_FAMILY_NAME_MAX_LENGTH_INCL_Z; var packageFamilyNameBuilder = new StringBuilder(packageFamilyNameLength); int packageRelativeApplicationIdLength = Kernel32.PACKAGE_RELATIVE_APPLICATION_ID_MAX_LENGTH_INCL_Z; var packageRelativeApplicationIdBuilder = new StringBuilder(packageRelativeApplicationIdLength); Kernel32.ParseApplicationUserModelId( appUserModelId, ref packageFamilyNameLength, packageFamilyNameBuilder, ref packageRelativeApplicationIdLength, packageRelativeApplicationIdBuilder); string packageFamilyName = packageFamilyNameBuilder.ToString(); int packageCount = 0; int packageNamesBufferLength = 0; Kernel32.FindPackagesByPackageFamilyInitial( packageFamilyName, Kernel32.PACKAGE_FILTER_HEAD | Kernel32.PACKAGE_INFORMATION_BASIC, ref packageCount, IntPtr.Zero, ref packageNamesBufferLength, IntPtr.Zero, IntPtr.Zero); if (packageCount > 0) { var pointers = new IntPtr[packageCount]; IntPtr buffer = Marshal.AllocHGlobal(packageNamesBufferLength * Kernel32.SIZEOF_WCHAR); Kernel32.FindPackagesByPackageFamily( packageFamilyName, Kernel32.PACKAGE_FILTER_HEAD | Kernel32.PACKAGE_INFORMATION_BASIC, ref packageCount, pointers, ref packageNamesBufferLength, buffer, IntPtr.Zero); var packageFullName = Marshal.PtrToStringUni(pointers[0]); Marshal.FreeHGlobal(buffer); Kernel32.OpenPackageInfoByFullName(packageFullName, 0, out IntPtr packageInfoReference); int bufferLength = 0; Kernel32.GetPackageApplicationIds(packageInfoReference, ref bufferLength, IntPtr.Zero, out int appIdCount); buffer = Marshal.AllocHGlobal(bufferLength); Kernel32.GetPackageApplicationIds(packageInfoReference, ref bufferLength, buffer, out appIdCount); appUserModelId = Marshal.PtrToStringUni(Marshal.ReadIntPtr(buffer)); Marshal.FreeHGlobal(buffer); Kernel32.ClosePackageInfo(packageInfoReference); } } } else { throw new ZombieProcessException(processId); } return(appUserModelId); }