ПРИМЕЧАНИЕ. Для всех этих методов я получаю исполняемый файл приложения (sourcePath) с помощью следующий метод:
Код: Выделить всё
private static string GetProcessExecutablePath(Process process) {
try {
StringBuilder buffer = new(1024);
uint size = (uint) buffer.Capacity;
IntPtr hProcess = process.Handle;
if (QueryFullProcessImageName(hProcess, 0, buffer, ref size) != 0) {
return buffer.ToString();
}
} catch (Win32Exception ex) {
Debug.WriteLine($"Error accessing process handle for {process.ProcessName}: {ex.Message}");
}
return null;
}
Код: Выделить всё
public static string ExtractIconFromFile(string sourcePath) {
try {
// using ensures that the Icon is disposed of
using Icon icon = Icon.ExtractAssociatedIcon(sourcePath);
// using ensures that the Bitmap is disposed of
using Bitmap bitmap = icon.ToBitmap();
return bitmap.SaveToFile(Path.Combine(Path.GetTempPath(), ".TestTaskbar2", "AppIcons"), $"{desktopApp.AppName}_{Guid.NewGuid()}");
} catch (Exception ex) when (ex is ArgumentNullException or IOException) {
return null;
}
}
Код: Выделить всё
sourcePath
2. [Функционально] Извлечение значка из ярлыка меню «Пуск» по пути к файлу:
Этот код ищет файл ярлыка в папке меню «Пуск» (я запускаю его как для конкретного пользователя, так и для операционной системы). -папка меню «Пуск»), которая указывает на тот же исполняемый файл, тот же каталог или подкаталог или родительский каталог исполняемого файла приложения, для которого мы получаем значок. Затем он получает значок, который использует файл ярлыка.
Код: Выделить всё
private static List FindShortcutIconsByPath(string directory, string sourceFile) {
string appDirectory = Path.GetDirectoryName(sourceFile);
List icons = [];
foreach (string file in Directory.GetFiles(directory, "*.lnk", SearchOption.AllDirectories)) {
WshShell shell = new();
IWshShortcut shortcut = null;
try {
shortcut = (IWshShortcut) shell.CreateShortcut(file);
string targetPath = shortcut.TargetPath;
string targetDirectory = Path.GetDirectoryName(targetPath);
// App location exists and target location exists and app does not reside in C:\Windows or C:\Windows\System32
// (Many windows apps are housed in Windows and System32, and all of their icons will be found for...
// ...each one of the apps, with no way to distinguish by path which is right)
if (appDirectory is not null && targetDirectory is not null && !appDirectory.ToLower().Equals(@"c:\windows") && !appDirectory.ToLower().Equals(@"c:\windows\system32")) {
// Target points to the exact folder the app is in,
// or target points to a subfolder of app's location,
// or app is in a subfolder of where target points
if (targetDirectory.Equals(appDirectory, StringComparison.OrdinalIgnoreCase)
|| targetPath.StartsWith(appDirectory, StringComparison.OrdinalIgnoreCase)
|| appPath.StartsWith(targetDirectory, StringComparison.OrdinalIgnoreCase)) {
icons.Add(ExtractIconFromFile(shortcut.IconLocation ?? targetPath));
}
}
} finally {
// COM objects must be released to prevent memory leaks
if (shortcut != null) {
Marshal.ReleaseComObject(shortcut);
}
Marshal.ReleaseComObject(shell);
}
}
return icons;
}
3. [Функционально] Извлечение значка из ярлыка меню «Пуск» по имени:
Этот код аналогичен приведенному выше, но находит ярлыки меню «Пуск», сопоставляя их имена с приложением.
Код: Выделить всё
private static List FindShortcutIconsByName(string directory, string appName) {
List icons = [];
foreach (string file in Directory.GetFiles(directory, "*.lnk", SearchOption.AllDirectories)) {
WshShell shell = new();
IWshShortcut shortcut = null;
try {
if (Path.GetFileNameWithoutExtension(file).ToLower().Replace("microsoft", "").Trim() == appName.ToLower().Replace("microsoft", "").Trim()) {
shortcut = (IWshShortcut) shell.CreateShortcut(file);
icons.Add(ExtractIconFromFile(shortcut.IconLocation ?? shortcut.TargetPath));
}
} finally {
// COM objects must be released to prevent memory leaks
if (shortcut != null) {
Marshal.ReleaseComObject(shortcut);
}
Marshal.ReleaseComObject(shell);
}
}
return icons;
}
4. [Не удалось] — получить значки приложений UWP
Я пытался использовать код из этого ответа, чтобы получить значки для приложений UWP, но он просто возвращает значение null для каждого отдельного процесса, и я не знаю почему.
Вот моя слегка измененная реализация кода в этом ответе: https://pastebin.com/rAuFgXge. В основном это связано с очисткой VS множества настроек форматирования и стиля, и я изменил метод Show, чтобы он стал методом AppxPackage, а не отдельной функцией. Он также использует Debug.WriteLine, а не Console.Writeline, поскольку я хочу видеть выходные данные в отладчике VS.
EDIT: Вот как я вызвал код для тестирования:
Код: Выделить всё
foreach (Process p in Process.GetProcesses()) {
AppxPackage package = AppxPackage.FromProcess(p);
if (package != null) {
package.Show();
Debug.WriteLine("\n\n");
} else {
Debug.WriteLine($"Could not find package for {p.ProcessName}");
}
}
Используя эти три метода вместе, я иногда могу найти три хороших значка (в этом случае я выбираю один с самым высоким разрешением), иногда получаю хороший значок из одного из них, иногда вообще не получаю хороших значков (я получаю значок исполняемого файла Windows по умолчанию или заполнитель по умолчанию), а иногда получаю дюжину значков, только один из которых правильный.
Для некоторых приложений лучше использовать исполняемый файл вместо значков ярлыков в меню «Пуск», для других лучше использовать значки ярлыков вместо исполняемых файлов, и я не знаю, как это сделать программно. решайте, что лучше. На данный момент мой план состоит в том, чтобы позволить пользователю выбирать между возможными значками приложений или загружать свои собственные, но это не идеально.
Самая большая проблема заключается в Приложения UWP. Из-за сложной и противоречивой структуры приложений ни один из этих методов на них не работает. Папки, в которых хранятся значки, часто имеют непоследовательные названия и расположение в лучшем случае, а обилие значков внутри не позволяет надежно выбрать одну.
Итак, в целом...< /p>
Как получить значок приложения для приложений UWP (и надежно получить значок приложения для других приложений)
Подробнее здесь: https://stackoverflow.com/questions/791 ... unning-app