in reply to Re^10: how to change process & thread priority on Win32 ?
in thread how to change process & thread priority on Win32 ?

Take a look at the prototype for OpenThread():

HANDLE OpenThread( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId );

The only parameter there for identifying the thread to open, is the dwThreadId. Remember I described ThreadId as process unique--not system unique. Basically, OpenThread() can only be used to obtain handles to threads within the process from which it is called.

To be able to do this across process boundaries, it would need to also take a PID, so that you could ask it to give you a handle to 'this thread', within 'this process'. Without that, it will always attempt to get a handle to the specified TID within the current process.

As I said, I am not aware of any API for obtaining a thread handle to a thread in another process.

You could try the CreateRemoteThread() API to inject a thread into the process you trying to alter, and run the CreateSnapshot/OpenThread/SetThreadPriority from there, but from experience, the first of those is not an easy API to make work. Even if you get that going, I am not sure that it would allow a thread created by another process to mess with priorities.


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

Replies are listed 'Best First'.
Re^12: how to change process & thread priority on Win32 ?
by rbutcher (Beadle) on Dec 12, 2005 at 09:47 UTC
    I hear you. But from what I can understand from the MSDN documentation the sequence of API calls required is :-
    • take a snapshot of currently executing processes in the system using CreateToolhelp32Snapshot
    • walk through the list recorded in the snapshot using Process32First and Process32Next, until we find the PID we want.
    • get the first (and in this case only) thread details for list recorded in the snapshot using Thread32First
    • use SetThreadPriority to modify the thread.
    Looks like there is no direct access to the thread of the PID I want, but by reading thru the whole list we can get there.
    I'm no expert, but the difficulty is getting Win32::API to let me make all the calls I need to. At the moment I'm getting error code 24 (incorrect length) on Process32First. My code :-
    $pid = 952; # 952 is a running job pid use threads; use threads::shared; use Win32::API; Win32::API->Import( 'Kernel32', q[ DWORD GetLastError( ) ] ); $retcode = Win32::API->Import( 'Kernel32', q[ HANDLE CreateToolhelp32Snapshot ( DWORD dwFlags, DWORD th32ProcessID ) ] ); print "import CreateToolhelp32Snapshot code $retcode \n"; $hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); $retcode = GetLastError(); print "CreateToolhelp32Snapshot error code $retcode \n"; print "hProcessSnap = $hProcessSnap \n"; # typedef for PROCESSENTRY32 typedef Win32::API::Struct AA => qw{ DWORD dwSize; DWORD cntUsage; DWORD th32ProcessID; ULONG_PTR th32DefaultHeapID; DWORD th32ModuleID; DWORD cntThreads; DWORD th32ParentProcessID; LONG pcPriClassBase; DWORD dwFlags; TCHAR szExeFile[MAX_PATH]; }; $retcode = Win32::API->Import( 'Kernel32', q[BOOL Process32First( + HANDLE hSnapshot, LPAA lppe ) ] ); print "import process32first code $retcode \n"; $Point = Win32::API::Struct->new( 'AA' ); $Point->{dwSize}=Win32::API::Struct::sizeof( $Point ); Process32First($hProcessSnap, $Point); $retcode = GetLastError(); print "process32first error $retcode \n"; $retcode = Win32::API->Import( 'Kernel32', q[BOOL Process32Next( + HANDLE hSnapshot, LPAA lppe ) ] ); print "import process32next code $retcode \n"; until ( $Point->th32OwnerProcessID == $pid ) { Process32Next($hProcessSnap, $Point); $retcode = GetLastError(); print "process32next error code $retcode \n"; }
    I get error 24 (incorrect length) on Process32First.
      Looks like there is no direct access to the thread of the PID I want, but by reading thru the whole list we can get there.

      But you are still missing the point. The information available in the THREADENTRY32 structure return by Thread32First/Next() calls does not include a thread handle, only a thread ID.

    • use SetThreadPriority to modify the thread.
    • SetThreadPriority() requires a thread handle as it's first parameter, and there is no way to go from a thread ID to a thread handle.

      Ergo. Even if you solve your current problem with Process32First, you will arrive at a place where you still cannot do what you are trying to do.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
        Ah, you're right.. OpenThread apparently bridges that gap : "The handle returned by OpenThread can be used in any function that requires a handle to a thread, such as the wait functions, provided you requested the appropriate access rights. The handle is granted access to the thread object only to the extent it was specified in the dwDesiredAccess parameter". So my call sequence should be :-
        Thread32First OpenThread SetThreadPriority
        Does this look better ? Now I still need to make Process32First work...