Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Microsoft Windows NT/2000/2003 (http://forum.oszone.net/forumdisplay.php?f=5)
-   -   [решено] Как ограничить количество запущенных копий приложения на терминальном сервере? (http://forum.oszone.net/showthread.php?t=64395)

SkyF 15-04-2006 16:53 428190

[решено] Как ограничить количество запущенных копий приложения на терминальном сервере?
 
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

qpa3ep 05-06-2006 13:31 446710

ограничение количества запущенных программ на w2k3
 
Нужно ограничить количество одновременно запускаемых программ для пользователей терминального доступа на w2k3.
Подскажите как это можно сделать?

foss 05-06-2006 17:46 446921

В групповых политиках:
User Configuration\Administrative Templates\Windows Components\Windows Explorer---> Maximum number of recent documents

Maximum number of recent documents Enabled
Maximum number of recent documents 15
(15 -кол-во приложений)

Blast 06-06-2006 16:50 447449

http://www.oszone.net/3644/#18

ShaddyR 06-07-2006 13:36 458490

проверил я предложенные варианты... вопрос не решен. Озвучу промежуточные результаты:
1) указанное foss: не то. Кто дружит с английским, поймет описание предложенного параметра:
Цитата:

Determines how many shortcuts the system can display in the Documents menu on the Start menu.

The Documents menu contains shortcuts to the nonprogram files the user has most recently opened. By default, the system displays shortcuts to the 10 most recently opened documents.
2) вариант скрипта vbs: более реально, но
2.1) Прежде всего, суммируются все инстанции названных процессов. То есть, если я запущу два калькулятора, то два нотепада я запустить уже не смогу
2.2) Нет возврата счетчика в обратное состояние, если одна из копий закрывается.

Ессно, я понимаю, что скрипт набросан на скорую руку. В содержимом разобрался, но с визуал бейсиком не дружен, посему:
1) можно ли создать массив из связок имя_процесса-кол-во_копий
2) можно ли добавлять в этот массив компоненты динамически, а не прописывать в скрипте
3) можно ли отслеживать завершение работы копии и делать соответствующие изменения в счетчике (с удалением единицы массива при закрытии последней из копий данного процесса)

hasherfrog 06-07-2006 18:37 458588

ShaddyR, я очень скоренько наборосал...
Не все проблемы решены.

Код:

Set Args = WScript.Arguments

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

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 colMonitoredProcesses = objWMIService. _       
    ExecNotificationQuery("select * from __InstanceCreationEvent" _
        & " within 1 where TargetInstance isa 'Win32_Process'")

  Set colMonitorProcessesd = objWMIService.ExecNotificationQuery _
  ("SELECT * FROM __InstanceDeletionEvent " & _
  "WITHIN 1 WHERE TargetInstance ISA 'Win32_Process' ")


  Do While 1
    Set objLatestProcess = colMonitoredProcesses.NextEvent

    For psn=0 to nToWatch-1
      If objLatestProcess.TargetInstance.Name = thePsArray(PSNAME, psn) Then
        thePsArray(PSNUMB, psn) = thePsArray(PSNUMB, psn) - 1
'        Wscript.Echo "Num: "& thePsArray(PSNUMB, psn)
        If thePsArray(PSNUMB, psn) < 0 then
          Wscript.Echo "Вы запустили лишнюю копию программы "&  objLatestProcess.TargetInstance.Name  _
                    & " - разрешенный лимит только " & thePsArray(PSMAXN, psn)
          objLatestProcess.TargetInstance.Terminate
          thePsArray(PSNUMB, psn) = thePsArray(PSNUMB, psn) + 1
        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 filename"
End If

Формат файла такой
Код:

имяпрограммы1.exe n1
имяпрограммы2.exe n2
имяпрограммы3.exe n3

Запускается скрипт watcher.vbs -f filename

но вот по поводу 2.2) Нет возврата счетчика в обратное состояние, если одна из копий закрывается. - это я не могу сейчас сообразить. как сделать


И вообще не уверен, что это возможно :-|

hasherfrog 06-07-2006 19:06 458603

А вообще нет, чего я... Можно просто пересчитывать количества процессов перед каждый новым запуском... Так, наверное.
Прошу прощения, если критично кому, но я завтра только смогу поковыряться...

Плюс второй вариант - http://www.microsoft.com/technet/scr....mspx?mfr=true

ShaddyR 06-07-2006 19:57 458620

Вложений: 1
hasherfrog: я понял)
Резалты теста (назвал скрипт Processrestrict.vbs):
1)
Код:

Processrestrict.vbs -f calc.exe
возвращает "File exists not."
2) Processrestrict.vbs -f "C:\WINDOWS\system32\calc.exe"
возвращает ошибку в аттаче)

hasherfrog 06-07-2006 22:43 458679

НЕЕЕЕЕ... Вы чего?
filename - это текстовый файл, в котором перечислены файлы, подлежащих "рестриктированию".
Там написано за кем следить - и сколько раз можно запускать.

Кстати, Вы бежите впереди паровоза :] Я как завтра хотел написать вторым вариантом решение таким образом, каким Вы сейчас предлагаете, когда на каждый файл рестрикта будет свой собственный "наблюдатель". А первым вариантом - доработать "комплексный" обработчик-рестриктизатор.

dosim 07-07-2006 17:20 458946

Цитата:

2.2) Нет возврата счетчика в обратное состояние, если одна из копий закрывается
hasherfrog

а когда сооборазите насчет возврата счетчика?? как раз то, что мне нужно.

hasherfrog 07-07-2006 22:27 458996

Скрипт watcher.vbs
ShaddyR> см. в прикрепленном сообщение.

ShaddyR 08-07-2006 12:59 459147

Спасибо, у тебя получилось!!
Единственный нюанс - терминальная система, для которой все пишется. Ибо в текущем варианте все работает на однопользовательской, а проверка в терминальной среде показала следующий глюк: запуск приложений контролируется, но
1) сообщение о лимите выводится в сеанс, в котором запущен скрипт.
2) ессно, закрытие копии в сеансе другого пользователя также не производится, вне зависимости от прав юзера, под которым скрипт запущен.

Если будет время, косметика:
1) переименуй конф-файл в .ini (с именем скрипта, но поиском и его поиском по умолчанию, если не задана командная строка)
2) добавь опцию командной строки для добавления файла и кол-ва запусков в указанный конф. файл (либо в к.ф. по-умолчанию, если ничего не указано). С удалением справятся вручную
ничего личного, все от имени и во благо юзеров ;)
А вообще - спасибо.. визуальный Барсик - сильная весчь)
dosim: есть еще пожелания к создателю скрипта?

hasherfrog 08-07-2006 21:53 459288

ShaddyR
Я боюсь, что Вы не совсем поняли, как это работает (или я сам не совсем понял).

1) сообщение о лимите выводится в сеанс, в котором запущен скрипт.
Конечно. Естественно. И я не знаю, а как же иначе-то?

Как я понял: Этот скрипт запускается при входе на сервер для каждого пользователя. Т.е. кто-то входит - у него запускается логон-скрипты, в том числе и этот. И для каждого, кто зашёл, действует _персональный_ лимит на количество блокнотов-калькуляторов. Не один на всех этот скрипт, а каждому - свой. Возможно, я не совсем вкурил механизм действия скрипта, но у меня нет терминал-севрера, к сожалению :-\

2) ессно, закрытие копии в сеансе другого пользователя также не производится, вне зависимости от прав юзера, под которым скрипт запущен.

И не должно, так как по замыслу (см. выше) скрипт не контролирует других пользователей, а лишь данного конкретного.

И кстати, вот какой момент. Закрытие сейчас производится _до_вывода_ сообщения "Вы превысили лимит". Т.е. пользователь запустил блокнот - скрип 1) проверил лимит, 2) _закрыл_блокнот, 3) сообщил о превышении лимита. Если поменять местами 2 и 3, пользователь может устроить затык скрипту (вообще-то, он и сейчас, наверное, сможет, при должном усердии).

---

По косметике:

1) переименуй конф-файл в .ini (с именем скрипта, но поиском и его поиском по умолчанию, если не задана командная строка)

Вроде не сложно, только несколько неоднозначностей. Где что лежит? Где (в какой папке) нужно искать конфиг?

2) добавь опцию командной строки для добавления файла и кол-ва запусков в указанный конф. файл (либо в к.ф. по-умолчанию, если ничего не указано). С удалением справятся вручную

Вот это - вообще нельзя, насколько я соображаю. Скрипт действует в своём "коконе". Чтобы кто-то смог сообщить ему об изменении политики партии ("следи, мол, ещё и за этим вот файлом"), этот кто-то должен... в общем, речь идёт о inter-process communications. (см тут, я слишком косноязык). А вот умеет ли wscript.exe делать такие штучки - я сомневаюсь.

dosim 10-07-2006 08:48 459659

:o

hasherfrog я запустил этот скрипт, всё работает т.е. процесс считывает, при запуске выше лимта выходит сообщение "Вы запустили лишную копию программы " ок нажимаешь програмка закрывается, но пока ты ок не нажмёшь програмка работает. Посмотрите в чем проблема? Сделайте чтобы, сообщение выходил и процесс сразу убивал, т.е до нажатие ОК.

hasherfrog 10-07-2006 10:18 459681

dosim
Как
Цитата:

но пока ты ок не нажмёшь програмка работает
соотносится с
Цитата:

Закрытие сейчас производится _до_вывода_ сообщения "Вы превысили лимит".
?

dosim 10-07-2006 12:30 459748

hasherfrog Нет, пока ОК не нажмешь программа не закрывается.

ShaddyR 10-07-2006 13:27 459777

dosim: ты не прав. Нелимитная копия закрывается прежде сообщения, проверено на калькуляторах.
>
Цитата:

переименуй конф-файл в .ini (с именем скрипта, но поиском и его поиском по умолчанию, если не задана командная строка)
Вроде не сложно, только несколько неоднозначностей. Где что лежит? Где (в какой папке) нужно искать конфиг?
в папке запуска скрипта, конечно. Если не указан другой путь\имя файла конфигурации.
>
насчет терминала... мож, я переборщил, это действительно не нужно. Просто основная идея озвучена в первом сообщении, примерно таким образом:
Цитата:

Цель: Имея Z пользователей терминальных, и N лицензий на Office 2003, как на сервере ограничить количество загрузок приложений Office, не более N-ти одновременно?
Но, думаю, достаточно предложенного тобой скрипта.

Еще раз спасибо.

dosim 10-07-2006 13:57 459792

всё работает

hasherfrog 10-07-2006 14:06 459799

ShaddyR
Давайте по мелочам доразберёмся. У меня нет терминального сервера, поэтому придётся спрашивать у Вас.

Если данный скрипт запустит администратор, пользователи, превысившие лимит, могут открыть блокноты-калькуляторы? Дело в том, что я (кажется) придумал, как сообщать именно контретному пользователю о том, что именно он превысил лимит. Причём "ступора" не будет (а сейчас он есть, возможен).
Уберите строку
Код:

Wscript.Echo "Вы запустили лишнюю копию программы "&        objLatestProcess.TargetInstance.Name  _
                                                        & " - разрешенный лимит только " & thePsArray(PSMAXN, psn)

и проверьте, пожалуйста.

А там, может и до IPC дойдём (есть идея).

ShaddyR 11-07-2006 15:20 460258

hasherfrog: честно - не понял идеи. Сделал: ничего не выводит, молча убивает в сеансе, где запущен.

hasherfrog 11-07-2006 15:25 460259

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

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

ShaddyR 11-07-2006 15:34 460264

hasherfrog
Цитата:

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

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

hasherfrog 11-07-2006 15:39 460269

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

hasherfrog 11-07-2006 16:44 460295

Молчание...
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

hasherfrog 12-07-2006 10:40 460570

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

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

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

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

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

hasherfrog 12-07-2006 18:24 460799

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

ShaddyR 12-07-2006 20:00 460816

По новой версии:
Работает, отсылает верно. Но лишнюю копию в чужом сеансе все еще не умеет закрывать.
>
Цитата:

Выгрузка себя из памяти.
добавь соответствующий ключ, как в свое время делали ДОСовские резиденты. Другими словами, 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. ИМХО скрипт не обещался быть рассчитаным на мальчиков-мажоров, а админ должен думать, что делает.

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

Butunin Klim 08-04-2009 14:38 1087908

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

slava_89 17-08-2011 02:40 1733457

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

ShaddyR 17-08-2011 11:23 1733617

Цитата:

Цитата slava_89
Как создать этот скрипт для 64 разрядную ОС »

этому скрипту фиолетова битность ОС
>
Цитата:

Цитата slava_89
где его сохранять »

на жестком диске? :dirol:
>
Цитата:

Цитата slava_89
как запуск проводить »

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

Цитата SkyF
cscript "<путь к файлу>watcher.vbs" »


S_M 28-08-2011 20:01 1741112

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

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

Wscript.Echo "Вы запустили лишнюю копию программы "&        objLatestProcess.TargetInstance.Name  _
        & " - разрешенный лимит только " & thePsArray(PSMAXN, psn)

Сообщения валить перестали, но только отключаешься от сеанса администратора (не завершаешь сеанс, а делаешь отключение) - скрипт перестает работать :(
В общем, помогите правильно прописать этот скрипт в автозагрузке (если можно в подробностях - как для дебилов).
Спасибо!

ShaddyR 28-08-2011 21:10 1741164

Цитата:

Цитата S_M
в свойствах пользователя прописать файл »

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

S_M 31-08-2011 21:54 1743583

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

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

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

Это как?

ShaddyR 31-08-2011 22:13 1743600

Цитата:

Цитата S_M
Это как? »

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

zavulon66 17-05-2016 06:00 2635305

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

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

Baldman73 27-09-2017 17:15 2767291

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


Время: 09:28.

Время: 09:28.
© OSzone.net 2001-