ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 2914|回复: 9

[求助] WScript.Shell 隐藏执行 并获取输出文本!

[复制链接]

TA的精华主题

TA的得分主题

发表于 2019-3-15 10:26 | 显示全部楼层 |阅读模式
本帖最后由 山中老人 于 2019-3-16 11:25 编辑

WScript.Shell  的 Run 可以隐藏没有办法获取输出;Exec 可以获取输出没有办法隐藏。
这真是个操蛋的事情,为了解决这个问题。找了几种办法都有问题。
用API管道:会不定期卡死在【ReadFile(hRead, sBuffer(0), 64, lgSize, ByVal 0&)】这个步骤上,导致程序崩溃! 还有API管道经常遭到杀毒软件拦截
用WScript 的Run与Exec组合:在VBA中无法获取到WScript对象

最后只好使用DOS的重定向输出,把输出文本写入到一个文件,再从文件中获取。

下面是演示代码:
RunStr:执行命令,获取输出文本
RunBatStr:批处理封装执行命令,获取输出文本(由于重定向会干扰部分命令的参数,需要使用批处理文件封装命令

Public Function Run(ByVal CMD As String, Optional ByVal ErrVisible As Boolean = True) As Long '执行 等待结果
    Run = 0
    On Error GoTo err1
    Dim SubName As String, SubTxt As String
    SubName = "Run"
    SubTxt = "执行等待结果" '
   
    Dim oShell As IWshRuntimeLibrary.WshShell
    Set oShell = CreateObject("WScript.Shell")
    Run = oShell.Run(CMD, 0, True)
    Set oShell = Nothing
    Exit Function
err1:
'    If ErrVisible Then Call ErrMsBox(ERR, SubName, SubTxt & " 失败!" & Chr(13) & CMD)
End Function


Public Function RunStr(ByVal CMD As String, Optional ByVal ErrVisible As Boolean = True) As String  '执行 获取返回文本
    On Error GoTo err1
    Dim SubName As String, SubTxt As String
    SubName = "RunStr"
    SubTxt = "执行,获取返回" '


    Dim fso As New Scripting.FileSystemObject
    Dim TF As TextStream, i As Long
    Dim TmpP As String, BatPF As String, LogPf As String, Name As String
    '--文件位置
    TmpP = Environ("TEMP")


    '--设置临时文件
loop1:
    Name = RndStr(8, 2) '临时文件名
    LogPf = TmpP & "\" & Name & ".log"
    If Dir(LogPf) <> "" Then GoTo loop1
   
    '执行
    Dim CMDStr As String
    CMDStr = CMD & " > """ & LogPf & """"
'    Debug.Print CMDStr
    Run CMDStr, ErrVisible '执行
    '--获取输出
    Set TF = fso.OpenTextFile(LogPf, ForReading, False, TristateMixed)  '打开输出文件
    If TF Is Nothing Then GoTo err1
    RunStr = TF.ReadAll
    TF.Close
    '--删除临时文件
    On Error Resume Next
    If fso.FileExists(LogPf) Then fso.DeleteFile LogPf
    Set TF = Nothing
    Set fso = Nothing
    Exit Function
err1:
'    If ErrVisible Then Call ErrMsBox(ERR, SubName, SubTxt & " 失败!" & Chr(13) & CMD)
    Set TF = Nothing
    Set fso = Nothing
End Function


Public Function RunBatStr(ByVal CMDs As String, Optional ByVal ErrVisible As Boolean = True) As String  '执行 获取返回文本
    On Error GoTo err1
    Dim SubName As String, SubTxt As String
    SubName = "RunBatStr"
    SubTxt = "批处理封装执行,获取返回" '

    Dim fso As New Scripting.FileSystemObject
    Dim TF As TextStream, i As Long
    Dim TmpP As String, BatPF As String, LogPf As String, Name As String
    '--文件位置
    TmpP = Environ("TEMP")


    '--设置临时文件
loop1:
    Name = RndStr(8, 2) '临时文件名
    BatPF = TmpP & "\" & Name & ".*"
    If Dir(BatPF) <> "" Then GoTo loop1
    BatPF = TmpP & "\" & Name & ".bat"
    LogPf = TmpP & "\" & Name & ".log"


    '--创建BAT文件
    Set TF = fso.CreateTextFile(BatPF, True)  '新建文件
    If TF Is Nothing Then GoTo err1
    Call TF.Write(CMDs)
    TF.Close
    '--执行BAT文件
    Dim CMDStr As String
    CMDStr = """" & BatPF & """ >> """ & LogPf & """"
    'Debug.Print CMDstr
    Run CMDStr, ErrVisible '执行
    '--获取输出
    Set TF = fso.OpenTextFile(LogPf, ForReading, False, TristateMixed)  '打开输出文件
    If TF Is Nothing Then GoTo err1
    RunBatStr = TF.ReadAll
    TF.Close
    '--删除临时文件
    On Error Resume Next
    fso.DeleteFile TmpP & "\" & Name & ".*"
    Set TF = Nothing
    Set fso = Nothing
    Exit Function
err1:
'    If ErrVisible Then Call ErrMsBox(ERR, SubName, SubTxt & " 失败!" & Chr(13) & CMDs)
    Set TF = Nothing
    Set fso = Nothing
End Function


Public Function RndStr(ByVal Length As Long, ByVal Level As Long) As String
    'Length=字符长度
    'Level=字符等级。1级=数字,2级=数字+小写字母,3级=数字+大小写字母,4级=数字+大小写字母+符号
    On Error GoTo err1
    Dim SubName As String, SubTxt As String
    SubName = "RndStr"
    SubTxt = "取随机字符串"
   
    If Length < 1 Then Exit Function
    Dim allstr As String, substr As String, Txt As String, i As Long
    allstr = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()"
    Select Case Level
    Case 1
        i = 10
    Case 2
        i = 36
    Case 3
        i = 62
    Case Else
        i = Len(allstr)
    End Select
    substr = Left(allstr, i)
'    Debug.Print substr
    Txt = ""
    For i = 1 To Length
        Txt = Txt & Mid(substr, Int(Rnd * i + 1), 1)
    Next
    RndStr = Txt
    Exit Function
err1:
'    Call ErrMsBox(ERR, SubName, SubTxt & " 失败!")
End Function




评分

2

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-3-16 06:05 | 显示全部楼层
本帖最后由 山中老人 于 2019-3-16 09:45 编辑

这是一个将命令Ping 封装的函数

Public Function Ping(ByVal IP As String, Optional ByVal TimeOut As Long = 1000) As Boolean
    'IP=目标主机IP
    'TimeOut=等待时间(毫秒)
    On Error GoTo err1
    Dim SubName As String, SubTxt As String
    SubName = "Ping"
    SubTxt = "检测远程主机IP"
   
    If TimeOut < 10 Then TimeOut = 10 '最小等待时间(毫秒)
    Dim CMD As String, Txt As String
    CMD = "CMD /c Ping -n 1 -w " & TimeOut & " " & IP
    Txt = Me.RunStr(CMD, TimeOut + 100)
    If Txt = "" Then Exit Function
'    Debug.Print Txt
    Dim Str As String
    Str = ": bytes=32 time"
    If VBA.InStr(1, Txt, Str) > 0 Then
        Ping = True
        GoTo Exit1
    End If
    Str = "的回复: 字节=32 时间"
    If VBA.InStr(1, Txt, Str) > 0 Then
        Ping = True
        GoTo Exit1
    End If
Exit1:
    Exit Function
err1:
    Call ErrMsBox(ERR, SubName, SubTxt & " 错误!")
End Function



TA的精华主题

TA的得分主题

发表于 2019-3-16 06:47 | 显示全部楼层
‘用暴力法凑了一个,,,

Option Explicit

Sub test()
  Dim filename
  filename = "d:\abc.txt"
  Shell "cmd.exe /c" & "ipconfig/all>" & filename
  Do
    DoEvents
    If Len(Dir(filename)) Then
      Do
        DoEvents
        If FileLen(filename) > 0 Then
          Open filename For Input As #1
          Debug.Print StrConv(InputB(LOF(1), 1), vbUnicode)
          Close #1
          Exit Sub
        End If
      Loop
    End If
  Loop
End Sub

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-3-16 10:07 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
一把小刀闯天下 发表于 2019-3-16 06:47
‘用暴力法凑了一个,,,

Option Explicit

你这个 实际用用,你就知道了,小问题不少!

TA的精华主题

TA的得分主题

发表于 2019-3-16 10:36 | 显示全部楼层
山中老人 发表于 2019-3-16 10:07
你这个 实际用用,你就知道了,小问题不少!

可以举个例子看看。觉得应该有几个问题:

未删除上次产生的文件(先判断进行删除)
cmd进行批处理进行多次写入文件(建立临时文件再复制或改名)
输出文件长度为0(加个延时判断)

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-3-16 11:23 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
一把小刀闯天下 发表于 2019-3-16 10:36
可以举个例子看看。觉得应该有几个问题:

未删除上次产生的文件(先判断进行删除)

主楼就是用来演示的,你把关键点找到就好了。

这种程序都是自己写自己用,很多问题在实际使用中才能发现!

TA的精华主题

TA的得分主题

发表于 2022-7-12 14:44 | 显示全部楼层
测试RunStr函数时,在Run CMDStr, ErrVisible这一行执行之后就结束了,在Temp文件夹中也没有看到生成的临时文件。求解答。

TA的精华主题

TA的得分主题

发表于 2022-7-12 14:59 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
用exec执行pythonw.exe这种不弹窗的(nodejs也有模块),可以获取stdout且没有弹窗

TA的精华主题

TA的得分主题

 楼主| 发表于 2022-7-12 21:59 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
游乐缘 发表于 2022-7-12 14:44
测试RunStr函数时,在Run CMDStr, ErrVisible这一行执行之后就结束了,在Temp文件夹中也没有看到生成的临时 ...

可以替换临时文件存储位置:
TmpP = Environ("TEMP")

将最后 删除临时文件 的代码注释掉:
If fso.FileExists(LogPf) Then fso.DeleteFile LogPf
fso.DeleteFile TmpP & "\" & Name & ".*"

TA的精华主题

TA的得分主题

发表于 2022-7-13 09:43 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
山中老人 发表于 2022-7-12 21:59
可以替换临时文件存储位置:
TmpP = Environ("TEMP")

感谢楼主回复。
替换存储位置以及注释删除临时文件,仍是到“Run CMDStr, ErrVisible”这行就结束了。
后来换成“Shell CMDStr”就可以了,也许是版本方面的问题吧。
再次感谢楼主的分享!
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-4-16 23:49 , Processed in 0.045636 second(s), 11 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表