如何在C# WPF中显示最近使用的程序?

huangapple go评论75阅读模式
英文:

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(@&quot;Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\MuiCache&quot;);
if (registryKey is null)
{
  this.ListBox.ItemsSource = Enumerable.Empty&lt;string&gt;();
  return;
}

IEnumerable&lt;string&gt; mostRecentApplicationPaths = registryKey.GetValueNames();
IEnumerable&lt;string&gt; applicationNames = mostRecentApplicationPaths
  .Select(path =&gt; registryKey.GetValue(path))
  .Cast&lt;string&gt;();

// Show application paths
this.ListBox.ItemsSource = mostRecentApplicationPaths;

// Show application display names
this.ListBox.ItemsSource = mostRecentApplicationNames;

</details>



huangapple
  • 本文由 发表于 2023年6月19日 06:46:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/76502794.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定