我正在对笔记本电脑的控制插件进行逆向工程,并试图找出如何调用模拟“应用程序”正在执行的操作的方法。它是用 C# 编写的,所以我想我可以使用 PowerShell 来调用它的方法。 我使用 DotPeek 发现所有内容都被处理到一个 DLL 中,该 DLL 实现了我想要访问的方法。
该类看起来像:
namespace Vendor.package1.package2.SomePlugin
{
internal class SomeClass : IInterfaceThatIWant, ...
{
~SomeClass()
{
}
public RequestObject SetSomething()
{
... method that I want to use
}
public ResponseObject GetSomething()
{
...
}
private SomeClass()
{
...
}
public static SomeClass GetInstance()
{
...
}
}
在 PowerShell 中,我尝试过:
Add-Type -Path "c:\pathtodll\x64\vendor.dll"
和
[System.Reflection.Assembly]::LoadFrom("c:\pathtodll\x64\vendor.dll")
...没有显示任何错误,所以我认为两者都有效。
接下来我正在尝试:
[Vendor.package1.package2.SomePlugin.SomeClass]::GetInstance()
Unable to find type [Vendor.package1.package2.SomePlugin.SomeClass].
New-Object Vendor.package1.package2.SomePlugin.SomeClass
New-Object : Cannot find type [Vendor.package1.package2.SomePlugin.SomeClass]: verify that the assembly containing this type is loaded.
[Vendor.package1.package2.SomePlugin.SomeClass]::GetInstance
Unable to find type [Vendor.package1.package2.SomePlugin.SomeClass].
以及各种其他排列,但我无法获得类句柄。
最佳答案
要获取对非公共(public) SomeClass
类型的引用,有几个选项:
1。让 Add-Type
返回程序集中的所有类型
Add-Type
有一个 -PassThru
开关,它将返回在加载的程序集中找到的所有类型,无论访问如何:
# Import assembly out emit types
$VendorTypes = Add-Type -Path "c:\pathtodll\x64\vendor.dll" -PassThru
# Filter the types for the one we need
$SomeClassType = $VendorTypes.Where({$_.FullName -eq 'Vendor.package1.package2.SomePlugin.SomeClass'})
# Invoke public static `GetInstance()` method
$SomeInstance = $SomeClassType::GetInstance()
$SomeInstance.SetSomething()
2。通过 Assembly.GetTypes()
发现类型元数据
As you've already found out ,[Assembly]::LoadFrom(...)
还返回一个 Assembly
对象,通过它我们可以发现它包含的类型:
# Load assembly, hold on to Assembly reference
$VendorAssembly = [System.Reflection.Assembly]::LoadFrom("c:\pathtodll\x64\vendor.dll")
# Get all contained types
$VendorTypes = $VendorAssembly.GetTypes()
# Same steps as above ...
[...] the dll is successfully loaded, I can access the public classes
在这种情况下,您还可以通过其中一种公共(public)类型访问程序集:
$VendorAssembly = [Vendor.package1.package2.SomePublicClass].Assembly
3。从 AppDomain
发现程序集元数据
如果您没有直接调用 Add-Type
或 [Assembly]::LoadFrom()
,而是尝试发现由GAC 中的程序集还是由模块间接加载?
幸运的是,我们可以让运行时告诉我们所有已通过 [AppDomain]
类加载的程序集:
# Enumerate all loaded assemblies
$AllAssemblies = [System.AppDomain]::CurrentDomain.GetAssemblies()
# Filter for the vendor assembly in question
$VendorAssembly = $AllAssemblies.Where({ $_.Location -like "C:\pathtodll\x64\vendor.dll" })
# Same steps as above
调用非公开成员
如果 GetInstance
也是非公开的,您可能必须使用反射来访问它:
# Use reflection to obtain a reference to the GetInstance method
$GetInstanceMethod = $SomeClassType.GetMethod("GetInstance", [System.Reflection.BindingFlags]'Static,NonPublic')
# Static methods need no invocation target, second argument is parameter args for the target method
$SomeInstance = $GetInstanceMethod.Invoke($null, @())
要调用实例方法,您需要传递对目标实例的引用:
# Use reflection to obtain a reference to the SetSomething method,
# Notice `Instance` instead of `Static` in the list of binding flags
$SetSomethingMethod = $SomeClassType.GetMethod("SetSomething", [System.Reflection.BindingFlags]'Instance,NonPublic')
# Pass the SomeClass instance we created in the previous example as the invocation target:
$RequestObject = $SetSomethingMethod.Invoke($SomeInstance, @())
关于c# - 如何从 Powershell 调用 GetInstance,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63532201/