Что нового

как завершить сеанс определенного терминального пользователя ?

mitiya

Новичок
Сообщения
75
Репутация
0
можно конечно запустить подобный код в командной строке

Код:
echo вычисляем ID сессии пользователя
SET ID_SES="null"
for /f "tokens=3" %%i in ('Query session username') do (
set ID_SES=%%i
)
 
echo завершаем сеанс пользователя по его ID
logoff %ID_SES%

но хотелось бы обойтись без батника внутри autoit скрипта
 

MnM

Post-Hardcore
Сообщения
679
Репутация
90
Код:
Run("Logoff.exe "&$ID)

Вот только как узнать ID требуемого пользователя не знаю, в вашем коде вроде бы идет перечисление но не совсем понятно что и откуда там(не знаю синтаксиса "батников")
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,486
Код:
Shutdown(0)
 
Автор
M

mitiya

Новичок
Сообщения
75
Репутация
0
Код:
Shutdown(0)


это действует на самого себя.

а с батником выяснилась еще одна проблема.

если его просто запустить то все ок. Но если его запустить из скрипта в 64х битной системе, то
он запускается почему-то из cmd ,которая находится по адресу C:\Windows\SysWOW64\cmd.exe, и вероятно из-за этого он пишет что
"Query" не является внутренней или внешней командой. При чем даже если я принудительно указываю что нужно использовать C:\Windows\system32\cmd.exe . Все равно, если посмотреть в том же ProcessHacker видно, что используется C:\Windows\SysWOW64\cmd.exe
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,486
mitiya [?]
если его запустить из скрипта в 64х битной системе, то
он запускается почему-то из cmd ,которая находится по адресу C:\Windows\SysWOW64\cmd.exe
У меня 64 битная система, и скрипт запускает cmd.exe с папки system32.

"Query" не является внутренней или внешней командой
А что если при запуске указать рабочий каталог (в виде системной папки)?
 
Автор
M

mitiya

Новичок
Сообщения
75
Репутация
0
путь и command line указывают на system32, но некое image file neme на C:\Windows\SysWOW64\cmd.exe
и не понятно как это обойти. Да и честно говоря не очень и хочется. Проблему хотелось бы решить без вызова внешнего батника.
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Есть функция WTSLogoffSession(), здесь, завершает сеанс текущего пользователя на текущем сервере, передавайте первым параметром id сессии нужного вам пользователя.

Код:
Global Const $WTS_CURRENT_SERVER_HANDLE = 0
Global Const $WTS_CURRENT_SESSION = -1

WTSLogoffSession()

Func WTSLogoffSession($SessionId = $WTS_CURRENT_SESSION,$hServer = $WTS_CURRENT_SERVER_HANDLE,$bWait = False)
	Local $aRet = DllCall('Wtsapi32.dll','BOOL','WTSLogoffSession','HANDLE',$hServer,'DWORD',$SessionId,'BOOL',$bWait)
	If @error Or Not IsArray($aRet) Or $aRet[0] = 0 Then Return SetError(1,0,0)
	Return $aRet[0]
EndFunc


http://msdn.microsoft.com/en-us/library/aa383836(v=vs.85).aspx
 
Автор
M

mitiya

Новичок
Сообщения
75
Репутация
0
вот как раз id то и не понятно как получить без батника
 

joiner

Модератор
Локальный модератор
Сообщения
3,557
Репутация
628
http://autoit-script.ru/index.php/topic,11239.0.html
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Получить ID, Имя и другую инфу можно из этого примера ;D
Код:
#include <Array.au3>
Global Const $WTS_CURRENT_SERVER_HANDLE = 0
$aData = WTSEnumerateSessionsEx()
_ArrayDisplay($aData, 'Массив текущих сессий', Default, Default, Default, Default, '№|ExecEnvId|State|SessionId|SessionName|HostName|UserName|DomainName|FarmName')

Func WTSEnumerateSessionsEx($hServer = $WTS_CURRENT_SERVER_HANDLE)
	Local $aRet = DllCall('Wtsapi32.dll', 'BOOL', 'WTSEnumerateSessionsEx', 'HANDLE', $hServer, 'DWORD*', 1, 'DWORD', 0, 'PTR*', 0, 'DWORD*', 0)
	If @error Or Not IsArray($aRet) Or $aRet[0] = 0 Then Return SetError(1, 0, 0)

	Local $Offset = 0, $tInfo
	Local Const $TAG_WTS_SESSION_INFO_1 = 'DWORD ExecEnvId;uint State;DWORD SessionId;PTR SessionName;PTR HostName;PTR UserName;PTR DomainName;PTR FarmName;'

	Local Enum $iExecEnvId, $iState, $iSessionId, $iSessionName, $iHostName, $iUserName, $iDomainName, $iFarmName, $iLAST
	Local $aOut[$aRet[5]][$iLAST] ;Выходной массив
	For $i = 1 To $aRet[5]
		$tInfo = DllStructCreate($TAG_WTS_SESSION_INFO_1, $aRet[4] + $Offset)
		$Offset += DllStructGetSize($tInfo)
		$aOut[$i - 1][$iExecEnvId] = DllStructGetData($tInfo, 'ExecEnvId')
		$aOut[$i - 1][$iState] = DllStructGetData($tInfo, 'State')
		$aOut[$i - 1][$iSessionId] = DllStructGetData($tInfo, 'SessionId')
		$aOut[$i - 1][$iSessionName] = DllStructGetData(DllStructCreate("char[" & 1024 & "]", DllStructGetData($tInfo, 'SessionName')), 1)
		$aOut[$i - 1][$iHostName] = DllStructGetData(DllStructCreate("char[" & 1024 & "]", DllStructGetData($tInfo, 'HostName')), 1)
		$aOut[$i - 1][$iUserName] = DllStructGetData(DllStructCreate("char[" & 1024 & "]", DllStructGetData($tInfo, 'UserName')), 1)
		$aOut[$i - 1][$iDomainName] = DllStructGetData(DllStructCreate("char[" & 1024 & "]", DllStructGetData($tInfo, 'DomainName')), 1)
		$aOut[$i - 1][$iFarmName] = DllStructGetData(DllStructCreate("char[" & 1024 & "]", DllStructGetData($tInfo, 'FarmName')), 1)
	Next

	;Освобождаем буфер
	Local Const $WTSTypeSessionInfoLevel1 = 2 ;??? не уверен
	DllCall('Wtsapi32.dll', 'BOOL', 'WTSFreeMemoryEx', 'UINT', $WTSTypeSessionInfoLevel1, 'PTR', $aRet[4], 'ULONG', $aRet[5])

	Return SetError(0, 0, $aOut)
EndFunc   ;==>WTSEnumerateSessionsEx
 

joiner

Модератор
Локальный модератор
Сообщения
3,557
Репутация
628
inververs
в опциональных параметрах лучше оставить параметр по умолчанию. иначе каша получается
то есть не Default а то, что в справке
 
Автор
M

mitiya

Новичок
Сообщения
75
Репутация
0
inververs

что-то у меня в 2003 этот код вообще не запускается. причем ни ошибки ни чего.

в 7ке показывает 2 строки с [0]Default0Default4Default0DefaultServicesDefault0Default0Default0Default0 и [1]Default1Default0Default1DefaultConsoleDefault0DefaultmitiyaDefaultpredatorDefault0. Но это может из-за того что тут rdp сессий нет, хз.
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
joiner
По логике, в место Default и должно подставлятся значение по умолчанию..
В какой то бете функция _ArrayDisplay была переписана под это требование.


mitiya
Да точно, в 2003 работать не будет, минимум windows 7 или server 2008 R2...

Тогда так:
Код:
#include <Array.au3>

Global Const $WTS_CURRENT_SERVER_HANDLE = 0
Global Const $WTS_CURRENT_SESSION = -1
Global Const $WTSUserName = 5

$aData = WTSEnumerateSessions()
_ArrayDisplay($aData,'Массив текущих сессий',-1,0,'','|','№|SessionId|SessionName')

Func WTSEnumerateSessions($hServer = $WTS_CURRENT_SERVER_HANDLE)
	;Windows XP; Windows Server 2003
	Local $aRet = DllCall('Wtsapi32.dll', 'BOOL', 'WTSEnumerateSessions', 'HANDLE', $hServer, 'DWORD', 0, 'DWORD', 1, 'PTR*', 0, 'DWORD*', 0)
	If @error Or Not IsArray($aRet) Or $aRet[0] = 0 Then Return SetError(1, 0, 0)

	Local $Offset = 0, $tInfo
	Local Const $TAG_WTS_SESSION_INFO = 'DWORD SessionId;PTR WinStationName;UINT State;'

	Local Enum $iSessionId,$iUserName,$iLAST
	Local $aOut[$aRet[5]][$iLAST] ;Выходной массив
	For $i = 1 To $aRet[5]
		$tInfo = DllStructCreate($TAG_WTS_SESSION_INFO, $aRet[4] + $Offset)
		$Offset += DllStructGetSize($tInfo)
		$aOut[$i - 1][$iSessionId] = DllStructGetData($tInfo, 'SessionId')
		$aOut[$i - 1][$iUserName] = WTSQuerySessionInformation($aOut[$i - 1][$iSessionId])
	Next

	;Освобождаем буфер
	DllCall('Wtsapi32.dll', 'NONE', 'WTSFreeMemory', 'PTR', $aRet[4])

	Return SetError(0,0,$aOut)
EndFunc

Func WTSQuerySessionInformation($SessionId = $WTS_CURRENT_SESSION, $WTSInfoClass = $WTSUserName, $hServer = $WTS_CURRENT_SERVER_HANDLE)
	Local $aRet = DllCall('Wtsapi32.dll', 'BOOL', 'WTSQuerySessionInformation', 'HANDLE', $hServer, 'DWORD', $SessionId, 'UINT', $WTSInfoClass, 'PTR*', 0, 'DWORD*', 0)
	If @error Or Not IsArray($aRet) Or $aRet[0] = 0 Then Return SetError(1, 0, 0)
	Local $sOut = DllStructGetData(DllStructCreate('char[' & $aRet[5] & ']', $aRet[4]), 1)
	DllCall('Wtsapi32.dll', 'NONE', 'WTSFreeMemory', 'PTR', $aRet[4])
	Return SetError(0, 0, $sOut)
EndFunc   ;==>WTSQuerySessionInformation
 
Верх