Skip to content

Instantly share code, notes, and snippets.

@joncloud
Created November 22, 2019 04:33
Show Gist options
  • Save joncloud/29491b7b596c16a49a9d85a5bfb82c6d to your computer and use it in GitHub Desktop.
Save joncloud/29491b7b596c16a49a9d85a5bfb82c6d to your computer and use it in GitHub Desktop.
Sideload Install AppGet Packages
$AppGetCommand = Get-Command -ErrorAction Ignore appget.exe
If ($null -eq $AppGetCommand) {
Throw "AppGet is not installed. Install from https://appget.net/"
}
# PowerShell hack to load the exe as a dll
$DllPath = ($AppGetCommand.Path.Replace('.exe', '.dll'))
If (-not (Test-Path $DllPath)) {
Copy-Item $AppGetCommand.Path $DllPath
}
# Get all assemblies that are necessary to use in this process
$AssemblyPaths = @(
$DllPath,
(Join-Path (Split-Path $DllPath) 'DryIoc.dll'),
(Join-Path (Split-Path $DllPath) 'NLog.dll'),
(Join-Path (Split-Path $DllPath) 'Newtonsoft.Json.dll')
)
Add-Type -Path $AssemblyPaths
# Copied from source to change the base directory location for
# where DLLs are loaded from, and ignores .EXE, because of the
# hack to load the DLL in PowerShell
$CSharpCode = @"
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using AppGet.Commands;
using AppGet.Infrastructure.Eventing;
using AppGet.Infrastructure.Eventing.Events;
using AppGet.Installers.InstallerWhisperer;
using AppGet.Installers.UninstallerWhisperer;
using DryIoc;
using NLog;
public static class CustomContainerBuilder
{
public static Container Container { get; private set; }
public static readonly List<Type> AssemblyTypes;
static CustomContainerBuilder()
{
var baseDirectory = new FileInfo(new Uri(typeof(AppGet.AppGetConsole).Assembly.CodeBase).LocalPath).Directory.FullName;
var files = Directory.GetFiles(baseDirectory, "appget.*", SearchOption.TopDirectoryOnly).Where(c => c.EndsWith(".dll"));
var ass = files.Select(Assembly.LoadFile).ToList();
AssemblyTypes = ass.SelectMany(c => c.ExportedTypes
.Where(t => !t.IsAbstract && !t.IsInterface && !t.IsEnum && t.Namespace != null && t.Namespace.StartsWith("AppGet.")))
.ToList();
var rules = Rules.Default
.WithAutoConcreteTypeResolution()
.WithDefaultReuse(Reuse.Singleton)
.WithDefaultIfAlreadyRegistered(IfAlreadyRegistered.AppendNotKeyed);
var made = FactoryMethod.Constructor(mostResolvable: true);
Container = new Container(rules);
Container.RegisterMany(ass, ShouldRegisterAs, made: made);
RegisterLoggerFactory();
RegisterTransienttInstallers(made);
RegisterHandlers<ICommandHandler>();
//Container.Resolve<IHub>().Publish(new ApplicationStartedEvent());
}
private static void RegisterLoggerFactory()
{
Container.Register(Made.Of(() => LogManager.GetLogger(Arg.Index<string>(0)), request => request.Parent.ImplementationType.Name), Reuse.Transient);
}
private static void RegisterTransienttInstallers(FactoryMethodSelector made)
{
Container.Unregister<InstallerBase>();
Container.RegisterMany(AssemblyTypes.Where(c => c.ImplementsServiceType<InstallerBase>()), serviceTypeCondition: ShouldRegisterAs, made: made,
reuse: Reuse.Transient);
Container.Unregister<UninstallerBase>();
Container.RegisterMany(AssemblyTypes.Where(c => c.ImplementsServiceType<UninstallerBase>()), serviceTypeCondition: ShouldRegisterAs, made: made,
reuse: Reuse.Transient);
}
private static bool ShouldRegisterAs(Type type)
{
if (type.Namespace != null && !type.Namespace.StartsWith("AppGet.")) return false;
if (type.IsInterface) return true;
if (type.IsAbstract) return true;
return false;
}
private static void RegisterHandlers<THandler>()
{
Container.Unregister<THandler>();
var made = FactoryMethod.Constructor(mostResolvable: true);
foreach (var handler in AssemblyTypes.Where(c => c.ImplementsServiceType<THandler>()))
{
var handles = AppGet.Infrastructure.Composition.HandlesAttribute.GetValue(handler);
if (handles != null)
{
Container.Register(typeof(THandler),
handler,
made: made,
serviceKey: handles);
}
}
}
}
"@
Add-Type -ReferencedAssemblies $AssemblyPaths -TypeDefinition $CSharpCode -Language CSharp
#AppGet.Manifest.InstallMethodTypes{ MSI }
#AppGet.Manifest.ArchitectureTypes{ x86, x64 }
#AppGet.Manifest.InstallArgs{ Passive: string, Silent: string, Interactive: string, Log: string }
#AppGet.PackageRepository.PackageInfo{ ManifestPath: string, Selected: bool,
# Repo: string, License: string,
# InstallArgs: Args, Tag: string }
#AppGet.Installers.InstallInteractivityLevel{ Interactive, Passive, Silent }
# var installOptions = (InstallOptions)commandOptions;
# Sample from 7zip yaml
$Json = @{
Id = '7zip';
Name = '7-Zip';
Version = '19.00';
Home = 'https://www.7-zip.org/';
InstallMethod = 'MSI';
Installers = @(
@{
Location = 'https://www.7-zip.org/a/7z1900.msi';
Sha256 = 'b49d55a52bc0eab14947c8982c413d9be141c337da1368a24aa0484cbb5e89cd'
},
@{
Location = 'https://www.7-zip.org/a/7z1900-x64.msi';
Sha256 = 'a7803233eedb6a4b59b3024ccf9292a6fffb94507dc998aa67c5b745d197a5dc';
Architecture = 'x64';
}
)
} | ConvertTo-Json
$Package = [Newtonsoft.Json.JsonConvert]::DeserializeObject(
$Json,
[AppGet.PackageRepository.PackageInfo]
)
$InteractivityLevel = [AppGet.Installers.InstallInteractivityLevel]::Interactive
$Container = [CustomContainerBuilder]::Container
$Type = [AppGet.Installers.IInstallService]
$Installer = [DryIoc.Resolver]::Resolve($Container, $Type)
# Install away!
$Task = $Installer.Install($Package, $InteractivityLevel)
While (-not $Task.AsyncWaitHandle.WaitOne(200)) { }
$Task.GetAwaiter().GetResult() | Out-Null
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment