Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
.Net8 downloading speed is too slow
#5
LINQPad's .NET downloader always manages to detect the latest version and downloads quickly. I'm not sure how it's implemented.

I found the source code of the downloader using ILSpy.
 
Code:
Copy      Help
// NetCoreDownloader.MainWindow
using System;
using System.CodeDom.Compiler;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Markup;
using NetCoreDownloader;

public class MainWindow : Window, IComponentConnector
{
    private bool _isBeta;

    private bool _is32Bit;

    private bool _isArm64;

    private string _x64Uri;

    private string _x86Uri;

    private CancellationTokenSource _cancelSource;

    internal TextBlock x64Text;

    internal TextBox txtX64Version;

    internal TextBox txtX86Version;

    internal TextBox txtX64Status;

    internal TextBox txtX86Status;

    internal TextBox txtDownloadSource;

    internal Grid grdDownloadButtons;

    internal Button btnDownloadX64;

    internal Button btnDownloadX86;

    internal GroupBox grpProgress;

    internal TextBlock lblAction;

    internal Button btnCancel;

    internal ProgressBar progressBar;

    internal TextBlock txtProgress;

    internal GroupBox grpLaunch;

    internal Button btnLaunchLINQPadX64;

    internal Button btnLaunchLINQPadX86;

    private bool _contentLoaded;

    public MainWindow()
    {
        _isBeta = File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "BetaUpdateStream"));
        _is32Bit = FxChecker.IsX86;
        _isArm64 = FxChecker.IsArm64;
        InitializeComponent();
        base.Title = base.Title + " (LINQPad 8.0.18" + (_isBeta ? ", beta update stream" : "") + ")";
        if (_isArm64)
        {
            x64Text.Text = "ARM64 (64-bit)";
            btnDownloadX64.Content = "Download Runtime - ARM64";
            btnLaunchLINQPadX64.Content = "Launch LINQPad (ARM64)";
        }
        grpProgress.Visibility = Visibility.Hidden;
        if (_is32Bit)
        {
            foreach (UIElement child in grdDownloadButtons.Children)
            {
                if (child is TextBlock || child is Label)
                {
                    child.Visibility = Visibility.Collapsed;
                }
            }
        }
        PopulateDownloadSource();
        PopulateStatus();
    }

    private string GetLINQPadPath(bool x86, bool cmd)
    {
        string text = (cmd ? "LPRun8" : "LINQPad8");
        string text2 = ((x86 || _is32Bit) ? "x86" : (_isArm64 ? "arm64" : "x64"));
        string text3 = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, text + "-" + text2 + ".exe");
        if (File.Exists(text3))
        {
            return text3;
        }
        text3 = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, text + ".exe");
        if (File.Exists(text3) && GetArchitectureFromExe(text3) == text2)
        {
            return text3;
        }
        return "executable";
    }

    public static string GetArchitectureFromExe(string path)
    {
        byte[] array = new byte[4096];
        using (FileStream fileStream = File.OpenRead(path))
        {
            if (fileStream.Length < 4096)
            {
                return null;
            }
            fileStream.Read(array, 0, 4096);
        }
        int num = BitConverter.ToInt32(array, 60);
        if (num < 0 || num + 4 > 4090)
        {
            return null;
        }
        return BitConverter.ToUInt16(array, num + 4) switch
        {
            332 => "x86",
            43620 => "arm64",
            34404 => "x64",
            _ => null,
        };
    }

    private async void PopulateStatus()
    {
        while (true)
        {
            string text3 = (txtX64Version.Text = (txtX86Version.Text = "?"));
            SemanticVersion semanticVersion;
            SemanticVersion semanticVersion2;
            try
            {
                semanticVersion = FxChecker.FindHighestValidVersion(for64bit: true);
                semanticVersion2 = FxChecker.FindHighestValidVersion(for64bit: false);
            }
            catch
            {
                break;
            }
            txtX64Version.Text = ((semanticVersion != null) ? ("Version " + semanticVersion?.ToString() + " installed") : "Not installed");
            txtX86Version.Text = ((semanticVersion2 != null) ? ("Version " + semanticVersion2?.ToString() + " installed") : "Not installed");
            PopulateStatusBox(txtX64Status, semanticVersion);
            PopulateStatusBox(txtX86Status, semanticVersion2);
            btnLaunchLINQPadX64.IsEnabled = FxChecker.MinVersion.CompareTo(semanticVersion) <= 0 && !_is32Bit;
            btnLaunchLINQPadX86.IsEnabled = FxChecker.MinVersion.CompareTo(semanticVersion2) <= 0;
            await Task.Delay(1000);
        }
    }

    private void PopulateStatusBox(TextBox box, SemanticVersion version)
    {
        if (version == null)
        {
            box.Text = "";
            return;
        }
        try
        {
            if (version.CompareTo(FxChecker.MinVersion) < 0)
            {
                box.Text = "Update required";
            }
            else if (version.CompareTo(FxChecker.MinRecommendedVersion) < 0)
            {
                box.Text = "Newer version available";
            }
            else
            {
                box.Text = "You're up to date!";
            }
        }
        catch
        {
        }
    }

    private async void PopulateDownloadSource()
    {
        Task<byte[]> task = new TapWebClient().DownloadDataAsync("https://api.nuget.org/v3/index.json");
        task.ContinueWith((Task<byte[]> t) => t.Exception);
        bool flag = await Task.WhenAny(task, Task.Delay(8000)) == task && !task.IsFaulted;
        string text;
        try
        {
            text = await new TapWebClient().DownloadStringAsync("https://www.linqpad.net/FxDownloadSource.8.0." + (flag ? "desktop" : "sdk") + ".txt");
        }
        catch (Exception ex)
        {
            txtDownloadSource.Text = "Cannot contact server: " + ex.Message;
            return;
        }
        string[] array = (from s in text.Split(new string[1] { "\n" }, StringSplitOptions.RemoveEmptyEntries)
            select s.Trim()).ToArray();
        if (array.Length < 3)
        {
            txtDownloadSource.Text = "Invalid response from server.";
            return;
        }
        txtDownloadSource.Text = array[0];
        FxChecker.MinRecommendedVersion = SemanticVersion.TryParse(array[0]) ?? FxChecker.MinRecommendedVersion;
        _x64Uri = (FxChecker.IsArm64 ? array[3] : array[1]);
        _x86Uri = array[2];
        btnDownloadX64.IsEnabled = !_is32Bit;
        btnDownloadX86.IsEnabled = true;
        if (App.AutoDownload)
        {
            Download(_is32Bit ? _x86Uri : _x64Uri);
        }
    }

    private void DownloadX64(object sender, RoutedEventArgs e)
    {
        Download(_x64Uri);
    }

    private void DownloadX86(object sender, RoutedEventArgs e)
    {
        Download(_x86Uri);
    }

    private void BtnCancel_Click(object sender, RoutedEventArgs e)
    {
        _cancelSource.Cancel();
    }

    private async void LlRefresh_Click(object sender, RoutedEventArgs e)
    {
        TextBox textBox = txtX64Version;
        TextBox textBox2 = txtX86Version;
        TextBox textBox3 = txtX64Status;
        string text2 = (txtX86Status.Text = "");
        string text4 = (textBox3.Text = text2);
        string text7 = (textBox.Text = (textBox2.Text = text4));
        await Task.Delay(300);
        PopulateStatus();
    }

    private void BtnLaunchLINQPadX64_Click(object sender, RoutedEventArgs e)
    {
        LaunchLINQPad(x86: false);
    }

    private void BtnLaunchLINQPadX86_Click(object sender, RoutedEventArgs e)
    {
        LaunchLINQPad(x86: true);
    }

    private void Hyperlink_Click(object sender, RoutedEventArgs e)
    {
        MessageBox.Show("The X86 runtime lets you run LINQPad8-x86.exe, which launches LINQPad as a 32-bit process.\r\n\r\nThis is required when you need to reference 32-bit native DLLs.");
    }

    private void LaunchLINQPad(bool x86)
    {
        string lINQPadPath = GetLINQPadPath(x86, cmd: false);
        if (!File.Exists(lINQPadPath))
        {
            MessageBox.Show("Cannot locate " + lINQPadPath + ".");
            return;
        }
        string lINQPadPath2 = GetLINQPadPath(x86, cmd: true);
        if (!File.Exists(lINQPadPath2))
        {
            MessageBox.Show("Cannot locate " + lINQPadPath2 + ".");
            return;
        }
        using (Process process = Process.Start(new ProcessStartInfo(lINQPadPath2)
        {
            UseShellExecute = false,
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            CreateNoWindow = true
        }))
        {
            StringBuilder errors = new StringBuilder();
            process.ErrorDataReceived += delegate(object sender, DataReceivedEventArgs errorArgs)
            {
                errors.AppendLine(errorArgs.Data);
            };
            process.BeginErrorReadLine();
            int num = 0;
            while (process.StandardOutput.ReadLine() != null)
            {
                num++;
            }
            int exitCode = process.ExitCode;
            if (exitCode != 0 && exitCode != 1)
            {
                string text = "Unable to start LINQPad.";
                if (errors.Length > 0)
                {
                    text = text + "\r\n\r\n" + errors.ToString();
                }
                MessageBox.Show(text, "LINQPad", MessageBoxButton.OK, MessageBoxImage.Hand);
                return;
            }
        }
        Process.Start(new ProcessStartInfo(lINQPadPath)
        {
            UseShellExecute = true
        }).Dispose();
    }

    private async void Download(string uri)
    {
        Button button = btnDownloadX64;
        bool isEnabled = (btnDownloadX86.IsEnabled = false);
        button.IsEnabled = isEnabled;
        grpProgress.Visibility = Visibility.Visible;
        _cancelSource = new CancellationTokenSource();
        btnCancel.Visibility = Visibility.Visible;
        progressBar.IsEnabled = true;
        txtProgress.Text = "Connecting...";
        try
        {
            string filename = new Uri(uri).Segments.Last();
            lblAction.Text = "Downloading " + filename;
            string tempFile = Path.Combine(Path.GetTempPath(), filename);
            if (File.Exists(tempFile))
            {
                File.Delete(tempFile);
            }
            Progress<DownloadProgressChangedEventArgs> progress = new Progress<DownloadProgressChangedEventArgs>(delegate(DownloadProgressChangedEventArgs p)
            {
                progressBar.Value = p.ProgressPercentage;
                txtProgress.Text = p.BytesReceived / 1000000 + "MB of " + (p.TotalBytesToReceive / 1000000 + 1) + "MB";
            });
            await new TapWebClient().DownloadFileAsync(uri, tempFile, _cancelSource.Token, progress);
            txtProgress.Text = "Complete";
            progressBar.Value = 100.0;
            Process.Start(tempFile);
            lblAction.Text = "Running " + filename;
        }
        catch when (_cancelSource.IsCancellationRequested)
        {
            txtProgress.Text = "";
            progressBar.Value = 0.0;
            lblAction.Text = "Operation canceled by user.";
        }
        catch (Exception ex)
        {
            txtProgress.Text = "Error: downloading via web browser...";
            lblAction.Text = ex.Message;
            progressBar.Value = 0.0;
            await Task.Delay(2000);
            Process.Start(new ProcessStartInfo(uri)
            {
                UseShellExecute = true
            });
        }
        finally
        {
            btnDownloadX64.IsEnabled = !_is32Bit;
            btnDownloadX86.IsEnabled = true;
            btnCancel.Visibility = Visibility.Collapsed;
            progressBar.IsEnabled = false;
        }
    }

    [DebuggerNonUserCode]
    [GeneratedCode("PresentationBuildTasks", "4.0.0.0")]
    public void InitializeComponent()
    {
        if (!_contentLoaded)
        {
            _contentLoaded = true;
            Uri resourceLocator = new Uri("/Download .NET;component/mainwindow.xaml", UriKind.Relative);
            Application.LoadComponent(this, resourceLocator);
        }
    }

    [DebuggerNonUserCode]
    [GeneratedCode("PresentationBuildTasks", "4.0.0.0")]
    [EditorBrowsable(EditorBrowsableState.Never)]
    void IComponentConnector.Connect(int connectionId, object target)
    {
        switch (connectionId)
        {
        case 1:
            x64Text = (TextBlock)target;
            break;
        case 2:
            txtX64Version = (TextBox)target;
            break;
        case 3:
            txtX86Version = (TextBox)target;
            break;
        case 4:
            txtX64Status = (TextBox)target;
            break;
        case 5:
            txtX86Status = (TextBox)target;
            break;
        case 6:
            txtDownloadSource = (TextBox)target;
            break;
        case 7:
            grdDownloadButtons = (Grid)target;
            break;
        case 8:
            btnDownloadX64 = (Button)target;
            btnDownloadX64.Click += DownloadX64;
            break;
        case 9:
            btnDownloadX86 = (Button)target;
            btnDownloadX86.Click += DownloadX86;
            break;
        case 10:
            ((Hyperlink)target).Click += Hyperlink_Click;
            break;
        case 11:
            grpProgress = (GroupBox)target;
            break;
        case 12:
            lblAction = (TextBlock)target;
            break;
        case 13:
            btnCancel = (Button)target;
            btnCancel.Click += BtnCancel_Click;
            break;
        case 14:
            progressBar = (ProgressBar)target;
            break;
        case 15:
            txtProgress = (TextBlock)target;
            break;
        case 16:
            grpLaunch = (GroupBox)target;
            break;
        case 17:
            btnLaunchLINQPadX64 = (Button)target;
            btnLaunchLINQPadX64.Click += BtnLaunchLINQPadX64_Click;
            break;
        case 18:
            btnLaunchLINQPadX86 = (Button)target;
            btnLaunchLINQPadX86.Click += BtnLaunchLINQPadX86_Click;
            break;
        default:
            _contentLoaded = true;
            break;
        }
    }
}

Accessing Line https://api.nuget.org/v3/index.json will automatically switch to CDN Line  https://nuget.cdn.azure.cn/v3/index.json


Messages In This Thread
.Net8 downloading speed is too slow - by Davider - 03-12-2024, 11:10 PM
RE: .Net8 downloading speed is too slow - by Davider - 03-13-2024, 07:07 AM

Forum Jump:


Users browsing this thread: 16 Guest(s)