1

Тема: VBScript: Как развернуть (активизировать) свернутое окно по его имени?

Всем привет! Сразу скажу, что я в этих скриптах ничего не понимаю. Столкнулся с такой задачей: необходимо развернуть форму подключения к терминалу "SERVER-Remote Desktop". Кому не лень, помогите пожалуйста!?;)

2

Re: VBScript: Как развернуть (активизировать) свернутое окно по его имени?

Обзор библиотеки AutoItX3.dll

3

Re: VBScript: Как развернуть (активизировать) свернутое окно по его имени?

Можно и без сторонних библиотек (пример на js)

var Shell = new ActiveXObject("WScript.shell")
Shell.AppActivate("Fear Factory - Slave Labor.mp3 - Media Player Classic")
Shell.SendKeys("~")

Где Fear Factory - Slave Labor.mp3 - Media Player Classic - полное название окна

4

Re: VBScript: Как развернуть (активизировать) свернутое окно по его имени?

Коллеги, подниму старую тему, т.к. давно работающий vbs-скрипт, преключающийся в окошко по имени методом "Shell.AppActivate", под системой Win-7 не активизирует окно, хотя визуально имя окна "Computer Managment" под 7-кой один к одному имени под Win XP.

Подскажите, плз: можно ли активизировать окно по имени процесса или его id, или подскажите - как скриптом получить перечень окон?

WBR. Roman

5

Re: VBScript: Как развернуть (активизировать) свернутое окно по его имени?

Rom5, если включён UAC, попробуйте сначала запуск имеющегося скрипта с правами администратора (elevate).

6

Re: VBScript: Как развернуть (активизировать) свернутое окно по его имени?

Скрипт запускается в HTA-приложении, которое в свою очередь работает от имени доменной админской учетки. И все остальные функции приложения работают прогнозируемо.
Надо как-то скриптами "уточнить" имя окна...

WBR. Roman

7

Re: VBScript: Как развернуть (активизировать) свернутое окно по его имени?

Rom5, Вы понимаете, что «от имени доменной админской учетки» и «elevate» — разные вещи.

8 (изменено: Xameleon, 2011-03-03 13:18:36)

Re: VBScript: Как развернуть (активизировать) свернутое окно по его имени?

Вообще в MSDN пишут следующее про параметры метода AppActivate

object
WshShell object.

title
Specifies which application to activate. This can be a string containing the title of the application (as it appears in the title bar) or the application's Process ID.

Раз он может быть ProcessID, то можем попробывать подсунуть его. Получить его можно, запустив приложение через WshShell.Exec

Собственно как то так.

Dim WshExec, ProcessID
Set WshShell = CreateObject("WScript.Shell")
Set WshExec = WshShell.Exec("notepad.exe")
ProcessID = WshExec.ProcessID
Do While WshExec.Status <> 1
    WshShell.AppActivate ProcessID
    WshShell.SendKeys "1"
    WScript.Sleep 1000
Loop

MsgBox "END"

Крутим цикл активации приложения до тех пор, пока оно не завершится.

Ну всё бы хорошо, только эффект всё равно невнятный какой то.

P.S Возникает только 1 вопрос - как может быть активация окна по ID процесса ?? А если у процесса несколько окон ? Какое тогда активизировать ? По логике для активации нужен hWnd. Обычный window handle, который передаётся в API функции. Это я бы понял, но вот по процессу...:| Что то я видимо ещё не изучил в этой схеме. )

P.P.S Да, и кстати рекомендую прислушаться к совету alexii. Я сам не проверял, но очень возможно, что дело именно в UAC.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

9

Re: VBScript: Как развернуть (активизировать) свернутое окно по его имени?

alexii пишет:

Rom5, Вы понимаете, что «от имени доменной админской учетки» и «elevate» — разные вещи.

Честно говоря, что это вещи разные - вижу, но, увы, пока еще не все понимаю - админская доменная учетка входит и в группу локальных администраторов, но ее действительно для запуска скрипта не хватает - сразу же ругается на строку с методом WshShell.Exec.

Если запускать под пользовательской учеткой с "Shift - Run as Administrator", то скрипт чудесно работает,  а это в моем случае - сначала проверяется перечень процессов, если интересующий процесс найден - беру его ID и метод WshShell.AppActivate нормально в окно процесса выполняет переключение (критичных "невнятностей" пока не увидел), если процесса не было, то он запускается и переключаемся. С этим все ОК, спасибо за подсказки!

В реальной работе мое HTA-приложение пользователь при работе под Win-7 запускает батником от имени админской учетки с помощью утилитки от Марка Руссиновича - PsExec. Утилита (в версии 1.98) имеет ключик:
"-h         If the target system is Vista or higher, has the process run with the account's elevated token, if available."
Но, увы, при совместном использовании его и ключа "-u  Specifies optional user name for login to remote computer." получаю на старте psexec сообщение "Access denied"

WBR. Roman

10

Re: VBScript: Как развернуть (активизировать) свернутое окно по его имени?

Rom5 пишет:

[..]
а это в моем случае - сначала проверяется перечень процессов, если интересующий процесс найден - беру его ID и метод WshShell.AppActivate нормально в окно процесса выполняет переключение (критичных "невнятностей" пока не увидел), если процесса не было, то он запускается и переключаемся. С этим все ОК, спасибо за подсказки!

Привожу код скрипта (под Win-7 будет возможность протестировать после праздников) для случая запуска оснастки управления компютером. В данном случае процесс я запускаю не через .Exec, а через .Run, т.к. все равно конкретная оснастка  запускается не прямым вызовом exe-шки. Под XP - пока без претензий)

'**** run_COMPMGMT.vbs **************************
' (COMPMGMT.MSC: opens the Computer management tool)
'
' Запуск "COMPMGMT" с набором имени машины
' Параметр - имя подключаемого компьютера
'
'************************************************

Option Explicit 

Dim giDebug
giDebug    = 0 ' 1-вывод отладочных сообщений и т.п. / 0 - обычный режим
' --- чтение своей инишки ----------------------------
' INI читается в случае ее наличия, 
' используется для переопеределения режима отладки (ищется строка: debug=...)
Const sMyINI = "run_COMPMGMT.ini"
Dim fso
Set fso=CreateObject("Scripting.FileSystemObject")
Dim CurDir
Dim yes_no, s, iPos
CurDir = fso.GetAbsolutePathName(".")
yes_no = fso.FileExists( CurDir & "\" & sMyINI)
If yes_no Then
    Dim fspi
    Set fspi=fso.OpenTextFile(sMyINI, 1)
    Do While not fspi.AtEndOfStream
        s = fspi.ReadLine
        iPos = InStr(1, s, "=")
        If iPos>0 Then
            If LCase(Trim(Left(s, iPos-1)))="debug" Then
                giDebug = CInt( Trim( Right(s, Len(s)-iPos) ) ) ' правая от "=" часть преобразовывается в целое число
            End IF
        End IF
    Loop
    fspi.Close
    Set fspi = Nothing
End IF '(yes_no)
Set fso = Nothing
' -----


Dim A
Set A=Wscript.Arguments

Dim sComp, sParamRD
sComp = ""
sParamRD = ""
If A.Count>=1 Then  ' имеется переданный параметр - имя компа
    sComp = A(0)
    If A.Count=2 Then  ' имеется переданный параметр - доп.параметр для запуска Remote Desktop
        sParamRD = A(1)
    End IF
else
    sComp = InputBox("Введите имя подключаемого компьютера", "Настройка запуска ""Computer Management""")
End IF


If sComp<>"" Then  ' имеется непустое имя компа

    Dim oShell
    Set oShell = WScript.CreateObject("WScript.Shell") 
    
    Dim sNmFileProcess : sNmFileProcess = "mmc.exe"
    Dim iProcessID : iProcessID = 0

    '--- Проверяем наличие процесса'
    Dim objWMIService, colProcesses, oPrc
    Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
    Set colProcesses = objWMIService.ExecQuery ("SELECT * FROM Win32_Process WHERE Name = '" & sNmFileProcess & "'")
    If colProcesses.Count = 0 Then '--- Запускаем свой процесс'
        oShell.Run "COMPMGMT.MSC", 1
        FuncAppendOneStrToTXTFile "run_COMPMGMT.log", Now() & " Start: " & "COMPMGMT.MSC"
        'надо опять искать процесс'
        Set colProcesses = objWMIService.ExecQuery ("SELECT * FROM Win32_Process WHERE Name = '" & sNmFileProcess & "'")
        If colProcesses.Count > 0 Then
            For Each oPrc In colProcesses
                If LCase(oPrc.Name)=LCase(sNmFileProcess) Then
                    FuncAppendOneStrToTXTFile "run_COMPMGMT.log", "name: " & oPrc.Name & " id:" & oPrc.ProcessID
                    iProcessID = oPrc.ProcessID
                    Exit FOR
                End IF
            Next
        End IF
        
    else '--- процесс существует, берем айди для преключения'
        FuncAppendOneStrToTXTFile "run_COMPMGMT.log",  Now() & " (i) Process found."
        For Each oPrc In colProcesses
            If LCase(oPrc.Name)=LCase(sNmFileProcess) Then
                FuncAppendOneStrToTXTFile "run_COMPMGMT.log", "name: " & oPrc.Name & " id:" & oPrc.ProcessID
                iProcessID = oPrc.ProcessID
                Exit FOR
            End IF
        Next
    End IF
    Set objWMIService = Nothing
    Set colProcesses = Nothing

    ' Dim sAppTitle
    ' sAppTitle = "Computer Management"
    
    If iProcessID=0 Then
        FuncAppendOneStrToTXTFile "run_COMPMGMT.log", "(!) Check start process: `" & sNmFileProcess & "` not found."
    else
        Dim ret : ret = false
        ret = oShell.AppActivate (iProcessID)

        Dim iSecAll, iSecWait, i, lTmp
        iSecAll = 10000 'всего отводим на попытку активации окна - 20сек
        iSecWait = 500  'время простоя
        While iSecAll>0 And (Not ret) ' выход из цикла - либо в окно переключились, либо время закончилось
            ret = oShell.AppActivate (iProcessID)
            If giDebug Then lTmp=FuncAppendOneStrToTXTFile( _
                "run_COMPMGMT.log", "Sleep: " & iSecWait & ", iSecAll: " & iSecAll & ",  ret: " & ret )
            If Not ret Then 
                WScript.Sleep iSecWait
                iSecAll = iSecAll - iSecWait
            End IF
        WEnd 
        Set oShell=Nothing 

        If ret Then 'при наличии успешного переключения - "набираем" имя компа

            WScript.Sleep 1000 ' 1 сек. дополнительного ожидания
            If giDebug Then lTmp=FuncAppendOneStrToTXTFile("run_COMPMGMT.log", Now() & " start sendkeys...")

            Dim oSHL
            Set oSHL = WScript.CreateObject("WScript.Shell") 
            oSHL.SendKeys("%")
            WScript.Sleep 200
            oSHL.SendKeys("A")
            oSHL.SendKeys("C")
            WScript.Sleep 500 ' 0.5 сек. дополнительного ожидания
            oSHL.SendKeys( sComp )
            Set oSHL=Nothing
            If giDebug Then lTmp=FuncAppendOneStrToTXTFile("run_COMPMGMT.log", "---- End OK: " & Now() )
            
        else
            If giDebug Then lTmp=FuncAppendOneStrToTXTFile("run_COMPMGMT.log", Now() &" Quit without sendkeys...")
            MsgBox "Неудачная попытка активации " & _
                chr(34)&sNmFileProcess&chr(34) & vbCrLf , _
                vbCritical, "Запуск оснастки управления компьютером"
        End IF
    End IF
    
else
    MsgBox "Goodbye!"

End IF ' (sComp<>"")
If giDebug Then lTmp=FuncAppendOneStrToTXTFile("run_COMPMGMT.log", vbCrLf)


'----------------функция---------------------------------------- 
'добавляет строчку в текстовый файл 
Function FuncAppendOneStrToTXTFile(FileName, StrText) 
   '------------------------Константы для задания типа открытия файла 
   Const ForReading = 1, ForWriting = 2, ForAppending = 8, OverwriteTrue = True, OverwriteFalse = False 
   ' Объявляем переменные 
   Dim  objFSO, FOut 
   ' Создаем объект FileSystemObject 
   Set  objFSO=WScript.CreateObject("Scripting.FileSystemObject") 
   ' Открываем выходной файл для записи 
   Set  FOut = objFSO.OpenTextFile (FileName,ForAppending,true) 
   ' Записываем текстовую строку в файл 
   FOut.WriteLine StrText' & vbcrlf 
   ' Закрываем выходной файл 
   FOut.Close 
   FuncAppendOneStrToTXTFile = true 
End Function 
'***************************************************************
WBR. Roman