Main Menu

Recent posts

#31
Process Lasso / Re: The foreground boost seems...
Last post by login404 - July 03, 2025, 01:07:41 AM
Script Implementation for Enforcing Affinity Binding and Modifying CPU Time Slice Allocation Using Job Objects

.\ProcessController.ps1 -ProcessName "Game" -Affinity "0-7" -Weight 1
.\ProcessController.ps1 -ProcessId 12345 -Affinity "8 10 12-15" -Weight 9

# =========================================================================
#  ProcessController.ps1
#
#  功能:
#  - 支持交互式控制和一次性参数化设置。
#  - 按 Ctrl+C 或输入 'exit' 可随时安全退出并自动解锁。
#
#  用法:
#  1. 交互模式 (无参数运行):
#     > .\ProcessController.ps1
#
#  2. 一次性模式 (提供 -Affinity 或 -Weight 参数):
#     > .\ProcessController.ps1 -ProcessName "Game" -Affinity "0-7" -Weight 9
#     > .\ProcessController.ps1 -ProcessId 12345 -Affinity "8 10 12-15" -Weight 1
#
#  警告:必须以管理员身份运行!
# =========================================================================

# 步骤 0: 定义脚本参数,以支持不同的启动模式
param(
    # 用于一次性模式的目标选择参数
    [string]$ProcessName,
    [int]$ProcessId,

    # 用于触发一次性模式的可选参数
    [string]$Affinity,
    [ValidateRange(1,9)]
    [int]$Weight
)

# 步骤 1: 使用 Add-Type 定义所有需要的 Win32 API 签名、结构体和枚举
try {
    Add-Type -TypeDefinition @"
    using System;
    using System.Runtime.InteropServices;

    public static class NativeMethods {
        // --- Job Object API ---
        [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        public static extern IntPtr CreateJobObjectW(IntPtr lpJobAttributes, string lpName);

        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool AssignProcessToJobObject(IntPtr hJob, IntPtr hProcess);

        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool SetInformationJobObject(IntPtr hJob, JOBOBJECT_INFO_CLASS JobObjectInfoClass, IntPtr lpJobObjectInfo, uint cbJobObjectInfoLength);

        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool CloseHandle(IntPtr hObject);

        // --- 枚举定义 ---
        public enum JOBOBJECT_INFO_CLASS {
            JobObjectBasicLimitInformation = 2,
            JobObjectCpuRateControlInformation = 15
        }

        [Flags]
        public enum JOB_OBJECT_LIMIT_FLAGS : uint {
            JOB_OBJECT_LIMIT_AFFINITY              = 0x00000010,
            JOB_OBJECT_CPU_RATE_CONTROL_ENABLE     = 0x1,
            JOB_OBJECT_CPU_RATE_CONTROL_WEIGHT_BASED = 0x2
        }

        // --- 结构体定义 ---
        [StructLayout(LayoutKind.Sequential)]
        public struct JOBOBJECT_BASIC_LIMIT_INFORMATION {
            public long PerProcessUserTimeLimit;
            public long PerJobUserTimeLimit;
            public JOB_OBJECT_LIMIT_FLAGS LimitFlags;
            public UIntPtr MinimumWorkingSetSize;
            public UIntPtr MaximumWorkingSetSize;
            public uint ActiveProcessLimit;
            public UIntPtr Affinity;
            public uint PriorityClass;
            public uint SchedulingClass;
        }

        [StructLayout(LayoutKind.Explicit)]
        public struct JOBOBJECT_CPU_RATE_CONTROL_INFORMATION {
            [FieldOffset(0)] public JOB_OBJECT_LIMIT_FLAGS ControlFlags;
            [FieldOffset(4)] public uint Weight;
        }
    }
"@ -PassThru -ErrorAction Stop | Out-Null
} catch {
    Write-Host "C# 编译失败: $($_.Exception.Message)" -ForegroundColor Red
    return
}

# --- 步骤 2: 辅助函数 ---

# 解析复杂的亲和性字符串 (例如 "2 5 8-11")
function Parse-AffinityString {
    param([string]$InputString)
   
    [uint64]$totalMask = 0
    # 使用正则表达式替换所有非数字和非连字符的分隔符为空格,然后按空格分割
    $tokens = $InputString -replace '[^\d\-,]', ' ' -split ' ' | Where-Object { $_ }

    foreach ($token in $tokens) {
        if ($token -match '^\d+$') { # 如果是单个数字
            $cpu = [int]$token
            $totalMask = $totalMask -bor (1L -shl $cpu)
        } elseif ($token -match '^(\d+)-(\d+)$') { # 如果是范围
            $startCpu = [int]$matches[1]
            $endCpu = [int]$matches[2]
            if ($startCpu -gt $endCpu) { continue } # 忽略无效范围
            for ($i = $startCpu; $i -le $endCpu; $i++) {
                $totalMask = $totalMask -bor (1L -shl $i)
            }
        } else {
            Write-Warning "已忽略无效的亲和性片段: '$token'"
        }
    }
    return $totalMask
}

# 应用亲和性设置
function Set-JobAffinity {
    param($JobHandle, [uint64]$Mask)

    $limitInfo = New-Object NativeMethods+JOBOBJECT_BASIC_LIMIT_INFORMATION
    $limitInfo.LimitFlags = [NativeMethods+JOB_OBJECT_LIMIT_FLAGS]::JOB_OBJECT_LIMIT_AFFINITY
    $limitInfo.Affinity = New-Object System.UIntPtr($Mask)
   
    # 手动管理内存以传递结构体指针
    $limitInfoPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal([System.Runtime.InteropServices.Marshal]::SizeOf($limitInfo))
    [System.Runtime.InteropServices.Marshal]::StructureToPtr($limitInfo, $limitInfoPtr, $false)
   
    $result = [NativeMethods]::SetInformationJobObject($JobHandle, [NativeMethods+JOBOBJECT_INFO_CLASS]::JobObjectBasicLimitInformation, $limitInfoPtr, [System.Runtime.InteropServices.Marshal]::SizeOf($limitInfo))
   
    [System.Runtime.InteropServices.Marshal]::FreeHGlobal($limitInfoPtr)
    return $result
}

# 应用时间片权重设置
function Set-JobWeight {
    param($JobHandle, [int]$Weight)

    $cpuInfo = New-Object NativeMethods+JOBOBJECT_CPU_RATE_CONTROL_INFORMATION
    $cpuInfo.ControlFlags = [NativeMethods+JOB_OBJECT_LIMIT_FLAGS]::JOB_OBJECT_CPU_RATE_CONTROL_ENABLE -bor [NativeMethods+JOB_OBJECT_LIMIT_FLAGS]::JOB_OBJECT_CPU_RATE_CONTROL_WEIGHT_BASED
    $cpuInfo.Weight = $Weight

    # 手动管理内存以传递结构体指针
    $cpuInfoPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal([System.Runtime.InteropServices.Marshal]::SizeOf($cpuInfo))
    [System.Runtime.InteropServices.Marshal]::StructureToPtr($cpuInfo, $cpuInfoPtr, $false)

    $result = [NativeMethods]::SetInformationJobObject($JobHandle, [NativeMethods+JOBOBJECT_INFO_CLASS]::JobObjectCpuRateControlInformation, $cpuInfoPtr, [System.Runtime.InteropServices.Marshal]::SizeOf($cpuInfo))
   
    [System.Runtime.InteropServices.Marshal]::FreeHGlobal($cpuInfoPtr)
    return $result
}

# --- 步骤 3: 主逻辑 ---

# 模式检测:检查是否提供了 -Affinity 或 -Weight 参数
$isOneShotMode = $PSBoundParameters.ContainsKey('Affinity') -or $PSBoundParameters.ContainsKey('Weight')

# 获取目标进程
$targetProcesses = $null
if ($isOneShotMode) {
    if ($PSBoundParameters.ContainsKey('ProcessName')) {
        $targetProcesses = Get-Process -Name $ProcessName -ErrorAction SilentlyContinue
    } elseif ($PSBoundParameters.ContainsKey('ProcessId')) {
        $targetProcesses = Get-Process -Id $ProcessId -ErrorAction SilentlyContinue
    } else {
        Write-Error "在一次性模式下,必须提供 -ProcessName 或 -ProcessId 参数。"
        return
    }
} else { # 交互模式
    $processNameInput = Read-Host -Prompt "请输入目标进程名 (不包含.exe), 或留空以输入进程ID"
    if (-not [string]::IsNullOrWhiteSpace($processNameInput)) {
        $targetProcesses = Get-Process -Name $processNameInput -ErrorAction SilentlyContinue
        $ProcessName = $processNameInput # 保存以用于Job名
    } else {
        $processIdInput = Read-Host -Prompt "请输入目标进程ID"
        if (-not [string]::IsNullOrWhiteSpace($processIdInput)) {
            try {
                $ProcessId = [int]$processIdInput
                $targetProcesses = Get-Process -Id $ProcessId -ErrorAction SilentlyContinue
            } catch {}
        }
    }
}

if (-not $targetProcesses) {
    Write-Host "未找到任何目标进程。脚本将退出。" -ForegroundColor Yellow
    return
}

Write-Host "已找到 $($targetProcesses.Count) 个目标进程:" -ForegroundColor Green
$targetProcesses | ForEach-Object { Write-Host "  - $($_.ProcessName) (PID: $($_.Id))" }

# 为 Job Object 起一个唯一的名字
$jobId = if ($ProcessName) { "Name_$($ProcessName)" } else { "PID_$($ProcessId)" }
$jobObjectName = "Global\ProcessControllerJob_For_$($jobId)"

# 创建/打开 Job Object
$jobHandle = [NativeMethods]::CreateJobObjectW([IntPtr]::Zero, $jobObjectName)
if ($jobHandle -eq [IntPtr]::Zero) {
    Write-Host "CreateJobObjectW 失败!错误码: $([System.Runtime.InteropServices.Marshal]::GetLastWin32Error())" -ForegroundColor Red
    return
}
Write-Host "Job Object '$jobObjectName' 已创建/打开。" -ForegroundColor Green

# 分配所有目标进程
foreach ($proc in $targetProcesses) {
    [NativeMethods]::AssignProcessToJobObject($jobHandle, $proc.Handle)
}
Write-Host "已将所有目标进程分配到 Job Object。" -ForegroundColor Cyan
Write-Host "----------------------------------------------------"

# --- 步骤 4: 根据模式执行不同逻辑 ---

if ($isOneShotMode) {
    # --- 一次性模式 ---
    Write-Host "正在应用一次性设置..." -ForegroundColor Yellow
    if ($PSBoundParameters.ContainsKey('Affinity')) {
        $parsedMask = Parse-AffinityString -InputString $Affinity
        if ($parsedMask -gt 0) {
            if (Set-JobAffinity -JobHandle $jobHandle -Mask $parsedMask) {
                Write-Host "成功!亲和性已设置为 0x$($parsedMask.ToString('X'))" -F Green
            } else {
                Write-Host "设置亲和性失败!" -F Red
            }
        }
    }
    if ($PSBoundParameters.ContainsKey('Weight')) {
        if (Set-JobWeight -JobHandle $jobHandle -Weight $Weight) {
            Write-Host "成功!时间片权重已设置为 $Weight" -F Green
        } else {
            Write-Host "设置时间片权重失败!" -F Red
        }
    }
    Write-Host "设置已应用,脚本将退出。限制将持续有效。"
    # 在一次性模式下,我们故意不关闭句柄,以使 Job Object 持续存在
    # [NativeMethods]::CloseHandle($jobHandle)
} else {
    # --- 交互式模式 ---
    # 将主循环包裹在 try...finally 中,以确保无论如何都能执行清理代码
    try {
        Write-Host "已进入交互模式。按 Ctrl+C 可随时安全退出并自动解锁。" -ForegroundColor Cyan
        $currentAffinityMask = $null
        $currentWeight = $null
       
        while ($true) {
            # -- 亲和性设置 --
            $affinityPrompt = "请输入亲和性, 或留空跳过, 或 'exit' 退出"
            if ($currentAffinityMask -ne $null) { $affinityPrompt += " [当前: 0x$($currentAffinityMask.ToString('X'))]" }
            $affinityInput = Read-Host -Prompt $affinityPrompt
            if ($affinityInput -eq 'exit') { break }

            if (-not [string]::IsNullOrWhiteSpace($affinityInput)) {
                $parsedMask = Parse-AffinityString -InputString $affinityInput
                if ($parsedMask -gt 0) {
                    if (Set-JobAffinity -JobHandle $jobHandle -Mask $parsedMask) {
                        $currentAffinityMask = $parsedMask
                        Write-Host "成功!亲和性已更新为 0x$($currentAffinityMask.ToString('X'))" -F Green
                    } else {
                        Write-Host "设置亲和性失败!" -F Red
                    }
                } else {
                    Write-Warning "未从输入中解析出有效的 CPU 核心,亲和性未改变。"
                }
            } else {
                Write-Host "亲和性设置已跳过。" -F Gray
            }

            # -- 时间片权重设置 --
            $weightPrompt = "请输入时间片权重 (1-9), 或留空跳过, 或 'exit' 退出"
            if ($currentWeight -ne $null) { $weightPrompt += " [当前: $currentWeight]" }
            $weightInput = Read-Host -Prompt $weightPrompt
            if ($weightInput -eq 'exit') { break }

            if (-not [string]::IsNullOrWhiteSpace($weightInput)) {
                if ($weightInput -match '^[1-9]$') {
                    if (Set-JobWeight -JobHandle $jobHandle -Weight ([int]$weightInput)) {
                        $currentWeight = [int]$weightInput
                        Write-Host "成功!时间片权重已更新为 $currentWeight" -F Green
                    } else {
                        Write-Host "设置时间片权重失败!" -F Red
                    }
                } else {
                    Write-Warning "无效的输入!权重必须是 1-9 之间的单个数字,权重未改变。"
                }
            } else {
                Write-Host "时间片权重设置已跳过。" -F Gray
            }
            Write-Host "----------------------------------------------------"
            Write-Host "设置完毕,等待下一次修改... (按 Enter 键以再次输入)"
            Read-Host | Out-Null
        }
    }
    finally {
        # --- 统一的、保证执行的解锁和清理逻辑 ---
        Write-Host "" # 换行
        Write-Host "正在退出... 自动移除所有限制以进行解锁..." -ForegroundColor Yellow

        # 检查句柄是否有效,防止在创建失败时也尝试解锁
        if ($jobHandle -and $jobHandle -ne [IntPtr]::Zero) {
            # 1. 解锁亲和性
            $unlockLimitInfo = New-Object NativeMethods+JOBOBJECT_BASIC_LIMIT_INFORMATION
            $unlockLimitInfo.LimitFlags = 0
            $unlockLimitInfoPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal([System.Runtime.InteropServices.Marshal]::SizeOf($unlockLimitInfo))
            [System.Runtime.InteropServices.Marshal]::StructureToPtr($unlockLimitInfo, $unlockLimitInfoPtr, $false)
            [NativeMethods]::SetInformationJobObject($jobHandle, [NativeMethods+JOBOBJECT_INFO_CLASS]::JobObjectBasicLimitInformation, $unlockLimitInfoPtr, [System.Runtime.InteropServices.Marshal]::SizeOf($unlockLimitInfo)) | Out-Null
            [System.Runtime.InteropServices.Marshal]::FreeHGlobal($unlockLimitInfoPtr)
           
            # 2. 解锁时间片权重
            $unlockCpuInfo = New-Object NativeMethods+JOBOBJECT_CPU_RATE_CONTROL_INFORMATION
            $unlockCpuInfo.ControlFlags = 0
            $unlockCpuInfoPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal([System.Runtime.InteropServices.Marshal]::SizeOf($unlockCpuInfo))
            [System.Runtime.InteropServices.Marshal]::StructureToPtr($unlockCpuInfo, $unlockCpuInfoPtr, $false)
            [NativeMethods]::SetInformationJobObject($jobHandle, [NativeMethods+JOBOBJECT_INFO_CLASS]::JobObjectCpuRateControlInformation, $unlockCpuInfoPtr, [System.Runtime.InteropServices.Marshal]::SizeOf($unlockCpuInfo)) | Out-Null
            [System.Runtime.InteropServices.Marshal]::FreeHGlobal($unlockCpuInfoPtr)
           
            Write-Host "解锁成功!" -ForegroundColor Green

            # 最终清理句柄
            [NativeMethods]::CloseHandle($jobHandle)
        }
        Write-Host "控制器已终止。"
    }
}
#32
Process Lasso / Re: Export entire configuratio...
Last post by Jeremy Collake - July 02, 2025, 09:06:26 PM
We'll try to get to this soon! Thanks for the feedback!
#33
General / Re: I want Help Understanding ...
Last post by ShaynaRobel - July 02, 2025, 02:52:55 AM
Quote from: Fanny Moen on June 09, 2025, 05:40:54 AMIt's fascinating to see how tools like Process Lasso help us optimize our computer's performance to make everything run smoother – from browsing the web to working to gaming. And speaking of smooth performance, it's impossible not to mention the refreshing feeling when you turn on a Basketball Stars game, all the controls are silky smooth, no lag, just you, the ball, and the ultimate scoring!
Of course, using tools to optimize performance is absolutely necessary in programs that require high programming requirements.
#34
Process Lasso / Re: Export entire configuratio...
Last post by TheRealBix - July 01, 2025, 03:30:39 PM
I agree, I already suggested this.
#35
Process Lasso / Export entire configuration up...
Last post by Peppo - June 30, 2025, 10:56:49 PM
It would be a welcome improvement if the backup function: "Export entire configuration" exported every setting made, even custom colors, column positions, etc.
Thanks for your attention.
#36
Process Lasso / Re: Game crashes while perform...
Last post by TheRealBix - June 30, 2025, 12:01:05 AM
Doesn't seem like a process lasso issue...
You can try setting Performance mode from windows with process lasso closed, but it doubt it would change anything.
#37
Process Lasso / Re: New to process lasso - 995...
Last post by evelynwang - June 29, 2025, 11:00:43 PM
Quote from: Lawlcakes on June 27, 2025, 10:14:04 AMHello there,

New to AMD and the x3D architecture. Did my research as best I could. Parking works on my 9950x3d and game mode parking works as well. I've turned game mode off now. Through investigation, I learned that Process Lasso could yield the best results for gaming. So I have the trial version now, tried setting up CPU affinity rules or CPU set rules for a particular game (and its launcher), but they aren't showing up in the Process Lasso Log. I read on another thread that when the rule changes aren't showing up in the log, something else is going on in the system.

Could someone please help direct me to what could be causing the issue? The system is brand new, X670E tomahawk gaming. Could there be a bios setting? I already created a BitDefender exception so it's most likely not AV related.
Check if Process Lasso is running as admin. Also, try disabling Core Parking in BIOS (look for "CPU Park Control" on MSI boards). Sometimes Windows Game Mode remnants interfere—verify it's fully off in both OS and BIOS.
#38
Process Lasso / Game crashes while performance...
Last post by bumper21 - June 29, 2025, 10:29:11 PM
I recently installed Process Lasso for a Ragnarok Online private server game. It seemed to work quite well but I noticed the game started crashing randomly. One by one i changed the settings and I've concluded with 100% certainty that when I set Performance Mode to anything higher performing than "balanced", the game client will crash.

Has anyone else run into this issue? I need the performance mode on a higher setting than balanced otherwise I get lag spikes in the game.

If it makes any difference I hear my fan start to go full blast as soon as high performance mode is set to anything other than balanced.
#39
ParkControl / Allow me to select which cores...
Last post by Rudolf Snail - June 29, 2025, 11:00:53 AM
Please allow me to specify which cores I want to park in ParkControl.
Currently I can specify what percentage of cores I want parked and what frequency should they be at, but not specific cores to be parked in a power profile, which would allow me to select only non-hyper-threaded cores, in my use case. I want this feature since I set the CPU sets of some performance heavy processes to only run on non-hyper-threaded cores in Process Lasso for better performance, and having to unpark all cores in ParkControl undoes this performance improvement somewhat, as well as using more power than needed.
Setting the amount of cores to be parked to half doesn't seem to solve my issue, since it seems to unpark/park adjacent cores, and thus doesn't select only the cores I want and need, and let the others be parked.
#40
Process Lasso / Re: Process Lasso Worth a Purc...
Last post by DanielGadson - June 29, 2025, 09:07:32 AM
Quote from: DanielGadson on June 27, 2025, 03:16:22 AMI've recently installed the free version of Process Lasso to further optimize my 4090 / 5800x3D system for VR gaming and have been very pleased so far with the results. I used a shared profile I found online that deprioritizes background system tasks, and I've manually added folders where I keep my games to toggle Performance mode on and favor even-core sets for my CPU. I've gotten a noticeable uptick in performance from using these settings on the free version, but I also see people suggesting to set high I/O priority for games in PL but that's not available on the free version. Have folks found it's worth the ~$30 or so sale price for unrestricted Process Lasso to get the I/O Priority functionality to further optimize for gaming?
Can someone help me?