基于 WebClient 的 C# 启动器

C# Launcher based on WebClient

我正在为我的其他应用程序创建简单的启动器,我需要有关程序逻辑部分的建议。启动器需要检查连接,然后检查文件版本(从站点),将其与当前下载的版本(如果有)进行比较,如果一切正常,启动程序,如果没有,更新(下载)与最新版本不同的文件.这些文件是: program.exe, config.cfg and mapFolderprogram.exemapFolder必须更新,config.cfg只有在没有该文件时才会下载。另外 mapFolder 是一个包含大量随机文件的文件夹(每个新版本在 mapFolder 中可能有完全不同的文件)。

对于文件版本,我想我会使用来自我的主站点的简单 DownloadString,它可能包含类似 program:6.0,map:2.3 的内容,所以最新的程序版本是 6.0,mapFolder 是 2.3。然后我可以使用 FileVersionInfo.GetVersionInfo 获取当前 program 的版本(如果有)并将文件 "version" 包含到 mapFolder 中以读取当前版本。

问题是我不知道如何使用 WebClient 下载整个文件夹,也不知道什么是完成我想做的事情的最佳方式。我尝试将 mapFolder 下载为 zip,然后自动解压,但启动器需要在 .net 3.0.

中编码

这是我目前的代码,这只是一个原型,用于熟悉整个情况,不要基于它。 `

   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();
    }`

我通过在 Web 服务器上启用 autoindex 并在以 .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) { }
}