static void Main(string[] args)
        {
            string fileListFileName = "Files.txt";

            string baseDirectory = Environment.CurrentDirectory;

            if (args.Length > 0)
            {
                if (Directory.Exists(args[0]))
                {
                    baseDirectory = args[0];
                }
                if (args.Length >= 2)
                {
                    fileListFileName = args[1];
                }
            }

            using (FileStream fs = File.Open(fileListFileName, File.Exists(fileListFileName) ? FileMode.Truncate : FileMode.Create, FileAccess.Write, FileShare.None))
            {
                StreamWriter   writer    = new StreamWriter(fs, Encoding.Default);
                Crc32Processor processor = new Crc32Processor();
                byte[]         buffer    = new byte[4096];
                foreach (string fileName in Directory.GetFiles(baseDirectory, "*.*", SearchOption.AllDirectories))
                {
                    if (String.Equals(Path.GetFullPath(fileListFileName), Path.GetFullPath(fileName), StringComparison.InvariantCultureIgnoreCase))
                    {
                        continue;
                    }

                    using (FileStream inStream = File.OpenRead(fileName))
                    {
                        int bytesRead = -1;
                        while (bytesRead != 0)
                        {
                            bytesRead = inStream.Read(buffer, 0, buffer.Length);
                            processor.Process(buffer, 0, bytesRead);
                        }
                    }

                    writer.Write(fileName.Substring(baseDirectory.Length + 1));
                    writer.Write('\t');
                    writer.Write(processor.Current.ToString("X8"));
                    writer.WriteLine();

                    processor.Reset();
                }
                writer.Flush();
            }
        }
        public void UpdateWithWorker(BackgroundWorker worker)
        {
            Progress progress1 = new Progress(0, 3);
            Progress progress2 = new Progress();

            int bytesRead;

            byte[] buffer = new byte[4096];

            worker.ReportProgress(DisplayProgress1, progress1);

            // Download File List
            using (WebClient client = new WebClient())
            {
                worker.ReportProgress(DisplayProgressText1, "Downloading File List ...");
                worker.ReportProgress(DisplayProgressText2, String.Empty);
                string files;
                try
                {
                    files = client.DownloadString(FileListUrl);
                }
                catch (Exception e)
                {
                    throw new ApplicationException("Could not download file-list.\nDetails: " + e.Message, e);
                }
                progress1.Increment();
                worker.ReportProgress(DisplayProgress1, progress1);

                worker.ReportProgress(DisplayProgressText1, "Validating File List ...");
                worker.ReportProgress(DisplayProgressText2, String.Empty);
                Items.Clear();
                StringReader reader = new StringReader(files);
                string       line   = reader.ReadLine();
                while (line != null)
                {
                    string[]   fragments = line.Split('\t');
                    UpdateItem item      = new UpdateItem(m_RootPath);
                    if (fragments.Length >= 1)
                    {
                        item.FileName = fragments[0];
                        if (String.Equals(Path.GetFullPath(item.FileName), Path.GetFullPath(Application.ExecutablePath), StringComparison.InvariantCultureIgnoreCase))
                        {
                            item.TargetFileName = item.FileName + ".tmp";
                            SelfUpdateDetected  = true;
                            SelfUpdateItem      = item;
                        }
                        if (String.IsNullOrEmpty(item.FileName))
                        {
                            continue;
                        }
                        m_Items.Add(item);
                    }
                    if (fragments.Length >= 2)
                    {
                        item.Hash = fragments[1];
                    }
                    line = reader.ReadLine();
                }
                progress1.Increment();
                worker.ReportProgress(DisplayProgress1, progress1);

                if (worker.CancellationPending)
                {
                    return;
                }

                progress2.Reset(0, Items.Count);
                worker.ReportProgress(DisplayProgress2, progress2);
                worker.ReportProgress(DisplayProgressText1, "Validating Files ...");
                Crc32Processor processor = new Crc32Processor();
                foreach (UpdateItem item in Items)
                {
                    if (worker.CancellationPending)
                    {
                        return;
                    }
                    worker.ReportProgress(DisplayProgressText2, item.FullName);

                    if (File.Exists(item.FullName) == false)
                    {
                        item.CheckStatus      = UpdateCheckStatus.NotExisiting;
                        item.IsUpdateRequired = true;
                    }
                    else
                    {
                        using (FileStream fs = File.OpenRead(item.FullName))
                        {
                            while (true)
                            {
                                bytesRead = fs.Read(buffer, 0, buffer.Length);
                                processor.Process(buffer, 0, bytesRead);
                                if (bytesRead != buffer.Length)
                                {
                                    break;
                                }
                            }
                        }
                        if (item.Hash != processor.Current.ToString("X8"))
                        {
                            item.CheckStatus      = UpdateCheckStatus.HashMismatch;
                            item.IsUpdateRequired = true;
                        }
                        else
                        {
                            item.CheckStatus = UpdateCheckStatus.Ok;
                        }
                        processor.Reset();
                    }

                    progress2.Increment();
                    worker.ReportProgress(DisplayProgress2, progress2);
                }
                progress1.Increment();
                worker.ReportProgress(DisplayProgress1, progress1);


                worker.ReportProgress(DisplayProgressText1, "Downloading Files ...");
                foreach (UpdateItem item in Items)
                {
                    if (worker.CancellationPending)
                    {
                        return;
                    }

                    if (item.IsUpdateRequired == false)
                    {
                        continue;
                    }

                    string fileName = item.FileName;
                    if (fileName.StartsWith("./"))
                    {
                        fileName = fileName.Substring(2);
                    }

                    using (Stream stream = client.OpenRead(WebPath.Combine(BaseUrl, fileName)))
                    {
                        // Create Directory If Missing
                        string directoryName = Path.GetDirectoryName(item.FullName);
                        if (Directory.Exists(directoryName) == false)
                        {
                            Directory.CreateDirectory(directoryName);
                        }

                        using (FileStream outStream = File.Open(m_RootPath + item.TargetFileName, File.Exists(m_RootPath + item.TargetFileName) ? FileMode.Truncate : FileMode.Create, FileAccess.Write, FileShare.None))
                        {
                            int contentLength = Int32.Parse(client.ResponseHeaders[HttpResponseHeader.ContentLength]);
                            progress2.Reset(0, contentLength);
                            worker.ReportProgress(DisplayProgress2, progress2);

                            int totalBytesRead = 0;
                            while (true)
                            {
                                worker.ReportProgress(DisplayProgressText2, String.Format("Downloading: {0} - {1:N0}/{2:N0}", fileName, totalBytesRead, contentLength));

                                bytesRead = stream.Read(buffer, 0, buffer.Length);
                                outStream.Write(buffer, 0, bytesRead);
                                totalBytesRead += bytesRead;

                                progress2.CurrentValue = totalBytesRead;
                                worker.ReportProgress(DisplayProgress2, progress2);

                                if (totalBytesRead >= contentLength)
                                {
                                    break;
                                }
                            }
                        }
                    }

                    // Validating File
                    if (String.IsNullOrEmpty(item.Hash) == false)
                    {
                        progress2.Reset();
                        worker.ReportProgress(DisplayProgressText2, String.Format("Validating: {0}", fileName));
                        using (FileStream fs = File.OpenRead(m_RootPath + item.TargetFileName))
                        {
                            while (true)
                            {
                                bytesRead = fs.Read(buffer, 0, buffer.Length);
                                processor.Process(buffer, 0, bytesRead);
                                if (bytesRead == 0)
                                {
                                    break;
                                }
                            }
                        }
                        if (item.Hash != processor.Current.ToString("X8"))
                        {
                            throw new ApplicationException("Downloaded file is invalid. Please restart launcher and repatch files.\nFile: " + m_RootPath + item.TargetFileName);
                        }
                        processor.Reset();
                    }
                }

                // Write Version File
                worker.ReportProgress(DisplayProgressText1, "Writing Version File ...");
                worker.ReportProgress(DisplayProgressText2, String.Empty);
                File.WriteAllText(VersionFileName, m_ServerVersionRawText, Encoding.Default);

                m_SuccessfulUpdated  = true;
                m_CurrentVersionText = m_NewVersionText;
            }
        }