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

.NET代码中PInvoke调用RtlIsNameInExpression方法的实现咨询

如何在.NET控制台应用中调用RtlIsNameInExpression实现Windows原生文件名匹配

我刚好对这个函数的P/Invoke实现有研究,直接给你整理好可用的代码和注意事项,保证你的应用和Windows原生行为完全对齐:

首先,这个函数属于ntdll.dll,需要先定义Windows原生的UNICODE_STRING结构体(因为函数参数用的是这个类型),然后再声明P/Invoke调用:

using System;
using System.Runtime.InteropServices;

internal static class NativeMethods
{
    // 定义Windows原生UNICODE_STRING结构体
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    internal struct UNICODE_STRING
    {
        public ushort Length;
        public ushort MaximumLength;
        public IntPtr Buffer;
    }

    // RtlIsNameInExpression的P/Invoke声明
    [DllImport("ntdll.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    internal static extern bool RtlIsNameInExpression(
        ref UNICODE_STRING Expression,
        ref UNICODE_STRING Name,
        bool IgnoreCase,
        IntPtr UpcaseTable
    );

    // 封装一个简化方法,直接接收C#字符串,不用手动处理UNICODE_STRING
    public static bool IsFileNameMatch(string wildcardPattern, string fileName)
    {
        // 将C#字符串转换为UNICODE_STRING
        var expression = CreateUnicodeString(wildcardPattern);
        var name = CreateUnicodeString(fileName);

        try
        {
            // 调用原生函数,IgnoreCase设为true(Windows默认不区分大小写),UpcaseTable传空用系统默认
            return RtlIsNameInExpression(ref expression, ref name, true, IntPtr.Zero);
        }
        finally
        {
            // 释放分配的内存,避免泄漏
            Marshal.FreeHGlobal(expression.Buffer);
            Marshal.FreeHGlobal(name.Buffer);
        }
    }

    // 辅助方法:把C#字符串转为UNICODE_STRING
    private static UNICODE_STRING CreateUnicodeString(string value)
    {
        if (string.IsNullOrEmpty(value))
        {
            return new UNICODE_STRING();
        }

        // 分配非托管内存存储Unicode字符串
        var buffer = Marshal.StringToHGlobalUni(value);
        return new UNICODE_STRING
        {
            Length = (ushort)(value.Length * 2), // 每个Unicode字符占2字节
            MaximumLength = (ushort)(value.Length * 2 + 2), // 预留终止符空间
            Buffer = buffer
        };
    }
}

使用示例

在你的控制台应用里直接调用封装好的方法就行,完全贴合Windows原生匹配逻辑:

var pattern = "*.txt";
var fileName = "Document1.TXT";
bool isMatch = NativeMethods.IsFileNameMatch(pattern, fileName);
Console.WriteLine(isMatch); // 输出True,和Windows资源管理器的匹配结果一致

关键注意事项

  • IgnoreCase参数:Windows文件名默认不区分大小写,所以这里设为true是符合原生行为的;如果需要严格区分大小写,改成false即可。
  • UpcaseTable参数:传IntPtr.Zero会让函数使用系统默认的大小写转换表,无需自己额外处理。
  • 内存管理:必须释放Marshal.StringToHGlobalUni分配的非托管内存,上面的封装方法已经在finally块里做了处理,不用担心内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:41:30