mirror of
https://github.com/tiennm99/time-mocker-csharp.git
synced 2026-06-05 22:13:22 +00:00
feat: add x86 support
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net48</TargetFramework>
|
||||
<Platforms>x64</Platforms>
|
||||
<Platforms>x64;x86</Platforms>
|
||||
<AssemblyName>TimeMocker.Hook</AssemblyName>
|
||||
<RootNamespace>TimeMocker.Hook</RootNamespace>
|
||||
<OutputType>Library</OutputType>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<PlatformTarget>$(Platform)</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="EasyHook" Version="2.7.7097.0"/>
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using EasyHook;
|
||||
|
||||
namespace TimeMocker.UI.Core
|
||||
@@ -20,8 +21,14 @@ namespace TimeMocker.UI.Core
|
||||
private readonly Dictionary<int, InjectedProcess> _injected
|
||||
= new Dictionary<int, InjectedProcess>();
|
||||
|
||||
private static readonly string HookDllPath =
|
||||
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TimeMocker.Hook.dll");
|
||||
private static readonly string HookDllPathX64 =
|
||||
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TimeMocker.Hook.x64.dll");
|
||||
|
||||
private static readonly string HookDllPathX86 =
|
||||
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TimeMocker.Hook.x86.dll");
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern bool IsWow64Process(IntPtr hProcess, out bool wow64Process);
|
||||
|
||||
public event Action<string> LogMessage;
|
||||
|
||||
@@ -46,16 +53,19 @@ namespace TimeMocker.UI.Core
|
||||
// Write initial delta (zero = real time) before hook starts reading
|
||||
entry.Shm.Write(new MockTimeInfo { DeltaTicks = 0 });
|
||||
|
||||
// Determine which DLL to use based on target process architecture
|
||||
string hookDllPath = GetHookDllPath(process);
|
||||
|
||||
RemoteHooking.Inject(
|
||||
process.Id,
|
||||
InjectionOptions.DoNotRequireStrongName,
|
||||
HookDllPath,
|
||||
HookDllPath,
|
||||
hookDllPath,
|
||||
hookDllPath,
|
||||
entry.Shm.MmfName);
|
||||
|
||||
entry.IsInjected = true;
|
||||
_injected[process.Id] = entry;
|
||||
Log($"Injected into [{process.Id}] {process.ProcessName}");
|
||||
Log($"Injected into [{process.Id}] {process.ProcessName} ({GetArchitectureName(process)})");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -67,6 +77,43 @@ namespace TimeMocker.UI.Core
|
||||
return entry;
|
||||
}
|
||||
|
||||
private static string GetHookDllPath(Process process)
|
||||
{
|
||||
bool is64BitTarget = Is64BitProcess(process);
|
||||
|
||||
if (is64BitTarget)
|
||||
{
|
||||
if (!File.Exists(HookDllPathX64))
|
||||
throw new FileNotFoundException($"x64 hook DLL not found: {HookDllPathX64}");
|
||||
return HookDllPathX64;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!File.Exists(HookDllPathX86))
|
||||
throw new FileNotFoundException($"x86 hook DLL not found: {HookDllPathX86}");
|
||||
return HookDllPathX86;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool Is64BitProcess(Process process)
|
||||
{
|
||||
if (!Environment.Is64BitOperatingSystem)
|
||||
return false;
|
||||
|
||||
bool isWow64;
|
||||
if (!IsWow64Process(process.Handle, out isWow64))
|
||||
return false;
|
||||
|
||||
// If IsWow64Process returns false, it's a 64-bit process
|
||||
// If it returns true, it's a 32-bit process running on 64-bit Windows
|
||||
return !isWow64;
|
||||
}
|
||||
|
||||
private static string GetArchitectureName(Process process)
|
||||
{
|
||||
return Is64BitProcess(process) ? "x64" : "x86";
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Update fake time for a process
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
@@ -363,6 +363,8 @@ namespace TimeMocker.UI.Forms
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Skip processes we can't access
|
||||
continue;
|
||||
}
|
||||
|
||||
_allRows.Add(new ProcessRow
|
||||
@@ -390,6 +392,8 @@ namespace TimeMocker.UI.Forms
|
||||
dgvProcesses.ResumeLayout();
|
||||
}
|
||||
|
||||
// =====================================================================
|
||||
// Patterns Tab
|
||||
// =====================================================================
|
||||
// Patterns Tab
|
||||
// =====================================================================
|
||||
|
||||
@@ -13,8 +13,41 @@
|
||||
<PackageReference Include="EasyHook" Version="2.7.7097.0"/>
|
||||
<PackageReference Include="System.Text.Json" Version="8.0.5"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<!-- Ensure the hook DLL is always next to the UI exe -->
|
||||
<ProjectReference Include="..\TimeMocker.Hook\TimeMocker.Hook.csproj"/>
|
||||
</ItemGroup>
|
||||
<!-- Build both x86 and x64 versions of the hook DLL and copy with architecture suffix -->
|
||||
<Target Name="BuildAllHookDlls" AfterTargets="Build" DependsOnTargets="_BuildX64Hook;_BuildX86Hook;_CopyHookDlls">
|
||||
</Target>
|
||||
<Target Name="_BuildX64Hook">
|
||||
<MSBuild Projects="$(SolutionDir)TimeMocker.Hook\TimeMocker.Hook.csproj"
|
||||
Properties="Platform=x64;Configuration=$(Configuration)"
|
||||
Targets="Build"
|
||||
RunEachTargetSeparately="true" />
|
||||
</Target>
|
||||
<Target Name="_BuildX86Hook">
|
||||
<MSBuild Projects="$(SolutionDir)TimeMocker.Hook\TimeMocker.Hook.csproj"
|
||||
Properties="Platform=x86;Configuration=$(Configuration)"
|
||||
Targets="Build"
|
||||
RunEachTargetSeparately="true" />
|
||||
</Target>
|
||||
<Target Name="_CopyHookDlls" DependsOnTargets="_BuildX64Hook;_BuildX86Hook">
|
||||
<PropertyGroup>
|
||||
<HookBuildDir>$(SolutionDir)TimeMocker.Hook\bin\</HookBuildDir>
|
||||
<X64DllPath>$(HookBuildDir)x64\$(Configuration)\net48\TimeMocker.Hook.dll</X64DllPath>
|
||||
<X86DllPath>$(HookBuildDir)x86\$(Configuration)\net48\TimeMocker.Hook.dll</X86DllPath>
|
||||
<X64Dest>$(OutputPath)TimeMocker.Hook.x64.dll</X64Dest>
|
||||
<X86Dest>$(OutputPath)TimeMocker.Hook.x86.dll</X86Dest>
|
||||
</PropertyGroup>
|
||||
<!-- Copy x64 version with x64 suffix -->
|
||||
<Copy SourceFiles="$(X64DllPath)"
|
||||
DestinationFiles="$(X64Dest)"
|
||||
SkipUnchangedFiles="true" />
|
||||
<!-- Copy x86 version with x86 suffix -->
|
||||
<Copy SourceFiles="$(X86DllPath)"
|
||||
DestinationFiles="$(X86Dest)"
|
||||
SkipUnchangedFiles="true" />
|
||||
</Target>
|
||||
<!-- Clean the renamed DLLs as well -->
|
||||
<Target Name="CleanRenamedHookDlls" AfterTargets="Clean">
|
||||
<Delete Files="$(OutputPath)TimeMocker.Hook.x64.dll" TreatErrorsAsWarnings="true" />
|
||||
<Delete Files="$(OutputPath)TimeMocker.Hook.x86.dll" TreatErrorsAsWarnings="true" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user