Skip to content

Instantly share code, notes, and snippets.

@meitinger
Last active April 1, 2016 21:38
Show Gist options
  • Save meitinger/dc5e52f3973c4bd3ec8a to your computer and use it in GitHub Desktop.
Save meitinger/dc5e52f3973c4bd3ec8a to your computer and use it in GitHub Desktop.
Utility that downloads all approved Windows 7 updates from WSUS that can be used with DISM.
/* Copyright (C) 2015, Manuel Meitinger
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime.InteropServices;
using Microsoft.UpdateServices.Administration;
[assembly: AssemblyTitle("Updates Downloader")]
[assembly: AssemblyDescription("Utility that downloads all approved Windows 7 updates from WSUS that can be used with DISM.")]
[assembly: AssemblyCompany("AufBauWerk - Unternehmen für junge Menschen")]
[assembly: AssemblyCopyright("Copyright © 2015 by Manuel Meitinger")]
[assembly: AssemblyVersion("1.2.0.3")]
[assembly: ComVisible(false)]
namespace Aufbauwerk.Tools.UpdatesDownloader
{
static class Program
{
public static bool IsSupported(this StringCollection languages, string language)
{
return language.Contains(UpdateLanguage.All) || language.Contains(language);
}
static readonly Guid Category = new Guid("bfe5b177-a086-47a0-b102-097e4fa1f807"); // Windows 7
static readonly HashSet<string> Extensions = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { ".cab", ".msu" }; // supported by DISM
static int Main(string[] args)
{
try
{
// check the args
if (args.Length != 3)
{
Console.Error.WriteLine(string.Format("USAGE: {0} <language> <targetgroup> <targetdir>", Environment.GetCommandLineArgs()[0]));
return -1;
}
// make sure the targetdir exists
var targetdir = Path.GetFullPath(args[2]);
Directory.CreateDirectory(targetdir);
// connect to the server
Console.Write("connect to server... ");
var server = AdminProxy.GetUpdateServer();
var subscriptions = server.GetSubscription();
Console.WriteLine(server.Name);
// get the category and classifications
Console.Write("check the language... ");
var language = server.GetConfiguration().GetEnabledUpdateLanguages().Cast<string>().Single(s => string.Equals(s, args[0], StringComparison.OrdinalIgnoreCase));
Console.WriteLine(language);
Console.Write("check the target group... ");
var targetGroup = server.GetComputerTargetGroups().Cast<IComputerTargetGroup>().Single(g => string.Equals(g.Name, args[1], StringComparison.OrdinalIgnoreCase));
Console.WriteLine(targetGroup.Name);
Console.Write("get the category... ");
var category = subscriptions.GetUpdateCategories().Cast<IUpdateCategory>().Single(c => c.Id == Category);
Console.WriteLine(category.Title);
// get all matching approved updates and files
Console.Write("get the updates... ");
var updateScope = new UpdateScope()
{
ApprovedStates = ApprovedStates.LatestRevisionApproved | ApprovedStates.HasStaleUpdateApprovals,
UpdateApprovalActions = UpdateApprovalActions.Install,
UpdateApprovalScope = new UpdateApprovalScope(),
UpdateSources = UpdateSources.MicrosoftUpdate,
UpdateTypes = UpdateTypes.SoftwareUpdate,
};
updateScope.Categories.Add(category);
updateScope.UpdateApprovalScope.ComputerTargetGroups.Add(targetGroup);
var updates = server.GetUpdates(updateScope).Cast<IUpdate>().ToArray();
Console.WriteLine(updates.Length);
Console.Write("copy the files... ");
using (var client = new WebClient() { UseDefaultCredentials = true })
{
var fileNo = 0;
foreach (var file in updates.OrderBy(u => u.CreationDate).SelectMany(u => u.GetInstallableItems().Where(i => i.Languages.IsSupported(language))).SelectMany(i => i.Files.Where(f => f.Type == FileType.SelfContained)))
{
// print the status and try to get the architecture and feature
Console.Write("\b\b\b\b\b\b{0,-6}", ++fileNo);
var ext = Path.GetExtension(file.Name);
var parts = Path.GetFileNameWithoutExtension(file.Name).Split('-');
var path = Extensions.Contains(ext) && parts.Length >= 3 ?
string.Format(@"{0}\{1:D6}-{2}{3}", Path.Combine(Path.Combine(targetdir, parts[parts.Length - 1]), parts[0]), fileNo, string.Join("-", parts.Skip(1).Take(parts.Length - 2).ToArray()), ext) :
string.Format(@"{0}\{1:D6}-{2}", Path.Combine(targetdir, "[other]"), fileNo, file.Name);
// download to path
Directory.CreateDirectory(Path.GetDirectoryName(path));
client.DownloadFile(file.FileUri, path);
File.SetLastWriteTime(path, file.Modified);
}
}
// done
Console.WriteLine();
Console.WriteLine("finished");
return 0;
}
catch (Exception e)
{
Console.Error.WriteLine(e);
return -1;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment