Форум программистов, компьютерный форум, киберфорум
Visual Basic
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.75/16: Рейтинг темы: голосов - 16, средняя оценка - 4.75
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18033 / 7736 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16

Как узнать объект ярлыка в 64-битной ОС

19.03.2014, 02:42. Показов 3526. Ответов 30

Студворк — интернет-сервис помощи студентам
Имею ярлык к Internet Explorer. Браузер находится в папке C:\program files
При выполнении кода:
Visual Basic
1
msgbox CreateObject("WScript.Shell").CreateShortcut(Link).TargetPath
получаю путь C:\program files (x86)

Воспользовался файловой переадресацией = не помогает.

Кликните здесь для просмотра всего текста

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
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Declare Function IsWow64Process Lib "kernel32" (ByVal hProc As Long, bWow64Process As Boolean) As Long
Private Declare Function GetSystemWow64Directory Lib "kernel32.dll" Alias "GetSystemWow64DirectoryA" (ByVal lpBuffer As String, ByVal uSize As Long) As Long
Private Declare Function Wow64DisableWow64FsRedirection Lib "kernel32" (ByRef oldvalue As Long) As Boolean
Private Declare Function Wow64RevertWow64FsRedirection Lib "kernel32" (ByVal oldvalue As Long) As Boolean
 
Option Explicit
 
Private Sub main()
    Dim lWow64RedirectReturn As Long: lWow64RedirectReturn = 0
    Dim ret As Boolean
    
    Dim is64 As Boolean: is64 = Is64bitOS
    Debug.Print "Is OS 64-bit? " & is64
    
    If is64 Then ret = Wow64DisableWow64FsRedirection(lWow64RedirectReturn)
    Debug.Print "API = " & ret
    CheckRedirection
    GetLinkTarget
 
    If is64 Then ret = Wow64RevertWow64FsRedirection(lWow64RedirectReturn)
    Debug.Print "API = " & ret
    CheckRedirection
    GetLinkTarget
End Sub
 
Public Function Is64bitOS() As Boolean
    Dim bWow64Process As Boolean
    Dim handle As Long: handle = GetProcAddress(GetModuleHandle("kernel32"), "IsWow64Process") ' if IsWow64Process function exists
    If handle > 0 Then IsWow64Process GetCurrentProcess(), bWow64Process ' Is running under Wow64
    Is64bitOS = bWow64Process
End Function
 
Sub CheckRedirection()
    Dim exe: exe = Environ("SystemRoot") & "\system32\msg.exe"
    Debug.Print "Redirect = " & (Dir$(exe, vbReadOnly Or vbSystem Or vbHidden) <> vbNullString)
End Sub
 
Sub GetLinkTarget()
    Dim Link: Link = "C:\Users\Alex\Desktop\IE.lnk"
    Dim oLink: Set oLink = CreateObject("WScript.Shell").CreateShortcut(Link)
    Debug.Print oLink.TargetPath
    'Debug.Print oLink.WorkingDirectory
End Sub


1) Какие будут советы?
2) Может есть где спецификация самого формата данных?
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
19.03.2014, 02:42
Ответы с готовыми решениями:

Как узнать, подвержена ли 64-битной переадресации указанная ветвь реестра?
Как это узнать программно? Кроме, как прямым сравнением со списком из базы знаний. И можно ли узнать новую цель (подраздел) после...

CMD/BAT: Узнать параметры ярлыка
Приветствую! Нужно узнать параметр (т.е. зачастую это &quot;C:\LOLKEK\app.exe -browser&quot;) ярлыков на рабочем столе (всех). Т.е. просто...

Как узнать существует ли объект ?
Родился новый вопрос: как узнать существует ли объект ??? тоесть есть ли в сесии Session('anArr'). в VB есть isObject, а как на...

30
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18033 / 7736 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
29.03.2014, 21:05  [ТС]
Студворк — интернет-сервис помощи студентам
Кстати, откуда такая инфа?
Цитата Сообщение от The trick Посмотреть сообщение
Переадресация работает только на System32/SysWOW64
0
Модератор
10057 / 3902 / 884
Регистрация: 22.02.2013
Сообщений: 5,853
Записей в блоге: 79
29.03.2014, 22:15
Цитата Сообщение от Dragokas Посмотреть сообщение
Кстати, откуда такая инфа?
http://msdn.microsoft.com/en-u... s.85).aspx
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18033 / 7736 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
30.03.2014, 02:45  [ТС]
Видел. Да, действительно, пишут только о System32/SysWow64.
Вопрос только, является ли преадресация Program Files -> Program Files(x86) частью этого механизма (но ее не упомянули в статье) или проблема с определением ярлыка - это особый частный случай. (я склоняюсь ко второму)

Цитата Сообщение от The trick Посмотреть сообщение
Цитата Сообщение от Dragokas
Вопрос на засыпку: почему тогда на команду Kill не действует правило переадресации "Program Files" -> "Program Files (x86)" ?
Kill для удаления файла вызывает API DeleteFileA из kernel32, Shell32 использует PIDL для идентификации,и возможно (пока не смотрел) меняет еще на этапе загрузки.
"DeleteFileA из kernel32" - За браком знаний в контексте данной темы это мне ни о чем не говорит, к сожалению.

Вот факт - из 32-битного процесса:

Kill "c:\windows\system32\file.txt"
удаляет файл в папке syswow64

kill "c:\program files\file.txt"
этот самый файл и удаляет. Переадресации нет.

P.S. Скомпилировал код C++ от Peter Thoemmes для выдергивания пути из ярлыка согласно спецификации.
Еще пригодится для будущих экспериментов.
Вложения
Тип файла: zip ReadLnkFile.zip (102.6 Кб, 5 просмотров)
0
Модератор
10057 / 3902 / 884
Регистрация: 22.02.2013
Сообщений: 5,853
Записей в блоге: 79
30.03.2014, 09:27
Цитата Сообщение от Dragokas Посмотреть сообщение
является ли преадресация Program Files -> Program Files(x86) частью этого механизм
Нет же я написал. Это "проделки" Shell32.
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
31.03.2014, 22:18
Лучший ответ Сообщение было отмечено The trick как решение

Решение

Насколько мне известно, файловые WOW64-редиректы работают только
для системных папок.

Для Program Files действует другой механизм.

Во-первых, у WOW64-процессов системная переменная ProgramFiles указывает на
"C:\Program Files (x86)".

Во-вторых, системные функции получения стандартных путей типа SHGetFolderPath
для WOW64-процессов тоже возвращают 32-битную "Program Files (x86)".

В-третьих, если WOW64-процесс пишет в реестр строковое значение,
содержащее путь к одной из системных папок, в том числе и "Program Files",
он автоматически преобразуется системой к 32-битному варианту.
За это уже отвечает registry redirector.

Но в остальном нет никаких препятствий, чтобы 32-битный exe поставить и
запускать из 64-битной "нативной" папки "Program Files", то же самое,
по идее, должно действовать и для ярлыков.

Хотя если 32-битная программа захочет "узнать", где находится "Program Files",
система неизбежно "подсунет" ей "Program Files (x86)".

Вот таким скриптом я создаю ярлык на запуск 64-битного Internet Explorer, и
не имеет значения, ни из-под какого процесса этот ярлык создается и запускается
(32 или 64 бита) - во всех случаях наблюдаю запуск именно 64-битной версии IE,
никаких редиректов в "Program Files (x86)" нету:
Visual Basic
1
2
3
4
5
6
set WshShell = WScript.CreateObject("WScript.Shell")
set Link = WshShell.CreateShortcut("C:\Scripts\ShortcutToIe64.lnk")
Link.TargetPath = "C:\Program Files\Internet Explorer\iexplore.exe"
Link.Save()
 
msgbox Link.TargetPath
Добавлено через 8 минут
Dragokas, кстати, откуда в исходном коде, приведенном в
первом сообщении темы, берется Program Files ? Не нашел.
Может, он уже "приходит" туда в 32-битном обличии (x86) ?
2
Модератор
10057 / 3902 / 884
Регистрация: 22.02.2013
Сообщений: 5,853
Записей в блоге: 79
31.03.2014, 22:36
На "обычные" API переадресация не работает с Program Files (CreateFile, FindFirstFile, GetFileAttributes и т.п.), работает только с функциями SHELL, так в MSDN и написано. Например написав в VB
Visual Basic
1
Open "C:\Program Files\tmp" For Bianry...
файл создастся именно там.
Dragokas, ты писал парсер, проверь чем отличается (изнутри) ярлык созданный через Explorer и через скрипт Убежденного (если он у тебя отрабатывает).
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18033 / 7736 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
31.03.2014, 23:43  [ТС]
Убежденный, превосходное наблюдение.
Ярлык создается примерно в 2х раза меньшего размера, при этом папка Program Files считывается из него без "переадресации" в отличие от ярлыка нативно созданного через explorer.
Создавал таким кодом под x32 процессом

Visual Basic
1
2
3
4
5
6
7
set oShell = CreateObject("WScript.Shell")
set oLink = oShell.CreateShortcut("C:\users\alex\desktop\ie_vbs.lnk")
oLink.TargetPath = "C:\Program Files\Internet Explorer\iexplore.exe"
oLink.WorkingDirectory = "C:\Program Files\Internet Explorer"
oLink.Save
 
msgbox oLink.TargetPath


Есть различия в 1 байте (смещение 16), а также всех байтов, начиная с 2DF (ярлыки приаттачил).
Пробую соотнести со спецификацией.
________________________
смещение 14 (4 байта) - LinkFlags, задающий наличие секций.
9B 00 00 00 (vbs) - отсутствует секция "EnableTargetMetadata".
9B 00 08 00 (explorer)

Да, похоже виноват алгоритм обработки KnownFolder.

Заодно еще один парсер нашел - shellify.
Вложения
Тип файла: zip Links.zip (1.4 Кб, 4 просмотров)
1
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18033 / 7736 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
01.04.2014, 00:45  [ТС]
А вот похоже и сам код, который Microsoft использует в ОС
для получения пути для указанного Known Folder GUID: CppShellKnownFolders
В нем используется функция SHGetKnownFolderPath.

Скомпилировал под x32 и x64 кому интересно.
x32 версия всегда выдает Program Files (x86).
Похоже тупо подставляет нужное значение переменной в зависимости от разрядности процесса, как и описано здесь.
Вложения
Тип файла: zip CppShellKnownFolders_compiled(x32,x64).zip (230.5 Кб, 7 просмотров)
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18033 / 7736 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
08.06.2015, 12:46  [ТС]
Чтобы дать теме логическое завершение, скажу, что ярлыки, создаваемые Explorer,
цель которых пролегает через специальные папки, создаются с добавлением Extra Data Block.

Когда система начинает разбор пути и видит наличие одной из секций:
- 2.5.6. KnownFolderDataBlock
- 2.5.9. SpecialFolderDataBlock
то формирование пути происходит с участием раскрытия переменной окружения, указанной в этих секциях (что приводит к получению другого значения под WOW64).

Чтобы однозначно идентифицировать реальный путь, можно, к примеру прочитать SpecialFolderDataBlock и по номеру CSIDL узнать:
'38 = %ProgramFiles%
'42 = %ProgramFiles(x86)%
Другие значения: CSIDL - http://code.snapstream.com/api... CSIDL.html
Аналогичная ситуация с переменной %CommonProgramFiles%.

Касаемо KnownFolderDataBlock, ее GUID можно также проверить по этому списку: https://msdn.microsoft.com/en-... s.85).aspx
Например,
{6D809377-6AF0-444b-8957-A3773F02200E} - ProgramFilesX64
{7C5A40EF-A0FB-4BFC-874A-C0F2E0B9FA8E} - ProgramFilesX86

Парсинг этих секций можно провести примерно так:
Кликните здесь для просмотра всего текста

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
    ' ===== 2.5. Extra Data Block ======
    
    Dim BlockSize As Long
    Dim BlockSignature As Long
    Dim KnownFolderID As UUID
    Dim KnownFolderIDListOffset As Long
    Dim SpecialFolderID As Long
    Dim SpecialFolderIDListOffset As Long
    Dim OtherStr As String
    Dim lr As Long
    
    If NextOffset + 1 < LOF(ff) Then    ' not EOF
        Get #ff, NextOffset + 1&, BlockSize
        
        Do While BlockSize >= 4     ' not TerminalBlock
        
            Get #ff, NextOffset + 4& + 1&, BlockSignature
            
            Debug.Print Hex(BlockSignature)
            
            Select Case BlockSignature
            
                'Case &HA0000002 '2.5.1. ConsoleDataBlock
                'Case &HA0000004 '2.5.2. ConsoleFEDataBlock
                'Case &HA0000006 '2.5.3. DarwinDataBlock
                'Case &HA0000001 '2.5.4. EnvironmentVariableDataBlock
                'Case &HA0000007 '2.5.5. IconEnvironmentDataBlock
            
                Case &HA000000B  '2.5.6. KnownFolderDataBlock
                    Get #ff, NextOffset + 8& + 1&, KnownFolderID
                    Get #ff, NextOffset + 8& + 16& + 1&, KnownFolderIDListOffset    'offset in link target ID List
                    Dim KnownFolderID_str As String
                    KnownFolderID_str = String$(39&, Chr$(0&))
                    lr = StringFromGUID2(KnownFolderID, StrPtr(KnownFolderID_str), Len(KnownFolderID_str))
                    KnownFolderID_str = Left$(KnownFolderID_str, 38)
                    Debug.Print KnownFolderID_str
                    
                    '7c5a40ef-a0fb-4bfc-874a-c0f2e0b9fa8e = ProgramFilesX86
                    'KnownFolderIDs - [url]http://msdn.microsoft.com/en-us/library/windows/desktop/dd378457(v=vs.85).aspx[/url]
                
                'Case &HA0000009 '2.5.7. PropertyStoreDataBlock
                'Case &HA0000008 '2.5.8. ShimDataBlock
                
                Case &HA0000005  '2.5.9. SpecialFolderDataBlock
                    Get #ff, NextOffset + 8& + 1&, SpecialFolderID
                    Get #ff, NextOffset + 8& + 12& + 1&, SpecialFolderIDListOffset  'offset in link target ID List
                    
                    'CSIDL - [url]http://code.snapstream.com/api/bm11/SnapStream.Util.CSIDL.html[/url]
                    '38 = %ProgramFiles%
                    '42 = %ProgramFiles(x86)%
                
                'Case &HA0000003 '2.5.10. TrackerDataBlock
                'Case &HA000000C '2.5.11. VistaAndAboveIDListDataBlock
                
                Case Else
                    OtherStr = String$(BlockSize - 8&, Chr$(0&))
                    Get #ff, NextOffset + 8& + 1&, OtherStr
                
            End Select
            
            NextOffset = NextOffset + BlockSize
        
            If NextOffset + 1 >= LOF(ff) Then Exit Do
            
            Get #ff, NextOffset + 1&, BlockSize
            
        Loop
        
    End If
2
08.06.2015, 13:53

Не по теме:

Dragokas, не перестаешь удивлять своими знаниями и
навыками ресерча, браво !
:good:

0
08.06.2015, 20:58  [ТС]

Не по теме:


Убежденный, это Вы преувеличиваете. Все таки уже почти как год в этой теме.
Обычная наблюдательность, просто догадался (не без чтения море исследовательских статей конечно).

Есть пару вещей (по этой же теме), в которых я действительно первопроходец, но чтоб довести их до логического конца как раз навыков реверсинга и не хватает.

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
08.06.2015, 20:58
Помогаю со студенческими работами здесь

Как узнать объект события?
Доброго времени суток. На фрейме несколько таблиц созданных в цикле. Все редактируемые. Как программно узнать какую из них я редактирую?...

Внедрение из 32-битной программы 64-битной dll в 64-битный процесс, возможно ли?
Добрый вечер. Для внедрение dll в сторонний процесс использую метод из книги Рихтера. Суть этого метода - создать удаленный поток в...

'Какой размер имеет переменная типа int в 32 битной и в 64 битной OC?
Объектно-ориентированное программирование в С++ Р. Лафоре.

Как узнать, открыт ли объект SELECT?
Как узнать, открыт ли объект SELECT, представленный в виде ComboBox?

Как узнать находится ли объект в фокусе
Создаю компонент. Как мне внутри компонента понять, что он находится в фокусе? if focused=true не пашет. Значение всегда false


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

Или воспользуйтесь поиском по форуму:
31
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru