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

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

21.04.2023, 13:30. Показов 5452. Ответов 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
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
21.04.2023, 13:50  [ТС]
Вы знаете, меня это поведение функции дико шокировало, конечно. Я только что проверил на других программах - тоже самое. После переименовывания папки любой программы, путь всегда будет старый почему-то.

Кстати, вот мой исходник. Для себя делаю вывод что функцией QueryFullProcessImageName лучше вообще никогда не пользоваться, если она постоянно врёт получается, стоит только переименовать папку и всё.
Вложения
Тип файла: zip App.Path с китайскими иероглифами.zip (6.3 Кб, 23 просмотров)
0
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
21.04.2023, 14:45  [ТС]
Самое смешное NtQueryInformationProcess возвращает тоже самое - старый путь, что за бред...

Добавлено через 15 минут
А NtQuerySystemInformation не возвращает полные пути
Проверим другие функции тогда...

Добавлено через 4 минуты
Попробуем функции PSAPI.DLL для интереса тогда ещё, хотя там минус что они не работают с 64-битными процессами, но всё же всё равно попробую для интереса

Добавлено через 2 минуты
Батюшки, а функции PSAPI.DLL работают правильно!

Добавлено через 10 минут
А так же работает правильно, если прочитать командную строку запуска процесса через ReadProcessMemory считывая структуру PEB, но это сложнее

Добавлено через 1 минуту
Легче всего тогда использовать функцию GetModuleFileNameExW учитывая что наш процесс это всегда 32 битный процесс то думаю всё будет работать на УРА
0
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
21.04.2023, 15:10  [ТС]
Всё! Готово! Просто поменял функцию QueryFullProcessImageName на GetModuleFileNameEx и всё заработало как надо! Теперь без обмана! Ура!!! Я справился с глюками майкрософта!

Просто поменял одну строчку

Visual Basic
1
QueryFullProcessImageName -1, 0, StrPtr(strProcName), lStr
На:

Visual Basic
1
GetModuleFileNameExW -1, 0, StrPtr(strProcName), lStr
И всё! Просто поменял функцию и всё заработало правильно как надо! И теперь можно переименовывать папки и не бояться, что вернёт неправильный результат! Ура!!!

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
Option Explicit
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 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
    
    GetModuleFileNameExW -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
PSAPI.DLL помог конечно, но для 64-битных процессов так не получится. Поэтому если писать функцию получения пути для чужих процессов придётся очень постараться чтобы комбинировать разные другие функции... Но для себя понял точно, что нельзя использовать QueryFullProcessImageName и NtQueryInformationProcess эти функции врут. Вот выкладываю готовый вариант программы теперь AppPath будет определяться всегда правильно!!! И можно переименовывать папки по 500 раз теперь!!! И с любыми китайскими иероглифами!!!

Кстати!!! Теперь так даже лучше стало! Теперь будет работать и в XP потому что, в отличии от QueryFullProcessImageName которая начиная только от Vista.

Переименуйте папку с "App.Path с китайскими иероглифами" на "App.Path с китайскими иероглифами 拷贝" запустите потом AppPath.exe и увидите сами, что всё работает шикарно, как надо!
Вложения
Тип файла: zip App.Path с китайскими иероглифами.zip (6.7 Кб, 14 просмотров)
0
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
21.04.2023, 16:34  [ТС]
Мало того, я сейчас проверил, функция NtQueryInformationProcess врёт даже в XP!!! Просто, запустите любую программу, потом закройте эту программу, потом переименуйте папку с этой программой и всё! И начинается враньё! Показывает старый путь.

Добавлено через 2 минуты
Тут даже программа ProcessHacker начинает показывать неправильно... Старый путь... И не загружается иконка к EXE файлу из-за этого...

Добавлено через 3 минуты
А стандартный диспетчер задач Windows 7 в колонке "Путь к образу" вообще ничего не выдаёт, полная пустота просто, если путь неправильный. Это реально глюк винды слушайте пипец просто...

Добавлено через 2 минуты
Ваш знаменитый ProcessExplorer думаю тоже споткнётся об эту ситуацию...

Добавлено через 6 минут
Вряд ли в Windows 10 исправили этот баг, но если у кого стоит десятка, проверьте пожалуйста
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18033 / 7736 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
21.04.2023, 19:23
Хмм, действительно какая-то дичь.

ProcMon:
https://ibb.co/jb8kRMp

PS. У меня кстати, DrawText из вашего примера ничего не рисует на форме почему-то, хз.
0
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
21.04.2023, 19:48  [ТС]
Цитата Сообщение от Dragokas Посмотреть сообщение
У меня кстати, DrawText из вашего примера
Скачайте ZIP архив, так проще, просто надо свойство окна менять на AutoRedraw = True и ScaleMode = vbPixels

Добавлено через 2 минуты
Dragokas, а у вас десятка наверное? и тоже глюк винды такой же?
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18033 / 7736 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
21.04.2023, 19:59
Спасибо, надо было сменить метрику на пиксели.

Потестировал на доступных системах:
Win XP
GetProcessImageFileName - Ложь
GetModuleFileNameEx - Истина

Win 7
QueryFullProcessImageName - Ложь
GetProcessImageFileName - Ложь
GetModuleFileNameEx - Истина

Win 10
QueryFullProcessImageName - Истина
GetProcessImageFileName - Истина
GetModuleFileNameEx - Истина

Win 11
QueryFullProcessImageName - Истина
GetProcessImageFileName - Истина
GetModuleFileNameEx - Истина

NtQueryInformationProcess не проверял.

Добавлено через 4 минуты
++ и на Windows 8.1 такой же баг.
0
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
21.04.2023, 20:07  [ТС]
Так в десятке этот глюк исправили что ли?

Добавлено через 1 минуту
Цитата Сообщение от Dragokas Посмотреть сообщение
NtQueryInformationProcess не проверял.
Мне кажется что QueryFullProcessImageName вызывает как раз таки NtQueryInformationProcess так как они оба врут одинаково...
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18033 / 7736 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
21.04.2023, 20:37
Цитата Сообщение от HackerVlad Посмотреть сообщение
Так в десятке этот глюк исправили что ли?
Да.

Цитата Сообщение от HackerVlad Посмотреть сообщение
Мне кажется что QueryFullProcessImageName вызывает как раз таки NtQueryInformationProcess так как они оба врут одинаково...
Если интересно, можете через Rohitab API Monitor посмотреть.
2
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
21.04.2023, 21:07  [ТС]
The trick, посмотри пожалуйста как написана функция QueryFullProcessImageName чего она так глючит
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18033 / 7736 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
21.04.2023, 21:11
Трику больше нечего делать, как сидеть в отладчике ядра над функционалом, который все равно уже пофиксили.

++ кстати, WMI исправно работает.
0
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
21.04.2023, 21:16  [ТС]
The trick любит анализировать функции и смотреть как они написаны
а вот WMI я как раз забыл проверить

Добавлено через 3 минуты
Цитата Сообщение от Dragokas Посмотреть сообщение
который все равно уже пофиксили
Но половина людей ещё всё равно на семёрке, так что эта тема актуальна
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18033 / 7736 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
21.04.2023, 21:21
Когда речь идёт об Nt*/Zw* функциях, там уже не так просто анализировать, да и уже известно, информация о процессе там берётся из ядра, структура EPROCESS. Почитайте.
А вот каким образом туда попадает эта инфа, там уже будет цепочка вызовов по-длиннее, чем анализ 1 функции.
Можно только строить предположения.
0
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
21.04.2023, 21:27  [ТС]
Лично я проверял что если читать структуру PEB то глюка никакого нет. Просто так геморно. Поэтому решил использовать GetModuleFileNameExW.
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18033 / 7736 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
21.04.2023, 21:34
HackerVlad, но раз вы уже добрались до PEB, тогда и сами в состоянии провести "отладку", просто возьмите любой редактор памяти, и подмените значение, где прописан путь к образу, и затем посмотрите, изменился ли ответ GetModuleFileNameExW. Судя по описанию на MSDN она смотрит путь в списке модулей самого процесса.
Раз пути в PEB и EPROCESS отличаются, то вот и частично ответ на ваш вопрос.
1
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
23.04.2023, 00:57  [ТС]
По совету The Trick решил использовать функцию GetModuleFileName простую для получения пути к EXE. Вместе с The Trick удалось создать неплохую функцию AppPath

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
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
 
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
    
    Debug.Assert MakeTrue(bInIDE)
    
    If bInIDE Then
        AppPath = App.Path
    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)
        Else
            AppPath = App.Path
            If Right$(AppPath, 1) = "\" Then AppPath = Mid$(AppPath, 1, Len(AppPath) - 1)
        End If
    End If
End Function
1
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18033 / 7736 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
23.04.2023, 01:15
Ещё вариант AppPathW
1
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
23.04.2023, 02:06  [ТС]
Цитата Сообщение от Dragokas Посмотреть сообщение
Ещё вариант AppPathW
The Trick говорит, что не надо использовать простой поиск косой черты на конце. Поэтому наш вариант лучше с функцией PathRemoveFileSpecW. Но зато мне очень понравилось у тебя что определяется в IDE или нет всего одной строкой кода, лучше чем у The Trick получается, спасибо за это.
0
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
23.04.2023, 12:42  [ТС]
Цитата Сообщение от HackerVlad Посмотреть сообщение
мне очень понравилось у тебя что определяется в IDE или нет всего одной строкой кода
The Trick меня убедил, что этот код

Code
1
inIDE = (App.LogMode = 0)
гораздо хуже, чем MakeTrue от The Trick
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
23.04.2023, 12:42
Помогаю со студенческими работами здесь

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru