VBA SendKeys到特定窗口

时间:2014-01-08 14:12:37

标签: linux bash excel-vba cygwin vba

我有一个电子表格,总结了服务器的用法。当我让VBA通过Windows命令提示符(和Cygwin)向Linux服务器发送一些命令时,电子表格引用了一个更新的文本文件。我的问题是,我发现在Cygwin中执行命令的唯一方法是通过SendKeys命令。这导致两个问题:

  1. 我必须相信,在脚本完成运行之前,用户不会单击某处。
  2. 我必须硬编码在下一个命令发送之前等待命令执行的时间。
  3. 我会(并且确实)尝试创建一个在Cygwin中运行的bash文件,但我不知道这样做的方法还允许用户输入他们的密码来登录Linux服务器。我目前从执行主代码之前运行的UserForm获取用户密码。然后,此密码将保存到“非常隐藏”的工作表中,该工作表将在应用程序关闭时删除。

    我目前正在使用以下脚本来运行命令:

    Public Sub test()
        ' Declare Variables
        Dim cmd As String
        Dim ret As Double
        Dim LastRow As Integer
        Dim PssWrd As String
    
        PssWrd = Worksheets("PssWrd").Range("A1").Value
    
        ' Run Linux Commands
        cmd = "C:\cygwin\Cygwin.bat"
        ret = Shell(cmd, vbMinimizedFocus)
        wait 0.02
        cmd = "ssh " & Worksheets("Settings").Range("LOGIN") & "~" ' Format: user@hostname
        SendKeys cmd
        cmd = PssWrd & "~"
        SendKeys cmd
        wait 2.78
        cmd = "{(} date ; fs ; qstat ; date {)} > & zout &~"
        SendKeys cmd
        cmd = "exit~"
        SendKeys cmd
        wait 0.5
        cmd = "exit~"
        SendKeys cmd
        wait 5
        ' Update PivotTable and other data
    End Sub
    Public Sub wait(PauseTime As Double)
        Dim Start As Double
        Dim Finish As Double
        Dim TotalTime As Double
        Start = Timer    ' Set start time
        Do While Timer < Start + PauseTime
            DoEvents    ' Yield to other processes
        Loop
        Finish = Timer    ' Set end time
        TotalTime = Finish - Start    ' Calculate total time
    End Sub
    

    有没有办法至少将键击发送到特定窗口而不仅仅是活动窗口?任何帮助将不胜感激,并将提供任何其他必要的信息。

1 个答案:

答案 0 :(得分:1)

好。我想我找到了解决方案。感谢所有的帮助(@anishsane)指向我正确的方向!这是我更新的代码:

Public Sub test()
    ' Declare Variables
    Dim cmd As String
    Dim ret As Double
    Dim LastRow As Integer
    Dim PssWrd As String
    Dim WshShell As Object
    Dim plink_object As Object

    PssWrd = Worksheets("PssWrd").Range("A1").Value

    ' Run Linux Commands
    Set WshShell = CreateObject("WScript.Shell")
    On Error Resume Next
    Set plink_object = WshShell.Run("""C:\Program Files (x86)\PuTTY\plink.exe"" -ssh " & Worksheets("Settings").Range("LOGIN") & " -pw " & PssWrd & " ""(date; fs; qstat; date) > &zout&""", 7, True)
    On Error GoTo 0
    ' Update PivotTable and other data
End Sub

显然,在VBA中不需要WScript。此外,wshshell.exec似乎在某些时候失败,因为命令永远不会被执行(尽管PuTTY / Plink已启动)。由于某种原因,WshShell.Run命令导致“运行时错误'424':对象需要”错误,但命令的基本部分仍然正确执行,所以我只是忽略了错误。我也想出了如何在一行中执行我的命令,所以我不必担心以前没有工作的stdIn.Write命令。我可以使用Shell()命令,但是我需要确保命令已经完成执行(通过bWaitOnReturn选项)以确保我在更新脚本时拥有最新的文件运行。话虽如此,我相信由于我让Linux将命令输出写入文件,因此当VBA表示命令已完成执行时,文件尚未完成更新。但是,我相信我已经找到了一种方法来检查文件的最后一行是否正确格式化(因为它应该是日期),所以这应该不是问题。