Leithauser
asked on
Find full path to EXE file from process information
I am using the following code to find the EXE of all the running processes. (This code is very stripped down to show only the essentials.) It works great on Windows 98. That is, it returns the full path of the program (e.g., "C:\Windows\Program.exe"). However, in XP this same code returns only the EXE file, without the path (e.g., "Program.exe"). For some aspects of my program, I need the full path. Specifically, the program is an anti-Trojan program designed to shut down any Trojan programs and optionally delete the file. In both 98 and XP this code allows me to shut down the program (using KillProcess(uProcess.th32P rocessID, 0)), but I need the full path to do a Kill afterward if the user elects to destroy the Trojan file. Someone please tell me how to get the full path under XP using the following code, or something very close to it using Visual Basic. I prefer something that works in VB 4 (smaller file size), but can do it in VB 6. Also, it would be preferable if it were an add-on to the existing code, rather than a total rewrite using a totally different proceedure, but again I can do what I must.
Here is my existing code, stripped to the essentials:
Type PROCESSENTRY32
dwSize As Long
cntUsage As Long
th32ProcessID As Long
th32DefaultHeapID As Long
th32ModuleID As Long
cntThreads As Long
th32ParentProcessID As Long
pcPriClassBase As Long
dwFlags As Long
szexeFile As String * MAX_PATH
End Type
Declare Function ProcessFirst _
Lib "kernel32" Alias "Process32First" _
(ByVal hSnapshot As Long, _
uProcess As PROCESSENTRY32) As Long
Declare Function ProcessNext _
Lib "kernel32" Alias "Process32Next" _
(ByVal hSnapshot As Long, _
uProcess As PROCESSENTRY32) As Long
Declare Function CreateToolhelpSnapshot _
Lib "kernel32" Alias "CreateToolhelp32Snapshot" _
(ByVal lFlags As Long, _
lProcessID As Long) As Long
Declare Function CloseHandle _
Lib "kernel32" (ByVal hObject As Long) As Long
Sub ListPrograms()
uProcess.dwSize = Len(uProcess)
hSnapshot = CreateToolhelpSnapshot(TH3 2CS_SNAPPR OCESS, 0&)
rProcessFound = ProcessFirst(hSnapshot, uProcess)
Do While rProcessFound
NumProcesses = NumProcesses + 1
i = InStr(1, uProcess.szexeFile, Chr(0))
szExename = LCase$(Left$(uProcess.szex eFile, i - 1))
MainForm.List1.AddItem szExename
rProcessFound = ProcessNext(hSnapshot, uProcess)
Loop
Call CloseHandle(hSnapshot)
End Sub
Here is my existing code, stripped to the essentials:
Type PROCESSENTRY32
dwSize As Long
cntUsage As Long
th32ProcessID As Long
th32DefaultHeapID As Long
th32ModuleID As Long
cntThreads As Long
th32ParentProcessID As Long
pcPriClassBase As Long
dwFlags As Long
szexeFile As String * MAX_PATH
End Type
Declare Function ProcessFirst _
Lib "kernel32" Alias "Process32First" _
(ByVal hSnapshot As Long, _
uProcess As PROCESSENTRY32) As Long
Declare Function ProcessNext _
Lib "kernel32" Alias "Process32Next" _
(ByVal hSnapshot As Long, _
uProcess As PROCESSENTRY32) As Long
Declare Function CreateToolhelpSnapshot _
Lib "kernel32" Alias "CreateToolhelp32Snapshot"
(ByVal lFlags As Long, _
lProcessID As Long) As Long
Declare Function CloseHandle _
Lib "kernel32" (ByVal hObject As Long) As Long
Sub ListPrograms()
uProcess.dwSize = Len(uProcess)
hSnapshot = CreateToolhelpSnapshot(TH3
rProcessFound = ProcessFirst(hSnapshot, uProcess)
Do While rProcessFound
NumProcesses = NumProcesses + 1
i = InStr(1, uProcess.szexeFile, Chr(0))
szExename = LCase$(Left$(uProcess.szex
MainForm.List1.AddItem szExename
rProcessFound = ProcessNext(hSnapshot, uProcess)
Loop
Call CloseHandle(hSnapshot)
End Sub
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Try this
Option Explicit
Private Sub Command1_Click()
Dim objWMIService As Object
Dim colProcesses As Object
Dim objProcess As Object
On Error Resume Next
Set objWMIService = GetObject("winmgmts:")
Set colProcesses = objWMIService.ExecQuery("S elect * from Win32_Process")
For Each objProcess In colProcesses
Debug.Print objProcess.Caption, objProcess.executablepath
Next
End Sub
Option Explicit
Private Sub Command1_Click()
Dim objWMIService As Object
Dim colProcesses As Object
Dim objProcess As Object
On Error Resume Next
Set objWMIService = GetObject("winmgmts:")
Set colProcesses = objWMIService.ExecQuery("S
For Each objProcess In colProcesses
Debug.Print objProcess.Caption, objProcess.executablepath
Next
End Sub
ASKER
mladenovicz:
Your solution sems to be the best, although there are some problems.
1) It appears to require that I provide an Exe name, then it finds the path. As I understand it, the program must be running for it to do this, because it refers to the process. Is this right? That could work for me. I could use the old sytem to get the Exe name, then call your code to get the full path if the OS is NT based, like XP.
2) I found that some EXE's I tried it with did not work (no result), even though they were clearly running (they came up in my old code). Any idea why? csrss.exe is one exmple. It is some kind of system file, found in C:\Windows\system32. alg.exe is another.
3) Some come up twice. svchost.exe is one of them. Any idea why?
Your solution sems to be the best, although there are some problems.
1) It appears to require that I provide an Exe name, then it finds the path. As I understand it, the program must be running for it to do this, because it refers to the process. Is this right? That could work for me. I could use the old sytem to get the Exe name, then call your code to get the full path if the OS is NT based, like XP.
2) I found that some EXE's I tried it with did not work (no result), even though they were clearly running (they came up in my old code). Any idea why? csrss.exe is one exmple. It is some kind of system file, found in C:\Windows\system32. alg.exe is another.
3) Some come up twice. svchost.exe is one of them. Any idea why?
Try this
'In a form
Private Sub Form_Load()
'Code submitted by Roger Taylor
'enumerate all the different explorer.exe processes
GetProcesses
End Sub
Public Declare Function GetProcessMemoryInfo Lib "PSAPI.DLL" (ByVal hProcess As Long, ppsmemCounters As PROCESS_MEMORY_COUNTERS, ByVal cb As Long) As Long
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 Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Public Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
Public Declare Sub GlobalMemoryStatus Lib "kernel32" (lpBuffer As MEMORYSTATUS)
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
Public Const PROCESS_ALL_ACCESS = &H1F0FFF
Public Const TH32CS_SNAPPROCESS = &H2&
Public Const hNull = 0
Public Const WIN95_System_Found = 1
Public Const WINNT_System_Found = 2
Public Const Default_Log_Size = 10000000
Public Const Default_Log_Days = 0
Public Const SPECIFIC_RIGHTS_ALL = &HFFFF
Public Const STANDARD_RIGHTS_ALL = &H1F0000
Type MEMORYSTATUS
dwLength As Long
dwMemoryLoad As Long
dwTotalPhys As Long
dwAvailPhys As Long
dwTotalPageFile As Long
dwAvailPageFile As Long
dwTotalVirtual As Long
dwAvailVirtual As Long
End Type
Type PROCESS_MEMORY_COUNTERS
cb As Long
PageFaultCount As Long
PeakWorkingSetSize As Long
WorkingSetSize As Long
QuotaPeakPagedPoolUsage As Long
QuotaPagedPoolUsage As Long
QuotaPeakNonPagedPoolUsage As Long
QuotaNonPagedPoolUsage As Long
PagefileUsage As Long
PeakPagefileUsage As Long
End Type
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 Function GetProcesses()
Dim booResult As Boolean
Dim lngLength As Long
Dim lngProcessID As Long
Dim strProcessName As String
Dim lngSnapHwnd As Long
Dim udtProcEntry As PROCESSENTRY32
Dim lngCBSize As Long 'Specifies the size, In bytes, of the lpidProcess array
Dim lngCBSizeReturned As Long 'Receives the number of bytes returned
Dim lngNumElements As Long
Dim lngProcessIDs() As Long
Dim lngCBSize2 As Long
Dim lngModules(1 To 200) As Long
Dim lngReturn As Long
Dim strModuleName As String
Dim lngSize As Long
Dim lngHwndProcess As Long
Dim lngLoop As Long
Dim b As Long
Dim c As Long
Dim e As Long
Dim d As Long
Dim pmc As PROCESS_MEMORY_COUNTERS
Dim lret As Long
Dim strProcName2 As String
Dim strProcName As String
'Turn on Error handler
On Error GoTo Error_handler
booResult = False
EXEName = UCase$(Trim$(EXEName))
lngLength = Len(EXEName)
'ProcessInfo.bolRunning = False
Select Case getVersion()
'I'm not bothered about windows 95/98 becasue this class probably wont be used on it anyway.
Case WIN95_System_Found 'Windows 95/98
Case WINNT_System_Found 'Windows NT
lngCBSize = 8 ' Really needs To be 16, but Loop will increment prior to calling API
lngCBSizeReturned = 96
Do While lngCBSize <= lngCBSizeReturned
DoEvents
'Increment Size
lngCBSize = lngCBSize * 2
'Allocate Memory for Array
ReDim lngProcessIDs(lngCBSize / 4) As Long
'Get Process ID's
lngReturn = EnumProcesses(lngProcessID s(1), lngCBSize, lngCBSizeReturned)
Loop
'Count number of processes returned
lngNumElements = lngCBSizeReturned / 4
'Loop thru each process
For lngLoop = 1 To lngNumElements
DoEvents
'Get a handle to the Process and Open
lngHwndProcess = OpenProcess(PROCESS_QUERY_ INFORMATIO N Or PROCESS_VM_READ, 0, lngProcessIDs(lngLoop))
If lngHwndProcess <> 0 Then
'Get an array of the module handles for the specified process
lngReturn = EnumProcessModules(lngHwnd Process, lngModules(1), 200, lngCBSize2)
'If the Module Array is retrieved, Get the ModuleFileName
If lngReturn <> 0 Then
'Buffer with spaces first to allocate memory for byte array
strModuleName = Space(MAX_PATH)
'Must be set prior to calling API
lngSize = 500
'Get Process Name
lngReturn = GetModuleFileNameExA(lngHw ndProcess, lngModules(1), strModuleName, lngSize)
'Remove trailing spaces
strProcessName = Left(strModuleName, lngReturn)
'Check for Matching Upper case result
strProcessName = UCase$(Trim$(strProcessNam e))
strProcName2 = GetElement(Trim(Replace(st rProcessNa me, Chr$(0), "")), "\", 0, 0, GetNumElements(Trim(Replac e(strProce ssName, Chr$(0), "")), "\") - 1)
'If strProcName2 = EXEName Then
'Get the Site of the Memory Structure
pmc.cb = LenB(pmc)
lret = GetProcessMemoryInfo(lngHw ndProcess, pmc, pmc.cb)
Debug.Print EXEName & "::" & CStr(pmc.WorkingSetSize / 1024)
Debug.Print "Path: " & strProcessName
'End If
End If
End If
'Close the handle to this process
lngReturn = CloseHandle(lngHwndProcess )
DoEvents
Next
End Select
IsProcessRunning_Exit:
'Exit early to avoid error handler
Exit Function
Error_handler:
Err.Raise Err, Err.Source, "ProcessInfo", Error
Resume Next
End Function
Private 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
Private Function StrZToStr(s As String) As String
StrZToStr = Left$(s, Len(s) - 1)
End Function
Public Function GetElement(ByVal strList As String, ByVal strDelimiter As String, ByVal lngNumColumns As Long, ByVal lngRow As Long, ByVal lngColumn As Long) As String
Dim lngCounter As Long
' Append delimiter text to the end of the list as a terminator.
strList = strList & strDelimiter
' Calculate the offset for the item required based on the number of columns the list
' 'strList' has i.e. 'lngNumColumns' and from which row the element is to be
' selected i.e. 'lngRow'.
lngColumn = IIf(lngRow = 0, lngColumn, (lngRow * lngNumColumns) + lngColumn)
' Search for the 'lngColumn' item from the list 'strList'.
For lngCounter = 0 To lngColumn - 1
' Remove each item from the list.
strList = Mid$(strList, InStr(strList, strDelimiter) + Len(strDelimiter), Len(strList))
' If list becomes empty before 'lngColumn' is found then just
' return an empty string.
If Len(strList) = 0 Then
GetElement = ""
Exit Function
End If
Next lngCounter
' Return the sought list element.
GetElement = Left$(strList, InStr(strList, strDelimiter) - 1)
End Function
'''''''''''''''''''''''''' '''''''''' '''''''''' '''''''''' ''''''
'Function GetNumElements (ByVal strList As String,
' ByVal strDelimiter As String)
' As Integer
'
' strList = The element list.
' strDelimiter = The delimiter by which the elements in
' 'strList' are seperated.
'
' The function returns an integer which is the count of the
' number of elements in 'strList'.
'
' Author: Roger Taylor
'
' Date:26/12/1998
'
' Additional Information:
'
' Revision History:
'
'''''''''''''''''''''''''' '''''''''' '''''''''' '''''''''' ''''''
Public Function GetNumElements(ByVal strList As String, ByVal strDelimiter As String) As Integer
Dim intElementCount As Integer
' If no elements in the list 'strList' then just return 0.
If Len(strList) = 0 Then
GetNumElements = 0
Exit Function
End If
' Append delimiter text to the end of the list as a terminator.
strList = strList & strDelimiter
' Count the number of elements in 'strlist'
While InStr(strList, strDelimiter) > 0
intElementCount = intElementCount + 1
strList = Mid$(strList, InStr(strList, strDelimiter) + 1, Len(strList))
Wend
' Return the number of elements in 'strList'.
GetNumElements = intElementCount
End Function
2. I am running Win XP and csrss.exe is found
3. svchost.exe comes up twice, because there are more than one instance, check task manager
'In a form
Private Sub Form_Load()
'Code submitted by Roger Taylor
'enumerate all the different explorer.exe processes
GetProcesses
End Sub
Public Declare Function GetProcessMemoryInfo Lib "PSAPI.DLL" (ByVal hProcess As Long, ppsmemCounters As PROCESS_MEMORY_COUNTERS, ByVal cb As Long) As Long
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 Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Public Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
Public Declare Sub GlobalMemoryStatus Lib "kernel32" (lpBuffer As MEMORYSTATUS)
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
Public Const PROCESS_ALL_ACCESS = &H1F0FFF
Public Const TH32CS_SNAPPROCESS = &H2&
Public Const hNull = 0
Public Const WIN95_System_Found = 1
Public Const WINNT_System_Found = 2
Public Const Default_Log_Size = 10000000
Public Const Default_Log_Days = 0
Public Const SPECIFIC_RIGHTS_ALL = &HFFFF
Public Const STANDARD_RIGHTS_ALL = &H1F0000
Type MEMORYSTATUS
dwLength As Long
dwMemoryLoad As Long
dwTotalPhys As Long
dwAvailPhys As Long
dwTotalPageFile As Long
dwAvailPageFile As Long
dwTotalVirtual As Long
dwAvailVirtual As Long
End Type
Type PROCESS_MEMORY_COUNTERS
cb As Long
PageFaultCount As Long
PeakWorkingSetSize As Long
WorkingSetSize As Long
QuotaPeakPagedPoolUsage As Long
QuotaPagedPoolUsage As Long
QuotaPeakNonPagedPoolUsage
QuotaNonPagedPoolUsage As Long
PagefileUsage As Long
PeakPagefileUsage As Long
End Type
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 Function GetProcesses()
Dim booResult As Boolean
Dim lngLength As Long
Dim lngProcessID As Long
Dim strProcessName As String
Dim lngSnapHwnd As Long
Dim udtProcEntry As PROCESSENTRY32
Dim lngCBSize As Long 'Specifies the size, In bytes, of the lpidProcess array
Dim lngCBSizeReturned As Long 'Receives the number of bytes returned
Dim lngNumElements As Long
Dim lngProcessIDs() As Long
Dim lngCBSize2 As Long
Dim lngModules(1 To 200) As Long
Dim lngReturn As Long
Dim strModuleName As String
Dim lngSize As Long
Dim lngHwndProcess As Long
Dim lngLoop As Long
Dim b As Long
Dim c As Long
Dim e As Long
Dim d As Long
Dim pmc As PROCESS_MEMORY_COUNTERS
Dim lret As Long
Dim strProcName2 As String
Dim strProcName As String
'Turn on Error handler
On Error GoTo Error_handler
booResult = False
EXEName = UCase$(Trim$(EXEName))
lngLength = Len(EXEName)
'ProcessInfo.bolRunning = False
Select Case getVersion()
'I'm not bothered about windows 95/98 becasue this class probably wont be used on it anyway.
Case WIN95_System_Found 'Windows 95/98
Case WINNT_System_Found 'Windows NT
lngCBSize = 8 ' Really needs To be 16, but Loop will increment prior to calling API
lngCBSizeReturned = 96
Do While lngCBSize <= lngCBSizeReturned
DoEvents
'Increment Size
lngCBSize = lngCBSize * 2
'Allocate Memory for Array
ReDim lngProcessIDs(lngCBSize / 4) As Long
'Get Process ID's
lngReturn = EnumProcesses(lngProcessID
Loop
'Count number of processes returned
lngNumElements = lngCBSizeReturned / 4
'Loop thru each process
For lngLoop = 1 To lngNumElements
DoEvents
'Get a handle to the Process and Open
lngHwndProcess = OpenProcess(PROCESS_QUERY_
If lngHwndProcess <> 0 Then
'Get an array of the module handles for the specified process
lngReturn = EnumProcessModules(lngHwnd
'If the Module Array is retrieved, Get the ModuleFileName
If lngReturn <> 0 Then
'Buffer with spaces first to allocate memory for byte array
strModuleName = Space(MAX_PATH)
'Must be set prior to calling API
lngSize = 500
'Get Process Name
lngReturn = GetModuleFileNameExA(lngHw
'Remove trailing spaces
strProcessName = Left(strModuleName, lngReturn)
'Check for Matching Upper case result
strProcessName = UCase$(Trim$(strProcessNam
strProcName2 = GetElement(Trim(Replace(st
'If strProcName2 = EXEName Then
'Get the Site of the Memory Structure
pmc.cb = LenB(pmc)
lret = GetProcessMemoryInfo(lngHw
Debug.Print EXEName & "::" & CStr(pmc.WorkingSetSize / 1024)
Debug.Print "Path: " & strProcessName
'End If
End If
End If
'Close the handle to this process
lngReturn = CloseHandle(lngHwndProcess
DoEvents
Next
End Select
IsProcessRunning_Exit:
'Exit early to avoid error handler
Exit Function
Error_handler:
Err.Raise Err, Err.Source, "ProcessInfo", Error
Resume Next
End Function
Private Function getVersion() As Long
Dim osinfo As OSVERSIONINFO
Dim retvalue As Integer
osinfo.dwOSVersionInfoSize
osinfo.szCSDVersion = Space$(128)
retvalue = GetVersionExA(osinfo)
getVersion = osinfo.dwPlatformId
End Function
Private Function StrZToStr(s As String) As String
StrZToStr = Left$(s, Len(s) - 1)
End Function
Public Function GetElement(ByVal strList As String, ByVal strDelimiter As String, ByVal lngNumColumns As Long, ByVal lngRow As Long, ByVal lngColumn As Long) As String
Dim lngCounter As Long
' Append delimiter text to the end of the list as a terminator.
strList = strList & strDelimiter
' Calculate the offset for the item required based on the number of columns the list
' 'strList' has i.e. 'lngNumColumns' and from which row the element is to be
' selected i.e. 'lngRow'.
lngColumn = IIf(lngRow = 0, lngColumn, (lngRow * lngNumColumns) + lngColumn)
' Search for the 'lngColumn' item from the list 'strList'.
For lngCounter = 0 To lngColumn - 1
' Remove each item from the list.
strList = Mid$(strList, InStr(strList, strDelimiter) + Len(strDelimiter), Len(strList))
' If list becomes empty before 'lngColumn' is found then just
' return an empty string.
If Len(strList) = 0 Then
GetElement = ""
Exit Function
End If
Next lngCounter
' Return the sought list element.
GetElement = Left$(strList, InStr(strList, strDelimiter) - 1)
End Function
''''''''''''''''''''''''''
'Function GetNumElements (ByVal strList As String,
' ByVal strDelimiter As String)
' As Integer
'
' strList = The element list.
' strDelimiter = The delimiter by which the elements in
' 'strList' are seperated.
'
' The function returns an integer which is the count of the
' number of elements in 'strList'.
'
' Author: Roger Taylor
'
' Date:26/12/1998
'
' Additional Information:
'
' Revision History:
'
''''''''''''''''''''''''''
Public Function GetNumElements(ByVal strList As String, ByVal strDelimiter As String) As Integer
Dim intElementCount As Integer
' If no elements in the list 'strList' then just return 0.
If Len(strList) = 0 Then
GetNumElements = 0
Exit Function
End If
' Append delimiter text to the end of the list as a terminator.
strList = strList & strDelimiter
' Count the number of elements in 'strlist'
While InStr(strList, strDelimiter) > 0
intElementCount = intElementCount + 1
strList = Mid$(strList, InStr(strList, strDelimiter) + 1, Len(strList))
Wend
' Return the number of elements in 'strList'.
GetNumElements = intElementCount
End Function
2. I am running Win XP and csrss.exe is found
3. svchost.exe comes up twice, because there are more than one instance, check task manager
ASKER
<<2. I am running Win XP and csrss.exe is found>>
For some reason,it is just not showing on mine, even with the new code. I even checked to see if it was a hidden file or anything. Nope. Just no explanation I can see. I am providing a backup procedure in my program. If my original code says the process is running and your code does not find it, I do a simple disk search. There are two problems with the disk search: It takes a long time, and it has to check to make sure there are not two EXE files with that name. If there are two files, it does not do the delete for fear of getting the wrong one. Fortunately, your code does find the file path most of the time.
<<3. svchost.exe comes up twice, because there are more than one instance, check task manager>>
You are correct. I suspected it was something like that, I jsut did not get around to testing my theory before I emailed you.
As I mentioned, my program is a Trojan Detector. It learns all the EXE files you normally run. Then if a new, unknown process starts running, it shuts it down. My old code could do that. The problem was an option to delete the file from disk too. That worked with my old code on Win 98, because on Win 98 my old code returned the full file path. Since my code did not return the full file path on NT based computers, my program could not delete the file. I have incorporated yor code into my program. My program now uses my old code to detect the EXE file. If the user has elected to have my program delete the file too and my code has not provided the full path, my code calls your code (the one you supplied first), supplies the EXE file name, and gets the full path (doing a disk search if your code fail to find the path). Then it shuts down the EXE file using my original code and deletes it using the path obtained by your code. It works.
I am awarding you the points, based on your first answer, which is what I am using. Thanks.
BTW, I'll be glad to give you a free copy of my Trojan Slayer program, if you like.
For some reason,it is just not showing on mine, even with the new code. I even checked to see if it was a hidden file or anything. Nope. Just no explanation I can see. I am providing a backup procedure in my program. If my original code says the process is running and your code does not find it, I do a simple disk search. There are two problems with the disk search: It takes a long time, and it has to check to make sure there are not two EXE files with that name. If there are two files, it does not do the delete for fear of getting the wrong one. Fortunately, your code does find the file path most of the time.
<<3. svchost.exe comes up twice, because there are more than one instance, check task manager>>
You are correct. I suspected it was something like that, I jsut did not get around to testing my theory before I emailed you.
As I mentioned, my program is a Trojan Detector. It learns all the EXE files you normally run. Then if a new, unknown process starts running, it shuts it down. My old code could do that. The problem was an option to delete the file from disk too. That worked with my old code on Win 98, because on Win 98 my old code returned the full file path. Since my code did not return the full file path on NT based computers, my program could not delete the file. I have incorporated yor code into my program. My program now uses my old code to detect the EXE file. If the user has elected to have my program delete the file too and my code has not provided the full path, my code calls your code (the one you supplied first), supplies the EXE file name, and gets the full path (doing a disk search if your code fail to find the path). Then it shuts down the EXE file using my original code and deletes it using the path obtained by your code. It works.
I am awarding you the points, based on your first answer, which is what I am using. Thanks.
BTW, I'll be glad to give you a free copy of my Trojan Slayer program, if you like.
How To List Running Processes
http://support.microsoft.com/default.aspx?scid=kb;en-us;187913