0

I am trying to create an auto update for an application however I am having a bit of trouble with the updating part. Basically what I have is a windows service that periodically checks for updates and when it finds and update it launches a console application to update itself. The code for the console application is below.

The problem I'm having is that when I uninstall the service and replace the file that drives the service, I get a system.badimageformat exception. Despite reinstalling an identical file. If I uninstall and re-install the file without downloading it and replacing it from FTP there is no issue, but as soon as I change the file it starts giving me exceptions. Does anyone have any ideas on how I can work around this error. I am confident its not a 32 vs 64 bit issue which is what commonly causes this error.

    static void Main(string[] args)
    {
        if (!System.Diagnostics.EventLog.SourceExists("OCR Updater"))
        {
            EventLog.CreateEventSource("OCR Updater", "Application");
        }
        ServiceController sc = new ServiceController("OCR Scheduler", ".");
        if (sc.Status == ServiceControllerStatus.Running)
        {
            sc.Stop();
            sc.WaitForStatus(ServiceControllerStatus.Stopped);
        }

        ProcessStartInfo Uninstallpsi = new ProcessStartInfo();
        Uninstallpsi.Verb = "runas";
        Uninstallpsi.UseShellExecute = false;
        Uninstallpsi.FileName = AppDomain.CurrentDomain.BaseDirectory.ToString() + "installutil.exe";
        Uninstallpsi.Arguments = " /u " + "\"" + AppDomain.CurrentDomain.BaseDirectory.ToString() + "OCR_Scheduler_Service.exe\"";
        Process.Start(Uninstallpsi);

        Console.WriteLine("Sleeping Thread after uninstall");
        System.Threading.Thread.Sleep(10000);


        OCRUpdater program = new OCRUpdater();
        List<string> Files = program.GetFiles();
        foreach (string item in Files)
        {

            if (item.ToString() == "Sqlite" || item.ToString() == "License.xml")
            {
                continue;
            }
            // Get the object used to communicate with the server.
            FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://ftp.mccinnovations.com/OCR_Scheduler/V2Updates/Files/" + item);
            request.Method = WebRequestMethods.Ftp.DownloadFile;

            // This example assumes the FTP site uses anonymous logon.
            request.Credentials = new NetworkCredential("ftp admin", "_Stingray_12");

            FtpWebResponse response = (FtpWebResponse)request.GetResponse();

            Stream responseStream = response.GetResponseStream();
            StreamReader reader = new StreamReader(responseStream);
            string[] temp = reader.ReadToEnd().Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
            reader.Close();
            response.Close();
            string DesktopFile = "";


            try
            {
                DesktopFile = @"C:\Users\hnelson\Desktop\" + item;
                if (File.Exists(DesktopFile))
                {
                    File.Delete(DesktopFile);   
                }
                File.WriteAllLines(DesktopFile, temp);
            }
            catch (Exception ex)
            {

                EventLog.WriteEntry("OCR Updater", "Error in file path" + DesktopFile + ex.Message);
                continue;
            }
            try
            {
                File.Delete(@"C:\Program Files (x86)\MCCi\OCR Scheduler V2\" + item);
                System.Threading.Thread.Sleep(2000);
                File.Copy(DesktopFile, @"C:\Program Files (x86)\MCCi\OCR Scheduler V2\" + item, true);
                File.Delete(DesktopFile);
                EventLog.WriteEntry("OCR Updater", DesktopFile);
            }
            catch (Exception)
            {

                EventLog.WriteEntry("OCR Updater", DesktopFile);
                EventLog.WriteEntry("OCR Updater", "Error in file path " + @"C:\Program Files (x86)\MCCi\OCR Scheduler V2\" + item);
                continue;
            }


        }




        try
        {

            System.Threading.Thread.Sleep(5000);

            ProcessStartInfo psi = new ProcessStartInfo();
            psi.Verb = "runas";
            psi.UseShellExecute = false;
            psi.FileName = AppDomain.CurrentDomain.BaseDirectory.ToString() + "installutil.exe";
            psi.Arguments = " " + "\"" + AppDomain.CurrentDomain.BaseDirectory.ToString() + "OCR_Scheduler_Service.exe\"";
            Process.Start(psi);


        }
        catch (Exception ex)
        {

            EventLog.WriteEntry("OCR Updater", "Could not reinstall service" + ex.Message + ex.InnerException);
        }


        System.Threading.Thread.Sleep(10000);

        Console.WriteLine("Finished resinstalling the service.");


        try
        {



            string[] serviceStartArgs = { "true" };

            sc.Start(serviceStartArgs);
            sc.WaitForStatus(ServiceControllerStatus.Running);

        }
        catch (Exception ex)
        {

            EventLog.WriteEntry("OCR Updater", "Could not start the service after install" + " " + ex.Message + ex.InnerException);
        }

    }

    public List<string> GetFiles()
    {
        // Get the object used to communicate with the server.
        FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://ftp.mccinnovations.com/OCR_Scheduler/V2Updates/Files/");
        request.Method = WebRequestMethods.Ftp.ListDirectory;

        // This example assumes the FTP site uses anonymous logon.
        request.Credentials = new NetworkCredential("ftp admin", "_Stingray_12");

        FtpWebResponse response = (FtpWebResponse)request.GetResponse();

        Stream responseStream = response.GetResponseStream();
        StreamReader reader = new StreamReader(responseStream);
        List<string> Files = new List<string>();
        while (reader.EndOfStream == false)
        {
            Files.Add(reader.ReadLine());
        }

        reader.Close();
        response.Close();
        return Files;


    }


}

}

Hunter Nelson
  • 1,707
  • 3
  • 20
  • 37

1 Answers1

2

The main problem is that you treat the files as text files:

string[] temp = reader.ReadToEnd().Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
....
File.WriteAllLines(DesktopFile, temp);

You can use this instead:

Stream responseStream = response.GetResponseStream();

...

using (FileStream destStream = File.Create(DesktopFile))
{
    responseStream.CopyTo(destStream);
}

responseStream.Close();
response.Close();

However, this is still not the best solution, since you should use the pattern

using (X123 x123 = new X123(y))
{
    // do something with x123
}

for all classes which support IDisposable.

In addition, I have some concerns about using Sleep() in so many situations. This is seldom a good idea.

Rainer Schaack
  • 1,558
  • 13
  • 16
  • This was exactly the problem, I've spent literally days investingating windows server permissions, configuing visual studio projects and 2nd guessing every dll in my project. Thanks so much, something so simple too but I would have never seen it. Haven't been programming long enough to know the difference. – Hunter Nelson Feb 17 '15 at 18:30