Skip to content

Instantly share code, notes, and snippets.

@mavaddat
Last active January 26, 2024 02:24
Show Gist options
  • Save mavaddat/67cae34abfd1388ace1d97582f0334f4 to your computer and use it in GitHub Desktop.
Save mavaddat/67cae34abfd1388ace1d97582f0334f4 to your computer and use it in GitHub Desktop.
PowerShell script and C# program to download and install latest SQLcl
$sqlclDownload = Invoke-RestMethod -Uri "https://www.oracle.com/database/sqldeveloper/technologies/sqlcl/download/"
$sqlclDownloadHash = ($sqlclDownload | Select-String -Pattern "SHA256: (?<sha256>[^<]+)" | Select-Object -ExpandProperty Matches).Groups['sha256'].Value
$sqlclDownloadUri = ($sqlclDownload | Select-String -Pattern "https:.*\.zip" | Select-Object -ExpandProperty Matches).Value
Invoke-WebRequest -Uri $sqlclDownloadUri -OutFile $env:TEMP\sqlcl.zip
if(Get-FileHash -Path $env:TEMP\sqlcl.zip | ForEach-Object { $_.Hash -ieq $sqlclDownloadHash }){
Expand-Archive -Path $env:TEMP\sqlcl.zip -DestinationPath $env:LOCALAPPDATA\Programs\ -Force
}
using System;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
// build using csc.exe -out:"$env:TEMP\DownloadSqlCl.exe" -reference:"C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.IO.Compression\v4.0_4.0.0.0__b77a5c561934e089\System.IO.Compression.dll" "$env:USERPROFILE\Downloads\sqlclUpdater.cs"; &"$env:TEMP\DownloadSqlCl.exe"
class Program
{
static readonly WebClient client = new WebClient();
static async Task Main(string[] args)
{
Uri downloadPageUrl = new("https://www.oracle.com/database/sqldeveloper/technologies/sqlcl/download/");
string tempPath = Path.GetTempPath();
string localAppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
string sqlclZipPath = Path.Combine(tempPath, "sqlcl.zip");
string destinationPath = Path.Combine(localAppDataPath, "Programs");
try
{
// Download the SQLcl download page
string sqlclDownloadPage = client.DownloadString(downloadPageUrl);
if (string.IsNullOrEmpty(sqlclDownloadPage))
{
Console.Error.WriteLine("SQLcl download page not found.");
Environment.Exit(-1);
return;
}
// Extract SHA256 hash
string sha256Pattern = @"SHA256: (?<sha256>[^<]+)";
string sqlclDownloadHash = Regex.Match(sqlclDownloadPage, sha256Pattern).Groups["sha256"].Value;
if (string.IsNullOrEmpty(sqlclDownloadHash))
{
Console.Error.WriteLine("SQLcl SHA256 hash not found.");
Environment.Exit(-2);
return;
}
// Extract download URI
string uriPattern = @"https:.*\.zip";
if (Regex.Match(sqlclDownloadPage, uriPattern) is not { Value: not null } sqlclDownloadUriMatch || !sqlclDownloadUriMatch.Success || new Uri(sqlclDownloadUriMatch.Value) is not { } sqlclDownloadUri)
{
Console.Error.WriteLine("SQLcl download URI not found.");
Environment.Exit(-3);
return;
}
// Download the SQLcl zip file
byte[] sqlclZipBytes = client.DownloadData(sqlclDownloadUri);
Console.WriteLine("Downloaded {0} bytes.", sqlclZipBytes.Length);
// Calculate the hash of the downloaded file and compare it with the extracted hash
using (var sha256 = SHA256.Create())
{
using (var stream = new MemoryStream(sqlclZipBytes, 0, sqlclZipBytes.Length))
{
var fileHash = sha256.ComputeHash(stream);
string fileHashString = BitConverter.ToString(fileHash).Replace("-", "").ToUpperInvariant();
if (fileHashString == sqlclDownloadHash.ToUpperInvariant())
{
// Extract the zip file contents
using (var zipFile = new ZipArchive(stream))
{
Console.WriteLine("Processing {0} entries.", zipFile.Entries.Count);
foreach (var entry in zipFile.Entries)
{
var destinationFilePath = Path.Combine(destinationPath, entry.FullName.Replace("/", "\\"));
if(entry.Length == 0){
// create the directory, if it doesn't already exist
Directory.CreateDirectory(Path.GetDirectoryName(destinationFilePath));
continue;
}
using (var entryStream = entry.Open())
{
Console.WriteLine("Extracting {0} to {1}", entry.FullName, destinationFilePath);
using (var destinationStream = File.Create(destinationFilePath))
{
entryStream.CopyTo(destinationStream);
}
}
}
}
Console.WriteLine("SQLcl has been successfully downloaded and extracted.");
}
else
{
Console.Error.WriteLine("The downloaded file's hash does not match the expected hash."); Environment.Exit(-5);
}
}
}
}
catch (Exception e)
{
Console.WriteLine($"An error occurred: {e.Message}");
if(e.InnerException is not null)
Console.WriteLine($"Inner exception: {e.InnerException.Message}");
Environment.Exit(-6);
}
await Task.CompletedTask;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment