注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

gmd20的个人空间

// 编程和生活

 
 
 

日志

 
 

献给那些想在.NET或者QTP的VBscript中使用STAF的人们  

2010-04-15 21:10:22|  分类: 程序设计 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

STAF( Software Testing Automation Framework http://staf.sourceforge.net/)是IBM推出的一个开源的测试平台,用于跨平台测试命令非常不错的,想了解的可以自己去看一下吧。

不过很遗憾,STAF并不提供.NET平台的C#, VB.Net这些语言的调用接口。可能是因为微软的产品不开放的原因? Linux平台也不能很好的支持.Net,所以那些作者只选择了可以支持多平台的语言来。我随便用VB.net写了简单的调用staf.dll中的c语言接口的类。这样就可以在.Net中使用STAF来执行远程命令来。我把它写成COM接口了,这样在VBscript等脚本语言中也可以调用了,在QTP测试工具中也可以调用STAF了。我是觉得QTP的终端模拟器不太好用,而且还要注册费很麻烦,其实在QTP中这样调用STAF应该是可以取代那些终端模拟器来执行远程命令等的。

有待增强的地方:

1、我只是简单的用正则出来了process那个service的返回,可能写个完整的解析类库比较好些吧。不过我没在STAF的主页看到marshalledData的详细定义文档,就不去进一步实现了。

2、其他STAF的service 的支持,这样也有待改进的。不过用的最多的还是process这个service吧。

总结遇到的问题:

1、C语言的Dll中的函数,(char **)指针的指针 已经其他指针类型,运用IntPtr类就可以解决了,结合ByRef 声明可以解决指针的声明问题。之后可以使用Marshal.PtrToStringAnsi 等函数从char 指针构建string变量。

2、STAF的C语言接口不是很完善的,我看了一下他的代码,是用C++写的,可能直接使用C++的接口封装一个COM端口还好一些。不过我前几天刚刚试了.Net里面实现COM的办法比较熟悉一些,而且C++的开发环境还没有,只有一个VB.Net2008 express 版的,所以我就用了VB.net了。直接用它的C解决去解析命令返回值是很麻烦的,我也尝试了一下,读出键值键值要麻烦死了,而且要用它的STAFstring_t 类型,而且有两个函数在他的文档中有说的,竟然代码里面没有实现,找不到。其实自己直接写个解析的类应该也不会很复杂的,真正在实际项目要用到话,还是实现一个吧。

3、我写这个东西主要是看QTP中的“终端模拟器”太难用了,所以看看能不能搞个接口给QTP里面的vbscript来用,我们现在用的“RUMBA”模拟终端来执行命令,还是要注册的,很不爽。其实这样使用STAF也是个不错的选择了。

代码:

===============Staf.vb=========================

Imports System.Runtime.InteropServices

Imports System.Text.RegularExpressions

<ComClass(Staf.ClassId, Staf.InterfaceId, Staf.EventsId)> _

Public Class Staf

Public Const ClassId As String = "22872C01-FFFA-4261-ADF1-24CA6E1F3C50"

Public Const InterfaceId As String = "CC8F3D9D-E27D-4f77-8275-B1275A3972B8"

Public Const EventsId As String = "F2D19D4B-79E6-4787-976B-488AD466CA2C"

Public Sub New()

MyBase.New()

End Sub

'STAFRC_t STAFRegister(char *processName, STAFHandle_t *handle);

'STAFRC_t STAFRegisterUTF8(char *processName, STAFHandle_t *handle);

'STAFRC_t STAFUnRegister(STAFHandle_t handle);

'STAFRC_t STAFSubmit(STAFHandle_t handle, char *where, char *service,

' char *request, unsigned int requestLength,

' char **resultPtr, unsigned int *resultLength);

'STAFRC_t STAFSubmitUTF8(STAFHandle_t handle, char *where,

' char *service, char *request,

' unsigned int requestLength,

' char **resultPtr,

' unsigned int *resultLength);

'STAFRC_t STAFSubmit2(STAFHandle_t handle, STAFSyncOption_t syncOption,

' char *where, char *service,

' char *request, unsigned int requestLength,

' char **resultPtr, unsigned int *resultLength);

'STAFRC_t STAFSubmit2UTF8(STAFHandle_t handle, STAFSyncOption_t syncOption,

' char *where, char *service, char *request,

' unsigned int requestLength,

' char **resultPtr,

' unsigned int *resultLength);

'STAFRC_t STAFFree(STAFHandle_t handle, char *result);

Private Declare Function STAFRegister Lib "STAF.dll" (ByVal processName As String, ByRef handle As UInteger) As UInteger

Private Declare Function STAFRegisterUTF8 Lib "STAF.dll" (ByVal processName As String, ByRef handle As UInteger) As UInteger

Private Declare Function STAFUnRegister Lib "STAF.dll" (ByVal handle As UInteger) As UInteger

Private Declare Function STAFSubmit Lib "STAF.dll" (ByVal handle As UInteger, _

ByVal where As String, _

ByVal service As String, _

ByVal request As String, _

ByVal requestLength As UInteger, _

ByRef resultPtr As IntPtr, _

ByRef resultLength As UInteger) As UInteger

Private Declare Function STAFSubmitUTF8 Lib "STAF.dll" (ByVal handle As UInteger, _

ByVal where As String, _

ByVal ByValservice As String, _

ByVal request As String, _

ByVal requestLength As UInteger, _

ByRef resultPtr As IntPtr, _

ByRef resultLength As UInteger) As UInteger

Private Declare Function STAFSubmit2 Lib "STAF.dll" (ByVal handle As UInteger, _

ByVal syncOption As UInteger, _

ByVal where As String, _

ByVal service As String, _

ByVal request As String, _

ByVal requestLength As UInteger, _

ByRef resultPtr As IntPtr, _

ByRef resultLength As UInteger) As UInteger

Private Declare Function STAFSubmit2UTF8 Lib "STAF.dll" (ByVal handle As UInteger, _

ByVal syncOption As UInteger, _

ByVal where As String, _

ByVal service As String, _

ByVal request As String, _

ByVal requestLength As UInteger, _

ByRef resultPtr As IntPtr, _

ByRef resultLength As UInteger) As UInteger

Private Declare Function STAFFree Lib "STAF.dll" (ByVal handle As UInteger, ByVal result As IntPtr) As UInteger

'===================================================================================

Private handle As UInteger = 0

Private processName As String = ""

Public Function Register(Optional ByVal handleName As String = "UnSet") As UInteger

If handleName = "UnSet" Then

processName = "MyStaf" + Guid.NewGuid.ToString()

Else

processName = handleName

End If

Register = STAFRegister(processName, handle)

End Function

Public Function UnRegister() As UInteger

UnRegister = STAFUnRegister(handle)

End Function

Public Function Submit(ByVal where As String, _

ByVal service As String, _

ByVal request As String) As Result

Dim res As New Result

res.returnCode = 0

res.outputText = ""

Dim str As New System.IntPtr(0)

str = IntPtr.Zero

Dim length As UInteger

res.returnCode = STAFSubmit(handle, where, service, request, request.Length, str, length)

If Not System.IntPtr.op_Equality(str, IntPtr.Zero) Then

If length > 0 Then

res.outputText = Marshal.PtrToStringAnsi(str)

End If

Dim freeOK = STAFFree(handle, str)

If freeOK <> 0 Then

res.outputText = res.outputText + vbCrLf + "free not Ok"

End If

End If

Submit = res

End Function

Public Function StartCMD(ByVal where As String, _

ByVal command As String) As Result

Dim res As New Result

res.returnCode = 0

res.outputText = ""

Dim str As New System.IntPtr(0)

str = IntPtr.Zero

Dim length As UInteger

Dim request As String = "start shell command " + command + " stderrtostdout returnstdout wait 1m" '

res.returnCode = STAFSubmit(handle, where, "process", request, request.Length, str, length)

If res.returnCode <> 0 Then 'staf

res.outputText = Marshal.PtrToStringAnsi(str)

StartCMD = res

Exit Function

End If

If Not System.IntPtr.op_Equality(str, IntPtr.Zero) Then

If length > 0 Then

res.outputText = Marshal.PtrToStringAnsi(str, length)

If IsStringMarshalledData(res.outputText) Then

ParserOutput(res)

End If

End If

Dim freeOK = STAFFree(handle, str)

If freeOK <> 0 Then

res.outputText = res.outputText + vbCrLf + "free not Ok"

End If

End If

StartCMD = res

End Function

Function IsStringMarshalledData(ByVal str As String) As Boolean

If str.StartsWith("@SDT/") Then

IsStringMarshalledData = True

Exit Function

End If

IsStringMarshalledData = False

End Function

'process service,

'result stafprocessservice

'CUnmarshall C++

'.

'process service

'-----------------------------------------------------------

'# @SDT<type><typeInfo>:<length>:<data>

' # @SDT/$S:<string-length>:<String>

'List # @SDT/[<number-of-items>:<array-length>:<SDT-Any-1>...<SDT-Any-n>

'map

' # @SDT/{:<map-length>::<key-1-length>:<key-1><SDT-Any>

' # ...

' # :<key-n-length>:<key-1><SDT-Any>

'map-class

' :::#@SDT/%:<map-class-instance-length>::<map-class-name-length>:<map-class-name>

' # <SDT-Any-value-1>

' # ...

' # <SDT-Any-value-n>

'---------------------------------------------------------------

' process service

' Service/Process/CompletionInfo

'{

' rc:

' key:

' fileList: ---map class STAF/Service/Process/ReturnFileInfo

' {

' list:[

' rc:

' data:

' ]

' }

'}

Private Function ParserOutput(ByRef res As Result) As Boolean

Dim marshalledData As String = res.outputText

Dim reg As New Regex("STAF\/Service\/Process\/CompletionInfo\@SDT/\$S\:\d+\:(\d+)\@SDT\/\$\d+\:\d+\:\@SDT\/\[")

Dim returnCodeMatch As Match = reg.Match(marshalledData)

If returnCodeMatch.Success = True Then

Dim a As Group = returnCodeMatch.Groups(0)

res.returnCode = CInt(returnCodeMatch.Groups(1).Value)

Else

ParserOutput = False

Exit Function

End If

Dim reg2 As New Regex("\@SDT\/\$S\:\d+\:(.*)", RegexOptions.Singleline)

marshalledData = marshalledData.Substring(marshalledData.LastIndexOf("@SDT/$S:"))

Dim outputMatch As Match = reg2.Match(marshalledData)

res.outputText = outputMatch.Groups(1).Value

ParserOutput = True

End Function

End Class

=================================================

Public Class Result

Public returnCode As Integer ‘运行命令的返回值

Public outputText As String   ‘命令的输出文本

End Class

-------------------------------。ne中的测试例程---------------------

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim mystaf As New Staf

        Dim ok As UInteger = mystaf.Register()

        If ok = 0 Then

            'Dim result As Result = mystaf.Submit("local", "process", "start shell command tasklist returnstdout wait")

            Dim result As Result = mystaf.StartCMD("local", "notepad")

            If result.returnCode <> 0 Then

                MsgBox("命令返回" + result.returnCode.ToString, MsgBoxStyle.Information, " 命令执行出错了")

            End If

            TextBox1.Text = result.outputText

            mystaf.UnRegister()

        End If

    End Sub

End Class

------------------test.vbs文件,vbscript中的测试例子-----------------------------------------------

Dim staf

Set staf = CreateObject("widebright.Staf")

    staf.Register()

dim result

set result =staf.StartCMD("local", "dir c:")

msgbox result.outputText

staf.UnRegister()

Set staf = Nothing

---------------

运行就可以看到命令的结果了,关于.Net类库的注册等参考我前面的文章。

  评论这张
 
阅读(1112)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017