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

Компьютерный форум 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

 
S_M S_M вне форума

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


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

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


добавить в список автозапускаемых программ строку

Прошу прощения, а где это надо добавлять? Сервер 2008 SP2, пользователь Администратор логинится автоматически. Думал, в свойствах пользователя прописать файл, который запускался бы при запуске - бесполезно (выдает ошибку при логине и сеанс завершается). Добавил в папку "Автозагрузка" - не работает! Через планировщик пытался (запускаю от имени SYSTEM) - задание просто висит в статусе "Это задание выполняется в настоящий момент", в процессах он есть, но ничего не происходит Плюнул на все, зашел терминально под Администратором, запустил, всё работает! Только если другие пользователи запускают лишние копии, то ругань идет в сеанс Администратору. Убрал из скрипта строки:
Код: Выделить весь код
Wscript.Echo "Вы запустили лишнюю копию программы "&	objLatestProcess.TargetInstance.Name  _
	 & " - разрешенный лимит только " & thePsArray(PSMAXN, psn)
Сообщения валить перестали, но только отключаешься от сеанса администратора (не завершаешь сеанс, а делаешь отключение) - скрипт перестает работать
В общем, помогите правильно прописать этот скрипт в автозагрузке (если можно в подробностях - как для дебилов).
Спасибо!

Отправлено: 20:01, 28-08-2011 | #31



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

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


Аватара для ShaddyR

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


Moderator


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

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


Цитата S_M:
в свойствах пользователя прописать файл »
не пойдет - ты его пытаешься установить как среду для запуска, это неверно.
Поставь его запуск в соотв. раздел реестра, подраздел RUN, пусть стартует под консольной учеткой, если таковая предусмотрена.

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


Отправлено: 21:10, 28-08-2011 | #32

S_M S_M вне форума

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


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

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


Поставь его запуск в соотв. раздел реестра, подраздел RUN

Поставил, перегрузил сервер - ничего не поменялось. В процессах программы нет, ограничения не работают.
Блин. Есть у кого-нибудь готовый кусок реестра с прописанной программулиной? Ну, капец просто. Элементарщина вроде, а не получается. Кошмар.

пусть стартует под консольной учеткой

Это как?

Отправлено: 21:54, 31-08-2011 | #33


Аватара для ShaddyR

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


Moderator


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

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


Цитата S_M:
Это как? »
консольная - та, под которой сервер загружается там, где стоит, не терминальная. Есть таковая?

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


Отправлено: 22:13, 31-08-2011 | #34


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


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

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


Запускается на хосте один раз резидентно. Всё оттестировано и работает.

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

'Протоколирование в одноимённый log файл
Sub AppLog( aMessage )
Dim fso, f, flnm, renflnm, dtmstr
flnm = Replace(Wscript.ScriptFullName,".vbs",".log")
Set fso = CreateObject("Scripting.FileSystemObject")
If (fso.FileExists(flnm)) Then
Set f = fso.GetFile(flnm)
If f.Size > 100000 then
dtmstr = Replace(Replace(Replace(FormatDateTime(Now),"/","-"),":",".")," ","-")
renflnm = Replace(flnm,".log","-" & dtmstr & ".log")
f.Move renflnm
End If
Set f = Nothing
End If
Set f = fso.OpenTextFile(flnm, 8, True)
f.WriteLine FormatDateTime(Now) & " - " & aMessage
f.Close
End Sub

'********************************************
Function CountUserProcess( ProcessName, ProcessId )
Dim strNameOfUser,strOwnerProcess,strDomain
CountUserProcess = 0
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set colProcessList = objWMIService.ExecQuery("Select * from Win32_Process Where ProcessId=" & CStr(ProcessId) )
For Each objProcess in colProcessList
colProps = objProcess.GetOwner(strOwnerProcess, strDomain)
Next
AppLog "-- ProcessName-" & ProcessName & ", ProcessId-" & CStr(ProcessId) & ", strOwnerProcess-" & strOwnerProcess & ", strDomain-" & strDomain
Set colProcessList = Nothing
Set colProcessList = objWMIService.ExecQuery("Select * from Win32_Process Where Name='" & ProcessName & "'")
For Each objProcess in colProcessList
colProps = objProcess.GetOwner(strNameOfUser, strDomain)
AppLog "strNameOfUser-" & strNameOfUser
if strNameOfUser = strOwnerProcess then
CountUserProcess = CountUserProcess + 1
end if
Next
End Function

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

Sub StartUpWatcher()
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\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
If objLatestProcess.Path_.Class = "__InstanceCreationEvent" Then
psCount = CountUserProcess(objLatestProcess.TargetInstance.Name, objLatestProcess.TargetInstance.ProcessId)
'Wscript.Echo thePsArray(PSNAME, psn), psCount
iF psCount > thePsArray(PSNUMB, psn) Then
Applog "Count of process " & objLatestProcess.TargetInstance.Name & " is " & Cstr(psCount) & "... Terminate last process."
objLatestProcess.TargetInstance.Terminate
End If
End If
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

Отправлено: 06:00, 17-05-2016 | #35


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


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

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


Спасибо огромное!
Я понимаю, что тема давно забыта, но есть ситуации, когда некоторым пользователям того-же терминального сервера нельзя ограничивать ресурсы. Генеральному не объяснишь, что "нехорошо так делать"! )
Я выкрутился добавив строки
if strNameOfUser = "Director" then
CountUserProcess = 1
end if
после подсчета процессов у пользователя.
Было бы неплохо вынести это в конфигурационный файл...

Отправлено: 17:15, 27-09-2017 | #36



Компьютерный форум 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




 
Переход