Boundinashes6
Boundinashes6

Reputation: 387

Background Worker to update multiple items in a listview

I am trying to update multiple values in a list box using this method: What this method does is copy the contents of the specified directory but it outputs the current file name to the background worker progress changed event.

private bool CopyDirectory(string SourcePath, string DestinationPath, bool Recursive, BackgroundWorker worker, DoWorkEventArgs e)
    {
        List<string> Paths = new List<string>();
        List<string> Files = new List<string>();

        //for windows xp My documents
        if(!Directory.Exists(SourcePath))
        {
            SourcePath = SourcePath.Replace(@"C$\Users\", @"C$\Documents and Settings");

            int doccount = Regex.Matches(SourcePath, "Documents").Count;

            //if source contains 2 documents
            if(doccount > 1)
            {
                ReplaceLastOccurrence(SourcePath, "Documents", "My Documents");
            }
        }


        //set file permissions
        FileIOPermission f2 = new FileIOPermission(FileIOPermissionAccess.Read, SourcePath);
        f2.AllLocalFiles = FileIOPermissionAccess.Read;

        f2.Demand();

        foreach (string StringPath in DirectoryList(SourcePath, Recursive, null))
            Paths.Add(StringPath);
        foreach (string StringPath in FileList(SourcePath, Recursive, null))
            Files.Add(StringPath);
        try
        {

            foreach (string dirPath in Paths)
                System.IO.Directory.CreateDirectory(dirPath.Replace(SourcePath, DestinationPath));
            foreach (string newPath in Files)
            {



                string[] filename = newPath.Split('$');

                string currentfile = "C:" + filename[1];

                //report the file name to the background worker
                worker.ReportProgress(0, currentfile);


                System.IO.File.Copy(newPath, newPath.Replace(SourcePath, DestinationPath), Recursive);




            }
            return true;
        }
        catch { return false; }
    }




    private static List<string> FileList(string RootDirectory,
        bool SearchAllDirectories, Predicate<string> Filter)
    {
        List<string> retList = new List<string>();

        try
        {
            List<string> DirList = new List<string> { RootDirectory };

            if (SearchAllDirectories)
                DirList.AddRange(DirectoryList(RootDirectory, SearchAllDirectories, Filter));

            foreach (string DirectoryStr in DirList)
            {
                DirectoryInfo di = new DirectoryInfo(DirectoryStr);
                try
                {
                    foreach (FileInfo FileStr in di.EnumerateFiles())
                    {
                        try
                        {
                            if ((Filter == null) || (Filter(FileStr.FullName)))
                                retList.Add(FileStr.FullName);
                        }

                        catch (Exception) { }
                    }
                }
                catch (UnauthorizedAccessException) { }
                catch (Exception) { }
            }
        }
        catch (Exception) { }
        return retList;
    }

    private static List<string> DirectoryList(string RootDirectory,
        bool SearchAllDirectories, Predicate<string> Filter)
    {
        List<string> retList = new List<string>();
        try
        {
            DirectoryInfo di = new DirectoryInfo(RootDirectory);

            foreach (DirectoryInfo DirectoryStr in di.EnumerateDirectories())
            {
                try
                {
                    if ((Filter == null) || (Filter(DirectoryStr.FullName)))
                    {
                        retList.Add(DirectoryStr.FullName);

                        if (SearchAllDirectories)
                            retList.AddRange(DirectoryList(DirectoryStr.FullName, SearchAllDirectories,
                                Filter));
                    }
                }
                catch (UnauthorizedAccessException) { }

                catch (Exception) { }
            }
        }
        catch (Exception) { }
        return retList;
    }

This works great for just one file name update, however, my program will do multiple copying of directors that i wish to update a list-view item to display it to the user.

private void bgwBackup_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        this.InvokeEx(c => this.lblBackupStatus.Text = e.UserState.ToString());
    }

My question is how would I update multiple listviewitems with the current filename of the specified path ? I can post my do work handler if needed. Thank you.

EDIT1 Here is my DO_WORK as requested:

  private void bgwBackup_DoWork(object sender, DoWorkEventArgs e)
    {

        //Textbox Array Values
        // 0 = computername
        // 1 = username
        // 2 = password
        string[] tbvalues = (string[])e.Argument;


        string computer = tbvalues[0];
        string user = tbvalues[1];
        string pass = tbvalues[2];






        try
        {
            //AD SEARCH

            DirectoryEntry de = new DirectoryEntry("WinNT://" + Environment.UserDomainName + "/" + user);
            string homepath = de.Properties["homedirectory"].Value.ToString();

            if (string.IsNullOrWhiteSpace(homepath))
            {
                //do something when home drive is missing
                MessageBox.Show("NO H DRIVE");
            }

            else
            {

                //Declare strings 
                string os = GetOsName(computer);

                string desktop="";
                    string documents="";
                        string favorites="";

                        string outlooksig = "";
                        string outlookcache = "";


                        string hdriveroot = homepath + @"\PKBACKUP " + DateTime.Now.ToString("MM-dd-yyyy--hh-mm-ss");

                        string hudp = hdriveroot + @"\Desktop";
                        string hudoc = hdriveroot + @"\Documents";
                        string hufav = hdriveroot + @"\Favorites";
                        string hprintdir = hdriveroot + @"\printers\";
                        string outlooksigdir = hdriveroot + @"\Outlook Files\Signatures";
                        string outlookcachedir = hdriveroot + @"\Outlook Files\Cache";






                if (os.Contains("XP"))
                {
                    desktop = @"\\" + computer + @"\C$\Documents and Settings\" + user + @"\Desktop";
                    documents = @"\\" + computer + @"\C$\Documents and Settings\" + user + @"\My Documents";
                    favorites = @"\\" + computer + @"\C$\Documents and Settings\" + user + @"\Favorites";

                    //outlook signatures
                    outlooksig = @"\\" + computer + @"\C$\Documents and Settings\" + user + @"\Application Data\Microsoft\Signatures";

                    //outlook cache
                    outlookcache = @"\\" + computer + @"\C$\Documents and Settings\" + user + @"\Application Data\Microsoft\Outlook";

                }


                else

                {
                    desktop = @"\\" + computer + @"\C$\Users\" + user + @"\Desktop";
                    documents = @"\\" + computer + @"\C$\Users\" + user + @"\Documents";
                    favorites = @"\\" + computer + @"\C$\Users\" + user + @"\Favorites";
                    outlooksig = @"\\" + computer + @"\C$\Users\" + user + @"\AppData\Roaming\Microsoft\Signatures";
                    outlookcache = @"\\" + computer + @"\C$\Users\" + user + @"\AppData\Roaming\Microsoft\Outlook";


                }










                //Copy Files 
                using (new Impersonator(user, "Domain.org", pass))
                {

                   string outlookext = "nk2";

                    CopyDirectory(favorites, hufav, true, bgwBackup, e);
                   CopyDirectory(documents, hudoc, true, bgwBackup, e);
                    CopyDirectory(desktop, hudp, true, bgwBackup, e);
                    CopyDirectory(outlooksig, outlooksigdir, true, bgwBackup, e); 
                    copybyext(outlookcache, outlookcachedir, outlookext, user); //copy nk2 file method







                    //Printers 
                    List<string> printers = new List<string>();

                        foreach (string printername in lbBackupprinters.Items)
                        {
                            if (printername.Contains("No Printers Found"))
                            {
                                //Add listview entry that no printers were found
                            }

                            else
                            {
                                if (Directory.Exists(hprintdir) == false)
                                {
                                    Directory.CreateDirectory(hprintdir);
                                }

                            string prntsvr;
                            string printer;

                            //strip out numbers in string
                            prntsvr = Regex.Replace(printername, "[^0-9]+", string.Empty);

                            //take the first number in the string
                            prntsvr = prntsvr[0].ToString();

                            //remote everything before last comma
                            printer = printername.Substring(printername.LastIndexOf(',') + 1);

                            //add vbs to printer name
                            printer = printer + ".vbs";

                            //get file path of printer vbs script
                            string[] printerpaths = Directory.GetFiles(@"\\dist-win-prnt-" + prntsvr + @"\printerscripts", printer);

                            //append string builder with print server path

                            if (!File.Exists(printerpaths[0]))
                            {
                                //do something if the printer does not exist, add error. 

                            }

                            else
                            {
                                printers.Add(printerpaths[0]);
                            }

                        }

                        string defaultprinter = lbBackupprinters.Items[0].ToString() + ".vbs";
                        defaultprinter = defaultprinter.Substring(defaultprinter.LastIndexOf(',') + 1);
                        //
                        //Download printer vbs script(s)
                        foreach (string printstring in printers)
                        {

                            string hprintfilename = printstring.Substring(printstring.LastIndexOf("\\") + 1);




                            if (hprintfilename.Equals(defaultprinter))
                            {


                                File.Copy(printstring, hprintdir +  "(Defualt) "+ hprintfilename, true);

                            }

                            else
                            {



                                File.Copy(printstring, hprintdir + hprintfilename, true);
                            }

                        }

                    } // end else





                }
            }

        } //end try

        catch (Win32Exception logonfail)
        {

            MessageBox.Show("LOGON FAIL" + logonfail);

            //add label for failure
            return;

        }

        catch (DirectoryServicesCOMException adfail)
        {
            MessageBox.Show(adfail.ToString());
        }

        catch (UnauthorizedAccessException accessex)
        {
            MessageBox.Show(accessex.ToString());
        }






    }

EDIT2: Image of program enter image description here

EDIT3: Here is my progress changed and completed code

      //this only updates the status text and does not update the listview control. 
    private void bgwBackup_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        this.InvokeEx(c => this.lblBackupStatus.Text = e.UserState.ToString());
    }

    private void bgwBackup_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        lblBackupStatus.Text = "Backup job completed";
    }`

Upvotes: 3

Views: 2856

Answers (1)

Peuczynski
Peuczynski

Reputation: 4733

First, add another class

class BackupTask
{
    public string MachineName { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public string CurrentFile { get; set; }
    public int OverallProgress { get; set; }
}

Then

private List<BackupTask> task_definitions = new List<BackupTask>();  //this is needed to parallel foreach 
private List<BackupTask> tasks = new List<BackupTask>();  //this is what you will use to report progress of your copying 

and suppose your backgroundworker is named 'bw`

private BackgroundWorker bw;

Add this to your XAML file (before main Grid)

<Window.Resources>
    <DataTemplate x:Key="BackupTask">            
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding MachineName}" Margin="2,4,2,4"/>
            <TextBlock Text="{Binding Username}" Margin="2,4,2,4" />
            <TextBlock Text="{Binding Password}" Margin="2,4,2,4"/>
            <TextBlock Text="{Binding CurrentFile}" Margin="2,4,2,4"/>
            <TextBlock Text="{Binding OverallProgress}" Margin="2,4,2,4"/>
        </StackPanel>
    </DataTemplate>
</Window.Resources>

in your listview set ItemTemplate="{StaticResource ResourceKey=BackupTask}

So in the window constructor

bw = new BackgroundWorker();
bw.WorkerReportsProgress = true;
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);

Your buttons

private void btn_AddToQueue_Click(object sender, RoutedEventArgs e)
{
    BackupTask bt = new BackupTask();
    bt.MachineName = //load these
    bt.Username = // from your 
    bt.Password = //textboxes
    bt.CurrentFile = "";
    bt.OverallProgress = 0;
    AddOrModifyTask(bt);    
    listView1.ItemsSource = tasks;
}


private void btn_StartBackup_Click(object sender, RoutedEventArgs e)
{
    if (!bw.IsBusy)
        bw.RunWorkerAsync();
}

Of cource you will also need

void AddOrModifyTask(BackupTask t)
{
    bool found = false;
    foreach (BackupTask bt in tasks)
    {
        if (bt.MachineName == t.MachineName)
        {
            found = true;
            bt.CurrentFile = t.CurrentFile;
            bt.OverallProgress = t.OverallProgress;
        }
    }
    if (!found)
        tasks.Add(t);
}

Your progressbar events

void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    lock (tasks)
    {
        AddOrModifyTask((BackupTask)e.UserState);
    }
    listView1.ItemsSource = tasks;
    listView1.Items.Refresh();
}


void bw_DoWork(object sender, DoWorkEventArgs e)
{
    task_definitions = tasks;
    Parallel.ForEach(task_definitions, task =>
        {
            string computer = task.MachineName;
            string user = task.Username;
            string pass = task.Password;
            //your old Do_Work code
        });
}

Instead of passing background worker as parameter pass associated BackupTask object and always use bw

Quick working example is here

Upvotes: 5

Related Questions