You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell 5.1调用C#实现Focus Assist状态查询报错求助

解决PowerShell 5.1中调用Focus Assist状态检查代码的报错问题

问题根源

报错的核心原因有两个:

  • PowerShell 5.1基于.NET Framework运行,Add-Type不会自动引入核心命名空间,原代码缺少System和System.Runtime.InteropServices命名空间引用,导致编译器无法识别uint、DllImport等类型与特性。
  • 原代码直接将IntPtr强制转换为枚举的逻辑错误,pBuffer是指向返回数据的内存指针,需读取指针指向的实际值才能得到正确状态。

修复后的完整代码

$Focus = @{
    Namespace        = "WinAPI"
    Name             = "Focus"
    Language         = "CSharp"
    MemberDefinition = @"
using System;
using System.Runtime.InteropServices;

[DllImport("NtDll.dll", SetLastError = true)]
private static extern uint NtQueryWnfStateData(IntPtr pStateName, IntPtr pTypeId, IntPtr pExplicitScope, out uint nChangeStamp, out IntPtr pBuffer, ref uint nBufferSize);

[StructLayout(LayoutKind.Sequential)]
public struct WNF_STATE_NAME
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
    public uint[] Data;

    public WNF_STATE_NAME(uint Data1, uint Data2) : this()
    {
        uint[] newData = new uint[2];
        newData[0] = Data1;
        newData[1] = Data2;
        Data = newData;
    }
}

public enum FocusAssistState
{
    NOT_SUPPORTED = -2,
    FAILED = -1,
    OFF = 0,
    PRIORITY_ONLY = 1,
    ALARMS_ONLY = 2
};

public static FocusAssistState GetFocusAssistState()
{
    IntPtr pStateName = IntPtr.Zero;
    IntPtr pBuffer = IntPtr.Zero;
    try
    {
        WNF_STATE_NAME WNF_SHEL_QUIETHOURS_ACTIVE_PROFILE_CHANGED = new WNF_STATE_NAME(0xA3BF1C75, 0xD83063E);
        uint nBufferSize = (uint)Marshal.SizeOf(typeof(int));
        pStateName = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(WNF_STATE_NAME)));
        Marshal.StructureToPtr(WNF_SHEL_QUIETHOURS_ACTIVE_PROFILE_CHANGED, pStateName, false);
        
        uint status = NtQueryWnfStateData(pStateName, IntPtr.Zero, IntPtr.Zero, out uint nChangeStamp, out pBuffer, ref nBufferSize);
        if (status == 0 && pBuffer != IntPtr.Zero)
        {
            int stateValue = Marshal.ReadInt32(pBuffer);
            return (FocusAssistState)stateValue;
        }
    }
    catch { }
    finally
    {
        if (pStateName != IntPtr.Zero) Marshal.FreeHGlobal(pStateName);
        if (pBuffer != IntPtr.Zero) Marshal.FreeHGlobal(pBuffer);
    }

    return FocusAssistState.FAILED;
}
"@
}

if (-not ("WinAPI.Focus" -as [type]))
{
    Add-Type @Focus
}
[WinAPI.Focus]::GetFocusAssistState()

关键修改说明

  1. 添加命名空间引用:在C#代码开头加入using System;和using System.Runtime.InteropServices;,解决类型识别错误。
  2. 修复状态值读取逻辑:用Marshal.ReadInt32(pBuffer)读取指针指向的实际整数状态,再转换为枚举类型,替代原代码直接转换IntPtr的错误逻辑。
  3. 完善内存管理:添加finally块确保pStateName和pBuffer的内存被正确释放,避免内存泄漏。
  4. 调整缓冲区大小:将缓冲区大小改为Marshal.SizeOf(typeof(int)),匹配WNF返回的状态数据类型(4字节整数)。

内容的提问来源于stack exchange,提问作者Sanctuary

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 04:57:03