如何使用间接字符串加载资源字符串?

时间:2017-02-19 16:04:05

标签: c# .net winapi resourcebundle

我尝试转换Grouping返回的防火墙规则的HNetCfg.FwPolicy2属性中的间接字符串。在PowerShell中:

$fw = New-Object -ComObject 'HNetCfg.FwPolicy2'
$fw.Rules | Select-Object -ExpandProperty 'Grouping' | Select-Object -Unique

返回MSDN docs refer to as "indirect strings"

的内容
@mqutil.dll,-6102
@%windir%\system32\inetsrv\iisres.dll,-30503
@%windir%\system32\inetsrv\iisres.dll,-30501
@%ProgramFiles%\Hyper-V\SnapInAbout.dll,-211
@FirewallAPI.dll,-32752

如何将这些间接字符串转换为托管代码中的实际组名?

我尝试使用GetModuleHandle加载模块/程序集,然后使用LoadString加载字符串,但LoadString没有加载资源。这是我的代码:

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr GetModuleHandle(string lpModuleName);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern int LoadString(IntPtr hInstance, uint uID, StringBuilder lpBuffer, int nBufferMax);

[DllImport("kernel32.dll")]
private static extern uint GetLastError();

public static string GetGroupingFromResource(string resourceInfo)
{
    if (String.IsNullOrEmpty(resourceInfo))
    {
        return resourceInfo;
    }

    var matches = Regex.Match(resourceInfo, @"^@([^,]+),-(\d+)$");
    if (! matches.Success)
    {
        return resourceInfo;
    }

    var modulePath = matches.Groups[1].Value;
    UInt32 resourceID;
    if (!UInt32.TryParse(matches.Groups[2].Value, out resourceID))
    {
        return resourceInfo;
    }

    resourceID += 10000;

    Console.Out.WriteLine(string.Format("Assembly Path: {0}", modulePath));
    Console.Out.WriteLine(string.Format("Resource ID:   {0}", resourceID));

    modulePath = Environment.ExpandEnvironmentVariables(modulePath);

    var searchPaths = Environment.GetEnvironmentVariable("PATH").Split(';');
    if (! System.IO.Path.IsPathRooted(modulePath))
    {
        foreach (var searchPath in searchPaths)
        {
            var fullModulePath = System.IO.Path.Combine(searchPath, modulePath);
            if (System.IO.File.Exists(fullModulePath))
            {
                modulePath = fullModulePath;
                break;
            }
        }
    }

    Console.Out.WriteLine(string.Format("Module Path: {0}", modulePath));
    var moduleHandle = GetModuleHandle(modulePath);
    var lastError = GetLastError();
    Console.Out.WriteLine("Last Error: {0}", lastError);
    if (lastError != 0x0)
    {
        return null;
    }

    var grouping = new StringBuilder();
    LoadString(moduleHandle, resourceID, grouping, 255);
    lastError = GetLastError();
    Console.Out.WriteLine("Last Error: {0}", lastError);
    if (lastError != Win32ErrorCodes.Ok)
    {
        return null;
    }

    Console.Out.WriteLine(grouping.ToString());
    return grouping.ToString();

}

1 个答案:

答案 0 :(得分:0)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace ConsoleApp
{
    class Program
    {
        [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
        public static extern int SHLoadIndirectString(string pszSource, StringBuilder pszOutBuf, int cchOutBuf, IntPtr ppvReserved);

        static void Main(string[] args)
        {
            StringBuilder buffer = new StringBuilder(1024);

            string resourcePath = "@FirewallAPI.dll,-32752";

            int result = SHLoadIndirectString(resourcePath, buffer, buffer.Capacity, IntPtr.Zero);

            if (result == 0) Console.WriteLine(buffer.ToString()); // return "Network Discovery" on Windows 10 (1607)

            Console.ReadKey();
        }
    }
}