Skip to main content

Allows a programmer to add simple update abilities to his/her stand alone applications. Basically you check tinyurl for updates to your program. When you want to update your program simply post up a link to tinyurl, the link is to your newer version (hosted anywhere), and change the alias to the alias you specified in the app, then add the "version". Example: My alias is 'asdflhedafAppa', and the current version out is 3. So to update, I upload the newest version to anywhere I can find, and post to tinyurl the download link, with an alias of 'asdflhedafAppa4'. NOTE: This has no hash check, and was meant for novelty, not production grade updates.

//
// This class was created to add an easy way to update stand alone executable It
// works by contacting the Tinyurl.com servers looking for a custom url of you
// choice, if the url exists, this program downloads it, checks the hash, then
// replaces this with it.
//
// You update by uploading the new exe somewhere (doesn't matter where), then
// adding that link to tinyurl.com with the custom url you specified here
//
// Thanks to VCSKicks.com for the download http article:
// http://www.vcskicks.com/download_file_http.php
//

class TinyUrlUpdate
{
    private string alias;

    /// <summary>
    /// Alias with version appended, what would be the real alias
    /// </summary>
    private string Ralias;

    private int Curversion;
    private string StartUpPath;

    private bool updateAvailableSet = false;
    private bool updateAvailable;

    /// <summary>
    /// Is there a new verison?
    /// </summary>
    public bool UpdateAvalibele
    {
        get
        {
            if (updateAvailableSet)
            {
                return updateAvailable;
            }

            updateAvailableSet = true;
            if (TinyUrlExists(Ralias))
            {
                updateAvailable = true;
                return true;
            }
            else
            {
                updateAvailable = false;
                return false;
            }
        }
    }

    //CONSTRUCTORS
    /// <summary>
    /// Allows you to update this program through TinyUrl
    /// </summary>
    /// <param name="alias">tinyurl alias to check if exists</param>
    /// <param name="Curversion">Current Version</param>
    public TinyUrlUpdate(string alias, int Curversion)
    {
        this.alias = alias;
        this.Ralias = alias + (Curversion + 1).ToString();
        this.Curversion = Curversion;

        //For Win Apps
        // Enviroment.Getpath Something like that
        //Use this line if your running from console
        this.StartUpPath = Process.GetCurrentProcess().MainModule.FileName;
    }

    /// <summary>
    /// Does the alias exist?
    /// </summary>
    /// <returns></returns>
    private bool TinyUrlExists(string alias)
    {
        try
        {
            var request = WebRequest.Create("http://tinyurl.com/" + alias);
            var res = request.GetResponse();
            string text;
            using(var reader = new StreamReader(res.GetResponseStream()))
            {
                text = reader.ReadToEnd();
            }
            if (text.IndexOf("<h1>Error: Unable to find site's URL to redirect to.</h1>") != -1)
            {
                // URL doesn't exist
                return false;
            }
            else
            {
                return true;
            }
        }
        catch (Exception)
        {
            return false;
        }
    }

    /// <summary>
    /// Delete old file, rename file with .new to the old filename
    /// </summary>
    private void DeleteSelf()
    {

        string bf = "@echo off" + Environment.NewLine +
                    ":dele" + Environment.NewLine +
                    "del \"" + StartUpPath + "\"" + Environment.NewLine +
                    "if Exist \"" + StartUpPath + "\" GOTO dele" + Environment.NewLine +
                    "move \"" + StartUpPath + ".new\" \"" + StartUpPath + "\"" + Environment.NewLine +
                    "del %0";

        string filename = Path.GetRandomFileName() + ".bat";

        StreamWriter file = new StreamWriter(Environment.GetEnvironmentVariable("TMP") + filename);
        file.Write(bf);
        file.Close();

        Process proc = new Process();
        proc.StartInfo.FileName = Environment.GetEnvironmentVariable("TMP") + filename;
        proc.StartInfo.CreateNoWindow = true;
        proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        proc.StartInfo.UseShellExecute = true;

        proc.Start();
        proc.PriorityClass = ProcessPriorityClass.Normal;
    }

    /// <summary>
    /// Download file from url, then return as byte array
    /// </summary>
    /// <param name="url">Url to file to download</param>
    /// <returns>File in byte array</returns>
    private byte[] downloadData(string url)
    {
        try
        {
            //Get a data stream from the url
            WebRequest req = WebRequest.Create(url);
            WebResponse response = req.GetResponse();
            Stream stream = response.GetResponseStream();

            //Download in chuncks
            byte[] buffer = new byte[1024];

            //Get Total Size
            int dataLength = (int)response.ContentLength;

            //Download to memory
            //Note: adjust the streams here to download directly to the hard drive
            MemoryStream memStream = new MemoryStream();
            while (true)
            {
                //Try to read the data
                int bytesRead = stream.Read(buffer, 0, buffer.Length);

                if (bytesRead == 0)
                {
                    break;
                }
                else
                {
                    //Write the downloaded data
                    memStream.Write(buffer, 0, bytesRead);
                }
            }
            //Clean up
            stream.Close();
            memStream.Close();

            //Convert the downloaded stream to a byte array
            return memStream.ToArray();
        }
        catch (Exception)
        {
            //May not be connected to the internet
            //Or the URL might not exist
            Console.WriteLine("There was an error accessing the URL.");
            return null;
        }
    }

    public void UpdateNow()
    {
        if (!UpdateAvalibele)
        {
            return;
        }
        //Download the new EXE
        byte[] EXE = downloadData("http://tinyurl.com/" + Ralias);
        if (EXE == null)
        {
            return;
        }

        FileStream newFile = new FileStream(StartUpPath + ".new", FileMode.Create);
        newFile.Write(EXE, 0, EXE.Length);
        newFile.Close();
        DeleteSelf();
    }

}


// USAGE
TinyUrlUpdate update = new TinyUrlUpdate("adfl43lkhasdf", 1);
update.UpdateNow();