예제 #1
0
        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));
            }
        }
예제 #2
0
        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);
        }