Cracking the Windows Update API

Something that I’ve been working on for a while is an application or script that checks the availability of other servers to decide if it should start the update/restart steps. Though testing and more testing, I’ve found that even with the awesome power of Powershell, I still needed the power of a binary to get the best performance and least complexity.

However, unlike with Powershell where you can just set a variable, you gotta put more effort with C# to do something similar, especially when there’s so little documentation and I know so little about nitty gritty COM programming.

So getting the WUApi working in C# things to know.

  1. You need to reference “c:\windows\system32\wuapi.dll”
  2. You must have have the resulting “Interop.WUApi.DLL” in the same directory as you executable. (I haven’t figured out a way past this yet.)
  3. WUApi likes to die and quickly if there is the slightest error, and under C# these errors seem to be harder to pick up on.
  4. Some updates don’t like to report back how far they are in their process. IE8 for example sits at 0% until its done, so you just have to wait and wait some more.

The following code you can pretty much copy and paste into a cs file add the necessary hooks into the blank C# project, compile and it should work. It’s very Alpha and there is little error checking since I haven’t taken the time to throw test cases its way. It should also work on any OS from XP to 7.

namespace winupdate_scheduler
{
    /// <remarks>Methods actual shutdown.</remarks>
    public class grunt
    {
        public void shutdown()
        {
            throw new System.NotImplementedException();
        }

        public void restart()
        {
            throw new System.NotImplementedException();
        }

        /// <summary>
        /// Initiate the update for great justice!
        /// </summary>
        public void update()
        {
            try
            {
                //Initate the session and begin the search!
                WUApiLib.UpdateSessionClass session = new WUApiLib.UpdateSessionClass();
                WUApiLib.IUpdateSearcher searcher = session.CreateUpdateSearcher();
                WUApiLib.ISearchResult result = searcher.Search("IsInstalled=0 and IsAssigned=1");

                //Initate the interfaces for progress and wholeness.
                InstallProgress progress = new InstallProgress();
                InstallComplete completion = new InstallComplete();

                //Dummy object for installer.BeginInstall
                object t3 = (new object());

                //Do we have anything to do?
                if (result.Updates.Count > 0)
                {
                    //Begin the long wait.
                    //Probably should look into doing that async thing here too....later.
                    Console.WriteLine("Downloading...");
                    WUApiLib.IUpdateDownloader download = session.CreateUpdateDownloader();
                    download.Updates = result.Updates;
                    download.Download();

                    //Finally, get around to installing the suckers!
                    Console.WriteLine("Installing...");
                    WUApiLib.IUpdateInstaller installer = session.CreateUpdateInstaller();
                    installer.Updates = download.Updates;
                    installer.BeginInstall(progress, completion, t3);

                    //Hold your horses! We're not done yet!
                    while (!completion.jobdone)
                    {
                        System.Threading.Thread.Sleep(2000);
                    }
                }

                //Now you can let go of your horses!
                Console.WriteLine("Done");
            }
                //Until I can get a grasp of all the exceptions that can be raised, this will have to do.
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }

        /// <summary>
        /// Get list of updates
        /// </summary>
        public void getupdates()
        {
            throw new System.NotImplementedException();
            WUApiLib.UpdateSessionClass session = new WUApiLib.UpdateSessionClass();
            WUApiLib.IUpdateSearcher searcher = session.CreateUpdateSearcher();
            WUApiLib.ISearchResult result = searcher.Search("IsInstalled=0 and IsAssigned=1");
        }
    }

    class InstallProgress : WUApiLib.IInstallationProgressChangedCallback
    {

        public void Invoke(WUApiLib.IInstallationJob job, WUApiLib.IInstallationProgressChangedCallbackArgs args)
        {
            this.job = job;
            this.OverallProgress = this.job.GetProgress().PercentComplete;
            this.UpdateProgress = this.job.GetProgress().CurrentUpdatePercentComplete;
            this.UpdateIndex = this.job.GetProgress().CurrentUpdateIndex;

            this.Update = this.job.Updates[this.UpdateIndex];

            string str = "Update: {0}, UpdateProgress: {1}%, Progress {2}%";
            Console.WriteLine(string.Format(str, (this.UpdateIndex + 1), this.UpdateProgress, this.OverallProgress));
        }

        public WUApiLib.IInstallationJob job;

        public int OverallProgress = 0;
        public int UpdateProgress = 0;
        public int UpdateIndex = 0;
        public WUApiLib.IUpdate Update;

    }

    class InstallComplete : WUApiLib.IInstallationCompletedCallback
    {
        public void Invoke(WUApiLib.IInstallationJob job, WUApiLib.IInstallationCompletedCallbackArgs args)
        {
            //string str = "job.IsCompleted: {0}, args.Progress: {1}% completed";
            //Console.WriteLine(string.Format(str, job.IsCompleted, job.GetProgress().PercentComplete));
            this.jobdone = job.IsCompleted;
        }
        public bool jobdone = false;
    }
}

More reading:

You can leave a response, or trackback from your own site.

2 Responses to “Cracking the Windows Update API”

  1. Ajay Singh Azad says:

    How to use this calss?
    Also, throw new System.NotImplementedException(); in getupdates() function making other code unreachable.

  2. josh says:

    Delete the line that throws the NotImplementedException?

    The code is alpha and does require a read through to understand what is going on.

Leave a Reply