Announcement

Collapse
No announcement yet.

Enumerate instances before running program

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Enumerate instances before running program

    I am trying to write a script to check how many instances of a program are running before running the program. This is on a Windows 2003 Server where we have a badly behaved program which, if you attempt to run more than the licenced number of copies will fail with a misleading error message. Our users will then report this "Error" to us rather than wait and try again.
    I attempted this with a batch file using Tasklist and Find but Find does not return the number of instances it finds, only True or False, so this could not enumerate the instances.
    How would I do this with Powershell or vbscript?

  • #2
    Re: Enumerate instances before running program

    In vbscript you can use WMI like this:

    Code:
    Option explicit
    Dim objWMIService, ColItems, objItem, objShell
    Dim iNrActiveProcesses
    
    Const wbemFlagReturnImmediately = &h10
    Const wbemFlagForwardOnly = &h20
    
    '==========================================================================
    ' Change values here
    '==========================================================================
    Const strAppName = "Internet Explorer"
    Const strProcessName = "IEXPLORE.EXE"
    Const strCommand = "C:\Program Files\Internet Explorer\IEXPLORE.EXE"
    Const iNrMaxProcesses = 10
    '==========================================================================
    
    Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2")
    Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Process", "WQL", _
    										wbemFlagReturnImmediately + wbemFlagForwardOnly)
    
    For Each objItem In ColItems
    	If objItem.Name = strProcessName Then x = x + 1
    Next
    
    wscript.echo "Found " & x & " processes of " & strProcessName & "..."
    
    If x < iNrMaxProcesses Then
    	Set objShell = CreateObject("WScript.Shell")
    	objShell.Run strCommand
    Else
    	MsgBox "The maximum number of simultaneous users has been reached. Please try again later.", vbOKOnly, "Error Starting application " & strAppName
    End If
    Hope this helps...
    Semper in faecibus sumus, sole profundum variat

    Comment


    • #3
      Re: Enumerate instances before running program

      Thank you SaMaLaKo, I can make that do what I want...
      Here is a supplementary question:
      The licence for this ill-behaved software also includes an earlier, 16-bit, version which is still on the server and could conceivably be used by one of our users. I can tweak the script to also look for instances of ntvdm, but is there a way to get the processname of the process that is running within ntvdm?

      Comment


      • #4
        Re: Enumerate instances before running program

        The discussions in this thread might be interesting too.

        Tracing process events: "Only-1-Instance-PerUser":
        http://forums.petri.com/showthread.php?t=15777


        \Rems

        This posting is provided "AS IS" with no warranties, and confers no rights.

        __________________

        ** Remember to give credit where credit's due **
        and leave Reputation Points for meaningful posts

        Comment


        • #5
          Re: Enumerate instances before running program

          When I run this as a normal user I get an error "Permission Denied" because I cannot list the processes.
          Can I get the script to work when run as a non-administrative user?

          Comment


          • #6
            Re: Enumerate instances before running program

            Originally posted by BartM View Post
            When I run this as a normal user I get an error "Permission Denied" because I cannot list the processes.
            Can I get the script to work when run as a non-administrative user?
            Can you show the script you have.
            Because the sample script provided by SaMaLaKo should not have permission issues. Or else, is there perhaps a vbs restriction policy on this computer?

            Note, that it is not possible for a normal user though to 'see' (and therefore cannot count) processes started in other security context (other users). The script is not trying, so that could not the cause of the errors.

            However, the sample does have three code errors.
            The corrections are in blue:
            Code:
            Option explicit
            Dim objWMIService, ColItems, objItem, objShell
            Dim iNrActiveProcesses
            Dim x : x = 0
            
            Const wbemFlagReturnImmediately = &h10
            Const wbemFlagForwardOnly = &h20
            
            '==========================================================================
            ' Change values here
            '==========================================================================
            Const strAppName = "Internet Explorer"
            Const strProcessName = "IEXPLORE.EXE"
            Const strCommand = "C:\Program Files\Internet Explorer\IEXPLORE.EXE"
            Const iNrMaxProcesses = 3
            '==========================================================================
            
            Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2")
            Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Process", "WQL", _
               wbemFlagReturnImmediately + wbemFlagForwardOnly)
            
            For Each objItem In ColItems
               If LCase(objItem.Name) = LCase(strProcessName) Then x = x + 1
            Next
            
             ' wscript.echo "Found", x, "processes of", strProcessName &"..."
            
            If x < iNrMaxProcesses Then
               Set objShell = CreateObject("WScript.Shell")
               objShell.Run chr(34) & strCommand & chr(34)
            
            Else
               MsgBox "The maximum number of simultaneous use of the application has been reached for this computer. Please try again later.", vbOKOnly, "Error Starting application " & strAppName
            End If
            Note, if the application should be executed with command line parameters, you must use "%comspec% /c " put in front of the command.


            \Rems
            Last edited by Rems; 10th June 2008, 21:40.

            This posting is provided "AS IS" with no warranties, and confers no rights.

            __________________

            ** Remember to give credit where credit's due **
            and leave Reputation Points for meaningful posts

            Comment


            • #7
              Re: Enumerate instances before running program

              Oh, I see what the problem is, though not the solution.
              I have written the script so that it attempts to find instances of the program running on two servers (because we have two Terminal Servers which share the pool of licences for this badly-behaved application)
              This runs OK as an administrator but not as a non-admin user, so my question is: can a non-admin user enumerate processes on another server?

              Code:
              Option explicit
              Dim objWMIService, ColItems, objItem, objShell, strComputer
              Dim iNrActiveProcesses
              Dim x : x = 0
              
              Const wbemFlagReturnImmediately = &h10
              Const wbemFlagForwardOnly = &h20
              
              '==========================================================================
              ' Change values here
              '==========================================================================
              Const strAppName = "Notepad"
              Const strProcessName = "Notepad.exe"
              Const strCommand = "C:\windows\system32\notepad.EXE"
              Const iNrMaxProcesses = 3
              '==========================================================================
              
              strComputer = "Server1"
              Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\CIMV2")
              Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Process", "WQL", wbemFlagReturnImmediately + wbemFlagForwardOnly)
              
              For Each objItem In ColItems
                 If LCase(objItem.Name) = LCase(strProcessName) Then x = x + 1
              Next
              
              wscript.echo "Found", x, "processes of", strProcessName &"..."
              
              strComputer = "Server2"
              Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\CIMV2")
              Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Process", "WQL", wbemFlagReturnImmediately + wbemFlagForwardOnly)
              
              For Each objItem In ColItems
                 If LCase(objItem.Name) = LCase(strProcessName) Then x = x + 1
              Next
              
              wscript.echo "Found", x, "processes of", strProcessName &"..."
              
              If x < iNrMaxProcesses Then
                 Set objShell = CreateObject("WScript.Shell")
                 objShell.Run chr(34) & strCommand & chr(34)
              
              Else
                 MsgBox "The maximum number of simultaneous use of the application has been reached for this computer. Please try again later.", vbOKOnly, "Error Starting application " & strAppName
              End If

              Comment


              • #8
                Re: Enumerate instances before running program

                OK, in reply to my own question, the way to allow a non-admin user to enumerate the processes on a remote computer is to enable remote WMI monitoring as described in http://www.poweradmin.com/help/enableWMI.aspx

                Comment

                Working...
                X