如何使用PowerShell从.dll或.exe文件中提取数据

3
我想列出所有启动类型设置为自动的服务。
我正在使用PowerShell 5。
$path = 'hklm:\SYSTEM\ControlSet001\Services'
$services = get-childitem $path | get-itemproperty -name 'Start'
foreach ($s in $services){
    if($s.'Start' -like '2'){
        $dn = get-itemproperty $s.'pspath' -name 'DisplayName'
        echo $dn
    }
}

但问题是,大部分条目使用的是这样的格式:

@%systemroot%\system32\SearchIndexer.exe,-103
@%SystemRoot%\System32\wscsvc.dll,-200

那么如何从中提取字符串呢?
更进一步澄清,对于“@%systemroot%\system32\SearchIndexer.exe,-103”,显示名称为“Windows 搜索”。问题是,PowerShell 是否能够从“SearchIndexer.exe”中提取字符串“Windows 搜索”?如何实现?
更新:
基本上从如何从 DLL 提取字符串资源中窃取了代码。
$source = @"
using System;
using System.Runtime.InteropServices;
using System.Text;

public class ExtractData
{
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
private static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName);

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

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool FreeLibrary(IntPtr hModule);

public string ExtractStringFromDLL(string file, int number) {
    IntPtr lib = LoadLibrary(file);
    StringBuilder result = new StringBuilder(2048);
    LoadString(lib, number, result, result.Capacity);
    FreeLibrary(lib);
    return result.ToString();
}
}
"@

Add-Type -TypeDefinition $source

$ed = New-Object ExtractData

$path = 'hklm:\SYSTEM\ControlSet001\Services'
$services = get-childitem $path | get-itemproperty -name 'Start' -ErrorAction SilentlyContinue
foreach ($s in $services){
    if($s.'Start' -like '2'){
        $dn = get-itemproperty $s.'pspath' -name 'DisplayName'
        try{
        $dn = $dn.DisplayName.Split(',')
        $dn = $ed.ExtractStringFromDLL([Environment]::ExpandEnvironmentVariables($dn[0]).substring(1), $dn[1].substring(1))
        }
        catch{}
        finally{
        echo $dn
        }
    }
}

虽然很丑,但最终还是可以工作的......


2个回答

5

有什么问题

get-service | where-object StartType -eq Automatic

?


谢谢!这是更好的方法。但我还是想知道如何从.dll、.exe文件中提取字符串,只是出于好奇。 - oNion
@oNion:我正在考虑这个问题。我认为你不能依赖于资源ID的附加或路径名不包含逗号!因此,可能需要应用一些启发式方法来实现强大的解决方案。但是简单情况下的解决方法是(字符串在$s中)[Environment] :: ExpandEnvironmentVariables($s.Substring(1, $s.LastIndexOf(',')-1)) - Richard
似乎不起作用,它使@%SystemRoot%\System32\wscsvc.dll,-200变成了@%SystemRoot%\System32\wscsvc.dll,并没有完全提取文件中的数据。但还是谢谢 :) - oNion
@oNion 在问题中,你提到了“提取字符串”,我理解为文件名。如果你需要从文件内部获取数据,这会很快变得复杂(你需要调用Win32资源API)。而且在许多情况下,它只是一个字符串(显示名称不一定要是资源引用)。 - Richard
@oNion:看看这个问题,C#代码可以被封装成一个类,然后通过Add-Type -TypeDefinition $codeString动态加载。 - Richard

2

试试这个。它在PowerShell 3中有效,所以在更高版本中也应该有效。

Get-WmiObject -Class Win32_Service | 
    Where-Object StartMode -eq Auto | 
    Select-Object -Property DisplayName

谢谢!你知道从.exe和.dll文件中提取数据的方法吗?只是好奇。 - oNion
我敢打赌,答案很可能在Stack Overflow上,而且找起来应该不难。 - andyb
也许可以考虑使用 get-content -encoding byte - andyb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接