MSH (codename Monad)

关注monad 关注脚本

导航

脚本也玩P/Invoke

既然MSH是基于.net的,那么理所当然也应该支持P/Invoke了。据我所知,原来在win32平台上,脚本能调用API的好像只有Perl可以,而官方的脚本从来没有这种能力。现在的话,MSH可以,IronPython应该也行吧。
不过MSH脚本不是programming language,不可能定义类啊,特性啊什么的。(貌似IronPython可以),那么怎么P/Invoke呢?答案显然就是:反射
下面看脚本:

$domain = [AppDomain]::CurrentDomain 
$name = New-Object Reflection.AssemblyName 'TestAssembly' 
$assembly = $domain.DefineDynamicAssembly($name, 'Run'
$module = $assembly.DefineDynamicModule('TestModule'
$type = $module.DefineType('TestType'

[Type[]]
$parameterTypes = [IntPtr], [string],[string], [int
$method = $type.DefineMethod("MessageBox", 'Public,Static,PinvokeImpl', [int], $parameterTypes


$ctor = [Runtime.InteropServices.DllImportAttribute].GetConstructor([string]) 
$attr = New-Object Reflection.Emit.CustomAttributeBuilder $ctor, 'user32' 
$method.SetCustomAttribute($attr

$realType = $type.CreateType() 
[object[]]
$args = [IntPtr]0, [string]'Bar',[string]'Foo', [int]0 
$realType.InvokeMember('MessageBox', 'Public,Static,InvokeMethod', $null, $null, $args

这个脚本显示一个MessageBox。
不过,这段脚本一点也不优雅,甚至用处不大,它不是脚本应该做的事情,如果真的需要这种能力,我们应该用VB,C#,或者为MSH写一个CmdLet。
但是它体现了Monad的哲学,让复杂的事情变的可能。

PS:脚本产生的Assembly是在当前的AppDomain里面,只有这个AppDomain卸载时,新的Assembly才会卸载。你也可以尝试建立一个新的AppDomain,最后卸载那个domain。但是这就涉及到AppDomain交互和序列化的问题了。利用反射你也可以做到。

posted on 2005-11-22 10:52  hayate  阅读(555)  评论(0编辑  收藏  举报