Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Серверные продукты Microsoft » Microsoft Windows NT/2000/2003 » [решено] Как ограничить количество запущенных копий приложения на терминальном сервере?

Ответить
Настройки темы
[решено] Как ограничить количество запущенных копий приложения на терминальном сервере?

Аватара для SkyF

Vladimir


Сообщения: 1070
Благодарности: 17

Профиль | Отправить PM | Цитировать


Изменения
Автор: ShaddyR
Дата: 10-07-2006
Q: Можно ли на терминальном сервере Windows Server 2003 ограничить одновременное количество запусков определённой программы терминальным пользователям?
Цель: Имея Z пользователей терминальных, и N лицензий на Office 2003, как на сервере ограничить количество загрузок приложений Office, не более N-ти одновременно?
Возможно ли это?

A: Стандартных способов ограничения по количеству копий процесса я не смог найти, однако в WMI командах есть возможность выполнять отображение количество запущенных процессов. Поэтому я обратился к Центру сценариев и составил небольшой сценарий, который, работая резидентно – отслеживает процессы загрузки приложения , например блокнота (notepad.exe) или калькулятора (calc.exe) - по счетчику отслеживает количество работающих приложений. При этом, он виден как процесс wscript.exe в диспетчере задач.
В целях понимания работы программы даны всплывающие окна, потом их можно убрать.
* Для добавления других приложений можно модифицировать данные файла конфигурации (например, вместо notepad.exe указать winword.exe, добавить WinRAR и т.д.)
** Сценарий, указанный тут, предназначем для запуска в приложении Cscript.exe. Поэтому если программой для запуска сценариев по умолчанию она не является на вашей системе - вам необходимо добавить перед сценарием имя программу "cscript", например, cscript watcher.vbs.



Скрипт watcher.vbs
Код: Выделить весь код
Set Args = WScript.Arguments

' *******************************************
' Script, that allow to limit quantity of the
' started applications on a terminal server.
' The names of applications and the maximum
' quantity of simultaneously started spears
' are stored in config file.
'
' @authors: SkyF, hasherfrog
' @site: oszone.net
'

CONST FIELDS = 3
CONST PSNAME = 0
CONST PSNUMB = 1
CONST PSMAXN = 2

Dim thePsArray ( )
Dim nToWatch
nToWatch = 0

Function AddPsToWath( name, number )
 ReDim Preserve thePsArray ( FIELDS, nToWatch )
 thePsArray(PSNAME, nToWatch) = name
 thePsArray(PSNUMB, nToWatch) = number
 thePsArray(PSMAXN, nToWatch) = number
 addPsToWatch = nToWatch
 nToWatch = nToWatch + 1
End Function

' *******************************************

Sub ReadPsWatchFile(filename)
 Dim fso, f
' On Error Resume Next 
 Set fso = CreateObject("Scripting.FileSystemObject")
 Set f = fso.OpenTextFile(filename, 1, False)
 if Err.Number<>0 then
   call Error_(0)
 else
   while not f.atEndOfStream
     s = f.ReadLine
     ms = Split(s, " ", -1, vbBinaryComapre)
     s1 = ms(0)
     n2 = CInt(ms(1))
     n = AddPsToWath(s1, n2)
     Err.Clear
   wend
   f.Close
 end if 
End Sub

' *******************************************

Sub StartUpWatcher()

	strComputer = "."
	Set objWMIService = GetObject("winmgmts:" _
		& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")


	Set colMonitoredEvents = objWMIService.ExecNotificationQuery _
		("SELECT * FROM __InstanceOperationEvent WITHIN 1 WHERE " _
			& "Targetinstance ISA 'Win32_Process'")


    Do While 1
	Set objLatestProcess = colMonitoredEvents.NextEvent

	For psn=0 to nToWatch-1
	  If objLatestProcess.TargetInstance.Name = thePsArray(PSNAME, psn) Then
		Select Case objLatestProcess.Path_.Class
			Case "__InstanceCreationEvent"
				thePsArray(PSNUMB, psn) = thePsArray(PSNUMB, psn) - 1 
				If thePsArray(PSNUMB, psn) < 0 then
				  objLatestProcess.TargetInstance.Terminate
				  Wscript.Echo "Вы запустили лишнюю копию программы "&	objLatestProcess.TargetInstance.Name  _
							 & " - разрешенный лимит только " & thePsArray(PSMAXN, psn)
				End If

			Case "__InstanceDeletionEvent"
				thePsArray(PSNUMB, psn) = thePsArray(PSNUMB, psn) + 1 
		End Select
	  End If
	Next

   Loop
End Sub

' *******************************************

for i=0 to Args.count-1
 If Args(i) = "-f" Then 
  iaFilename = Args(i+1)
 End If
Next

If iaFilename<>"" Then
  Set fso = CreateObject("Scripting.FileSystemObject")
  If (fso.FileExists(iaFilename)) Then
	Call ReadPsWatchFile(iaFilename)
	If nToWatch=0 Then
	  Wscript.Echo "File is empty."
	Else
	  Call StartUpWatcher()
	End If
  Else
	Wscript.Echo "File exists not." 
  End If
Else
  Wscript.Echo "watcher.vbs -f config.txt" 
End If
Запуск
Код: Выделить весь код
watcher -f config.txt
Пример config.txt
Код: Выделить весь код
notepad.exe 2
calc.exe 3


После запуска сценария - он запускается резидентно и выполняет перехват событий запуска процесса, сравнивает название процесса с заранее заданными и в случае совпадения - передает управление счетчику. Если лимит будет исчерпан - для нового процесса будет вызван метод завершения.
Процесс может быть запущен из любой терминальной сессии, а сценарий должен запускаться от имени системы (те при запуске ОС)

Любые изменения приветствуются!

ЗЫ полезные ссылки:
http://www.microsoft.com/technet/scr.../shop0505.mspx
http://www.microsoft.com/technet/com...ts/sg0103.mspx
http://msdn.microsoft.com/library/de..._processes.asp (тут иной вариант - через получение списка из процессов – можно тоже попробовать)


Благодарим за доработку скрипта hasherfrog

Отправлено: 16:53, 15-04-2006

 

Аватара для hasherfrog

Старый параноик


Сообщения: 2423
Благодарности: 85

Профиль | Отправить PM | Цитировать


Гррр. Да я ж не скрипт новый написал :-) Я по старому хотел спросить: _уточнить_ его работу. Как он там вообще работает в полевых условиях, я ж не вижу :]

Ещё раз. У Вас скрипт запускает администратор? Один раз? Правильно? А потом скрипт умудряется контролировать всех остальных пользователей, так?

Отправлено: 15:25, 11-07-2006 | #21



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Аватара для ShaddyR

Железных Дел Мастер


Moderator


Сообщения: 24527
Благодарности: 4498

Профиль | Сайт | Отправить PM | Цитировать


hasherfrog
Цитата:
Да я ж не скрипт новый написал :-) Я по старому хотел спросить: _уточнить_ его работу. Как он там вообще работает в полевых условиях, я ж не вижу :]
по данным бетатестеров - намана). Просто ты говорил об терминале, затем просьба удалить строки.. звиняй, попутал с контекстом.
>
Цитата:
У Вас скрипт запускает администратор? Один раз? Правильно? А потом скрипт умудряется контролировать всех остальных пользователей, так?
угум-с. То бишь, скрипт сечет, что процессы в терминале запущены. Но команду тушить лишний отправляет не тому юзеру либо пытается в текущем юзере тушить копию с дескриптором запущенной где-то копии. Посему у него кроме мониторинга ничего не получается.

-------
[FAQ] Как определить аппаратную конфигурацию компьютера и правильно задать вопрос
-------
В благодарность за помощь нажимаем ссылочку "Полезное сообщение" внизу этого самого сообщения (подробнее). Помните: админ конфеты НЕ ПЬЁТ ;)
-------
Говори, что думаешь и думай, что говоришь! (c) || МОЙ ShaddyR.at.UA/blog - Как поменять термопасту за 100+ баксов


Отправлено: 15:34, 11-07-2006 | #22


Аватара для hasherfrog

Старый параноик


Сообщения: 2423
Благодарности: 85

Профиль | Отправить PM | Цитировать


ShaddyR
Так. Теперь такой момент (я сам не могу проверить). Что если на терминал-сервере сказать "net send имяпользователя 123123123", где имяпользователя - имя какого-нибудь пользователя, подключённого в настоящий момент. Только он увидит сообщение 123123123 (и увидит ли, кстати, вообще)?

Отправлено: 15:39, 11-07-2006 | #23


Аватара для hasherfrog

Старый параноик


Сообщения: 2423
Благодарности: 85

Профиль | Отправить PM | Цитировать


Молчание...
Ok, вот новая версия, отсылающая сообщение пользователю, превысившему лимит:
Код: Выделить весь код
Set Args = WScript.Arguments
iaFilename = "watcher.cfg"

' *******************************************
' Script, that allow to limit quantity of the
' started applications on a terminal server.
' The names of applications and the maximum
' quantity of simultaneously started spears
' are stored in config file.
'
' @authors: SkyF, hasherfrog
' @site: oszone.net
'

CONST FIELDS = 3
CONST PSNAME = 0
CONST PSNUMB = 1
CONST PSMAXN = 2

Dim thePsArray ( )
Dim nToWatch
nToWatch = 0

Function AddPsToWath( name, number )
 ReDim Preserve thePsArray ( FIELDS, nToWatch )
 thePsArray(PSNAME, nToWatch) = name
 thePsArray(PSNUMB, nToWatch) = number
 thePsArray(PSMAXN, nToWatch) = number
 addPsToWatch = nToWatch
 nToWatch = nToWatch + 1
End Function

' *******************************************

Sub ReadPsWatchFile(filename)
 Dim fso, f
' On Error Resume Next 
 Set fso = CreateObject("Scripting.FileSystemObject")
 Set f = fso.OpenTextFile(filename, 1, False)
 if Err.Number<>0 then
   call Error_(0)
 else
   while not f.atEndOfStream
     s = f.ReadLine
     ms = Split(s, " ", -1, vbBinaryComapre)
     s1 = ms(0)
     n2 = CInt(ms(1))
     n = AddPsToWath(s1, n2)
     Err.Clear
   wend
   f.Close
 end if 
End Sub

' *******************************************

Sub StartUpWatcher()

	strComputer = "."
	Set objWMIService = GetObject("winmgmts:" _
		& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")


	Set colMonitoredEvents = objWMIService.ExecNotificationQuery _
		("SELECT * FROM __InstanceOperationEvent WITHIN 1 WHERE " _
			& "Targetinstance ISA 'Win32_Process'")


    Do While 1
	Set objLatestProcess = colMonitoredEvents.NextEvent

	For psn=0 to nToWatch-1
	  If objLatestProcess.TargetInstance.Name = thePsArray(PSNAME, psn) Then
		Select Case objLatestProcess.Path_.Class
			Case "__InstanceCreationEvent"
				thePsArray(PSNUMB, psn) = thePsArray(PSNUMB, psn) - 1 
				If thePsArray(PSNUMB, psn) < 0 then
				  colProperties = objLatestProcess.TargetInstance.GetOwner(strNameOfUser, strUserDomain)
				  objLatestProcess.TargetInstance.Terminate
				  msg = "Вы запустили лишнюю копию программы "&	objLatestProcess.TargetInstance.Name _
					 & " - разрешенный лимит только " & thePsArray(PSMAXN, psn)
				  Set objShell = CreateObject("WScript.Shell")
				  objShell.Exec("%COMSPEC% /k net send " & strNameOfUser & " " & msg)
				End If

			Case "__InstanceDeletionEvent"
				thePsArray(PSNUMB, psn) = thePsArray(PSNUMB, psn) + 1 
		End Select
	  End If
	Next

   Loop
End Sub

' *******************************************

for i=0 to Args.count-1
 If (Args(i) = "-f") AND (i+1 < Args.count) Then 
  iaFilename = Args(i+1)
 End If
Next

Set fso = CreateObject("Scripting.FileSystemObject")
If (fso.FileExists(iaFilename)) Then
  Call ReadPsWatchFile(iaFilename)
  If nToWatch=0 Then
    Wscript.Echo "File is empty."
  Else
    Call StartUpWatcher()
  End If
Else
  Wscript.Echo "Config file is not found." 
End If
Требования: У пользователя на машине должна работать "Служба сообщений".
Фичи: поддерживается дефолтный конфиг-файл watcher.cfg
Это сообщение посчитали полезным следующие участники:

Отправлено: 16:44, 11-07-2006 | #24


Аватара для hasherfrog

Старый параноик


Сообщения: 2423
Благодарности: 85

Профиль | Отправить PM | Цитировать


Я вчера писал-писал новую версию скрипта (фичи перечислю ниже) и у меня вышла кошмарная вещь. Переименовывал файл конфига, перезатёр скрипт этим конфигом. Вырвав себе полголовы волос, лёг спать :-)

Уважаемые заказчики :-) :-) :-)
Хотелось бы узнать несколько вещей.

1. В последней версии есть требование, У пользователя на машине должна работать "Служба сообщений". Это вообще нормально? приемлимо? Стоит ли мне развивать скрипт дальше, основываясь на том положении, что у пользователя на машине БУДЕТ работать "Служба сообщений"?
2. Вопрос косвенно включает в себя (и вытекает из) 1 пункт. Стоит ли разрабатывать дальше, увешивая простенький скрипт (в том виде, что сейчас) новыми штучками-дрючками, которые повлекут за собой новые требования. У кого-то сложится мнение о наигранности этого вопроса; но я серьёзно. Я вот лично не люблю программ-утилит, в которых 90% фич не использую - и на фига они?

А фичи будут такие (если надо? надо ли? я чего-то засомневался)
1. Поиск себя в памяти (работающих процессах), это не позволит запускать скрипт дважды. Но есть натяжечка - поиск идёт по имени скрипта, соответственно, возникает требование на его имя, а следом тут же возникают несколько вопросов, которые и вовсе не хотелось бы решать - например, написание подробнейшей документации на все случаи жизни.
2. Выгрузка себя из памяти. Сейчас это можно только по ошибке и/или из "Диспетчера задач", мне надоело уже; плюс - не всегда ясно, какой именно процесс выгружать. Требования те же - ограничение на имя скрипта. Захотите благозвучно переименовать скрипт, придётся лезть и в его код.
3. Поддержка добавления программ для отслеживание "на лету". Кроме уже дважды упомянутого требования на имя, возникает требование на корректность командной строки. Мне откровенно не хочется писать полномасштбную защиту от дурака, а как следствие, получится скрипт, который работает только в умелых руках. Плюс, Возникнет неоднозначность в изменении параметров уже отслеживаемых задач (пример: в конфиге ноутпад можно запускать 3 раза, пользователь запустил 2, и тут админ вносит вручную директиву использовать только 1)
4. Вывод статуса. Фича полезная (сколько загружено, какие текущие установки), но вызывает ещё более стрёмные следствия. Куда и как выводить? Если в Echo, то скрипт "встанет", и в это время пользователь может начудить. Если в блонкот - а не мы ли отслеживаем блокноты? а если лимит кончился? :] В файл? А какой?
5. Считывание и проверка при старте скрипта исполняемых процессов. Уже запущенные процессы будут "посчитаны", из этого состояния и будут дальше вестись наблюдения. Но следствие такое: а что, если админ _специально_ хотел запустить себе лишний блокнот?

Я понимаю, что многие "но" выглядят надуманными. Просто для меня это принципиально - делать функционально, но не перегруженно. Всё дело в том, чтобы не превратить удобства в неудобства. Сейчас, например, админ сам контролирует всё. А при повышении "умности" скрипта это станет невозможным.
Жду ответов...

Отправлено: 10:40, 12-07-2006 | #25


Аватара для hasherfrog

Старый параноик


Сообщения: 2423
Благодарности: 85

Профиль | Отправить PM | Цитировать


Up. Вопросы всё ещё в силе...

Отправлено: 18:24, 12-07-2006 | #26


Аватара для ShaddyR

Железных Дел Мастер


Moderator


Сообщения: 24527
Благодарности: 4498

Профиль | Сайт | Отправить PM | Цитировать


По новой версии:
Работает, отсылает верно. Но лишнюю копию в чужом сеансе все еще не умеет закрывать.
>
Цитата:
Выгрузка себя из памяти.
добавь соответствующий ключ, как в свое время делали ДОСовские резиденты. Другими словами, watcher.vbs -d убивает первый встреченный процесс wscript.exe, а, скажем, watcher.vbs -x убивает ВСЕ процессы с данным именем (последнее можно использовать, если скрипт запускается для каждого пользователя терминала в отдельности).
>
Цитата:
Вывод статуса.
добавь, скажем, параметр -l, пусть выводит в указанный текстовый файл либо в файл с именем скрипта и расширением .log в текущей директории
>
Цитата:
Считывание и проверка при старте скрипта исполняемых процессов. Уже запущенные процессы будут "посчитаны", из этого состояния и будут дальше вестись наблюдения.
полезно, уже сталкивался при тестах.
Цитата:
В последней версии есть требование, У пользователя на машине должна работать "Служба сообщений".
если без этого не обойтись - записать как особенность работы скрипта. Мне интересно другое: даже при выключенной службе Messenger'a сообщения можно отсылать с использованием интерфейса Диспетчера Задач. Может, отсылку сообщений можно реализовать через этот механизм?
>
Минус в мелькании ДОС-окна в момент отправки сообщения пользователю. Можно прятать окно известной утилой либо реализовать другой механизм отсылки сообщений, чтобы не привязываться к статусу службы сообщений.

Итого:
1) нужна расширенная командная строка. Что-то типа
watcher.vbs
-f имя_конф_файла[.cfg]: загрузка параметров из файла конфигурации
-d : удаление первого встреченного процесса данного скрипта из памяти
-x : удаление всех найденных процессов данного скрипта из памяти
-l: имя_файла[.log]: вывод информации о текущих параметрах мониторинга процессов и значениях счетчиков
2) завершать неликвидную копию процесса в сеансе терминального клиента
3) скрывать окно сообщения net send\ попробовать другой механизм отправки сообщения

Что касается обработки ошибок - сделай минимум. Либо игнорировать их, либо, максимум - сливать их в текстовый файл, хоть и в папке temp. ИМХО скрипт не обещался быть рассчитаным на мальчиков-мажоров, а админ должен думать, что делает.

Можно еще добавить обработку режима работы, т. е. - один скрипт на всех либо по скрипту на каждого. Ессно, если разница в реализации версий не потребует полной переделки программы.

-------
[FAQ] Как определить аппаратную конфигурацию компьютера и правильно задать вопрос
-------
В благодарность за помощь нажимаем ссылочку "Полезное сообщение" внизу этого самого сообщения (подробнее). Помните: админ конфеты НЕ ПЬЁТ ;)
-------
Говори, что думаешь и думай, что говоришь! (c) || МОЙ ShaddyR.at.UA/blog - Как поменять термопасту за 100+ баксов


Отправлено: 20:00, 12-07-2006 | #27


Аватара для Butunin Klim

Ветеран


Сообщения: 1482
Благодарности: 117

Профиль | Отправить PM | Цитировать


А как сделать что бы он не выдавал сообщение а переключался на прошлы процесс?
Тобишь при запуске 2 приложения он бы переключался на 1. Это удобнее нежели выдавать сообщение

-------
Сообщение помогло? В знак благодарности НАЖМИТЕ ПОЛЕЗНОЕ СООБЩЕНИЕ

Мы зрим не то, что есть вокруг,
А то, что можем видеть зримо.
А то, что зреть не достижимо
Нам не узреть во век веков.

Мой веб-магазин товары Amway http://butunina.ru


Отправлено: 14:38, 08-04-2009 | #28


Новый участник


Сообщения: 5
Благодарности: 0

Профиль | Отправить PM | Цитировать


Здравствуйте! Я прочитал тему созданную и не понял немного. Как создать этот скрипт для 64 разрядную ОС, где его сохранять и как запуск проводить?

Отправлено: 02:40, 17-08-2011 | #29


Аватара для ShaddyR

Железных Дел Мастер


Moderator


Сообщения: 24527
Благодарности: 4498

Профиль | Сайт | Отправить PM | Цитировать


Цитата slava_89:
Как создать этот скрипт для 64 разрядную ОС »
этому скрипту фиолетова битность ОС
>
Цитата slava_89:
где его сохранять »
на жестком диске?
>
Цитата slava_89:
как запуск проводить »
добавить в список автозапускаемых программ строку
Цитата SkyF:
cscript "<путь к файлу>watcher.vbs" »

-------
[FAQ] Как определить аппаратную конфигурацию компьютера и правильно задать вопрос
-------
В благодарность за помощь нажимаем ссылочку "Полезное сообщение" внизу этого самого сообщения (подробнее). Помните: админ конфеты НЕ ПЬЁТ ;)
-------
Говори, что думаешь и думай, что говоришь! (c) || МОЙ ShaddyR.at.UA/blog - Как поменять термопасту за 100+ баксов


Отправлено: 11:23, 17-08-2011 | #30



Компьютерный форум OSzone.net » Серверные продукты Microsoft » Microsoft Windows NT/2000/2003 » [решено] Как ограничить количество запущенных копий приложения на терминальном сервере?

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
Win 2003 SP1 - Как ограничить количество подключений под одним логином? allzero Microsoft Windows NT/2000/2003 7 19-01-2009 14:19
Разное - Количество одновременно запущенных приложений или окон Sandjar Microsoft Windows 2000/XP 7 21-05-2008 16:28
[решено] Как на терминальном сервере 2003 у каждого нового юзера задать тему оформления? Angry Demon Microsoft Windows NT/2000/2003 7 23-10-2006 11:17
[решено] Как в списке принтеров на терминальном сервере сделать только 1 принтер,а не все rooty Microsoft Windows NT/2000/2003 7 23-09-2005 08:38
Как ограничить количество одновреммено качаемых файлов ? allalone Сетевые технологии 8 22-05-2004 03:12




 
Переход