2017-02-19 163 views
1

我試圖轉換由HNetCfg.FwPolicy2返回的防火牆規則的Grouping屬性中的間接字符串。在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(); 

} 
+0

你需要使用[SHLoadIndirectString(https://msdn.microsoft.com/en-us/library/windows/desktop/bb759919(V = vs.85)的.aspx ) – RbMm

+0

on C++ code like this'WCHAR sz [1024]; if(S_OK == SHLoadIndirectString(L「@ FirewallAPI.dll,-32752」,sz,RTL_NUMBER_OF(sz),0)){..}' – RbMm

+0

@RbMm如果您將其添加爲答案,我會接受它。不過,不是C++代碼。 –

回答

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(); 
     } 
    } 
}