英文:
How to show recently used programs in C# WPF?
问题
你可以尝试以下方式来获取最近使用的程序列表并将其绑定到你的 ListBox 控件:
string recentProgramsKey = @"Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocs";
RegistryKey recentProgramsRegistryKey = Registry.CurrentUser.OpenSubKey(recentProgramsKey);
string[] recentPrograms = recentProgramsRegistryKey.GetSubKeyNames();
recentProgramsListBox.ItemsSource = null;
// 过滤列表以仅显示应用程序
var applicationExtensions = new[] { ".exe" };
var filteredPrograms = recentPrograms
.Where(program => applicationExtensions.Contains(Path.GetExtension(program)))
.Select(program =>
{
string filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Recent), program);
string programName = DecodeProgramName(System.IO.File.ReadAllBytes(filePath), 0);
return new RecentProgram
{
FileName = program,
FilePath = filePath,
ProgramName = programName
};
})
.ToArray();
// 将过滤后的最近使用的程序列表绑定到 ListBox 控件
recentProgramsListBox.ItemsSource = filteredPrograms;
这段代码首先打开注册表中的 "RecentDocs" 键,获取最近使用的项目的子键名称。然后,它过滤出扩展名为 ".exe" 的程序,并创建一个 RecentProgram 对象的数组。最后,它将这个数组绑定到 recentProgramsListBox
控件的 ItemsSource
属性,以在用户界面中显示最近使用的程序列表。
请确保你的 RecentProgram
类已经正确定义,以便与列表进行绑定。
英文:
I'm working on a C# WPF application, and I would like to show a list of recently used programs in my application's user interface. I have a ListBox control where I want to display the program names. However, I'm not sure how to populate the ListBox with the list of recently used programs.
Here is the relevant code I have in my MainWindow.xaml.cs file:
using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.Windows.Data;
using System.Globalization;
using System.Drawing;
using System.Windows.Input;
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Management;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Speech.Synthesis;
using System.Threading.Tasks;
using System.Windows;
using Microsoft.Win32;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using Newtonsoft.Json.Linq;
using System.Numerics;
using System.Windows.Shell;
using Microsoft.WindowsAPICodePack.Shell;
using Syncfusion.Presentation;
using Syncfusion.Presentation.Drawing;
namespace MyApp
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private DateTime _lastLoginTime;
private List<string> _lastUsedPrograms;
private readonly SpeechSynthesizer _speechSynthesizer;
private HttpClient _httpClient;
private string _accessToken;
private string _trackName;
private string _artistName;
private TimeSpan? _songDuration;
private BitmapImage _songImage;
public MainWindow()
{
InitializeComponent();
string recentProgramsKey = @"Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocs";
RegistryKey recentProgramsRegistryKey = Registry.CurrentUser.OpenSubKey(recentProgramsKey);
string[] recentPrograms = recentProgramsRegistryKey.GetSubKeyNames();
recentProgramsListBox.ItemsSource = null;
// Filter the list to show only applications
// Filter the list to show only applications
var applicationExtensions = new[] { ".exe" };
var filteredPrograms = recentPrograms
.Where(program => applicationExtensions.Contains(Path.GetExtension(program)))
.Select(program =>
{
string filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Recent), program);
string programName = DecodeProgramName(System.IO.File.ReadAllBytes(filePath), 0);
return new RecentProgram
{
FileName = program,
FilePath = filePath,
ProgramName = programName
};
})
.ToArray();
// Bind the filtered list of recently used programs to the ListBox control
recentProgramsListBox.ItemsSource = filteredPrograms;
// Create a SpeechSynthesizer instance
_speechSynthesizer = new SpeechSynthesizer();
// Retrieve user's name
string userName = Environment.UserName ?? string.Empty;
nameTextBlock.Text = $"Welcome back, {userName}!";
// Say the welcome message
SayWelcome(userName);
// Retrieve last login time
_lastLoginTime = System.IO.File.GetLastWriteTime(@"C:\Windows\System32\winevt\Logs\Microsoft-Windows-Winlogon%4Operational.evtx");
lastLoginTextBlock.Text = $"{_lastLoginTime}";
// Initialize the HttpClient
_httpClient = new HttpClient();
_accessToken = string.Empty;
// Call the InitializeSpotify method
_ = InitializeSpotify();
// Bind the properties to the UI elements
DataContext = this;
MouseDown += (sender, e) =>
{
if (e.ChangedButton == MouseButton.Left)
{
Activate();
}
};
// Subscribe to the Activated event to bring the window to the top
Activated += (sender, e) =>
{
Activate();
};
// Subscribe to the Deactivated event to stop speech synthesis
Deactivated += (sender, e) =>
{
_speechSynthesizer.SpeakAsyncCancelAll();
};
}
public string TrackName
{
get { return _trackName; }
private set
{
_trackName = value;
OnPropertyChanged(nameof(TrackName));
}
}
public string ArtistName
{
get { return _artistName; }
private set
{
_artistName = value;
OnPropertyChanged(nameof(ArtistName));
}
}
public TimeSpan? SongDuration
{
get { return _songDuration; }
private set
{
_songDuration = value;
OnPropertyChanged(nameof(SongDuration));
}
}
public BitmapImage SongImage
{
get { return _songImage; }
private set
{
_songImage = value;
OnPropertyChanged(nameof(SongImage));
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private async Task InitializeSpotify()
{
string clientId = "";
string clientSecret = "";
string tokenEndpoint = "";
string refreshToken = "";
try
{
// Build the request content
var requestContent = new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "grant_type", "refresh_token" },
{ "refresh_token", refreshToken },
{ "client_id", clientId },
{ "client_secret", clientSecret }
});
// Send the request to refresh the access token
var response = await _httpClient.PostAsync(tokenEndpoint, requestContent);
var responseContent = await response.Content.ReadAsStringAsync();
var json = JObject.Parse(responseContent);
_accessToken = json.Value<string>("access_token");
// Start monitoring the currently playing track
StartPlaybackListener();
}
catch (Exception ex)
{
WriteLineToConsole($"An error occurred while initializing Spotify: {ex.Message}");
}
}
public class RecentProgram
{
public string FileName { get; set; }
public string FilePath { get; set; }
public string ProgramName { get; set; }
}
private async Task StartPlaybackListener()
{
string playbackEndpoint = "https://api.spotify.com/v1/me/player";
TimeSpan pollInterval = TimeSpan.FromSeconds(5); // Adjust the interval as per your requirement
while (true)
{
try
{
// Make a GET request to retrieve the current playback state
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _accessToken);
var response = await _httpClient.GetAsync(playbackEndpoint);
var responseContent = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
if (!string.IsNullOrEmpty(responseContent))
{
var responseObject = JObject.Parse(responseContent);
// Check if a track is currently playing
bool isPlaying = responseObject["is_playing"]?.Value<bool>() ?? false;
if (isPlaying)
{
await RetrieveAndDisplayCurrentlyPlayingTrack();
}
else
{
WriteLineToConsole("No track is currently playing.");
}
}
else
{
WriteLineToConsole("Empty response content received.");
}
}
else
{
WriteLineToConsole($"Error: {response.StatusCode} - {response.ReasonPhrase}");
}
}
catch (Exception ex)
{
WriteLineToConsole($"An error occurred during playback listening: {ex.Message}");
WriteLineToConsole($"Exception details: {ex.ToString()}");
}
await Task.Delay(pollInterval);
}
}
private async Task RetrieveAndDisplayCurrentlyPlayingTrack()
{
string playbackEndpoint = "https://api.spotify.com/v1/me/player/currently-playing";
try
{
// Make a GET request to retrieve the currently playing track
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _accessToken);
var response = await _httpClient.GetAsync(playbackEndpoint);
var responseString = await response.Content.ReadAsStringAsync();
var responseObject = JObject.Parse(responseString);
// Retrieve the track information
string trackName = (string)responseObject["item"]["name"];
string artistName = (string)responseObject["item"]["artists"][0]["name"];
TimeSpan songDuration = TimeSpan.FromMilliseconds((double)responseObject["item"]["duration_ms"]);
string imageUrl = (string)responseObject["item"]["album"]["images"][0]["url"];
// Load the image from the URL
BitmapImage songImage = await LoadImage(imageUrl);
// Update the properties
Dispatcher.Invoke(() =>
{
TrackName = trackName;
ArtistName = artistName;
SongDuration = songDuration;
SongImage = songImage;
});
}
catch (Exception)
{
// Handle any exceptions that occur during track retrieval and display
WriteLineToConsole("Failed to retrieve currently playing track.");
}
}
private async Task<BitmapImage> LoadImage(string imageUrl)
{
try
{
using (var httpClient = new HttpClient())
{
// Download the image data asynchronously
var imageBytes = await httpClient.GetByteArrayAsync(imageUrl);
// Create a MemoryStream from the image data
using (var memoryStream = new MemoryStream(imageBytes))
{
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.StreamSource = memoryStream;
bitmap.EndInit();
bitmap.Freeze();
return bitmap;
}
}
}
catch (Exception ex)
{
// Log the exception or display an error message
Console.WriteLine($"An error occurred during image loading: {ex.Message}");
return null;
}
}
private string DecodeProgramName(byte[] rawData, int offset)
{
const int programNameOffset = 56;
const int programNameLength = 72;
byte[] encodedName = new byte[programNameLength];
Array.Copy(rawData, offset + programNameOffset, encodedName, 0, programNameLength);
string programName = Encoding.UTF8.GetString(encodedName).TrimEnd('\0');
return programName;
}
internal static class NativeMethods
{
[DllImport("gdi32.dll", EntryPoint = "DeleteObject")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool DeleteObject([In] IntPtr hObject);
}
public class Program
{
public string ProgramName { get; set; }
public DateTime LastUsedDate { get; set; }
public string Name { get; set; }
}
private void SayWelcome(string userName)
{
string welcomeMessage = $"Welcome back, {userName}! I'm your personal assistant. How can I assist you today?";
_speechSynthesizer.Speak(welcomeMessage);
}
// private void WriteLineToConsole(string message)
// {
// consoleTextBox.AppendText(message + Environment.NewLine);
// consoleTextBox.ScrollToEnd();
// }
private void WriteLineToConsole(string message) { }
private void Window_Closing(object sender, CancelEventArgs e)
{
// Dispose the SpeechSynthesizer instance
_speechSynthesizer?.Dispose();
// Dispose the HttpClient instance
_httpClient?.Dispose();
}
private void MainWindow_PreviewKeyDown(object sender, KeyEventArgs e)
{
if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
{
switch (e.Key)
{
case Key.C:
// Handle Ctrl+C here
e.Handled = true;
break;
case Key.V:
// Handle Ctrl+V here
e.Handled = true;
break;
case Key.A:
// Handle Ctrl+X here
e.Handled = true;
break;
// Add more cases for other shortcuts as needed
}
}
}
}
}
Could someone please guide me on how to fetch the recently used programs and bind them to the ListBox control in my C# WPF application? Any help or code examples would be greatly appreciated. Thank you!
I tried this:
string recentProgramsKey = @"Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocs";
RegistryKey recentProgramsRegistryKey = Registry.CurrentUser.OpenSubKey(recentProgramsKey);
string[] recentPrograms = recentProgramsRegistryKey.GetSubKeyNames();
recentProgramsListBox.ItemsSource = null;
// Filter the list to show only applications
// Filter the list to show only applications
var applicationExtensions = new[] { ".exe" };
var filteredPrograms = recentPrograms
.Where(program => applicationExtensions.Contains(Path.GetExtension(program)))
.Select(program =>
{
string filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Recent), program);
string programName = DecodeProgramName(System.IO.File.ReadAllBytes(filePath), 0);
return new RecentProgram
{
FileName = program,
FilePath = filePath,
ProgramName = programName
};
})
.ToArray();
// Bind the filtered list of recently used programs to the ListBox control
recentProgramsListBox.ItemsSource = filteredPrograms;
and I expected it to work
答案1
得分: 1
你可以查询注册表中的 HKEY_CURRENT_USER\Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\MuiCache
键:
RegistryKey? registryKey = Registry.CurrentUser.OpenSubKey(@"Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\MuiCache");
if (registryKey is null)
{
this.ListBox.ItemsSource = Enumerable.Empty<string>();
return;
}
IEnumerable<string> mostRecentApplicationPaths = registryKey.GetValueNames();
IEnumerable<string> applicationNames = mostRecentApplicationPaths
.Select(path => registryKey.GetValue(path))
.Cast<string>();
// 展示应用程序路径
this.ListBox.ItemsSource = mostRecentApplicationPaths;
// 展示应用程序显示名称
this.ListBox.ItemsSource = mostRecentApplicationNames;
英文:
You can query the registry for the HKEY_CURRENT_USER\Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\MuiCache
key:
RegistryKey? registryKey = Registry.CurrentUser.OpenSubKey(@"Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\MuiCache");
if (registryKey is null)
{
this.ListBox.ItemsSource = Enumerable.Empty<string>();
return;
}
IEnumerable<string> mostRecentApplicationPaths = registryKey.GetValueNames();
IEnumerable<string> applicationNames = mostRecentApplicationPaths
.Select(path => registryKey.GetValue(path))
.Cast<string>();
// Show application paths
this.ListBox.ItemsSource = mostRecentApplicationPaths;
// Show application display names
this.ListBox.ItemsSource = mostRecentApplicationNames;
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论