Last active
January 26, 2024 02:24
-
-
Save mavaddat/67cae34abfd1388ace1d97582f0334f4 to your computer and use it in GitHub Desktop.
PowerShell script and C# program to download and install latest SQLcl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$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 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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