Skip to content

Commit

Permalink
Correct installers get picked (#46)
Browse files Browse the repository at this point in the history
- Get neutral installer fixed #35
- guess installer filename Fixed #44
  • Loading branch information
svrooij authored Apr 9, 2024
1 parent e59d3fb commit 5223c56
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 24 deletions.
6 changes: 3 additions & 3 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/src/WingetIntune.Cli/bin/Debug/net8.0/WingetIntune.Cli.dll",
"args": [
"update",
"list",
"--username", "[email protected]"
"package",
"Microsoft.SQLServerManagementStudio",
"--package-folder", "C:\\tools\\packages"
],
"cwd": "${workspaceFolder}",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
Expand Down
8 changes: 5 additions & 3 deletions src/WingetIntune/Implementations/DefaultFileManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,14 @@ public async Task DownloadFileAsync(string url, string path, string? expectedHas
}
result.EnsureSuccessStatusCode();

if (result.Content.Headers.ContentLength > 100 * 1024 * 1024)
bool largeFile = result.Content.Headers.ContentLength > 50 * 1024 * 1024;

if (largeFile)
{
logger.LogWarning("Downloading large file {url} to {path} with size {size}", url, path, result.Content.Headers.ContentLength);
logger.LogWarning("Downloading large file {url} to {path} with size {size}MB", url, path, (result.Content.Headers.ContentLength / 1024 / 1024));
}

using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true))
using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: largeFile ? 81920 : 4096, useAsync: true))
{
await result.Content.CopyToAsync(fileStream, cancellationToken);
await fileStream.FlushAsync(cancellationToken);
Expand Down
47 changes: 40 additions & 7 deletions src/WingetIntune/Intune/IntuneManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,8 @@ private void LoadMsiDetails(string installerPath, ref PackageInfo packageInfo)
private void ComputeInstallerDetails(ref PackageInfo package, PackageOptions packageOptions)
{
var installer = package.GetBestFit(packageOptions.Architecture, packageOptions.InstallerContext)
?? package.GetBestFit(Architecture.Neutral, InstallerContext.Unknown)
?? package.GetBestFit(Architecture.Neutral, packageOptions.InstallerContext)
?? package.GetBestFit(packageOptions.Architecture, InstallerContext.Unknown);
if (installer == null && packageOptions.Architecture == Architecture.X64)
{
Expand All @@ -488,8 +490,14 @@ private void ComputeInstallerDetails(ref PackageInfo package, PackageOptions pac

package.InstallerUrl = new Uri(installer.InstallerUrl!);
package.InstallerFilename = Path.GetFileName(package.InstallerUrl.LocalPath.Replace(" ", ""));

if (string.IsNullOrEmpty(package.InstallerFilename))
{
package.InstallerFilename = $"{package.PackageIdentifier}_{package.Version}.{GuessInstallerExtension(installer.ParseInstallerType())}";
}

// Maybe this should be done for other installers as well?
if (installer.InstallerType!.Equals("exe", StringComparison.OrdinalIgnoreCase) && package.InstallerFilename!.EndsWith(".exe", StringComparison.OrdinalIgnoreCase) == false)
if ((installer.InstallerType!.Equals("exe", StringComparison.OrdinalIgnoreCase) || installer.InstallerType!.Equals("burn", StringComparison.OrdinalIgnoreCase)) && package.InstallerFilename!.EndsWith(".exe", StringComparison.OrdinalIgnoreCase) == false)
{
package.InstallerFilename += ".exe";
}
Expand All @@ -498,19 +506,44 @@ private void ComputeInstallerDetails(ref PackageInfo package, PackageOptions pac
package.InstallerContext = installer.ParseInstallerContext() == InstallerContext.Unknown ? (package.InstallerContext ?? packageOptions.InstallerContext) : installer.ParseInstallerContext();
package.InstallerType = installer.ParseInstallerType();
package.Installer = installer;
if (package.InstallerType.IsMsi())
{
package.MsiVersion ??= installer.AppsAndFeaturesEntries?.FirstOrDefault()?.DisplayVersion;
package.MsiProductCode ??= installer.ProductCode;
}
else
if (!package.InstallerType.IsMsi())
{
ComputeInstallerCommands(ref package, packageOptions);
}

package.MsiVersion ??= installer.AppsAndFeaturesEntries?.FirstOrDefault()?.DisplayVersion;
package.MsiProductCode ??= installer.ProductCode ?? installer.AppsAndFeaturesEntries?.FirstOrDefault()?.ProductCode;

}

private static readonly InstallerType[] SupportedInstallers = new[] { InstallerType.Inno, InstallerType.Msi, InstallerType.Burn, InstallerType.Wix, InstallerType.Nullsoft, InstallerType.Exe };
private static string GuessInstallerName(InstallerType installerType) => installerType switch
{
InstallerType.Inno => "setup.exe",
InstallerType.Msi => "setup.msi",
InstallerType.Msix => "setup.msix",
InstallerType.Appx => "setup.appx",
InstallerType.Burn => "setup.exe",
InstallerType.Wix => "setup.msi",
InstallerType.Nullsoft => "setup.exe",
InstallerType.Exe => "setup.exe",
InstallerType.Zip => "setup.zip",
_ => throw new ArgumentException("Unknown installer type", nameof(installerType))
};

private static string GuessInstallerExtension(InstallerType installerType) => installerType switch
{
InstallerType.Inno => "exe",
InstallerType.Msi => "msi",
InstallerType.Msix => "msix",
InstallerType.Appx => "appx",
InstallerType.Burn => "exe",
InstallerType.Wix => "msi",
InstallerType.Nullsoft => "exe",
InstallerType.Exe => "exe",
InstallerType.Zip => "zip",
_ => throw new ArgumentException("Unknown installer type", nameof(installerType))
};
private static readonly Dictionary<InstallerType, string> DefaultInstallerSwitches = new()
{
{ InstallerType.Inno, "/VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-" },
Expand Down
2 changes: 2 additions & 0 deletions src/WingetIntune/Models/Enums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public enum Architecture
X86,
X64,
Arm64,
Neutral,
}

internal static class EnumParsers
Expand Down Expand Up @@ -85,6 +86,7 @@ public static Architecture ParseArchitecture(string? input)
"x86" => Architecture.X86,
"x64" => Architecture.X64,
"arm64" => Architecture.Arm64,
"neutral" => Architecture.Neutral,
_ => Architecture.Unknown,
};
}
Expand Down
11 changes: 10 additions & 1 deletion src/WingetIntune/Models/Manifest/WingetInstallerExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,21 @@ internal static class WingetInstallerExtensions
public static Winget.CommunityRepository.Models.WingetInstaller? SingleOrDefault(this IList<Winget.CommunityRepository.Models.WingetInstaller>? installers, InstallerType installerType, Architecture architecture, InstallerContext installerContext)
{
if (installers is null || !installers.Any()) { return null; }
return installers.singleOrDefault(installerType, architecture, installerContext, "en-US")
?? installers.singleOrDefault(installerType, architecture, installerContext);
}

private static Winget.CommunityRepository.Models.WingetInstaller? singleOrDefault(this IList<Winget.CommunityRepository.Models.WingetInstaller> installers, InstallerType installerType, Architecture architecture, InstallerContext installerContext, string? locale = null)
{
return installers.FirstOrDefault(i =>
(i.ParseInstallerType() == installerType || installerType == InstallerType.Unknown)
&& (i.InstallerArchitecture() == architecture || architecture == Architecture.Unknown)
&& (i.ParseInstallerContext() == installerContext || installerContext == InstallerContext.Unknown));
&& (i.ParseInstallerContext() == installerContext || installerContext == InstallerContext.Unknown)
&& (string.IsNullOrWhiteSpace(locale) || i.InstallerLocale == locale));
}



public static InstallerContext ParseInstallerContext(this Winget.CommunityRepository.Models.WingetInstaller installer)
{
return EnumParsers.ParseInstallerContext(installer.Scope);
Expand Down
22 changes: 13 additions & 9 deletions src/WingetIntune/Models/Mapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,18 @@ public Win32LobApp ToWin32LobApp(PackageInfo packageInfo)

app.ApplicableArchitectures = ToGraphArchitecture(packageInfo.Architecture);

if (packageInfo.InstallerType.IsMsi())
if (packageInfo.MsiProductCode is not null && packageInfo.MsiVersion is not null) // packageInfo.InstallerType.IsMsi()
{
app.MsiInformation = new Win32LobAppMsiInformation
if (packageInfo.InstallerType.IsMsi())
{
ProductCode = packageInfo.MsiProductCode!,
ProductVersion = packageInfo.MsiVersion!,
Publisher = packageInfo.Publisher,
ProductName = packageInfo.DisplayName
};
app.MsiInformation = new Win32LobAppMsiInformation
{
ProductCode = packageInfo.MsiProductCode,
ProductVersion = packageInfo.MsiVersion,
Publisher = packageInfo.Publisher,
ProductName = packageInfo.DisplayName
};
}

app.DetectionRules = new List<Win32LobAppDetection>
{
Expand All @@ -83,7 +86,7 @@ public Win32LobApp ToWin32LobApp(PackageInfo packageInfo)
app.Developer = packageInfo.Publisher;
app.FileName = Path.GetFileNameWithoutExtension(packageInfo.InstallerFilename) + ".intunewin";
app.SetupFilePath = packageInfo.InstallerFilename ?? "install.ps1";
app.Notes = $"Generated by {nameof(WingetIntune)} at {DateTimeOffset.UtcNow} [WingetIntune|{packageInfo.Source}|{packageInfo.PackageIdentifier}]";
app.Notes = $"Generated by {nameof(WingetIntune)} at {DateTimeOffset.UtcNow} [WinTuner|{packageInfo.Source}|{packageInfo.PackageIdentifier}]";
return app;
}

Expand All @@ -94,7 +97,8 @@ public Win32LobApp ToWin32LobApp(PackageInfo packageInfo)
Architecture.Arm64 => WindowsArchitecture.Arm64,
Architecture.X86 => WindowsArchitecture.X86 | WindowsArchitecture.X64,
Architecture.X64 => WindowsArchitecture.X64,
_ => WindowsArchitecture.Neutral
Architecture.Neutral => WindowsArchitecture.Neutral | WindowsArchitecture.X86 | WindowsArchitecture.X64 | WindowsArchitecture.Arm64,
_ => WindowsArchitecture.None
};

public WinGetApp ToWinGetApp(MicrosoftStoreManifest storeManifest)
Expand Down
2 changes: 1 addition & 1 deletion src/WingetIntune/WingetServiceCollectionExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public static IServiceCollection AddWingetServices(this IServiceCollection servi
client.Timeout = TimeSpan.FromSeconds(180);
// Set buffer size to 500MB
// TODO: fix this in some other way, by not loading the whole file into memory.
//client.MaxResponseContentBufferSize = 1024L * 1024 * 512;
client.MaxResponseContentBufferSize = 1024L * 1024 * 50;
});
});
services.AddTransient<IFileManager, Os.DefaultFileManager>();
Expand Down

0 comments on commit 5223c56

Please sign in to comment.