Форум программистов, компьютерный форум, киберфорум
Visual Basic
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.95/19: Рейтинг темы: голосов - 19, средняя оценка - 4.95
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769

Функция QueryFullProcessImageName врёт и возвращает неправильный, уже не существующий, путь к исполняемому файлу

21.04.2023, 13:30. Показов 5380. Ответов 63
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Столкнулся сегодня с небывалом чудом. Функция QueryFullProcessImageName врёт и возвращает не правду, наглую ложь и враньё. Позор Microsoft'у! Я такого от Microsoft'а не ожидал, честно! Баг майкрософта!!!

Всё началось с того, что я решил написать простенькую функцию AppPath для получения пути к своему исполняемому файлу с учётом уникодных символов, с китайскими иероглифами или другими сложными уникодными символами, в пути, в именах папок. Конечно стандартный App.Path нам такого не вернёт, но в стандартном App.Path хотя бы не врёт с получением правильного пути. Хоть и не поддерживает уникод.

Итак сначала я создал новый проект:

Форма:

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Option Explicit
Private Declare Function QueryFullProcessImageName Lib "kernel32" Alias "QueryFullProcessImageNameW" (ByVal hProcess As Long, ByVal dwFlags As Long, ByVal lpExeName As Long, lpdwSize As Long) As Long
Private Const MAX_PATH As Long = 260
 
Public Function AppPath() As String
    Dim strProcName As String
    Dim lStr As Long
    
    strProcName = Space$(MAX_PATH * 2): lStr = MAX_PATH
    QueryFullProcessImageName -1, 0, StrPtr(strProcName), lStr
    strProcName = Left$(strProcName, lStr)
    
    AppPath = Left$(strProcName, InStrRev(strProcName, "\"))
End Function
 
Private Sub Command1_Click()
    Me.Cls
    PrintW Chr(34) & AppPath & Chr(34), Me
End Sub
 
Private Sub Command2_Click()
    Me.Cls
    PrintW Chr(34) & App.Path & Chr(34), Me
End Sub
Модуль:

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Option Explicit
Private Declare Function DrawText Lib "user32" Alias "DrawTextW" (ByVal hdc As Long, ByVal lpStr As Long, ByVal nCount As Long, lpRect As RECT, ByVal wFormat As Long) As Long
 
Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type
 
Private Const DT_CENTER = &H1
Private Const DT_SINGLELINE = &H20
Private Const DT_VCENTER = &H4
 
Public Function PrintW(PrintText As String, PrintForm As Form)
    Dim myRect As RECT
    
    myRect.Left = 0
    myRect.Top = 0
    myRect.Right = PrintForm.ScaleWidth
    myRect.Bottom = PrintForm.ScaleHeight
    
    DrawText PrintForm.hdc, StrPtr(PrintText), Len(PrintText), myRect, DT_SINGLELINE Or DT_VCENTER Or DT_CENTER
End Function
В форме ScaleMode выставил на пиксели. Далее всё заработало правильно как надо. Скомпилировал EXE, вышел из VB6 так как он и не сможет запуститься вообще, если проект находится в папках с уникодными сложными символами, с китайщиной.

Переименовал свою папку с программой в "App.Path с китайскими иероглифами 拷贝" для теста, как будет работать функция.
Запустил EXE и первый раз функция сработала правильно! Потом переименовал папку в другое имя, для проверки. Переименовал в "App.Path с китайскими иероглифами ñ" и решил проверить, в результате получил в пути старое имя папки! Майкрософтовская функция QueryFullProcessImageName даже и не подумала обновить путь к EXE-файлу! Ладно, подумал может это лёгкий баг и нужно просто перезапустить программу заного. Полностью закрыл, потом открыл программу снова! И то же самое! Опять старый путь с китайскими символами!!!! Я был в шоке! Потом 10 раз закрывал и перезапускал и всё так же старая папка с китайщиной. И самое смешное то, что стандартный App.Path правильно меняет путь и китайских символов в пути уже нет, НО конечно не поддерживает букву n диакритическую с тильдой сверху буквы.

Вопрос почему функция майкрософта такая ерундовая!? И как правильно получать путь в уникоде чтобы небыло этой ерунды со старыми путями, после переименовывания папок...
Миниатюры
Функция QueryFullProcessImageName врёт и возвращает неправильный, уже не существующий, путь к исполняемому файлу   Функция QueryFullProcessImageName врёт и возвращает неправильный, уже не существующий, путь к исполняемому файлу  
1
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
21.04.2023, 13:30
Ответы с готовыми решениями:

Путь к исполняемому файлу
Всем доброго времени суток. Я делаю приложение пока под платформу виндовс. Рядом с приложением есть База Данных и используемые ресурсы....

Путь к исполняемому файлу
Хочу написать программу из двух частей. Вторую часть программы запускает первая, а вторая должна сохранять свои настройки к себе в папку....

Путь к исполняемому файлу
Здравствуйте, вообщем проблема в следующем, необходимо указать путь к исполяемому файлу, т.е. я запускаю свой exe-шник(построенный в...

63
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18031 / 7734 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
23.04.2023, 13:45
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от HackerVlad Посмотреть сообщение
что не надо использовать простой поиск косой черты на конце
почему?

Цитата Сообщение от HackerVlad Посмотреть сообщение
гораздо хуже, чем MakeTrue
почему?
0
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
23.04.2023, 13:51  [ТС]
Цитата Сообщение от Dragokas Посмотреть сообщение
почему?
The Trick говорит что бывают пути без косой черты, хотя я лично никогда не видел

Добавлено через 4 минуты
Цитата Сообщение от Dragokas Посмотреть сообщение
чем MakeTrue
https://www.vbforums.com/showt... ost4842077
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18031 / 7734 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
23.04.2023, 15:06
Цитата Сообщение от HackerVlad Посмотреть сообщение
The Trick говорит что бывают пути без косой черты, хотя я лично никогда не видел
Интересно, конечно, что это за путя такие. С прямым слешем эта функция все равно не умеет работать.
Цитата Сообщение от HackerVlad Посмотреть сообщение
https://www.vbforums.com/showthread.php?789371-Math-Issue-Long-to-WORD-converstion-problem&p=4842077&viewfull=1#post4842077
Посмотрел, действительно в таком варианте компилятор выбрасывает часть кода. Однако, в конкретном случае, "гораздо лучше", преувеличение. Ты же не на серьезе будешь в цикле гонять эту функцию с экономией в 1 строку. Скорее просто закешируешь ее значение.
0
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
23.04.2023, 15:37  [ТС]
Цитата Сообщение от Dragokas Посмотреть сообщение
Интересно, конечно, что это за путя такие.
The trick скидывал эту ссылку на официальную документацию https://learn.microsoft.com/en... ing-a-file там вроде есть пример от майкрософта с путями без слэша, но честно, я никогда в жизни не видел путей без слэша, максимум что я видел это с обратным слэшем как в линуксе

Добавлено через 2 минуты
Цитата Сообщение от Dragokas Посмотреть сообщение
Однако, в конкретном случае, "гораздо лучше", преувеличение.
The trick говорил что там кроме этого ещё что-то app.logmode ерунда короче полная

Добавлено через 2 минуты
Цитата Сообщение от Dragokas Посмотреть сообщение
будешь в цикле гонять эту функцию
Ты про какую функцию

Добавлено через 1 минуту
Жаль сам The trick не отвечает, он бы точно тебе объяснил

Добавлено через 7 минут
Цитата из MSDN:

Если имя файла начинается только с обозначения диска, но без обратной косой черты после двоеточия, оно интерпретируется как относительный путь к текущему каталогу на диске с указанной буквой. Обратите внимание, что текущий каталог может быть или не быть корневым каталогом в зависимости от того, что он был установлен во время самой последней операции «изменить каталог» на этом диске. Примеры этого формата следующие:

«C:tmp.txt» относится к файлу с именем «tmp.txt» в текущем каталоге на диске C.
«C:tempdir\tmp.txt» относится к файлу в подкаталоге текущего каталога на диске C.

Добавлено через 1 минуту
Но я лично не очень верю в то, что функция GetModuleFileName может вернуть путь без косой черты хоть раз в жизни хоть когда-то хоть где-то у кого-то, но мало ли... Проверял на корне диска косая черта всегда есть...

Добавлено через 1 минуту
Хотя кто знает может есть системы такие где и диски без букв A-Z может по именам каким другим кто знает кто знает...
1
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18031 / 7734 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
23.04.2023, 15:45
Цитата Сообщение от HackerVlad Посмотреть сообщение
Ты про какую функцию
Про твою), если и оптимизировать, то ее просто один раз вызовут и запомнят, нежели будут гонять в цикле.

Кстати, поиск концевого слеша в твоем коде лишний. По описанию PathRemoveFileSpecW, она гарантирует удаление такого слеша.
0
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
23.04.2023, 15:52  [ТС]
Цитата Сообщение от Dragokas Посмотреть сообщение
По описанию PathRemoveFileSpecW, она гарантирует удаление такого слеша
Я же проверял в корне диска слэш есть, я реально проверял

Добавлено через 1 минуту
Цитата Сообщение от Dragokas Посмотреть сообщение
нежели будут гонять в цикле
думаешь она долго будет подвисать? её работа занимает 0 миллисекунд, но если так хочешь оптимизировать запоминай в Static
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18031 / 7734 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
23.04.2023, 15:53
Цитата Сообщение от HackerVlad Посмотреть сообщение
Я же проверял в корне диска слэш есть, я реально проверял
Проверь ещё раз)
0
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
23.04.2023, 15:59  [ТС]
Цитата Сообщение от Dragokas Посмотреть сообщение
Проверь ещё раз)
А ты проверял?
0
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
23.04.2023, 16:02  [ТС]
Хочешь доказательстьв? Вот пожалуйста, я говорю у меня слеш есть! Если в корне диска.
Миниатюры
Функция QueryFullProcessImageName врёт и возвращает неправильный, уже не существующий, путь к исполняемому файлу  
0
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
23.04.2023, 18:46  [ТС]
Именно поэтому я его отрубаю этот слеш такой строкой кода:
Visual Basic
1
If Right$(AppPath, 1) = "\" Then AppPath = Mid$(AppPath, 1, Len(AppPath) - 1)
Добавлено через 19 секунд
Вдруг человек запустит программу в корне диска!?

Добавлено через 2 часа 42 минуты
Цитата Сообщение от Dragokas Посмотреть сообщение
По описанию PathRemoveFileSpecW, она гарантирует удаление такого слеша
Не видел я таких гарантий в описании функции

Добавлено через 54 секунды
Функция удаляет слеш только если не в корне диска - это факт, сам проверь, прежде чем утверждать
0
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
24.04.2023, 14:23  [ТС]
Цитата Сообщение от Dragokas Посмотреть сообщение
Про твою), если и оптимизировать
Вот решил оптимизировать, вот новый вариант модуля:

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
Option Explicit
 
Private Declare Function GetModuleFileNameW Lib "kernel32.dll" (ByVal hModule As Long, ByVal lpFilename As Long, ByVal nSize As Long) As Long
Private Declare Function PathRemoveFileSpecW Lib "shlwapi.dll" (ByVal pszPath As Long) As Byte
 
Private Const MAX_PATH As Long = 260
 
' It works faster here than Static inside the function
Dim SaveAppPath As String
 
Private Function MakeTrue(ByRef bValue As Boolean) As Boolean
    MakeTrue = True
    bValue = True
End Function
 
' //
' // App.Path - Unicode aware
' // by The Trick and HackerVlad
' //
Public Function AppPath() As String
    Dim bInIDE As Boolean
    Dim lNullPos As Long
    
    If Len(SaveAppPath) > 0 Then
        AppPath = SaveAppPath
    Else
        Debug.Assert MakeTrue(bInIDE)
        
        If bInIDE Then
            AppPath = App.Path
            SaveAppPath = AppPath
        Else
            AppPath = Space$(MAX_PATH)
            GetModuleFileNameW 0, StrPtr(AppPath), 260
            PathRemoveFileSpecW StrPtr(AppPath)
            
            lNullPos = InStr(1, AppPath, vbNullChar)
            If lNullPos Then
                AppPath = Left$(AppPath, lNullPos - 1)
                If Right$(AppPath, 1) = "\" Then AppPath = Mid$(AppPath, 1, Len(AppPath) - 1)
                SaveAppPath = AppPath
            Else
                AppPath = App.Path
                If Right$(AppPath, 1) = "\" Then AppPath = Mid$(AppPath, 1, Len(AppPath) - 1)
                SaveAppPath = AppPath
            End If
        End If
    End If
End Function
Кстати по моим тестам, я заметил, что Dim SaveAppPath As String в модуле работает чуть быстрее, чем Static SaveAppPath As String в функции, это действительно правда.
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18031 / 7734 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
25.04.2023, 00:28
Цитата Сообщение от HackerVlad Посмотреть сообщение
Функция удаляет слеш только если не в корне диска - это факт, сам проверь, прежде чем утверждать
Виноват, напутал описание с ее соседкой PathCchRemoveFileSpec
А я проверял, как раз не в корне.

Цитата Сообщение от HackerVlad Посмотреть сообщение
Вот решил оптимизировать, вот новый вариант модуля:
Можешь оптимизировать ещё, удалив две одинаковые строчки кода
0
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
25.04.2023, 01:32  [ТС]
Цитата Сообщение от Dragokas Посмотреть сообщение
Можешь оптимизировать ещё, удалив две одинаковые строчки кода
Какие ещё одинаковые строчки кода, я тоже, знаешь, могу сказать, как тебе оптимизировать твою функцию

Добавлено через 8 минут
Подумаешь две строки одинаковых, не 10 же
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18031 / 7734 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
25.04.2023, 02:44
Цитата Сообщение от HackerVlad Посмотреть сообщение
Какие ещё одинаковые строчки кода
Отгадай с одной попытки:
Цитата Сообщение от HackerVlad
Code
1
2
3
4
5
6
7
8
9
            If lNullPos Then
                AppPath = Left$(AppPath, lNullPos - 1)
                If Right$(AppPath, 1) = "" Then AppPath = Mid$(AppPath, 1, Len(AppPath) - 1)
                SaveAppPath = AppPath
            Else
                AppPath = App.Path
                If Right$(AppPath, 1) = "" Then AppPath = Mid$(AppPath, 1, Len(AppPath) - 1)
                SaveAppPath = AppPath
            End If
Ну не знаю-не знаю, до этого у вас целая 1 строчка кода вызывала эмоцию:
Цитата Сообщение от HackerVlad Посмотреть сообщение
гораздо хуже
А тут аж целых две. Что-то поменялось?
0
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
25.04.2023, 13:19  [ТС]
Да Господи сэкономишь ты эти 100 байт какая разница

Добавлено через 39 минут
Цитата Сообщение от Dragokas Посмотреть сообщение
Отгадай с одной попытки
Поздравляю, оптимизировали на 130 байт!

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
Option Explicit
Private Declare Function GetModuleFileNameW Lib "kernel32.dll" (ByVal hModule As Long, ByVal lpFilename As Long, ByVal nSize As Long) As Long
Private Declare Function PathRemoveFileSpecW Lib "shlwapi.dll" (ByVal pszPath As Long) As Long
 
Private Const MAX_PATH As Long = 260
 
' It works faster here than Static inside the function
Dim SaveAppPath As String
 
Private Function MakeTrue(ByRef bValue As Boolean) As Boolean
    MakeTrue = True
    bValue = True
End Function
 
' //
' // App.Path - Unicode aware
' // by The Trick and HackerVlad
' //
Public Function AppPath() As String
    Dim bInIDE As Boolean
    Dim lNullPos As Long
    
    If Len(SaveAppPath) > 0 Then
        AppPath = SaveAppPath
    Else
        Debug.Assert MakeTrue(bInIDE)
        
        If bInIDE Then
            AppPath = App.Path
            SaveAppPath = AppPath
        Else
            AppPath = Space$(MAX_PATH)
            GetModuleFileNameW 0, StrPtr(AppPath), 260
            PathRemoveFileSpecW StrPtr(AppPath)
            
            lNullPos = InStr(1, AppPath, vbNullChar)
            If lNullPos Then
                AppPath = Left$(AppPath, lNullPos - 1)
            Else
                AppPath = App.Path
            End If
            
            If Right$(AppPath, 1) = "\" Then AppPath = Mid$(AppPath, 1, Len(AppPath) - 1)
            SaveAppPath = AppPath
        End If
    End If
End Function
0
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
12.12.2024, 15:32  [ТС]
Итак, стоит вернуться к этой теме, так как появился новый код, способный правильно определять пути к процессам EXE, даже в версиях до Windows 10, и даже если переименовывать папку с программой и запускать её снова из переименованной папки. Этот код я частично позаимствовал у fafalone так как он в ноябре 2023 года изобрёл технологию получения полного пути ко всем процессам в системе, даже если нет особых прав доступа у пользователя. Но основной код я написал конечно же сам. Итак, новая технология определения правильного пути к процессу:
1. Если процесс 32-битный то это очень просто, вызываем функцию из PSAPI.DLL которая всегда правильно определяет пути
2. Если процесс 64-битный тот тут уже будет сложнее, читаем структуру PEB 64-битного процесса и от туда уже выдираем правильный путь к процессу EXE
3. Если определение пути к процессу не удалось из-за отсутствия привилегий текущего пользователя, тогда используем технологию fafalone

Свой новый проект, я разместил здесь в готовых решениях: Готовые решения и полезные коды на Visual Basic 6.0

Так как нужно и в этой теме ответить на этот очень важный вопрос для решения этой сложной задачи, я так же напишу этот код и здесь в этой теме (это решение для этой темы):

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
Option Explicit
Private Declare Function NtQuerySystemInformation Lib "ntdll.dll" (ByVal infoClass As Long, Buffer As Any, ByVal BufferSize As Long, ret As Long) As Long
Private Declare Function GetMem4 Lib "msvbvm60" (src As Any, dst As Any) As Long
Private Declare Function GetMem8 Lib "msvbvm60" (src As Any, dst As Any) As Long
Private Declare Function GetLogicalDriveStrings Lib "kernel32" Alias "GetLogicalDriveStringsW" (ByVal nBufferLength As Long, ByVal lpBuffer As Long) As Long
Private Declare Function QueryDosDevice Lib "kernel32" Alias "QueryDosDeviceA" (ByVal lpDeviceName As String, ByVal lpTargetPath As String, ByVal ucchMax As Long) As Long
Private Declare Function lstrlen Lib "kernel32" Alias "lstrlenW" (ByVal lpString As Long) As Long
Private Declare Sub memcpy Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function GetModuleFileNameExW Lib "psapi.dll" (ByVal hProcess As Long, ByVal hModule As Long, ByVal ModuleName As Long, ByVal nSize As Long) As Long
Private Declare Function NtWow64QueryInformationProcess64 Lib "ntdll.dll" (ByVal ProcessHandle As Long, ByVal InformationClass As Long, ByRef ProcessInformation As Any, ByVal ProcessInformationLength As Long, ByRef ReturnLength As Long) As Long
Private Declare Function NtWow64ReadVirtualMemory64 Lib "ntdll.dll" (ByVal hProcess As Long, ByVal BaseAddress As Currency, ByRef Buffer As Any, ByVal BufferLengthL As Long, ByVal BufferLengthH As Long, ByRef ReturnLength As Currency) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
 
Private Const SystemProcessInformation As Long = &H5&
Private Const SystemProcessIdInformation = 88
Private Const ProcessBasicInformation = 0
Private Const STATUS_INFO_LENGTH_MISMATCH As Long = &HC0000004
Private Const STATUS_SUCCESS As Long = 0&
Private Const MAX_PATH = 260
Private Const PROCESS_QUERY_INFORMATION = 1024
Private Const PROCESS_VM_READ = 16
 
Private Type UNICODE_STRING
    Length As Integer
    MaxLength As Integer
    lpBuffer As Long
End Type
 
Private Type SYSTEM_PROCESS_ID_INFORMATION
    ProcessId As Long
    ImageName As UNICODE_STRING
End Type
 
Private Type PROCESS_BASIC_INFORMATION_WOW64
    ExitStatus As Long
    Reserved0 As Long
    PebBaseAddress As Currency
    AffinityMask As Currency
    BasePriority As Long
    Reserved1 As Long
    UniqueProcessId As Currency
    InheritedFromUniqueProcessId As Currency
End Type
 
Private Type UNICODE_STRING64
    Length As Integer
    MaxLength As Integer
    Fill As Long
    lpBuffer As Currency
End Type
 
Private Function GetProcessFullPathEx(ByVal pid As Long) As String
    Dim spii As SYSTEM_PROCESS_ID_INFORMATION
    Dim ProcName As String
    Dim cbRet As Long
    Dim cbMax As Long
    Dim sDrives As String
    Dim strBuff As String * MAX_PATH
    Dim DosDeviceName As String
    Dim cnt As Long
    Dim aDrive() As String
    Dim i As Long
    
    cbMax = MAX_PATH * 2
    ProcName = Space$(cbMax)
    
    spii.ProcessId = pid
    spii.ImageName.MaxLength = cbMax
    spii.ImageName.lpBuffer = StrPtr(ProcName)
    
    If NtQuerySystemInformation(SystemProcessIdInformation, spii, LenB(spii), cbRet) >= 0 Then
        ProcName = Left$(ProcName, spii.ImageName.Length / 2)
        
        cnt = GetLogicalDriveStrings(0&, StrPtr(sDrives))
        sDrives = Space$(cnt * 2)
        cnt = GetLogicalDriveStrings(Len(sDrives), StrPtr(sDrives))
        
        If Err.LastDllError = 0 Then
            aDrive = Split(Left$(sDrives, cnt - 1), vbNullChar)
            
            For i = 0 To UBound(aDrive)
                If QueryDosDevice(Left$(aDrive(i), 2), strBuff, MAX_PATH) Then
                    DosDeviceName = Left$(strBuff, lstrlen(StrPtr(strBuff)))
                    
                    If InStr(1, ProcName, DosDeviceName, vbTextCompare) > 0 Then
                        GetProcessFullPathEx = Replace(ProcName, DosDeviceName, Left$(aDrive(i), 2), , 1, vbTextCompare)
                        Exit Function
                    End If
                End If
            Next
        End If
    End If
End Function
 
' This function should get the correct paths, unlike another functions which can sometimes cheat
Private Function GetProcessPathName(ByVal pid As Long) As String
    Dim hProc As Long
    Dim lStr As Long
    Dim strProcName As String
    Dim cmd64 As UNICODE_STRING64
    Dim pbi64 As PROCESS_BASIC_INFORMATION_WOW64
    Dim pParam64 As Currency
    Dim i As Long
    
    hProc = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 0, pid)
    
    If hProc > 0 Then
        strProcName = Space$(MAX_PATH)
                
        If GetModuleFileNameExW(hProc, 0, StrPtr(strProcName), MAX_PATH) Then
            strProcName = Left$(strProcName, lstrlen(StrPtr(strProcName)))
            strProcName = Replace(strProcName, "\??\", vbNullString)
            strProcName = Replace(strProcName, "%SystemRoot%", Environ("windir"))
            strProcName = Replace(strProcName, "\SystemRoot", Environ("windir"))
            GetProcessPathName = strProcName
        Else ' 64-bit process
            If NtWow64QueryInformationProcess64(hProc, ProcessBasicInformation, pbi64, Len(pbi64), 0) = STATUS_SUCCESS Then
                If NtWow64ReadVirtualMemory64(hProc, pbi64.PebBaseAddress + 0.0032@, pParam64, Len(pParam64), 0, 0) = STATUS_SUCCESS Then
                    If NtWow64ReadVirtualMemory64(hProc, pParam64 + 0.0112@, cmd64, Len(cmd64), 0, 0) = STATUS_SUCCESS Then
                        If cmd64.Length > 0 Then
                            lStr = cmd64.Length \ 2
                            strProcName = Space$(MAX_PATH) ' We allocate a buffer of sufficient length
                            
                            NtWow64ReadVirtualMemory64 hProc, cmd64.lpBuffer, ByVal StrPtr(strProcName), cmd64.Length, 0, 0
                            
                            If Len(strProcName) > 0 Then
                                If Mid$(strProcName, 1, 1) = Chr(34) And Len(strProcName) > 1 Then
                                    i = InStr(2, strProcName, Chr(34))
                                    strProcName = Mid$(strProcName, 2, i - 2)
                                End If
                                strProcName = Replace(strProcName, vbNullChar, " ")
                                strProcName = Replace(strProcName, "\??\", vbNullString)
                                
                                i = 0
                                i = InStr(1, strProcName, ".exe ", vbTextCompare)
                                If i > 0 Then
                                    strProcName = Mid$(strProcName, 1, i + 3)
                                End If
                                
                                strProcName = Replace(strProcName, "%SystemRoot%", Environ("windir"), , , vbTextCompare)
                                strProcName = Replace(strProcName, "\SystemRoot", Environ("windir"), , , vbTextCompare)
                                strProcName = Trim$(strProcName)
                            End If
                            
                            GetProcessPathName = strProcName
                        End If
                    End If
                End If
            End If
        End If
        
        CloseHandle hProc
    End If
End Function
 
' Universal function
Public Function GetProcessFullPath(ByVal pid As Long) As String
    Dim ProcName As String
    
    ProcName = GetProcessPathName(pid) ' Technology from HackerVlad
    
    If InStr(1, ProcName, "\") = 0 Then ' Retrying
        ProcName = GetProcessFullPathEx(pid) ' Technology from fafalone
    End If
    
    GetProcessFullPath = ProcName
End Function
 
Private Sub Command1_Click()
    Dim ret As Long
    Dim buf() As Byte
    Dim Offset As Long
    Dim deltaOffset As Long
    Dim pid As Long
    Dim ImgName As UNICODE_STRING
    Dim ProcName As String
    Dim nProc As Long
    
    Text1.Text = vbNullString
    
    If NtQuerySystemInformation(SystemProcessInformation, ByVal 0&, 0&, ret) = STATUS_INFO_LENGTH_MISMATCH Then
        ReDim buf(ret - 1)
        
        If NtQuerySystemInformation(SystemProcessInformation, buf(0), ret, ret) = STATUS_SUCCESS Then
            Do
                nProc = nProc + 1
                
                GetMem4 buf(Offset + &H44), pid
                GetMem8 buf(Offset + &H38), ImgName
                ProcName = Space$(ImgName.Length \ 2)
                memcpy ByVal StrPtr(ProcName), ByVal ImgName.lpBuffer, ImgName.Length
                
                If pid = 0 Then
                    PostLog "ProcId 0: [System idle process]"
                ElseIf pid = 4 Then
                    PostLog "ProcId 4: [System]"
                Else
                    PostLog "ProcId " & pid & " (" & ProcName & "): " & Chr(34) & GetProcessFullPath(pid) & Chr(34)
                End If
                
                GetMem4 buf(Offset), deltaOffset
                Offset = Offset + deltaOffset
            Loop While deltaOffset
            
            Text1.Text = Text1.Text & "Done. Enumerated " & nProc & " processes."
        End If
    End If
End Sub
 
Private Sub PostLog(sMsg As String)
    Text1.Text = Text1.Text & sMsg & vbCrLf
End Sub
 
Private Sub Form_Resize()
    On Error Resume Next
    Text1.Width = Me.Width - 380
    Text1.Height = Me.Height - 1270
End Sub
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18031 / 7734 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
12.12.2024, 16:05
HackerVlad, уже без стеснения и совести присваиваешь себе чужие труды буквально вчера откомментировав в теме автора, даже технология создана лично тобой.
Дизлайк.
0
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
12.12.2024, 16:07  [ТС]
Цитата Сообщение от HackerVlad Посмотреть сообщение
ProcName = GetProcessFullPathEx(pid) ' Technology from fafalone
Вот написано же Technology from fafalone
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18031 / 7734 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
12.12.2024, 16:14
Цитата Сообщение от HackerVlad Посмотреть сообщение
ProcName = GetProcessPathName(pid) ' Technology from HackerVlad
If InStr(1, ProcName, "") = 0 Then ' Retrying
       ProcName = GetProcessFullPathEx(pid) ' Technology from fafalone
   End If
Ну так и написал бы, в каких случаях и для каких процессов этот способ фейлится.
И из какого поля PE берется инфа взамен.
0
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
12.12.2024, 16:19  [ТС]
Dragokas, ты бы лучше прежде чем критиковать взял бы да и сравнил полностью весь код от fafalone и мой код который я старался почти полностью написал сам. От fafalone там осталось очень мало кода,и здесь в этой теме запрещено комментировать выложенные здесь работы, я буду жаловаться.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
12.12.2024, 16:19
Помогаю со студенческими работами здесь

Получить путь к исполняемому файлу
такой вопрос, мне надо написать функцию, которая будет возвращать путь к файлу. то есть к примеру я запускаю файл с рабочего стола и она...

Узнать путь к исполняемому файлу приложения
Как узнать где находиться файл запуска моего проекта просто потом хочу привентитить относительна к нему другие файлы.

Как узнать путь к исполняемому файлу?
запускаю прогу test.exe как в ней самой определить где она находится(путь) всякие getCurrentDirectory выдают путь откуда стартует...

Получить путь к исполняемому bat файлу
Здравствуйте. У меня есть bat файл, который должен копировать определённые файлы, что лежат с ним в одной папке в другую, заранее...

Получить путь к исполняемому файлу службы
Доброго времени суток. мне нужно получить информацию о службах Windows. Путь, отобр имя, имя сервиса, статус но проблема в том что...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru