Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replaced the dubugger-key-based approach with the service that sets the affinity. #3

Merged
merged 4 commits into from
Dec 30, 2024
Merged
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
8 changes: 6 additions & 2 deletions .github/workflows/Main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,15 @@ jobs:
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x


- name: Set up a Rust toolchain
uses: hecrj/[email protected]


# Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild
- name: Setup MSBuild.exe
uses: microsoft/setup-msbuild@v2

# Build
- name: Build the application
run: dotnet build src\PPM.InstallerBundle\PPM.InstallerBundle.wixproj -c ${{ matrix.configuration}} -p:Platform=${{ matrix.platform }}
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ jobs:
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x

- name: Set up a Rust toolchain
uses: hecrj/[email protected]

# Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild
- name: Setup MSBuild.exe
Expand All @@ -41,7 +44,7 @@ jobs:
- name: Release
uses: softprops/action-gh-release@v2
with:
files: src/Release/PPM.InstallerBundle.exe
files: src/Release/*.exe
fail_on_unmatched_files: true
prerelease: true
generate_release_notes: true
Expand Down
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -396,3 +396,12 @@ FodyWeavers.xsd

# JetBrains Rider
*.sln.iml

# Generated by Cargo
# will have compiled files and executables
debug/
target/

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
15 changes: 12 additions & 3 deletions src/Affinity_Manager_Installer/AppComponents.wxs
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">
<Fragment>
<ComponentGroup Id="AppComponents" Directory="INSTALLFOLDER">
<Component>
<File Source="!(bindpath.x64)\Affinity_manager.exe" Id="MainExecutable"/>
<Shortcut Name="!(bind.Property.ProductName)" Directory="ProgramMenuFolder" IconIndex="0" Advertise="yes"/>
</Component>
<File Source="!(bindpath.x64)\Cpu_affinity.exe" Id="Affinity_setter" />
<Component>
<File Source="!(bindpath.x64)\PPM_Service.exe" Id="PPM_Service" />
<ServiceInstall Id="PPM_Service" Name="PPM_Service" DisplayName="!(loc.PpmServiceName)" Description="!(loc.PpmServiceDescription)" Start="auto" Type="ownProcess" ErrorControl="ignore" Account="LocalSystem" Vital="yes" Interactive="no">
<util:ServiceConfig FirstFailureActionType="restart" SecondFailureActionType="restart" ThirdFailureActionType="none" ResetPeriodInDays="1" RestartServiceDelayInSeconds="60"/>
</ServiceInstall>
<ServiceControl Id="PPM_Service_control" Name="PPM_Service" Start="install" Stop="both" Remove="uninstall" Wait="no"/>
</Component>
<Files Include="!(bindpath.x64)\*.dll"/>
<Files Include="!(bindpath.x64)\*.json"/>
<Files Include="!(bindpath.x64)\*.runtimeconfig.json"/>
<Files Include="!(bindpath.x64)\*.pri"/>
<Files Include="!(bindpath.x64)\**.png">
<Exclude Files="!(bindpath.x64)\WindowsAppRuntime.png"/>
</Files>
<Files Include="!(bindpath.x64)\**.ico"/>
<Files Include="!(bindpath.x64)\en-us\*.mui" Directory="EN_US"/>
<Component Id="Registry_HKLM" Guid="1F167EEE-4394-4FBB-87A1-3AEA39137E64">
<RegistryKey Id="Settings" Root="HKLM" Key="SOFTWARE\Processes Priority Manager\" ForceDeleteOnUninstall="yes"></RegistryKey>
</Component>
</ComponentGroup>
</Fragment>
</Wix>
2 changes: 2 additions & 0 deletions src/Affinity_Manager_Installer/Package.en-us.wxl
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@ This file contains the declaration of all the localizable strings.
<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="en-US">

<String Id="DowngradeError" Value="A newer version of [ProductName] is already installed." />
<String Id="PpmServiceName" Value="Processes Priority Manager Service" />
<String Id="PpmServiceDescription" Value="Support functionality for Processes Priority Manager" />

</WixLocalization>
24 changes: 17 additions & 7 deletions src/Affinity_manager/Affinity_manager.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
<RootNamespace>Affinity_manager</RootNamespace>
<ApplicationManifest>app.manifest</ApplicationManifest>
<Platforms>x86;x64;ARM64</Platforms>
<RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers>
<Platforms>x64</Platforms>
<RuntimeIdentifiers>;win-x64</RuntimeIdentifiers>
<PublishProfile>win-$(Platform).pubxml</PublishProfile>
<UseWinUI>true</UseWinUI>
<EnableMsixTooling>true</EnableMsixTooling>
Expand Down Expand Up @@ -46,13 +46,12 @@
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.1742" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.6.241114003" />
<PackageReference Include="ReswPlus" Version="0.2.6" Publish="false" />
<PackageReference Include="Vanara.PInvoke.Kernel32" Version="4.0.4" />
<PackageReference Include="ReswPlus" Version="0.2.6" Publish="false">
<TreatAsUsed>true</TreatAsUsed>
</PackageReference>
<PackageReference Include="System.ServiceProcess.ServiceController" Version="9.0.0" />
<PackageReference Include="Vanara.PInvoke.User32" Version="4.0.4" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Cpu_affinity\Cpu_affinity.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
Expand Down Expand Up @@ -129,6 +128,11 @@
</ItemGroup>
<ItemGroup>
<Folder Include="Assets\" />
</ItemGroup>
<ItemGroup>
<Content Include="..\pm_affinityservice\target\release\PPM_Service.exe" Link="PPM_Service.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Target Name="WindowsAppSdk_Issue_3843_Workaround_MsixContent" AfterTargets="AddMicrosoftWindowsAppSDKPayloadFiles">
<ItemGroup>
Expand Down Expand Up @@ -315,4 +319,10 @@
<None Remove="$(MicrosoftWindowsAppSDKMsixContent)\zh-TW\Microsoft.UI.Xaml.Phone.dll.mui" />
</ItemGroup>
</Target>
<Target Name="Rust Build" BeforeTargets="Compile">
<Exec Command="cargo b --release" WorkingDirectory="..\pm_affinityservice" />
</Target>
<ItemGroup>
<UpToDateCheckInput Include="..\pm_affinityservice" />
</ItemGroup>
</Project>
12 changes: 10 additions & 2 deletions src/Affinity_manager/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Diagnostics;
using System.Linq;
using Affinity_manager.Model;
using Affinity_manager.Model.CRUD;
using Affinity_manager.Pages;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
Expand All @@ -22,6 +23,13 @@ public partial class App : Application
public App()
{
this.InitializeComponent();
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}

private void CurrentDomain_UnhandledException(object sender, System.UnhandledExceptionEventArgs e)
{
// Add some pre-crash window here.
Trace.WriteLine(e.ExceptionObject);
}

/// <summary>
Expand All @@ -32,7 +40,7 @@ protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs ar
{
if (Environment.GetCommandLineArgs().Contains("--clear"))
{
Cleaner cleaner = new();
ProcessConfigurationsRepository cleaner = new();
cleaner.Clean();
Environment.Exit(0);
}
Expand Down
32 changes: 32 additions & 0 deletions src/Affinity_manager/Exceptions/ServiceNotInstalledException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;
using System.ComponentModel;
using System.Runtime.ExceptionServices;

namespace Affinity_manager.Exceptions
{
public class ServiceNotInstalledException : Exception
{
private const int ERROR_SERVICE_DOES_NOT_EXIST = 1060;

public ServiceNotInstalledException(string serviceName)
: base(string.Format("Service {0} is not installed", serviceName))
{
}

public ServiceNotInstalledException(string? serviceName, Exception? innerException)
: base(string.Format("Service {0} is not installed", serviceName), innerException)
{
}


public static void ThrowFromInvalidOperationException(InvalidOperationException e, string serviceName)
{
if (e.InnerException is Win32Exception inner && inner.NativeErrorCode == ERROR_SERVICE_DOES_NOT_EXIST)
{
throw new ServiceNotInstalledException(serviceName, e);
}

ExceptionDispatchInfo.Throw(e);
}
}
}
10 changes: 0 additions & 10 deletions src/Affinity_manager/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Affinity_manager.Utils;
using Microsoft.UI.Xaml;

// To learn more about WinUI, the WinUI project structure,
Expand All @@ -14,15 +13,6 @@ public sealed partial class MainWindow : Window
public MainWindow()
{
this.InitializeComponent();
base.Activated += MainWindow_Activated;
}

private void MainWindow_Activated(object sender, WindowActivatedEventArgs args)
{
if (RusDetector.Check())
{
// TODO: show message;
}
}
}
}
41 changes: 0 additions & 41 deletions src/Affinity_manager/Model/AffinityConverter.cs

This file was deleted.

113 changes: 113 additions & 0 deletions src/Affinity_manager/Model/CRUD/ImageOptionsFiller.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Win32;

namespace Affinity_manager.Model.CRUD
{
internal class ImageOptionsFiller : IDisposable
{
public const string ImageOptionsRegistryPath = "SOFTWARE\\Processes Priority Manager\\Image Options\\";
public const string AffinityValueName = "Affinity";

private RegistryKey? _imageOptionsKey;

public void ReadAffinityFromRegistry(ProcessConfiguration item)
{
using RegistryKey? processKey = GetImageOptions(false)?.OpenSubKey(item.Name);
if (processKey == null)
{
item.CpuAffinityMask = ProcessConfiguration.AffinityDefaultValue;
return;
}

item.CpuAffinityMask = ReadAffinityValue(processKey);
}

public void SaveToRegistry(ProcessConfiguration item)
{
bool needToSave = item.CpuAffinityMask != ProcessConfiguration.AffinityDefaultValue;
RegistryKey? imageOptionsKey = GetImageOptions(needToSave);
if (imageOptionsKey == null && needToSave)
{
throw new InvalidOperationException("Image Options not found!");
}
else if (imageOptionsKey == null)
{
return;
}

if (needToSave)
{
using RegistryKey processKey = imageOptionsKey.OpenSubKey(item.Name, true) ?? imageOptionsKey.CreateSubKey(item.Name);
processKey.SetValue(AffinityValueName, unchecked((long)item.CpuAffinityMask), RegistryValueKind.QWord);
}
else
{
using RegistryKey? processKey = imageOptionsKey.OpenSubKey(item.Name, true);
if (processKey == null)
{
return;
}

processKey.DeleteValue(AffinityValueName);
if (processKey.SubKeyCount == 0 && processKey.ValueCount == 0)
{
processKey.DeleteSubKey(string.Empty);
}
}
}

public IEnumerable<ProcessConfiguration> GetAbsentItems(IReadOnlyList<ProcessConfiguration> items)
{
RegistryKey? imageOptionsKey = GetImageOptions(false);
if (imageOptionsKey == null)
{
yield break;
}

foreach (string key in imageOptionsKey.GetSubKeyNames())
{
if (!items.Any(item => string.Equals(item.Name, key, StringComparison.OrdinalIgnoreCase)))
{
using RegistryKey processKey = imageOptionsKey.OpenSubKey(key)!;
yield return new ProcessConfiguration(key)
{
CpuAffinityMask = ReadAffinityValue(processKey)
};
}
}
}

private RegistryKey? GetImageOptions(bool createIfNotExist)
{
return _imageOptionsKey ??= Registry.LocalMachine.OpenSubKey(ImageOptionsRegistryPath, true)
?? (createIfNotExist ? Registry.LocalMachine.CreateSubKey(ImageOptionsRegistryPath) : null);
}

private static ulong ReadAffinityValue(RegistryKey processKey)
{
if (processKey.GetValue(AffinityValueName) == null || processKey.GetValueKind(AffinityValueName) != RegistryValueKind.QWord)
{
return ProcessConfiguration.AffinityDefaultValue;
}

return unchecked((ulong)(long)processKey.GetValue(AffinityValueName)!);
}

protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_imageOptionsKey?.Dispose();
}
}

public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}
Loading
Loading