Use C# to interact with Windows Update

2019-01-11 07:27发布

问题:

Is there any API for writing a C# program that could interface with Windows update, and use it to selectively install certain updates?

I'm thinking somewhere along the lines of storing a list in a central repository of approved updates. Then the client side applications (which would have to be installed once) would interface with Windows Update to determine what updates are available, then install the ones that are on the approved list. That way the updates are still applied automatically from a client-side perspective, but I can select which updates are being applied.

This is not my role in the company by the way, I was really just wondering if there is an API for windows update and how to use it.

回答1:

Add a Reference to WUApiLib to your C# project.

using WUApiLib;
protected override void OnLoad(EventArgs e){
    base.OnLoad(e);
    UpdateSession uSession = new UpdateSession();
    IUpdateSearcher uSearcher = uSession.CreateUpdateSearcher();
    uSearcher.Online = false;
    try {
        ISearchResult sResult = uSearcher.Search("IsInstalled=1 And IsHidden=0");
        textBox1.Text = "Found " + sResult.Updates.Count + " updates" + Environment.NewLine;
        foreach (IUpdate update in sResult.Updates) {
                textBox1.AppendText(update.Title + Environment.NewLine);
        }
    }
    catch (Exception ex) {
        Console.WriteLine("Something went wrong: " + ex.Message);
    }
}

Given you have a form with a TextBox this will give you a list of the currently installed updates. See http://msdn.microsoft.com/en-us/library/aa387102(VS.85).aspx for more documentation.

This will, however, not allow you to find KB hotfixes which are not distributed via Windows Update.



回答2:

The easiest way to do what you want is using WSUS. It's free and basically lets you setup your own local windows update server where you decide which updates are "approved" for your computers. Neither the WSUS server nor the clients need to be in a domain, though it makes it easier to configure the clients if they are. If you have different sets of machines that need different sets of updates approved, that's also supported.

Not only does this accomplish your stated goal, it saves your overall network bandwidth as well by only downloading the updates once from the WSUS server.



回答3:

If in your context you're allowed to use Windows Server Update Service (WSUS), it will give you access to the Microsoft.UpdateServices.Administration Namespace.

From there, you should be able to do some nice things :)



回答4:

I wrote some dummycode for this (a simple console application, that'll install all updates that we want based on commandline parameters, it can be found here and contains everything needed to perform updates)

https://bitbucket.org/LilleCarl/c-windowsupdate

What you need if you wanna do it yourself:

Add reference to C:\Windows\System32\wuapi.dll
using WUApiLib;

Useful interfaces:

UpdateSession
UpdateCollection
UpdateDownloader
IUpdateInstaller
IInstallationResult


回答5:

P-L right. I tried first the Christoph Grimmer-Die method, and in some case, it was not working. I guess it was due to different version of .net or OS architecture (32 or 64 bits). Then, to be sure that my program get always the Windows Update waiting list of each of my computer domain, I did the following :

  • Install a serveur with WSUS (may save some internet bandwith) : http://www.microsoft.com/en-us/download/details.aspx?displaylang=en&id=5216
  • Add all your workstations & servers to your WSUS server

  • Get SimpleImpersonation Lib to run this program with different admin right (optional)

  • Install only the administration console component on your dev workstation and run the following program :

It will print in the console all Windows updates with UpdateInstallationStates.Downloaded

using System;
using Microsoft.UpdateServices.Administration;
using SimpleImpersonation;

namespace MAJSRS_CalendarChecker
{
    class WSUS
    {
        public WSUS()
        {
            // I use impersonation to use other logon than mine. Remove the following "using" if not needed
            using (Impersonation.LogonUser("mydomain.local", "admin_account_wsus", "Password", LogonType.Batch))
            {
                ComputerTargetScope scope = new ComputerTargetScope();
                IUpdateServer server = AdminProxy.GetUpdateServer("wsus_server.mydomain.local", false, 80);
                ComputerTargetCollection targets = server.GetComputerTargets(scope);
                // Search
                targets = server.SearchComputerTargets("any_server_name_or_ip");

                // To get only on server FindTarget method
                IComputerTarget target = FindTarget(targets, "any_server_name_or_ip");
                Console.WriteLine(target.FullDomainName); 
                IUpdateSummary summary = target.GetUpdateInstallationSummary();
                UpdateScope _updateScope = new UpdateScope();
                // See in UpdateInstallationStates all other properties criteria
                _updateScope.IncludedInstallationStates = UpdateInstallationStates.Downloaded;
                UpdateInstallationInfoCollection updatesInfo = target.GetUpdateInstallationInfoPerUpdate(_updateScope);

                int updateCount = updatesInfo.Count;

                foreach (IUpdateInstallationInfo updateInfo in updatesInfo)
                {
                    Console.WriteLine(updateInfo.GetUpdate().Title);
                }
            }
        }
        public IComputerTarget FindTarget(ComputerTargetCollection coll, string computername)
        {
            foreach (IComputerTarget target in coll)
            {
                if (target.FullDomainName.Contains(computername.ToLower()))
                    return target;
            }
            return null;
        }
    }
}