Add standalone OCSentinel setup executable builder
Some checks failed
OfficeCom Sentinel Client / build-client (push) Has been cancelled

This commit is contained in:
OfficeCom Codex
2026-07-17 01:07:37 +02:00
parent 38a99f2706
commit fde24f2616
4 changed files with 149 additions and 0 deletions

1
.gitignore vendored
View File

@@ -10,6 +10,7 @@ payload/
*.log
*.zip
*.sha256
payload.zip
SetupAttackTracer.exe
decompiled/
msi-admin/

View File

@@ -0,0 +1,50 @@
param(
[string]$Configuration = "Release"
)
$ErrorActionPreference = "Stop"
$repoRoot = Split-Path -Parent $PSScriptRoot
$artifactsRoot = Join-Path $repoRoot "artifacts"
$zipPath = Join-Path $artifactsRoot "OCSentinelClient-win-x64.zip"
$bootstrapperRoot = Join-Path $repoRoot "installer\OCSentinelBootstrapper"
$payloadPath = Join-Path $bootstrapperRoot "payload.zip"
$projectPath = Join-Path $bootstrapperRoot "OCSentinelBootstrapper.csproj"
$publishRoot = Join-Path $artifactsRoot "bootstrapper-publish\win-x64"
$outputExe = Join-Path $artifactsRoot "OCSentinelSetup.exe"
if (-not (Test-Path $zipPath)) {
& powershell.exe -ExecutionPolicy Bypass -File (Join-Path $repoRoot "build\build-client-package.ps1") -Configuration $Configuration
if ($LASTEXITCODE -ne 0) {
throw "build-client-package.ps1 failed"
}
}
Copy-Item -Path $zipPath -Destination $payloadPath -Force
if (Test-Path $publishRoot) {
Remove-Item -LiteralPath $publishRoot -Recurse -Force
}
if (Test-Path $outputExe) {
Remove-Item -LiteralPath $outputExe -Force
}
New-Item -ItemType Directory -Force -Path $publishRoot | Out-Null
& dotnet publish $projectPath `
-c $Configuration `
-r win-x64 `
--self-contained true `
-p:PublishSingleFile=true `
-p:EnableCompressionInSingleFile=true `
-p:IncludeNativeLibrariesForSelfExtract=true `
-o $publishRoot
if ($LASTEXITCODE -ne 0) {
throw "dotnet publish failed for bootstrapper"
}
Copy-Item -Path (Join-Path $publishRoot "OCSentinelBootstrapper.exe") -Destination $outputExe -Force
Write-Host "OfficeCom Sentinel setup executable created at $outputExe"

View File

@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0-windows</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UseWindowsForms>false</UseWindowsForms>
<AssemblyName>OCSentinelBootstrapper</AssemblyName>
<RootNamespace>OCSentinelBootstrapper</RootNamespace>
<PublishSingleFile>true</PublishSingleFile>
<SelfContained>true</SelfContained>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="payload.zip" LogicalName="payload.zip" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,76 @@
using System.Diagnostics;
using System.IO.Compression;
using System.Reflection;
namespace OCSentinelBootstrapper;
internal static class Program
{
private static int Main()
{
string tempRoot = Path.Combine(Path.GetTempPath(), "OCSentinelSetup", Guid.NewGuid().ToString("N"));
string zipPath = Path.Combine(tempRoot, "payload.zip");
string extractRoot = Path.Combine(tempRoot, "payload");
try
{
Directory.CreateDirectory(tempRoot);
Directory.CreateDirectory(extractRoot);
ExtractEmbeddedPayload(zipPath);
ZipFile.ExtractToDirectory(zipPath, extractRoot, overwriteFiles: true);
string installScript = Path.Combine(extractRoot, "scripts", "install-ocsentinel.ps1");
if (!File.Exists(installScript))
{
throw new FileNotFoundException("Embedded payload did not contain install-ocsentinel.ps1", installScript);
}
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "powershell.exe",
Arguments = $"-ExecutionPolicy Bypass -File \"{installScript}\"",
UseShellExecute = false
}
};
process.Start();
process.WaitForExit();
return process.ExitCode;
}
catch (Exception ex)
{
Console.Error.WriteLine($"OCSentinel installer failed: {ex}");
return 1;
}
finally
{
try
{
if (Directory.Exists(tempRoot))
{
Directory.Delete(tempRoot, recursive: true);
}
}
catch
{
// Best-effort cleanup only.
}
}
}
private static void ExtractEmbeddedPayload(string destinationPath)
{
Assembly assembly = Assembly.GetExecutingAssembly();
using Stream? resourceStream = assembly.GetManifestResourceStream("payload.zip");
if (resourceStream is null)
{
throw new InvalidOperationException("Embedded payload.zip resource was not found.");
}
using FileStream output = File.Create(destinationPath);
resourceStream.CopyTo(output);
}
}