Search code examples
c#webclientlauncher

C# Launcher based on WebClient


I'm creating simple launcher for my other application and I need advise on logical part of the program. Launcher needs to check for connection, then check for file versions (from site), compare it with currently downloaded versions (if any) and if everything is alright, start the program, if not, update (download) files that differs from newest version. The files are: program.exe, config.cfg and mapFolder. The program.exe and mapFolder must be updated, and config.cfg is only downloaded when there is no such file. Additionaly mapFolder is an folder which contains lots of random files (every new version can have totally different files in mapFolder).

For the file version I thought I would use simple DownloadString from my main site, which may contain something like program:6.0,map:2.3, so newest program ver is 6.0 and mapFolder is 2.3. Then I can use FileVersionInfo.GetVersionInfo to get the version of current program (if any) and include a file "version" into mapFolder to read current version.

The problem is I dont know how to download whole folder using WebClient and what's the best way to do what I want to do. I've tried to download the mapFolder as zip and then automatically unpack it, but the launcher need to be coded in .net 3.0.

Here is my current code, that's just a prototype to get familiar with whole situation, dont base on it. `

   WebClient wc = new WebClient();
    string verifySite = "google.com/downloads/version";
    string downloadSite = "google.com/downloads/program.exe";
    Uri verifyUri, downloadUri = null;

    string userVer, currVer = "";
    string downloadPath = Directory.GetCurrentDirectory();
    string clientName = "program.exe";

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        wc.DownloadFileCompleted += new AsyncCompletedEventHandler(FileDownloaded);
        wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(FileDownloadProgress);
        chckAutorun.Checked = Properties.Settings.Default.autorun;

        checkConnection();

        if(!checkVersion())
            downloadClient();
        else
        {
            pbDownload.Value = 100;
            btnPlay.Enabled = true;
            lblProgress.Text = "updated";

            if (chckAutorun.Checked)
                btnPlay.PerformClick();
        }
    }

    private bool checkConnection()
    {
        verifyUri = new Uri("http://" + verifySite);
        downloadUri = new Uri("http://" + downloadSite);
        WebRequest req = WebRequest.Create(verifyUri);
        try
        {
            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
            return true;
        }
        catch { }

        verifyUri = new Uri("https://" + verifySite);
        downloadUri = new Uri("https://" + downloadUri);
        req = WebRequest.Create(verifyUri);
        try
        {
            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
            return true;
        }
        catch { }

        return false;
    }

    private void downloadClient()
    {
        try
        {
            wc.DownloadFileAsync(downloadUri, Path.Combine(downloadPath, clientName));
        }
        catch { }
    }

    private bool checkVersion()
    {
        lblProgress.Text = "checking for updates";
        try
        {
            currVer = FileVersionInfo.GetVersionInfo(Path.Combine(downloadPath, clientName)).FileVersion;
        }
        catch {
            currVer = "";
        }

        try
        {
            userVer = wc.DownloadString(verifyUri);
        }
        catch {
            userVer = "";
        }

        return currVer == userVer && currVer != "";
    }

    private void FileDownloaded(object sender, AsyncCompletedEventArgs e)
    {
        btnPlay.Enabled = true;
        lblProgress.Text = "updated";

        if (chckAutorun.Checked)
            btnPlay.PerformClick();
    }

    private void FileDownloadProgress(object sender, DownloadProgressChangedEventArgs e)
    {
        long received = e.BytesReceived / 1000;
        long toReceive = e.TotalBytesToReceive / 1000;

        lblProgress.Text = string.Format("{0}KB {1}/ {2}KB", received, Repeat(" ", Math.Abs(-5 + Math.Min(5, received.ToString().Length))*2), toReceive);
        pbDownload.Value = e.ProgressPercentage;
    }

    private void btnPlay_Click(object sender, EventArgs e)
    {
        btnPlay.Enabled = false;
       if(checkVersion())
       {
           lblProgress.Text = "Starting...";
           Process.Start(Path.Combine(downloadPath, clientName));
           this.Close();
       }
       else
       {
           downloadClient();
       }
    }

    public static string Repeat(string instr, int n)
    {
        if (string.IsNullOrEmpty(instr))
            return instr;

        var result = new StringBuilder(instr.Length * n);
        return result.Insert(0, instr, n).ToString();
    }

    private void chckAutorun_CheckedChanged(object sender, EventArgs e)
    {
        Properties.Settings.Default.autorun = chckAutorun.Checked;
        Properties.Settings.Default.Save();
    }`

Solution

  • I've managed to achieve what I need by enabling autoindex on web server and download string of files in folder ending with .map .

    string mapSite = wc.DownloadString(new Uri("http://" + mapsSite));
    maps = Regex.Matches(mapSite, "<a href=\"(.*).map\">");
    foreach (Match m in maps)
    {
    string mapName = m.Value.Remove(0, 9).Remove(m.Length - 11);
    downloaded = false;
    wc.DownloadFileAsync(new Uri("http://" + mapsSite + mapName), Path.Combine(downloadPath, @"mapFolder/" + mapName));
    while (!downloaded) { }
    }