Solved

Application exe file path from application window handle

Posted on 2010-09-08
20
2,165 Views
Last Modified: 2012-05-10
Hi,
I need a method to get the exe file path (full path, not just the file name) of an application to which belongs the window for which you have hWnd. However, the method must work equally well on 32 and 64-bit systems, and to be reasonably fast, not slower then few milliseconds.

I tried a standard method based on GetModuleFileNameExA (example given), but it doesn’t work on 64bit systems. More precise, it work only for 32 applications, but if the window handle belongs to an 64bit app it will return nothing. This is limitation of the GetModuleFileNameExA, which cannot return information for a 64bit application handle if it is used in a 32bit application. If VB6 could be compiled with 64bit compiler it would work fine, but since there is no 64bit version of VB6…

Also, the method MUST NOT be based on WMI, i.e. something like

    Set Processes = GetObject("winmgmts://localhost")
    Set myProcEnum = Processes.ExecQuery("select * from Win32_Process")

as this usually takes about 50 milliseconds per call, and it is way to slow for my need. I need something based on APIs…

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Private Declare Function OpenProcess Lib "KERNEL32.DLL" (ByVal dwDesiredAccessas As Long, ByVal bInheritHandle As Long, ByVal dwProcId As Long) As Long

Private Declare Function EnumProcessModules Lib "PSAPI.DLL" (ByVal hProcess As Long, ByRef lphModule As Long, ByVal cb As Long, ByRef cbNeeded As Long) As Long

Private Declare Function GetModuleBaseName Lib "PSAPI.DLL" Alias "GetModuleBaseNameA" (ByVal hProcess As Long, ByVal hModule As Long, ByVal lpFileName As String, ByVal nSize As Long) As Long

Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long

Private Declare Function GetModuleFileNameExA Lib "PSAPI.DLL" (ByVal hProcess As Long, ByVal hModule As Long, ByVal ModuleName As String, ByVal nSize As Long) As Long

Private Declare Function CloseHandle Lib "KERNEL32.DLL" (ByVal Handle As Long) As Long



Private Const MAX_PATH = 260

Private Const PROCESS_QUERY_INFORMATION = 1024

Private Const PROCESS_VM_READ = 16



Private Sub Command1_Click()

    Dim hWnd As Long

    Dim Path As String, Name As String

    

    hWnd = FindWindow(vbNullString, "Untitled - Notepad")

    

    If hWnd = 0 Then

        MsgBox "Notepad is not opened!"

        Exit Sub

    End If

    

    Path = ExePath(hWnd)

    Debug.Print Path, "|||"

End Sub



Public Function ExePath(ByVal hWnd As Long) As String

    Dim ThreadID As Long, ProcessID As Long

    Dim lngReturn As Long

    Dim strEXEPath As String

    Dim lngSize As Long

    Dim hProcess As Long

    Dim hMod(0 To 1023) As Long

    Dim cbNeeded As Long

    

    ThreadID = GetWindowThreadProcessId(hWnd, ProcessID)

    

    lngSize = MAX_PATH

    

    'Get a handle to the Process

    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 0, ProcessID)



    lngReturn = EnumProcessModules(hProcess, hMod(0), 1024, cbNeeded)

    

    strEXEPath = String$(lngSize, 0)

    lngReturn = GetModuleFileNameExA(hProcess, hMod(0), strEXEPath, lngSize)

    strEXEPath = Left(strEXEPath, lngReturn)

    

    

    lngReturn = CloseHandle(hProcess)

    

    ExePath = strEXEPath

End Function

Open in new window

0
Comment
Question by:npaun
  • 10
  • 7
  • 2
  • +1
20 Comments
 
LVL 14

Expert Comment

by:VBClassicGuy
Comment Utility
This is not written in VB6, but could be converted. If not a solution, it may at least give you some ideas:
[DllImport("user32.dll")]
public static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);
 
void GetProcessPathFromWindowHandle(IntPtr hwnd)
{
   uint pid = 0;
   Win32.GetWindowThreadProcessId(hwnd, out pid);
   Process p = Process.GetProcessById((int)pid);
   return p.MainModule.FileName;
}
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
Comment Utility
@VBClassicGuy...

This part:

    Process p = Process.GetProcessById((int)pid);
    return p.MainModule.FileName;

uses the .Net Process() class which has no equivalent in VB6 so it can't be converted.
0
 
LVL 14

Expert Comment

by:VBClassicGuy
Comment Utility
Good catch. Oh well...
0
 
LVL 29

Accepted Solution

by:
nffvrxqgrcfqvvc earned 500 total points
Comment Utility
You have to use the correct versions there is an issue with GetModuleFileName() on x64 systems.
Use the following table below. I added this information to MSDN documentation almost two years ago maybe you didn't see it :(
Windows 2000 = GetModuleFileName()
Windows XP x32 = GetProcessImageFileName()
Windows XP x64 = GetProcessImageFileName()
Windows Vista = QueryFullProcessImageName()
Windows 7 = QueryFullProcessImageName()


Note: If you are not aware the API GetProcessImageFileName() returns a kernel DOS device path. You can use the following API to map the device paths to a Win32 format.

GetLogicalDriveStrings
QueryDosDevice  
0
 

Author Comment

by:npaun
Comment Utility
Hi egl1044,
Thank you for your suggestion!

I actually tried with GetProcessImageFileName once before, but it was not working quite best. Now I see it was because I used a bad code snippet from internet. Now I rewrote it and it seems to work just fine.

One thing: I was under impression that I will need to use GetProcessImageFileName on XP, but I would need to develop an alternative approach based on QueryFullProcessImageName for Vista/Win7 (based on your comment I supposed that GetProcessImageFileName will not work on Vista/Win7). However, my preliminary test shows that my version with GetProcessImageFileName works just fine on Vista-x64/Win7-x64? I just want to check that there is no hidden catch which would require to use QueryFullProcessImageName too?

Public Function ExePath(ByVal hWnd As Long) As String

    Dim szName As String

    Dim ThreadID As Long

    Dim ProcessID As Long

    Dim hProcess As Long

    Dim lenName As Integer

    Dim DevicePath As String

    Dim p As Integer

    

    ThreadID = GetWindowThreadProcessId(hWnd, ProcessID)

    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 0, ProcessID)

    

    szName = String(MAX_PATH, Chr(0))

    lenName = GetProcessImageFileName(hProcess, szName, MAX_PATH)

    p = InStr(1, szName, Chr(0))

    

    DevicePath = Left$(szName, p - 1)

    

    ExePath = ConvertDevicePathToStandardPath(DevicePath)

End Function



Private Function ConvertDevicePathToStandardPath(ByVal DevFilePath As String) As String

    Dim ret As Long

    Dim k As Integer

    Dim strSave As String

    Dim sl As String

    Dim DevPath As String

    Dim l As Long

    Dim p As Integer

    

    strSave = String(255, Chr$(0))

    ret = GetLogicalDriveStrings(255, strSave)

    

    For k = 1 To 100

        If Left$(strSave, InStr(1, strSave, Chr$(0))) = Chr$(0) Then Exit For

        sl = Left$(strSave, InStr(1, strSave, Chr$(0)) - 2)

        

        DevPath = String(255, Chr$(0))

        l = QueryDosDevice(sl, DevPath, 255)

        DevPath = Left$(DevPath, InStr(1, DevPath, Chr$(0)) - 1)

        

        p = InStr(1, DevFilePath, DevPath)

        If p <> 0 Then

            ConvertDevicePathToStandardPath = sl & Right(DevFilePath, Len(DevFilePath) - Len(DevPath))

            Exit Function

        End If

        

        strSave = Right$(strSave, Len(strSave) - InStr(1, strSave, Chr$(0)))

    Next k

    

End Function

Open in new window

0
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
Comment Utility
GetProcessImageFileName() is exported on Windows XP and later it will work for later versions but it's best to use the newest functions since they provide some more power and in some rare cases they are updated to fix some issues from previous versions.
Internally they all wrap the ntdll.dll functions... I found an example in my backups that I wrote years ago but I can't remember if it works for x64 systems. I must have written for some purpose and it might be that I wrote it to test if the NT function had the same behavior on x64 systems as GetModuleFileName() for external processes.
You can test the example and let me know ... :)

Option Explicit



Private Const ProcessImageFileName = 27

Private Const STATUS_INFO_LENGTH_MISMATCH = &HC0000004

Private Const PROCESS_QUERY_INFORMATION = &H400&

Private Const PROCESS_VM_READ = &H10&

Private Const HEAP_ZERO_MEMORY = &H8&



Private Type UNICODE_STRING

Length As Integer

MaximumLength As Integer

Buffer As Long

End Type



Private Declare Function GetProcessHeap Lib "kernel32.dll" () As Long

Private Declare Function HeapAlloc Lib "kernel32.dll" (ByVal hHeap As Long, ByVal dwFlags As Long, ByVal dwBytes As Long) As Long

Private Declare Function HeapFree Lib "kernel32.dll" (ByVal hHeap As Long, ByVal dwFlags As Long, ByVal lpMem As Long) As Long

Private Declare Function OpenProcess Lib "kernel32.dll" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessid As Long) As Long

Private Declare Function NtQueryInformationProcess Lib "ntdll.dll" (ByVal ProcessHandle As Long, ByVal ProcessInformationClass As Long, ByVal ProcessInformation As Long, ByVal ProcessInformationLength As Long, ByRef ReturnLength As Long) As Long

Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As Long) As Long

Private Declare Sub RtlMoveMemory Lib "kernel32.dll" (ByVal lpDest As Long, ByVal lpSource As Long, ByVal cbCopy As Long)



Public Function GetProcessNameByPid(ByVal pid As Long) As String



  Dim uni             As UNICODE_STRING

  Dim Buffer          As Long

  Dim hProcess        As Long

  Dim FileName        As String

  Dim cbNeeded        As Long

  

  hProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 0, pid)

  If hProcess = 0 Then

    Exit Function

  End If

  ' Get the buffer size needed for the call.

  If NtQueryInformationProcess(hProcess, ProcessImageFileName, VarPtr(uni), 8, cbNeeded) = STATUS_INFO_LENGTH_MISMATCH Then

    ' Allocate the required buffer from the heap.

    Buffer = HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, cbNeeded)

    If NtQueryInformationProcess(hProcess, ProcessImageFileName, Buffer, cbNeeded, cbNeeded) = 0 Then

      ' UNICODE_STRING

      RtlMoveMemory VarPtr(uni), ByVal Buffer&, Len(uni)

      FileName = String$(uni.Length / 2, vbNullChar)

      RtlMoveMemory StrPtr(FileName), ByVal uni.Buffer, uni.Length

      GetProcessNameByPid = FileName

    End If

   HeapFree GetProcessHeap, 0, Buffer

  End If

  CloseHandle hProcess

  

End Function



Private Sub Command1_Click()

  Debug.Print GetProcessNameByPid(1092)

End Sub

Open in new window

0
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
Comment Utility
In your example above I don't see CloseHandle() call on the process handle. Make sure you call CloseHandle() when your finished or you will get "handle" leak in your application.
0
 

Author Comment

by:npaun
Comment Utility
Hi egl1044,

a)      Thanks for noting missing CloseHandle…

b)      I’ve tested your alternative GetProcessNameByPid, and it seems to be working too! I tested it on XP32, and Vista64/Win7x64 and it seems to work just fine. I don’t have XP64 at my disposal right now, but I don’t expect o have problem there too. Any preferences between these two approaches?

c)      One more question if I can: I’ve noticed that for some applications, it seems I can’t get full app path, no matter what method I’m using, even for those methods that are working perfectly fine on XP32, or any other OSver…For instance, “wow.exe” of “World of Warcraft” is such a case. After some testing with “wow.exe” example, I found that in this case I actually don’t get appropriate handle when calling OpenProcess, just zero! After consulting MSDN, I would say because of the “access control to process objects” for such applications? Anyway, do you have some idea how to get path to exe even for such applications? Is there a way to do that without need for handle to the process? Even the robust WMI approach I mentioned at the beginning is not working for such applications, probably because WMI itself is unsuccessfully using OpenProcess somewhere…
0
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
Comment Utility
I knew I wrote it for something, I probrably did it to use for all versions but couldn't remember nor did I put any comments in the example that would remind me what I was doing.
<One more question if I can: I’ve noticed that for some applications, it seems I can’t get full app path, no matter what method I’m using >>
Yes some process will change the DACL and deny access in most cases SYSTEM process will be denied but in the case of (wow.exe) it removed VM_READ from the security so you don't get a valid handle for that process, if you would enable SeDebugPrivilege which I think (requires administrator) then you would be able to access the handle and should be able to get the requested output correctly. You will have this issue with "Windows Services".
0
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
Comment Utility
Make sure you test the code from (User) accounts and not Administrative accounts. This is especially the case under XP where no UAC is implemented. I think this (wow.exe) process might try to change the security but only if it has the required privileges to do so.. If you run under Administrator on XP then it probrably attempts to change the security on its process but if it didn't have the rights to do so it simply fails.
So try running wow.exe from a user account and see what results you get..
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:npaun
Comment Utility
ok, I tried the wow.exe on a User account (on XPx32), however the results are the same: OpenProcess returns zero handle for this process…
0
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
Comment Utility
OK. Well I have Windows 7 and it works fine but they add security when it gets the administrative token so they might always add the security on XP but it doesn't appear they always enable it on Windows 7.
You will have this problem for process that deny PROCESS_QUERY_INFORMATION | PROCESS_VM_READ access on the security DACL.. You can always get a handle for the process if you enable SeDebugPrivilege.
0
 

Author Comment

by:npaun
Comment Utility
a) I tried wow.exe on XP32 and Win7-64 and it always returns zero handle, regardless of User/Admin-UAC_On/UAC_Off combination, if it means something to you.

b) Nevertheless, SeDebugPrivilege seems to be working. Although, it doesn’t work on Win7 if UAC is enabled, and it doesn’t work on XP/Win7 on User account regardless of UAC. Is that what should be expected?

c) For SeDebugPrivilege I used example from of your other posts
http://www.experts-exchange.com/Programming/Languages/Visual_Basic/Q_24106182.html?sfQueryTermInfo=1+10+30+egl1044+sedebugprivileg

Is there a way to release SeDebugPrivilege after use? Can your code be modified so it can also unset this privilege? My idea is to use this approach only if and when needed, and to return to previous state immediately afterwards. Somehow I feel a little bit uncomfortable to simply enable SeDebugPrivilege at the beginning of my program regardless whether it will be needed or not.

d) This is a little bit of topic but connected: Do you know is there a way to know if user is having UAC enabled or disabled (or even which 1-3 level on Win7)? I know how to check is it Admin, but I haven’t found an example for this. If Yes, then I’ can put this as a new question…
0
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
Comment Utility
A) I don't know how (wow.exe) works internally but it's changing the security on the DACL and removing specific process access rights.
B) SeDebugPrivilege overrides the security so that an application can always obtain PROCESS_ALL_ACCESS right regardless of the security DACL. Except for system critical processes where they change the critical bit flag ( the processes that always need to run for windows to work).
C) You can disable the privilege in two different ways, if you enable multiple privileges you can use the second parameter (DisableAllPrivileges) set to TRUE removes all privileges and ignores the third parameter. To disable specific privilege use the same code but instead of passing SE_PRIVILEGE_ENABLED specify NONE (0) that will remove the privilege.

See AdjustTokenPrivileges specifially the parameters: (DisableAllPrivileges and NewState)
http://msdn.microsoft.com/en-us/library/aa375202(VS.85).aspx
0
 

Author Comment

by:npaun
Comment Utility
thanks.
Regarding B)
So SeDebugPrivilege should be able to get handle to process regardless if account is User, or UAC is On? And in this case, inability to get handle for wow.exe when User or UAC=On is just some peculiarity of this particular program?
I’m happy even now (as 95% comps are with Admin rights, and most users turns UAC off), butt I’m just a little concerned with resistance of this wow.exe, and possibility that some other programs might also resist in this way…
0
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
Comment Utility
No unfortuanetley that is something that requires administrative privileges :(
Just to cheer you up a bit, even the latest Windows Task Manager has the same issues when running with user tokens. Windows 7 Task Manager has another option to "Show Image paths" if you run in normal mode it misses some system processes and so forth but it has an option called "show processes from all users" which has the UAC shield icon basically what that does is request administrative rights and enable SeDebugPrivilege and then you can see that all the paths are available and not missing.
0
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
Comment Utility
My Bad.
<< So SeDebugPrivilege should be able to get handle to process regardless if account is User, or UAC is On? >>
Yes.
In the previous post my first statment "No unfortuanetley that is something that requires administrative privileges " was refering that you need "Administrative rights" to enable the privilege.
I can show you how exactly this "resistance" is accomplished (Just wrote something the other day to work with changing process privileges) but it's in VB.NET. I can show you how how to change the DACL on your process so that other processes can't obtain access which would be exactly what some processes are doing and that is why OpenProcess() fails.
0
 

Author Comment

by:npaun
Comment Utility
Well, now you have confused me:) If you need Admin for installing SeDebugPrivilege  then << So SeDebugPrivilege should be able to get handle to process regardless if account is User, or UAC is On? >>=YES have collision, as you can’t get SeDebugPrivilege  on User?

Do you wish to say that:
a) SeDebugPrivilege should be able to get handle to process only on Admin account
b) SeDebugPrivilege should be able to get handle to process on Admin account regardless on UAC
c) something else…

regarding the "resistance" method, it not quite necessary, but if you have it your disposal, it might me useful as information. VB.Net doesn’t matter…
0
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
Comment Utility
Well I am looking to deep into this I suppose, but just look at from a process token point of view.
Your process could be running on a user account but it would need to request and administrative token to enable the privilege so (yes it can be enabled from a user account) but it doesn't change the fact that in order for it to be enabled your process must request the administrative token first.
I'll just share my class with you if you feel the need to use it for debugging purposes (or to see what some of these process are doing and why your calls sometimes fail.)
The ProcessSecurity Class is still under construction but the basic functionality of adding and removing access rights in the DACL works.
Create new class named ProcessSecurity.vb
Using the class is very easy, in the following example I obtain the the everyoneSid and Deny access to PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE.
If you try and terminate or kill the process using (End Process) from task manager you will get (Access Denied) because we set Deny access for PROCESS_TERMINATE. The same is true for the other two access rights we denied no process(Including our own) will be allowed to query information or rather (get the file path).
Add 2 Buttons to Form then this code.

Imports System.Security.AccessControl
Imports System.Security.Principal
Imports Microsoft.Win32.SafeHandles
Public Class Form1
Dim hProcess As SafeFileHandle = Nothing
Dim pSecurity As ProcessSecurity = Nothing
Dim sid As SecurityIdentifier = Nothing
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
' Deny Button
pSecurity.AddAccessRule(New ProcessAccessRule(sid, ProcessRights.ProcessQueryInformation Or ProcessRights.ProcessVmRead Or ProcessRights.ProcessTerminate, AccessControlType.Deny))
pSecurity.Persist(hProcess)
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
' Allow Button
pSecurity.RemoveAccessRule(New ProcessAccessRule(sid, ProcessRights.ProcessQueryInformation Or ProcessRights.ProcessVmRead Or ProcessRights.ProcessTerminate, AccessControlType.Deny))
pSecurity.Persist(hProcess)
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
hProcess = New SafeFileHandle(Process.GetCurrentProcess.Handle, False)
sid = New SecurityIdentifier(WellKnownSidType.WorldSid, Nothing)
pSecurity = New ProcessSecurity(hProcess)
End Sub
End Class

'ProcessSecurity.vb

'egl1044



Imports System.Runtime.InteropServices

Imports System.Security.AccessControl

Imports System.Security.Principal





Public NotInheritable Class ProcessSecurity

    Inherits NativeObjectSecurity

    Public Sub New(ByVal handle As SafeHandle)

        MyBase.New(False, Security.AccessControl.ResourceType.KernelObject, handle, _

                   AccessControlSections.Access Or _

                   AccessControlSections.Group Or _

                   AccessControlSections.Owner)

    End Sub

    Public Overrides Function AccessRuleFactory(ByVal identityReference As IdentityReference, ByVal accessMask As Integer, ByVal isInherited As Boolean, ByVal inheritanceFlags As System.Security.AccessControl.InheritanceFlags, ByVal propagationFlags As System.Security.AccessControl.PropagationFlags, ByVal type As System.Security.AccessControl.AccessControlType) As System.Security.AccessControl.AccessRule

        Return New ProcessAccessRule(identityReference, accessMask, type)

    End Function

    Public Overrides Function AuditRuleFactory(ByVal identityReference As IdentityReference, ByVal accessMask As Integer, ByVal isInherited As Boolean, ByVal inheritanceFlags As System.Security.AccessControl.InheritanceFlags, ByVal propagationFlags As System.Security.AccessControl.PropagationFlags, ByVal flags As System.Security.AccessControl.AuditFlags) As System.Security.AccessControl.AuditRule

        Return Nothing

    End Function

    Public Overloads Sub AddAccessRule(ByVal rule As ProcessAccessRule)

        MyBase.AddAccessRule(rule)

    End Sub

    Public Overloads Function RemoveAccessRule(ByVal rule As ProcessAccessRule) As Boolean

        Return MyBase.RemoveAccessRule(rule)

    End Function

    Public Overloads Sub Persist(ByVal handle As SafeHandle)

        WriteLock()

        Try

            Persist(handle, _

                    AccessControlSections.Access Or _

                    AccessControlSections.Group Or _

                    AccessControlSections.Owner)

        Finally

            WriteUnlock()

        End Try

    End Sub

    Public Overrides ReadOnly Property AccessRightType As System.Type

        Get

            Return GetType(Integer)

        End Get

    End Property

    Public Overrides ReadOnly Property AccessRuleType As System.Type

        Get

            Return GetType(ProcessAccessRule)

        End Get

    End Property

    Public Overrides ReadOnly Property AuditRuleType As System.Type

        Get

            Return Nothing

        End Get

    End Property

End Class

Public NotInheritable Class ProcessAccessRule

    Inherits AccessRule

    Public Sub New(ByVal identity As IdentityReference, ByVal accessRights As ProcessRights, ByVal accessType As AccessControlType)

        MyBase.New(identity, accessRights, False, InheritanceFlags.None, PropagationFlags.None, accessType)

    End Sub

End Class

<Flags()>

Public Enum ProcessRights

    'ProcessAllAccess = 0

    ProcessCreateProcess = &H80

    ProcessCreateThread = &H2

    ProcessDupHandle = &H40

    ProcessQueryInformation = &H400

    ProcessQueryLimitedInformation = &H1000

    ProcessSetInfromation = &H200

    ProcessSetQuota = &H100

    ProcessSuspendResume = &H800

    ProcessTerminate = &H1

    ProcessVmOperation = &H8

    ProcessVmRead = &H10

    ProcessVmWrite = &H20

    ProcessSynchronize = &H100000

End Enum

Open in new window

0
 

Author Comment

by:npaun
Comment Utility
Ok, I see.
Thank you very much. You were very helpful and thorough!
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

When trying to find the cause of a problem in VBA or VB6 it's often valuable to know what procedures were executed prior to the error. You can use the Call Stack for that but it is often inadequate because it may show procedures you aren't intereste…
You can of course define an array to hold data that is of a particular type like an array of Strings to hold customer names or an array of Doubles to hold customer sales, but what do you do if you want to coordinate that data? This article describes…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now