Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,7 @@ FodyWeavers.xml.bak
*.exe
*.pdb
*.dll
!EasyExtractUnitypackageRework/EasyExtractCrossPlatform/ThirdParty/EverythingSdk/Everything64.dll
*.dylib

# Other
Expand All @@ -832,4 +833,4 @@ FodyWeavers.xml.bak
*.psess
*.vsp
*.vspx
*.sap
*.sap
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ public async Task EnsureDllForTestsAsync_ReusesValidExistingDllWithoutRewrite()
EverythingSdkBootstrapper.ConfigureForTests(
appDataPathOverride: () => appDataPath,
validateDllHashOverride: (path, _) =>
string.Equals(Path.GetFullPath(path), Path.GetFullPath(dllPath), StringComparison.OrdinalIgnoreCase));
string.Equals(Path.GetFullPath(path), Path.GetFullPath(dllPath), StringComparison.OrdinalIgnoreCase),
localProbeDirectoriesOverride: () => new[] { sdkDirectory });

var resolvedPath = await EverythingSdkBootstrapper.EnsureDllForTestsAsync();
var currentWriteTime = File.GetLastWriteTimeUtc(dllPath);
Expand All @@ -132,7 +133,7 @@ public async Task EnsureDllForTestsAsync_ReusesValidExistingDllWithoutRewrite()
}

[Fact]
public async Task EnsureDllForTestsAsync_SerializesConcurrentReuseWhileValidationRetries()
public async Task EnsureDllForTestsAsync_SerializesConcurrentBundledDllResolution()
{
if (!OperatingSystem.IsWindows())
return;
Expand Down Expand Up @@ -160,11 +161,10 @@ public async Task EnsureDllForTestsAsync_SerializesConcurrentReuseWhileValidatio
StringComparison.OrdinalIgnoreCase))
return true;

if (Interlocked.Increment(ref validationAttempts) == 1)
throw new SharingViolationIOException();

Interlocked.Increment(ref validationAttempts);
return true;
});
},
localProbeDirectoriesOverride: () => new[] { sdkDirectory });

var callers = Enumerable.Range(0, 4)
.Select(_ => EverythingSdkBootstrapper.EnsureDllForTestsAsync())
Expand All @@ -173,13 +173,13 @@ public async Task EnsureDllForTestsAsync_SerializesConcurrentReuseWhileValidatio
var resolvedPaths = await Task.WhenAll(callers);

Assert.All(resolvedPaths, path => Assert.Equal(dllPath, path, true));
Assert.True(validationAttempts >= 2);
Assert.Equal(1, validationAttempts);

Directory.Delete(root, true);
}

[Fact]
public async Task EnsureDllForTestsAsync_CleansOrphanedTemporaryDlls()
public async Task EnsureDllForTestsAsync_LeavesUnrelatedTemporaryFilesUntouched()
{
if (!OperatingSystem.IsWindows())
return;
Expand Down Expand Up @@ -214,12 +214,13 @@ public async Task EnsureDllForTestsAsync_CleansOrphanedTemporaryDlls()

return string.Equals(Path.GetFullPath(path), Path.GetFullPath(dllPath),
StringComparison.OrdinalIgnoreCase);
});
},
localProbeDirectoriesOverride: () => new[] { sdkDirectory });

var resolvedPath = await EverythingSdkBootstrapper.EnsureDllForTestsAsync();

Assert.Equal(dllPath, resolvedPath, true);
Assert.False(File.Exists(orphanedTempPath));
Assert.True(File.Exists(orphanedTempPath));

Directory.Delete(root, true);
}
Expand Down Expand Up @@ -291,6 +292,18 @@ public void IsTransientDownloadFailure_TruncatedHttpResponse_IsRetryable()
Assert.True(EverythingSdkBootstrapper.IsTransientDownloadFailure(exception));
}

[Fact]
public async Task EnsureDllForTestsAsync_MissingBundledDll_DoesNotDownload()
{
if (!OperatingSystem.IsWindows())
return;

EverythingSdkBootstrapper.ResetForTests();
EverythingSdkBootstrapper.ConfigureForTests(localProbeDirectoriesOverride: Array.Empty<string>);

await Assert.ThrowsAsync<FileNotFoundException>(() => EverythingSdkBootstrapper.EnsureDllForTestsAsync());
}

[Fact]
public async Task EnsureDllForTestsAsync_FallsBackToDllNextToTheExecutable()
{
Expand Down Expand Up @@ -368,4 +381,4 @@ public SharingViolationIOException() : base("Simulated sharing violation")
HResult = SharingViolationHResult;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@
<ItemGroup>
<AvaloniaResource Include="Assets\**" />
</ItemGroup>
<ItemGroup>
<None Remove="ThirdParty\EverythingSdk\Everything64.dll" />
<Content Include="ThirdParty\EverythingSdk\Everything64.dll">
<TargetPath>Everything64.dll</TargetPath>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\EasyExtract.Core\EasyExtract.Core.csproj" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ internal static class EverythingSdkBootstrapper
private static readonly TimeSpan DllPromotionInitialDelay = TimeSpan.FromMilliseconds(40);
private static readonly TimeSpan DownloadInitialRetryDelay = TimeSpan.FromMilliseconds(500);

// Legacy helpers and their tests remain below, but EnsureDllAsync no longer calls the network path.
private static readonly Uri SdkDownloadUri = new("https://www.voidtools.com/Everything-SDK.zip");
private static readonly HttpClient HttpClient = new();
private static readonly SemaphoreSlim DllInstallGate = new(1, 1);
Expand All @@ -24,7 +25,7 @@ internal static class EverythingSdkBootstrapper
private static readonly IReadOnlyDictionary<string, string> ExpectedDllHashes =
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
["Everything64.dll"] = "C7AB8B47F7DD4C41AA735F4BA40B35AD5460A86FA7ABE0C94383F12BCE33BFB6",
["Everything64.dll"] = "81B5BE18126ACD2C2B913F8F4A821E476B18393CDD3DEBD03387C50AFD8DB88F",
["Everything32.dll"] = "C28CD066AF36CAE4403A9933847AFF01DB928787D86751F014A1FA60D8B97FDA"
};

Expand Down Expand Up @@ -105,42 +106,17 @@ private static async Task<string> EnsureDllAsync()
return _everythingDllPath;
}

var appData = (_appDataPathOverride?.Invoke() ??
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)).Trim();
var sdkDirectory = Path.Combine(appData, "EasyExtract", "ThirdParty", "EverythingSdk");
Directory.CreateDirectory(sdkDirectory);

var dllPath = Path.Combine(sdkDirectory, TargetDllFileName);

await DllInstallGate.WaitAsync().ConfigureAwait(false);
try
{
CleanupOrphanedTemporaryDlls(sdkDirectory);

if (_everythingDllPath is { Length: > 0 } existingPath && File.Exists(existingPath))
{
LoggingService.LogInformation($"Everything SDK DLL already present at '{existingPath}'.");
return existingPath;
}

if (await TryReuseExistingDllAsync(dllPath).ConfigureAwait(false))
{
_everythingDllPath = dllPath;
return dllPath;
}

// The error messages tell users to drop the SDK DLL next to the executable, so honour
// that before going to the network. It is also the only way out on an offline machine.
if (TryUseLocallyShippedDll(out var localDllPath))
{
_everythingDllPath = localDllPath;
return localDllPath;
}

await DownloadDllWithRetryAsync(sdkDirectory, dllPath).ConfigureAwait(false);

_everythingDllPath = dllPath;
return dllPath;
throw new FileNotFoundException(
$"Bundled {TargetDllFileName} was not found next to the EasyExtract executable.");
}
finally
{
Expand Down Expand Up @@ -594,4 +570,4 @@ internal static bool ValidateDllHashForTests(string dllPath, bool deleteOnMismat
{
return ValidateDllHash(dllPath, deleteOnMismatch);
}
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Everything SDK runtime

`Everything64.dll` is bundled next to the Windows executable at build and publish time.
It is the x64 file from the Voidtools Everything SDK archive verified on 2026-08-22.

- SHA-256: `81B5BE18126ACD2C2B913F8F4A821E476B18393CDD3DEBD03387C50AFD8DB88F`
- Size: 91,304 bytes

The application validates this exact hash and does not download an SDK DLL at runtime.
Loading