Link to home
Start Free TrialLog in
Avatar of TeknikDev
TeknikDevFlag for United States of America

asked on

Delete from ListBox broken shortcuts in C# WPF

Hi, this code works and what it does is basically search in all folders for shortcuts based on the file extension of ".lnk" and then list the files found in the list box.

What I want now, is:

1.

delete the files found based on selections (multiple or singular).  

2.

display the item count in the list box

3.

  sorting so that the directories are listed alphabetically - currently its out of order  

I used to be able to do this in Windows form using the iwshruntimelibrary based on TargetPath not found based on the search files found. However, this library is nonexistent for WPF.

Any thoughts how I can achieve this? Here's the working code.
 // Holds a collection of all the found files
        ObservableCollection<String> lstFilesFound = new ObservableCollection<string>();

        // Property used by the list box to display the list of files
        public ObservableCollection<string> FilesFound { get { return lstFilesFound; } }

        private void Button3_Click(object sender, RoutedEventArgs e)
        {
            Splash sp = new Splash();
            sp.Show();
            DirSearch(@"C:\\");   
            MessageBox.Show("Search Completed");
            sp.Close();
             
        }

        void DirSearch(string sDir)
        {
             
            Stack<string> dirs = new Stack<string>(20);

            if (!System.IO.Directory.Exists(sDir))
            {
                throw new ArgumentException();
            }
            dirs.Push(sDir);

            while (dirs.Count > 0)
            {
                string currentDir = dirs.Pop();
                string[] subDirs = null;
                try
                {
                    subDirs = System.IO.Directory.GetDirectories(currentDir);
                }
                
                catch (UnauthorizedAccessException e)
                {
                    
                    continue;
                }
                catch (System.IO.PathTooLongException e)
                {

                    
                    continue;
                }
                catch (System.IO.DirectoryNotFoundException e)
                {
                   
                    continue;
                }

                string[] files = null;
                try
                {
                    files = System.IO.Directory.GetFiles(currentDir, "*.lnk");
                }
                catch (System.IO.PathTooLongException e)
                {
                    
                    continue;
                }
                catch (UnauthorizedAccessException e)
                {
                     
                    continue;
                }
                catch (System.IO.DirectoryNotFoundException e)
                {
                   
                    continue;
                }  
                foreach (string file in files)
                {
                    try
                    {
                       
                        System.IO.FileInfo fi = new System.IO.FileInfo(file);
                        lstFilesFound.Add(fi.FullName);
                    }
                    catch (System.IO.PathTooLongException e)
                    {
                        
                        continue;
                    }
                    catch (System.IO.FileNotFoundException e)
                    {
                        
                        continue;
                    }
                }

                
                foreach (string str in subDirs)
                    dirs.Push(str);

            }
        }

Open in new window

Avatar of Naman Goel
Naman Goel
Flag of India image

Here is code for the same:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            FileShortcutsListBox.SelectionMode = SelectionMode.Multiple;
            ManualResetEvent mr = new ManualResetEvent(false);
            new DirSearchDelegate(DirSearch).BeginInvoke(@"c:\temp", mr, null, null);
            mr.WaitOne();

            FileShortcutsListBox.ItemsSource = lstFilesFound;
            FileShortcutsListBox.Items.SortDescriptions.Add(
            new System.ComponentModel.SortDescription(String.Empty,
            System.ComponentModel.ListSortDirection.Ascending));
        }

        private void DeleteButton_Click(object sender, RoutedEventArgs e)
        {
           

           foreach (var item in FileShortcutsListBox.SelectedItems)
           {
               IWshRuntimeLibrary.IWshShell shell = new IWshRuntimeLibrary.WshShell();

               IWshRuntimeLibrary.IWshShortcut shortcut = (IWshRuntimeLibrary.IWshShortcut)shell.CreateShortcut(item.ToString());

              FileInfo fi = new FileInfo(shortcut.TargetPath);
              fi.Delete();
               
           }
        }

        // Holds a collection of all the found files
        static ObservableCollection<String> lstFilesFound = new ObservableCollection<string>();

        // Property used by the list box to display the list of files
        public static ObservableCollection<string> FilesFound { get { return lstFilesFound; } }

        delegate void DirSearchDelegate(string sDir,ManualResetEvent mr);

        static void DirSearch(string sDir, ManualResetEvent mr)
        {
            try
            {
                Stack<string> dirs = new Stack<string>(20);
                if (!System.IO.Directory.Exists(sDir))
                {
                    throw new ArgumentException();
                }
                dirs.Push(sDir);

                while (dirs.Count > 0)
                {
                    string currentDir = dirs.Pop();
                    string[] subDirs = null;
                    try
                    {
                        subDirs = System.IO.Directory.GetDirectories(currentDir);
                    }

                    catch (UnauthorizedAccessException e)
                    {

                        continue;
                    }
                    catch (System.IO.PathTooLongException e)
                    {


                        continue;
                    }
                    catch (System.IO.DirectoryNotFoundException e)
                    {

                        continue;
                    }

                    string[] files = null;
                    try
                    {
                        files = System.IO.Directory.GetFiles(currentDir, "*.lnk");
                    }
                    catch (System.IO.PathTooLongException e)
                    {

                        continue;
                    }
                    catch (UnauthorizedAccessException e)
                    {

                        continue;
                    }
                    catch (System.IO.DirectoryNotFoundException e)
                    {

                        continue;
                    }
                    foreach (string file in files)
                    {
                        try
                        {

                            System.IO.FileInfo fi = new System.IO.FileInfo(file);
                            lstFilesFound.Add(fi.FullName);
                        }
                        catch (System.IO.PathTooLongException e)
                        {

                            continue;
                        }
                        catch (System.IO.FileNotFoundException e)
                        {

                            continue;
                        }
                    }


                    foreach (string str in subDirs)
                        dirs.Push(str);
                }
            }
            finally
            {
                mr.Set();
            }

        }
    }
}

Open in new window


Add reference to Windows Script Host Object Model in COM tab of Add Reference dialogue.

I don't know what do you mean in second point. If you want count of items you can use Items.Count property, do you want it to display in listbox? where in listbox? It is not making any sense for me to display items count in listbox itself. you can use label or some other control for same.
Avatar of TeknikDev

ASKER

Opps sorry, 2nd item means to display the record count in the list box into a textbox.
Wow! This is a much cleaner and faster way to do the job! Thank you Naman!

Can you help me with a few update? The search is working, but i need only BROKEN shortcuts. Also, when i changed the code from c:\temp to just c:\ the delete function stopped working. I selected multiple items and single items and it wont delete anymore.

  new DirSearchDelegate(DirSearch).BeginInvoke(@"c:\", mr, null, null);

Open in new window


1.

Refresh the list box after shortcut is deleted

2.

Find only broken shortcut links

3.

Instead of hardcoding the c:\temp folder, give users the ability to define a drive via drive selection box or enter value into textbox whichever you think is easier to code for you. The search will be based off this selection otherwise default to the c:\ drive

4.

A checkbox to delete ALL broken shortcuts found
if you give c:\\ then also it will work, it will just take more time for searching whole drive.

Please find the modified code:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            FileShortcutsListBox.SelectionMode = SelectionMode.Multiple;
            ManualResetEvent mr = new ManualResetEvent(false);
            new DirSearchDelegate(DirSearch).BeginInvoke(DirectoryTextBox.Text, mr, null, null);
            mr.WaitOne();

            FileShortcutsListBox.ItemsSource = lstFilesFound;
            CountTextBox.Text = lstFilesFound.Count.ToString();
            FileShortcutsListBox.Items.SortDescriptions.Add(
            new System.ComponentModel.SortDescription(String.Empty,
            System.ComponentModel.ListSortDirection.Ascending));
        }

    

        private void DeleteButton_Click(object sender, RoutedEventArgs e)
        {
            List<string> deletedItems = new List<string>();
            if (chkDeleteAll.IsChecked.Value== true)
            {
                foreach (var item in FileShortcutsListBox.Items)
                {

                    FileInfo fi = new FileInfo(item.ToString());
                    fi.Delete();
                    deletedItems.Add(item.ToString());

                }
            }
            else
            {

                foreach (var item in FileShortcutsListBox.SelectedItems)
                {

                    FileInfo fi = new FileInfo(item.ToString());
                    fi.Delete();
                    deletedItems.Add(item.ToString());

                }
            }
           for (int i = 0; i < deletedItems.Count; i++)
           {
               lstFilesFound.Remove(deletedItems[i]);
           }
        }

        // Holds a collection of all the found files
        static ObservableCollection<String> lstFilesFound = new ObservableCollection<string>();

        // Property used by the list box to display the list of files
        public static ObservableCollection<string> FilesFound { get { return lstFilesFound; } }

        delegate void DirSearchDelegate(string sDir,ManualResetEvent mr);

        static void DirSearch(string sDir, ManualResetEvent mr)
        {
            try
            {
                Stack<string> dirs = new Stack<string>(20);
                if (!System.IO.Directory.Exists(sDir))
                {
                    throw new ArgumentException();
                }
                dirs.Push(sDir);

                while (dirs.Count > 0)
                {
                    string currentDir = dirs.Pop();
                    string[] subDirs = null;
                    try
                    {
                        subDirs = System.IO.Directory.GetDirectories(currentDir);
                    }

                    catch (UnauthorizedAccessException e)
                    {

                        continue;
                    }
                    catch (System.IO.PathTooLongException e)
                    {


                        continue;
                    }
                    catch (System.IO.DirectoryNotFoundException e)
                    {

                        continue;
                    }

                    string[] files = null;
                    try
                    {
                        files = System.IO.Directory.GetFiles(currentDir, "*.lnk");
                    }
                    catch (System.IO.PathTooLongException e)
                    {

                        continue;
                    }
                    catch (UnauthorizedAccessException e)
                    {

                        continue;
                    }
                    catch (System.IO.DirectoryNotFoundException e)
                    {

                        continue;
                    }
                    foreach (string file in files)
                    {
                        try
                        {

                            System.IO.FileInfo fi = new System.IO.FileInfo(file);
                            IWshRuntimeLibrary.IWshShell shell = new IWshRuntimeLibrary.WshShell();

                            IWshRuntimeLibrary.IWshShortcut shortcut = (IWshRuntimeLibrary.IWshShortcut)shell.CreateShortcut(file.ToString());

                            FileInfo fiTemp = new FileInfo(shortcut.TargetPath);
                            if (fiTemp.Exists == false)
                            {
                                lstFilesFound.Add(fi.FullName);
                            }
                        }
                        catch (System.IO.PathTooLongException e)
                        {

                            continue;
                        }
                        catch (System.IO.FileNotFoundException e)
                        {

                            continue;
                        }
                    }


                    foreach (string str in subDirs)
                        dirs.Push(str);
                }
            }
            finally
            {
                mr.Set();
            }

        }
    }
}

Open in new window

Error when attempting to debug - might be easier to put a button for search and not auto-populate list?

dirs.Push(sDir);

Open in new window

Value does not fall within the expected range
here is code for same:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            
        }

    

        private void DeleteButton_Click(object sender, RoutedEventArgs e)
        {
            List<string> deletedItems = new List<string>();
            if (chkDeleteAll.IsChecked.Value== true)
            {
                foreach (var item in FileShortcutsListBox.Items)
                {

                    FileInfo fi = new FileInfo(item.ToString());
                    fi.Delete();
                    deletedItems.Add(item.ToString());

                }
            }
            else
            {

                foreach (var item in FileShortcutsListBox.SelectedItems)
                {

                    FileInfo fi = new FileInfo(item.ToString());
                    fi.Delete();
                    deletedItems.Add(item.ToString());

                }
            }
           for (int i = 0; i < deletedItems.Count; i++)
           {
               lstFilesFound.Remove(deletedItems[i]);
           }
        }

        // Holds a collection of all the found files
        static ObservableCollection<String> lstFilesFound = new ObservableCollection<string>();

        // Property used by the list box to display the list of files
        public static ObservableCollection<string> FilesFound { get { return lstFilesFound; } }

        delegate void DirSearchDelegate(string sDir,ManualResetEvent mr);
        static List<string> lstValues = new List<string>();
        static void DirSearch(string sDir, ManualResetEvent mr)
        {
            lstValues.Clear();
            try
            {
                Stack<string> dirs = new Stack<string>(20);
                if (!System.IO.Directory.Exists(sDir))
                {
                    throw new ArgumentException();
                }
                dirs.Push(sDir);

                while (dirs.Count > 0)
                {
                    string currentDir = dirs.Pop();
                    string[] subDirs = null;
                    try
                    {
                        subDirs = System.IO.Directory.GetDirectories(currentDir);
                    }

                    catch (UnauthorizedAccessException e)
                    {

                        continue;
                    }
                    catch (System.IO.PathTooLongException e)
                    {


                        continue;
                    }
                    catch (System.IO.DirectoryNotFoundException e)
                    {

                        continue;
                    }

                    string[] files = null;
                    try
                    {
                        files = System.IO.Directory.GetFiles(currentDir, "*.lnk");
                    }
                    catch (System.IO.PathTooLongException e)
                    {

                        continue;
                    }
                    catch (UnauthorizedAccessException e)
                    {

                        continue;
                    }
                    catch (System.IO.DirectoryNotFoundException e)
                    {

                        continue;
                    }
                    foreach (string file in files)
                    {
                        try
                        {

                            System.IO.FileInfo fi = new System.IO.FileInfo(file);
                            IWshRuntimeLibrary.IWshShell shell = new IWshRuntimeLibrary.WshShell();

                            IWshRuntimeLibrary.IWshShortcut shortcut = (IWshRuntimeLibrary.IWshShortcut)shell.CreateShortcut(file.ToString());

                            FileInfo fiTemp = new FileInfo(shortcut.TargetPath);
                            if (fiTemp.Exists == false)
                            {
                                lstValues.Add(fi.FullName);
                            }
                        }
                        catch (System.IO.PathTooLongException e)
                        {

                            continue;
                        }
                        catch (System.IO.FileNotFoundException e)
                        {

                            continue;
                        }
                    }


                    foreach (string str in subDirs)
                        dirs.Push(str);
                }
            }
            finally
            {
                mr.Set();
            }
            
        }

        private void FillButton_Copy_Click_1(object sender, RoutedEventArgs e)
        {
            FileShortcutsListBox.ItemsSource = null;
            FileShortcutsListBox.SelectionMode = SelectionMode.Multiple;
            ManualResetEvent mr = new ManualResetEvent(false);
            new DirSearchDelegate(DirSearch).BeginInvoke(DirectoryTextBox.Text, mr, null, null);
            mr.WaitOne();
            lstFilesFound.Clear();
            
            foreach (var item in lstValues)
            {
                lstFilesFound.Add(item);
            }

            FileShortcutsListBox.ItemsSource = lstFilesFound;
            CountTextBox.Text = lstFilesFound.Count.ToString();
            FileShortcutsListBox.Items.SortDescriptions.Add(
            new System.ComponentModel.SortDescription(String.Empty,
            System.ComponentModel.ListSortDirection.Ascending));
        }
    }
}

Open in new window

I'm still getting this error message. It looks like it's trying to get a value for the sDir variable which is currently just " ".

{"Value does not fall within the expected range."}
dirs.Push(sDir);

Open in new window


So I went ahead and added a default text of C:\ in the DirectoryTextBox textbox. When I click Search, nothing happens.

I debugged and found the following.
dirs.Count is 0 and sDir does show that its passing the c:\temp path. I noticed that the stack is not defined, so its passing in null?

Stack<string> dirs = new Stack<string>(20);

Open in new window

ok, that can be debugged on your environment. let me know if you face any other issue with logic. Retrieval of files  is fine and can be debugged and modified accordingly.
yes, but I'm not how to fix it. Could you tell me based on the information provided thus far?
This error can be caused when there are two elements being added with the same name. That is rarely possible in your case. Please debug and check and if possible please check using Contains method if the string is already added in your stack. I am not getting much idea beyond this as this is working fine in my env.
Ok I realized that I had to put a value into the textbox. It was telling me that the exception handler for no files found was not found. So I created shortcuts that were broken and it got close to the end of the code and got this error in this function.

FillButton_Copy_Click_1(object sender, RoutedEventArgs e)


{"Items collection must be empty before using ItemsSource."} Invalid Operation Exception was unhandled by user code.

  FileShortcutsListBox.ItemsSource = lstFilesFound;

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Naman Goel
Naman Goel
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I added before and it worked! thanks