Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Set the priority of a process 1

Status
Not open for further replies.

fischadler

Programmer
May 31, 2002
258
MT
I have this code that I got from the Microsoft site for getting a list of running processes.

Code:
  Public Declare Function Process32First Lib "kernel32" (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long
  Public Declare Function Process32Next Lib "kernel32" (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long
  Public Declare Function CloseHandle Lib "Kernel32.dll" (ByVal Handle As Long) As Long
  Public Declare Function OpenProcess Lib "Kernel32.dll" (ByVal dwDesiredAccessas As Long, ByVal bInheritHandle As Long, ByVal dwProcId As Long) As Long
  Public Declare Function EnumProcesses Lib "psapi.dll" (ByRef lpidProcess As Long, ByVal cb As Long, ByRef cbNeeded As Long) As Long
  Public Declare Function GetModuleFileNameExA Lib "psapi.dll" (ByVal hProcess As Long, ByVal hModule As Long, ByVal ModuleName As String, ByVal nSize As Long) As Long
  Public Declare Function EnumProcessModules Lib "psapi.dll" (ByVal hProcess As Long, ByRef lphModule As Long, ByVal cb As Long, ByRef cbNeeded As Long) As Long
  Public Declare Function CreateToolhelp32Snapshot Lib "kernel32" (ByVal dwFlags As Long, ByVal th32ProcessID As Long) As Long
  Public Declare Function GetVersionExA Lib "kernel32" (lpVersionInformation As OSVERSIONINFO) As Integer

  Public Type PROCESSENTRY32
     dwSize As Long
     cntUsage As Long
     th32ProcessID As Long           ' This process
     th32DefaultHeapID As Long
     th32ModuleID As Long            ' Associated exe
     cntThreads As Long
     th32ParentProcessID As Long     ' This process's parent process
     pcPriClassBase As Long          ' Base priority of process threads
     dwFlags As Long
     szExeFile As String * 260       ' MAX_PATH
  End Type

  Public Type OSVERSIONINFO
     dwOSVersionInfoSize As Long
     dwMajorVersion As Long
     dwMinorVersion As Long
     dwBuildNumber As Long
     dwPlatformId As Long           '1 = Windows 95.
                                    '2 = Windows NT

     szCSDVersion As String * 128
  End Type

  Public Const PROCESS_QUERY_INFORMATION = 1024
  Public Const PROCESS_VM_READ = 16
  Public Const MAX_PATH = 260
  Public Const STANDARD_RIGHTS_REQUIRED = &HF0000
  Public Const SYNCHRONIZE = &H100000
  'STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or &HFFF
  Public Const PROCESS_ALL_ACCESS = &H1F0FFF
  Public Const TH32CS_SNAPPROCESS = &H2&
  Public Const hNull = 0

  Function StrZToStr(s As String) As String
     StrZToStr = Left$(s, Len(s) - 1)
  End Function

  Public Function getVersion() As Long
     Dim osinfo As OSVERSIONINFO
     Dim retvalue As Integer
     osinfo.dwOSVersionInfoSize = 148
     osinfo.szCSDVersion = Space$(128)
     retvalue = GetVersionExA(osinfo)
     getVersion = osinfo.dwPlatformId
  End Function

Code:
Private Sub LoadTaskList()
  Dim TopIndex As Integer
  
  TopIndex = lstProcesses.TopIndex
  lstProcesses.Clear
  Select Case getVersion()
    Case 1 'Windows 95/98
      Dim f As Long, sname As String
      Dim hSnap As Long, proc As PROCESSENTRY32
      hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
      If hSnap = hNull Then Exit Sub
      proc.dwSize = Len(proc)
      ' Iterate through the processes
      f = Process32First(hSnap, proc)
      Do While f
        sname = StrZToStr(proc.szExeFile)
        lstProcesses.AddItem sname
        f = Process32Next(hSnap, proc)
      Loop
    
    Case 2 'Windows NT
    
      Dim cb                As Long
      Dim cbNeeded          As Long
      Dim NumElements       As Long
      Dim ProcessIDs()      As Long
      Dim cbNeeded2         As Long
      Dim NumElements2      As Long
      Dim Modules(1 To 200) As Long
      Dim lRet              As Long
      Dim ModuleName        As String
      Dim nSize             As Long
      Dim hProcess          As Long
      Dim i                 As Long
      'Get the array containing the process id's for each process object
      cb = 8
      cbNeeded = 96
      Do While cb <= cbNeeded
      cb = cb * 2
      ReDim ProcessIDs(cb / 4) As Long
      lRet = EnumProcesses(ProcessIDs(1), cb, cbNeeded)
      Loop
      NumElements = cbNeeded / 4
      
      For i = 1 To NumElements
      'Get a handle to the Process
      hProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 0, ProcessIDs(i))
      'Got a Process handle
      If hProcess <> 0 Then
        'Get an array of the module handles for the specified
        'process
        lRet = EnumProcessModules(hProcess, Modules(1), 200, cbNeeded2)
        'If the Module Array is retrieved, Get the ModuleFileName
        If lRet <> 0 Then
          ModuleName = Space(MAX_PATH)
          nSize = 500
          lRet = GetModuleFileNameExA(hProcess, Modules(1), ModuleName, nSize)
          lstProcesses.AddItem Left(ModuleName, lRet)
        End If
      End If
      'Close the handle to the process
      lRet = CloseHandle(hProcess)
      Next
  End Select
  Text1.Text = lstProcesses.ListCount
  lstProcesses.TopIndex = TopIndex
End Sub

It does the job quite well, but I need to see the priority level of every process and even set it, if possible. However I fail to understand how this works.

Maybe I am simplifying things too much but I was hoping that it was possible to do something in the lines:

Code:
For Each process in processes
  If process.name = "TheProceesIamLookingFor" THEN
    process.priority = vbLow
  END IF
Next

OK, I invented a couple of commands, but was wondering if it can be done in a similar way.

-Fischadler
 
I suspect that you're going to both love and hate me. You'll love me when I tell you that you can write almost exactly the simplified code that you have described:
Code:
[blue]Option Explicit

Private Enum ProcessPriority
    PriorityIdle = &H40&
    PriorityBelowNormal = &H4000&
    PriorityNormal = &H20&
    PriorityAboveNormal = &H8000&
    PriorityHigh = &H80&
    PriorityRealtime = &H100&
End Enum

Private Function ChangePriority(strProcessName As String, Optional NewPriority As ProcessPriority = PriorityNormal) As Long
    Dim objProcess As Object
    For Each objProcess In GetObject("Winmgmts:").ExecQuery("Select * from Win32_Process")
        If objProcess.Name = strProcessName Then
            ChangePriority = objProcess.SetPriority = NewPriority
        End If
    Next
End Function[/blue]
And you'll hate me because you're current complete code can be entirely replaced with:
Code:
[blue]Private Sub LoadTaskList()
    Dim TopIndex As Long
    TopIndex = lstProcesses.TopIndex
    lstProcesses.Clear

    Dim objProcess As Object
    For Each objProcess In GetObject("Winmgmts:").ExecQuery("Select * from Win32_Process")
        If Not IsNull(objProcess.ExecutablePath) Then lstProcesses.AddItem objProcess.ExecutablePath
    Next
    Text1.Text = lstProcesses.ListCount
    lstProcesses.TopIndex = TopIndex
End Sub[/blue]

(note that, by default W95/W98/Me and NT4 don't have WMI - which is what we're using here - installed, but just make it a requirement of your app if either of these platforms are likely deployment targets; the relvant installation packages are available on the Microsoft website)



 
Cool! I am glad you provided me with that alternative. At least now it's easier for me to understand what each line of code is doing.

Where can I find a list of properties and methods for objProcess? Typing "objProcess." does not bring the intellisense list of options.

Thanks again!

-Fischadler
 
>Typing "objProcess." does not bring the intellisense list of options

No. Firstly because it is late bound, so no Intellisense because of that.

Secondly, even if we early bind (after setting a necessary reference to the Microsoft WMI Scripting Library) then you'll find that the object in question (SWbemObject) still won't give you what you want ... because it is a generic management object that could hold a number of different WMI objects, and so it works a little differently than COM objects you might normally encounter

It is posible to interrogate the SWbemObject for the specific methods and properties it supports for the current management object that it represents (get a single instance of the object in question, then enumerate the Methods_ and Properties_ properties)

Alternatively, just look up Win32_Process on MSDN ...
 
OK. Just found the info here:


Now, the last thing that remains is set the affinity certain processes when a dual core processor is being used. I am doing this because certain games (like C&C Zero Hour) work better on a single core than on a dual core.

I found this code here:

that I think will do the trick when combined with the code you provided me.

Thanks again!

-Fischadler
 
You can also use the Win32_Processor object's NumberofCores property to enumerate the physical processors on a system.

 
I'm afraid I've been guilty of careless reading, fisch. The doc says "Windows Server 2003, Windows XP, Windows 2000, Windows NT 4.0, and Windows Me/98/95: This property is not available" which I read incorrectly as the property was unavailable on the Win9x platforms. My apologies. It would seem the property is a "vaporproperty" at present.

Bob
 
On the other hand, looking a little further: if you iterate through the collection with a for each, as in strongm's code, you can count the instances as they come up and find the number of processors on the machine. I don't have a multiprocessor machine to test this on, but it looks like that should work.

HTH

Bob
 
I don't think I understand what you mean, Bob. How can I find the number of processors by iterating through the running processes? And once I find the number of processors, how can I set a particular process to use just one of them, which is where I am heading?
I also have a single core and testing this will require me to test the prog on a machine other than my work station. But I'll post my results if I manage to make it work.

Thanks again!

-Fischadler
 
This is just a hypothesis, you understand: you iterate through the collection returned by the query of Win32_Processor. That collection should have one item per processor, so you can count the iterations in the for each loop, discarding things like math coprocessors and the like. Each processor has a unique ID which you can capture as well. I don't know how you can assign work to a particular processor, though, once you've learned its id.

HTH

Bob
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top