Solved

Delete from ListBox broken shortcuts in C# WPF

Posted on 2014-01-08
13
651 Views
Last Modified: 2014-01-12
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

0
Comment
Question by:TeknikDev
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 6
13 Comments
 
LVL 13

Expert Comment

by:Naman Goel
ID: 39767601
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.
0
 

Author Comment

by:TeknikDev
ID: 39767804
Opps sorry, 2nd item means to display the record count in the list box into a textbox.
0
 

Author Comment

by:TeknikDev
ID: 39767926
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
0
Resolve Critical IT Incidents Fast

If your data, services or processes become compromised, your organization can suffer damage in just minutes and how fast you communicate during a major IT incident is everything. Learn how to immediately identify incidents & best practices to resolve them quickly and effectively.

 
LVL 13

Expert Comment

by:Naman Goel
ID: 39768863
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

0
 

Author Comment

by:TeknikDev
ID: 39769352
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
0
 
LVL 13

Expert Comment

by:Naman Goel
ID: 39770122
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

0
 

Author Comment

by:TeknikDev
ID: 39771519
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

0
 
LVL 13

Expert Comment

by:Naman Goel
ID: 39771890
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.
0
 

Author Comment

by:TeknikDev
ID: 39772231
yes, but I'm not how to fix it. Could you tell me based on the information provided thus far?
0
 
LVL 13

Expert Comment

by:Naman Goel
ID: 39772920
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.
0
 

Author Comment

by:TeknikDev
ID: 39774093
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

0
 
LVL 13

Accepted Solution

by:
Naman Goel earned 500 total points
ID: 39774291
Add FileShortcutsListBox.Items.Clear() at start of event. or create a new List out of lstFilesFound and attach it with ItemSource.
0
 

Author Closing Comment

by:TeknikDev
ID: 39774665
I added before and it worked! thanks
0

Featured Post

Space-Age Communications Transitions to DevOps

ViaSat, a global provider of satellite and wireless communications, securely connects businesses, governments, and organizations to the Internet. Learn how ViaSat’s Network Solutions Engineer, drove the transition from a traditional network support to a DevOps-centric model.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Many of us here at EE write code. Many of us write exceptional code; just as many of us write exception-prone code. As we all should know, exceptions are a mechanism for handling errors which are typically out of our control. From database errors, t…
Entering time in Microsoft Access can be difficult. An input mask often bothers users more than helping them and won't catch all typing errors. This article shows how to create a textbox for 24-hour time input with full validation politely catching …
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Are you ready to implement Active Directory best practices without reading 300+ pages? You're in luck. In this webinar hosted by Skyport Systems, you gain insight into Microsoft's latest comprehensive guide, with tips on the best and easiest way…

733 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question