Skip to content
Open
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 AsusFanControl/AsusFanControl.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
<Compile Include="AsusControl.cs" />
<Compile Include="AsusWinIO64.cs" />
<Compile Include="Program.cs" />
<Compile Include="SystemRelaunch.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
Expand All @@ -77,4 +78,4 @@
</Content>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
</Project>
53 changes: 51 additions & 2 deletions AsusFanControl/Program.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
using System;

using System.Collections.Generic;
using System.Diagnostics;
using System.IO;

namespace AsusFanControl
{
internal static class Program
Expand All @@ -10,7 +14,29 @@ internal static class Program
[STAThread]
static int Main(string[] args)
{
if (args.Length < 1)
args = args ?? new string[0];

var filteredArgs = new List<string>();
bool isPsExecRelaunch = false;
bool autoRelaunch = false;

foreach (var a in args)
{
if (string.Equals(a, SystemRelaunch.PsExecRelaunchFlag, StringComparison.OrdinalIgnoreCase))
{
isPsExecRelaunch = true;
continue;
}
if (string.Equals(a, SystemRelaunch.AutoRelaunchFlag, StringComparison.OrdinalIgnoreCase))
{
autoRelaunch = true;
continue;
}

filteredArgs.Add(a);
}

if (filteredArgs.Count < 1)
{
Console.WriteLine("Usage: AsusFanControl <args>");
Console.WriteLine("\t--get-fan-speeds");
Expand All @@ -19,12 +45,35 @@ static int Main(string[] args)
Console.WriteLine("\t--get-fan-speed=fanId (comma separated)");
Console.WriteLine("\t--set-fan-speed=fanId:0-100 (comma separated, percent value, 0 for turning off test mode)");
Console.WriteLine("\t--get-cpu-temp");
Console.WriteLine("\t--relaunch-system (optional, auto-relaunch via PsExec if needed)");
return 1;
}

if (!isPsExecRelaunch && !SystemRelaunch.IsRunningAsSystem() && !SystemRelaunch.CanAccessFanDriver())
{
if (autoRelaunch && SystemRelaunch.TryRelaunchAsSystem(filteredArgs.ToArray()))
return 0;

Console.WriteLine("Fan driver access requires running as SYSTEM (LocalSystem) on some newer ASUS drivers.");

var psExecPath = SystemRelaunch.FindPsExecPath();
if (!string.IsNullOrWhiteSpace(psExecPath))
{
var sessionId = Process.GetCurrentProcess().SessionId;
Console.WriteLine("Relaunch example:");
Console.WriteLine(string.Format(" {0} -accepteula -d -s -i {1} AsusFanControl.exe {2}", Path.GetFileName(psExecPath), sessionId, string.Join(" ", filteredArgs.ToArray())));
}
else
{
Console.WriteLine("Place PsExec64.exe / PsExec.exe next to AsusFanControl.exe, or use AsusFanControlGUI (it can self-relaunch).");
}

return 2;
}

var asusControl = new AsusControl();

foreach (var arg in args)
foreach (var arg in filteredArgs)
{
if (arg.StartsWith("--get-fan-speeds"))
{
Expand Down
128 changes: 128 additions & 0 deletions AsusFanControl/SystemRelaunch.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.Principal;
using AsusSystemAnalysis;

namespace AsusFanControl
{
public static class SystemRelaunch
{
public const string PsExecRelaunchFlag = "--psexec-relaunch";
public const string AutoRelaunchFlag = "--relaunch-system";

public static bool IsRunningAsSystem()
{
try
{
using (var identity = WindowsIdentity.GetCurrent())
{
return identity != null && identity.IsSystem;
}
}
catch
{
return false;
}
}

public static bool CanAccessFanDriver()
{
try
{
var dllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AsusWinIO64.dll");
if (!File.Exists(dllPath))
return false;

AsusWinIO64.InitializeWinIo();
var fanCount = AsusWinIO64.HealthyTable_FanCounts();
AsusWinIO64.ShutdownWinIo();

return fanCount > 0;
}
catch
{
try { AsusWinIO64.ShutdownWinIo(); } catch { }
return false;
}
}

public static string FindPsExecPath()
{
var baseDir = AppDomain.CurrentDomain.BaseDirectory;
var candidates = new[]
{
"PsExec64.exe",
"PsExec.exe",
"psexec64.exe",
"psexec.exe",
"PsExec64",
"PsExec",
"psexec64",
"psexec"
};

foreach (var candidate in candidates)
{
var path = Path.Combine(baseDir, candidate);
if (File.Exists(path)) return path;
}

return null;
}

public static bool TryRelaunchAsSystem(string[] args)
{
if (!Environment.UserInteractive) return false;
if (IsRunningAsSystem()) return false;

if (args != null && args.Any(a => string.Equals(a, PsExecRelaunchFlag, StringComparison.OrdinalIgnoreCase)))
return false;

var psExecPath = FindPsExecPath();
if (psExecPath == null) return false;

string exePath;
try { exePath = Process.GetCurrentProcess().MainModule.FileName; }
catch { return false; }

if (string.IsNullOrWhiteSpace(exePath) || !File.Exists(exePath))
return false;

try
{
var forwardArgs = (args ?? new string[0])
.Where(a => !string.Equals(a, PsExecRelaunchFlag, StringComparison.OrdinalIgnoreCase))
.Concat(new[] { PsExecRelaunchFlag })
.ToArray();

var forwarded = string.Join(" ", forwardArgs.Select(QuoteArg));
var sessionId = Process.GetCurrentProcess().SessionId;

var psi = new ProcessStartInfo
{
FileName = psExecPath,
Arguments = string.Format("-accepteula -d -s -i {0} \"{1}\" {2}", sessionId, exePath, forwarded),
UseShellExecute = true,
Verb = "runas",
WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory
};

Process.Start(psi);
return true;
}
catch
{
return false;
}
}

private static string QuoteArg(string arg)
{
if (string.IsNullOrEmpty(arg)) return "\"\"";
if (!arg.Contains(" ") && !arg.Contains("\"")) return arg;
return "\"" + arg.Replace("\"", "\\\"") + "\"";
}
}
}
10 changes: 9 additions & 1 deletion AsusFanControlGUI/AsusFanControlGUI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<RootNamespace>AsusFanControlGUI</RootNamespace>
<AssemblyName>AsusFanControlGUI</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<GenerateResourceUsePreserializedResources>true</GenerateResourceUsePreserializedResources>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
Expand Down Expand Up @@ -65,6 +66,10 @@
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Resources.Extensions">
<HintPath>$(NuGetPackageRoot)system.resources.extensions\8.0.0\lib\net462\System.Resources.Extensions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
Expand Down Expand Up @@ -112,5 +117,8 @@
<ItemGroup>
<Content Include="propeller.ico" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Resources.Extensions" Version="8.0.0" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
</Project>
16 changes: 15 additions & 1 deletion AsusFanControlGUI/Form1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ namespace AsusFanControlGUI
{
public partial class Form1 : Form
{
AsusControl asusControl = new AsusControl();
AsusControl asusControl;
int fanSpeed = 0;
Timer timer;
NotifyIcon trayIcon;

public Form1()
{
InitializeComponent();
asusControl = new AsusControl();
AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnProcessExit);

toolStripMenuItemTurnOffControlOnExit.Checked = Properties.Settings.Default.turnOffControlOnExit;
Expand All @@ -31,6 +32,19 @@ private void OnProcessExit(object sender, EventArgs e)

private void Form1_Load(object sender, EventArgs e)
{
var fanCount = asusControl.HealthyTable_FanCounts();
if (fanCount <= 0)
{
MessageBox.Show(
"Unable to access ASUS fan driver.\n\n" +
"If you are on a newer ASUS System Control Interface driver, run this app as SYSTEM (LocalSystem).\n" +
"Place PsExec64.exe / PsExec.exe next to AsusFanControlGUI.exe and start again.",
"Asus Fan Control",
MessageBoxButtons.OK,
MessageBoxIcon.Warning
);
}

timerRefreshStats();
}

Expand Down
24 changes: 23 additions & 1 deletion AsusFanControlGUI/Program.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Windows.Forms;
using AsusFanControl;

namespace AsusFanControlGUI
{
Expand All @@ -9,8 +10,29 @@ internal static class Program
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
static void Main(string[] args)
{
args = args ?? new string[0];

bool isPsExecRelaunch = false;
foreach (var a in args)
if (string.Equals(a, SystemRelaunch.PsExecRelaunchFlag, StringComparison.OrdinalIgnoreCase))
isPsExecRelaunch = true;

if (!isPsExecRelaunch && Environment.UserInteractive && !SystemRelaunch.IsRunningAsSystem() && !SystemRelaunch.CanAccessFanDriver())
{
if (SystemRelaunch.TryRelaunchAsSystem(args))
return;

MessageBox.Show(
"Fan driver access requires running as SYSTEM (LocalSystem) on some newer ASUS drivers.\n\n" +
"Place PsExec64.exe / PsExec.exe next to AsusFanControlGUI.exe to enable auto-relaunch.",
"Asus Fan Control",
MessageBoxButtons.OK,
MessageBoxIcon.Warning
);
}

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,15 @@ Go to [releases](../../releases)
--get-fan-speed=fanId (comma separated)
--set-fan-speed=fanId:0-100 (comma separated, percent value, 0 for turning off test mode)
--get-cpu-temp
--relaunch-system (optional, auto-relaunch via PsExec if needed)
</details>

GUI: `AsusFanControlGUI.exe`

> [!NOTE]
> **SYSTEM requirement (newer ASUS drivers):** On some ASUS System Control Interface driver versions (3.1.41.0+), low-level fan access is restricted to **LocalSystem**.
> If fan control doesn't work, place `PsExec64.exe` or `PsExec.exe` next to `AsusFanControlGUI.exe` and start the GUI again — it will relaunch itself as SYSTEM automatically.

![AsusFanControlGUI](https://github.com/Karmel0x/AsusFanControl/assets/25367564/fe197ad0-7079-4d51-ae78-177cb6369e96)

### Why need it?
Expand Down