I've written a Universal Windows Application which allows you to select a folder and shows the icon and name of a random executable from anywhere in that folder. The intent is to be a Game Roulette, where if you install all your games in a certain folder, it will tell you what game to play.MainPage.xaml:<Page    x:Class=GameRoulette.MainPage    xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation    xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml    xmlns:local=using:GameRoulette    xmlns:d=http://schemas.microsoft.com/expression/blend/2008    xmlns:mc=http://schemas.openxmlformats.org/markup-compatibility/2006    xmlns:viewmodels=using:GameRoulette     mc:Ignorable=d Width=400 Height=400>    <Grid x:Name=prgrGettingGames Background={ThemeResource ApplicationPageBackgroundThemeBrush}>        <Button x:Name=btnSelectGames Content=Click here to select your games                HorizontalAlignment=Left Margin=110,50,0,0                VerticalAlignment=Top Height=40 Width=240                Click=SelectGames_Click/>        <Button x:Name=btnChooseGame Content={Binding ChooseGameText, Mode=OneWay}                HorizontalAlignment=Left Margin=110,150,0,0                VerticalAlignment=Top Width=240 Height=40                Click=ChooseGame_Click IsEnabled={Binding ChooseGameEnabled, Mode=OneWay}/>        <ProgressRing HorizontalAlignment=Left Margin=200,100,0,0                       VerticalAlignment=Top RenderTransformOrigin=1.05,1.983                      Height=45 Width=45 IsActive=True Visibility={Binding ProgressRingVisibility, Mode=OneWay}/>        <Image x:Name=imgFileIcon HorizontalAlignment=Left               Height=64 Margin=110,224,0,0               VerticalAlignment=Top Width=64 Source={Binding FileThumbnail, Mode=OneWay}/>        <TextBlock x:Name=lblFileName HorizontalAlignment=Left                   Margin=200,224,0,0 TextWrapping=Wrap                   Text={Binding Filename, Mode=OneWay} VerticalAlignment=Top/>       </Grid>  </Page>MainPage.xaml.csusing System;using System.Collections.Generic;using System.Linq;using Windows.UI.Xaml;using Windows.UI.Xaml.Controls;using Windows.UI.Xaml.Media;using Windows.UI.Xaml.Media.Imaging;using Windows.Storage.Pickers;using Windows.Storage;using System.ComponentModel;namespace GameRoulette{    public sealed partial class MainPage : Page    {        private IEnumerable<StorageFile> Files;        public MainPageViewModel PageViewModel { get; set; }        int i;        int fileCount;        int exeFileCount;        public MainPage()        {            InitializeComponent();            PageViewModel = new MainPageViewModel();            i = 0;            DataContext = PageViewModel;        }        private async void SelectGames_Click(object sender, RoutedEventArgs e)        {            FolderPicker folderPicker = new FolderPicker();            folderPicker.FileTypeFilter.Add(.exe);            PageViewModel.ProgressRingVisibility = Visibility.Visible;            StorageFolder selectedFolder = await folderPicker.PickSingleFolderAsync();            PageViewModel.ChooseGameText = retrieving files;            IEnumerable<StorageFile> retrievedFiles = await selectedFolder.GetFilesAsync(Windows.Storage.Search.CommonFileQuery.OrderByName);            fileCount = retrievedFiles.Count();            Files = retrievedFiles.Where(file => ValidateFile(file)).ToList();            if (!Files.Any())            {                PageViewModel.Filename = No executables found.;                return;            }            exeFileCount = Files.Count();            PageViewModel.ProgressRingVisibility = Visibility.Collapsed;            PageViewModel.ChooseGameText = string.Format({0} games found. Click here to choose your game., exeFileCount);            PageViewModel.ChooseGameEnabled = true;        }        private bool ValidateFile(StorageFile file)        {            string[] blacklist = { uninst, system, redist };            PageViewModel.ChooseGameText = string.Format({0} of {1} files checked., i, fileCount);            i++;            if (file.FileType != .exe)            {                return false;            }            foreach(string item in blacklist)            {                if (file.Name.ToLowerInvariant().Contains(item))                {                    return false;                }            }            return true;        }        private async void ChooseGame_Click(object sender, RoutedEventArgs e)        {            if (!Files.Any())            {                return;            }            Random generator = new Random();            int index = generator.Next(0, exeFileCount - 1);            StorageFile chosenGame = Files.ToList().ElementAt(index);            Windows.Storage.FileProperties.StorageItemThumbnail thumbnail = await chosenGame.GetScaledImageAsThumbnailAsync(Windows.Storage.FileProperties.ThumbnailMode.SingleItem, 64);            BitmapImage image = new BitmapImage();            image.SetSource(thumbnail);            PageViewModel.FileThumbnail = image;            PageViewModel.Filename = chosenGame.DisplayName;        }    }    public class MainPageViewModel : INotifyPropertyChanged, INotifyPropertyChanging    {        public MainPageViewModel()        {            fileThumbnail = new BitmapImage();            progressRingVisibility = Visibility.Collapsed;            chooseGameEnabled = false;            filename = no games loaded;            chooseGameText = Please choose a game first;        }        private ImageSource fileThumbnail;        private Visibility progressRingVisibility;        private bool chooseGameEnabled;        private string filename;        private string chooseGameText;        public event PropertyChangedEventHandler PropertyChanged;        public event PropertyChangingEventHandler PropertyChanging;        public void OnPropertyChanging(string propertyName)        {            if (PropertyChanging != null)                PropertyChanging.Invoke(this, new PropertyChangingEventArgs(propertyName));        }        public void OnPropertyChanged(string propertyname)        {            if (PropertyChanged != null)            {                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyname));            }        }        public string ChooseGameText        {            get { return chooseGameText; }            set            {                OnPropertyChanging(ChooseGameText);                chooseGameText = value;                OnPropertyChanged(ChooseGameText);            }        }        public ImageSource FileThumbnail        {            get { return fileThumbnail; }            set            {                OnPropertyChanging(FileThumbnail);                fileThumbnail = value;                OnPropertyChanged(FileThumbnail);            }        }        public Visibility ProgressRingVisibility        {            get            {                return progressRingVisibility;            }            set            {                OnPropertyChanging(ProgressRingVisibility);                progressRingVisibility = value;                OnPropertyChanged(ProgressRingVisibility);            }        }        public bool ChooseGameEnabled        {            get { return chooseGameEnabled; }            set            {                OnPropertyChanging(ChooseGameEnabled);                chooseGameEnabled = value;                OnPropertyChanged(ChooseGameEnabled);            }        }        public string Filename        {            get { return filename; }            set            {                OnPropertyChanging(Filename);                filename = value;                OnPropertyChanged(Filename);            }        }    }}This code does what it should do. I have knowledge of 1 major and 2 minor bugs, but none of them are really breaking bugs:MAJOR: from what I can tell, it does not handle symbolic links well. I have several games symbolically linked from another drive, but they're not found.MINOR: PageViewModel.ChooseGameText isn't updated during the Where() clause, which means that doesn't show a progress.MINOR: my blacklist is incomplete, but that's just a matter of adding the right items.I have also noticed that it's quite slow compared to other similar software. For example, WinDirStat takes under 2 minutes to check my entire C: drive. This program isn't finished with that after 20 minutes AND makes the Runtime Broker use 4 GB of memory, which causes system warning for out of memory.
Randomly choose a game executable from a folder
c#;performance;file system;xaml
A few things noticed by just looking over the code in no particular order:The blacklist should be a static readonly class member - there is no need to create the array on every call to ValidateFile.The variable i should not be a class member. Where has an overload which passes the current index along so you should use that instead. Also fileCount should not be a class member since it's only used to track progress. The current index and total count should be passed in as parameters to the ValidateFile method rather than being class state.Files gets set as ToList() yet you have another ToList() call on it in the ChooseGame_Click method. This will create another copy of the whole list and wastes time and memory for no reason at all. Just have the type as IList instead of IEnumerable. In that case exeFileCount becomes obsolete.In ValidateFile the filename gets converted to lower case for every entry in the blacklist - again waste of memory and time. Just store the lowered file name in a local variable and compare against it. Also some LINQ could be employed to make this a bit more succinct.The canonical way to invoke an event handler was this:var handler = MyEventHandler;if (handler != null){    handler(this, new MyEventArgs());}This avoids a potential race where the last handler unsubscribes after checking against null but before actually executing the handler.In C# 6.0 you can simply use the Null-conditional operator:MyEventHandler?.Invoke(this, new MyEventArgs())A simple rewrite of MainPage would look like this:public sealed partial class MainPage : Page{    private IList<StorageFile> Files;    public MainPageViewModel PageViewModel { get; set; }    public MainPage()    {        InitializeComponent();        PageViewModel = new MainPageViewModel();        DataContext = PageViewModel;    }    private async void SelectGames_Click(object sender, RoutedEventArgs e)    {        FolderPicker folderPicker = new FolderPicker();        folderPicker.FileTypeFilter.Add(.exe);        PageViewModel.ProgressRingVisibility = Visibility.Visible;        StorageFolder selectedFolder = await folderPicker.PickSingleFolderAsync();        PageViewModel.ChooseGameText = retrieving files;        var retrievedFiles = await selectedFolder.GetFilesAsync(Windows.Storage.Search.CommonFileQuery.OrderByName);        var fileCount = retrievedFiles.Count;        Files = retrievedFiles.Where((file, index) => ValidateFile(file, index, fileCount)).ToList();        if (!Files.Any())        {            PageViewModel.Filename = No executables found.;            return;        }        PageViewModel.ProgressRingVisibility = Visibility.Collapsed;        PageViewModel.ChooseGameText = string.Format({0} games found. Click here to choose your game., exeFileCount);        PageViewModel.ChooseGameEnabled = true;    }    static readonly string[] blacklist = { uninst, system, redist };    private bool ValidateFile(StorageFile file, int currentIndex, int totalNumberOfFiles)    {        PageViewModel.ChooseGameText = string.Format({0} of {1} files checked., currentIndex, totalNumberOfFiles);        if (file.FileType != .exe)        {            return false;        }        var lowerCaseFilename = file.Name.ToLowerInvariant();        return blacklist.Any(e => lowerCaseFilename.Contains(e));    }    private async void ChooseGame_Click(object sender, RoutedEventArgs e)    {        if (!Files.Any())        {            return;        }        Random generator = new Random();        int index = generator.Next(0, Files.Count - 1);        StorageFile chosenGame = Files[index];        Windows.Storage.FileProperties.StorageItemThumbnail thumbnail = await chosenGame.GetScaledImageAsThumbnailAsync(Windows.Storage.FileProperties.ThumbnailMode.SingleItem, 64);        BitmapImage image = new BitmapImage();        image.SetSource(thumbnail);        PageViewModel.FileThumbnail = image;        PageViewModel.Filename = chosenGame.DisplayName;    }}This could probably still be improved but it's somewhat cleaner now.