Форум программистов, компьютерный форум, киберфорум
Visual Basic
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.50/10: Рейтинг темы: голосов - 10, средняя оценка - 4.50
182 / 33 / 3
Регистрация: 28.05.2015
Сообщений: 148

Не правильно воспринимается путь Comdlg32.dll

28.08.2016, 08:21. Показов 2282. Ответов 11
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
На самом деле вопроса 2.

Вопрос 1:

Модуль:
Кликните здесь для просмотра всего текста
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
Declare Function GetSaveFileName Lib "comdlg32.dll" Alias "GetSaveFileNameA" (pOpenfilename As OPENFILENAME) As Long
Declare Function GetOpenFileName Lib "comdlg32.dll" Alias "GetOpenFileNameA" (pOpenfilename As OPENFILENAME) As Long
 
Public Type OPENFILENAME
   lStructSize As Long
   hwndOwner As Long
   hInstance As Long
   lpstrFilter As String
   lpstrCustomFilter As String
   nMaxCustFilter As Long
   nFilterIndex As Long
   lpstrFile As String
   nMaxFile As Long
   lpstrFileTitle As String
   nMaxFileTitle As Long
   lpstrInitialDir As String
   lpstrTitle As String
   flags As Long
   nFileOffset As Integer
   nFileExtension As Integer
   lpstrDefExt As String
   lCustData As Long
   lpfnHook As Long
   lpTemplateName As String
End Type
 
Public Const OFN_ALLOWMULTISELECT = &H200
Public Const OFN_CREATEPROMPT = &H2000
Public Const OFN_DONTADDTORECENT = &H2000000
Public Const OFN_ENABLEHOOK = &H20
Public Const OFN_ENABLEINCLUDENOTIFY = &H400000
Public Const OFN_ENABLESIZING = &H800000
Public Const OFN_ENABLETEMPLATE = &H40
Public Const OFN_ENABLETEMPLATEHANDLE = &H80
Public Const OFN_EXPLORER = &H80000
Public Const OFN_EXTENSIONDIFFERENT = &H400
Public Const OFN_FILEMUSTEXIST = &H1000
Public Const OFN_FORCESHOWHIDDEN = &H10000000
Public Const OFN_HIDEREADONLY = &H4
Public Const OFN_LONGNAMES = &H200000
Public Const OFN_NOCHANGEDIR = &H8
Public Const OFN_NODEREFERENCELINKS = &H100000
Public Const OFN_NOLONGNAMES = &H40000
Public Const OFN_NONETWORKBUTTON = &H20000
Public Const OFN_NOREADONLYRETURN = &H8000
Public Const OFN_NOTESTFILECREATE = &H10000
Public Const OFN_NOVALIDATE = &H1000
Public Const OFN_OVERWRITEPROMPT = &H2
Public Const OFN_PATHMUSTEXIST = &H800
Public Const OFN_READONLY = &H1
Public Const OFN_SHAREAWARE = &H4000
Public Const OFN_SHOWHELP = &H10

Форма:
Кликните здесь для просмотра всего текста
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Prvate Sub Form_Load()
   Dim OpenFile As OPENFILENAME
   Dim lReturn As Long
   Dim sFilter As String
   
   OpenFile.lStructSize = Len(OpenFile)
   OpenFile.hwndOwner = Me.HWND
   OpenFile.hInstance = App.hInstance
   sFilter = "ALL Files (*.*)" & Chr(0) & "*.*" & Chr(0)
   OpenFile.lpstrFilter = sFilter
   OpenFile.nFilterIndex = 1
   OpenFile.lpstrFile = String(65536, 0)
   OpenFile.nMaxFile = Len(OpenFile.lpstrFile) - 1
   OpenFile.lpstrFileTitle = OpenFile.lpstrFile
   OpenFile.nMaxFileTitle = OpenFile.nMaxFile
   OpenFile.lpstrInitialDir = App.Path
   OpenFile.lpstrTitle = "Выберите путь..."
 
   OpenFile.flags = &H80000 + &H4
   lReturn = GetOpenFileName(OpenFile)
   MsgBox OpenFile.lpstrFileName
End Sub

Некоторые имена файлов, папок воспринимаются неверно. Но когда я сам вручную пишу то же самое название, воспринимается верно.

Пример №1:Best Music Mix 2016 - ♫ 1H Gaming Music ♫ - Dubstep, Electro House, EDM, Trap.mp3. Вместо ♫ будет "d".

Пример №2: дейтрейдер.pdf. Воспринимается как "дэи?треи?дер.pdf"

Когда встречается неверное название файла, то программа, которая обрабатывает их, не может открыть для чтения и вылетает с ошибкой. Может что в коде неверно? Файлы открываются API CreateFile в режиме "для чтения". Каким образом конвертировать в корректное имя?

Вопрос 2:

Допустим, имеется простенькая процедура работы с файлом:

Visual Basic
1
2
3
4
5
6
7
8
Private Sub FileWorking()
   Open File$ For Append As #1
      Do
         Print #1, "rrr"
         If anything Then Exit Do
      Loop
   Close #1
End Sub
Предположим, на форме есть кнопка паузы. Каким образом приостановить работу с файлом и продолжить после отжатия паузы? Естественно, чтобы форма не "замерзала", т.е. Sleep не подойдёт.
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
28.08.2016, 08:21
Ответы с готовыми решениями:

Отсутствует gbs32.dll, fbclient.dll или путь к ним
Я не смогла зарегистрировать базу, так как мэнеджер запросил указать путь к gbs32.dll или fbclient.dll. Файлы скачала и установила, но...

Как узнать путь к загруженной DLL из самой DLL?
Создаю небольшую программку в папке c:/test/app/, есть DLL в папке c:/test/dll/. В коде самой dll, после её подгрузки в программу, можно...

Недопустимый путь. Убедитесь, что путь указан правильно и
Мне скинули БД, при открытии в ней любого объекта влезает такая ерунда...

11
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18030 / 7733 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
28.08.2016, 20:28
Цитата Сообщение от CharlyChaplin Посмотреть сообщение
Некоторые имена файлов, папок воспринимаются неверно. Но когда я сам вручную пишу то же самое название, воспринимается верно.
Пример №1:Best Music Mix 2016 - ♫ 1H Gaming Music ♫ - Dubstep, Electro House, EDM, Trap.mp3. Вместо ♫ будет "d".
Пример №2: дейтрейдер.pdf. Воспринимается как "дэи?треи?дер.pdf"
Нужно воспользоваться юникодной версией.

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
Option Explicit
 
Private Type OPENFILENAME
    lStructSize As Long
    hwndOwner As Long
    hInstance As Long
    lpstrFilter As Long
    lpstrCustomFilter As Long
    nMaxCustFilter As Long
    nFilterIndex As Long
    lpstrFile As Long
    nMaxFile As Long
    lpstrFileTitle As Long
    nMaxFileTitle As Long
    lpstrInitialDir As Long
    lpstrTitle As Long
    flags As Long
    nFileOffset As Integer
    nFileExtension As Integer
    lpstrDefExt As Long
    lCustData As Long
    lpfnHook As Long
    lpTemplateName As Long
End Type
 
Private Declare Function GetOpenFileName Lib "comdlg32.dll" Alias "GetOpenFileNameW" (pOpenfilename As OPENFILENAME) As Long
 
Private Sub Form_Load()
    MsgBox GetFile(Me.hwnd, App.Path)
End Sub
 
Public Function GetFile(ByVal hwnd As Long, Optional InitDir As String) As String
    Dim ofn As OPENFILENAME
    Dim Title As String, out As String
    Dim Filter As String, i As Long
    
    ofn.nMaxFile = 260
    out = String(260, 0)
    Title = "Открыть файл"
    Filter = "Музыкальные файлы" & vbNullChar & "*.mp3;.wav;*.ac3;*.flac" & vbNullChar & _
        "Все файлы" & vbNullChar & "*.*" & vbNullChar
    ofn.hwndOwner = hwnd
    ofn.lpstrTitle = StrPtr(Title)
    ofn.lpstrFile = StrPtr(out)
    ofn.lStructSize = Len(ofn)
    ofn.lpstrFilter = StrPtr(Filter)
    ofn.lpstrInitialDir = StrPtr(InitDir)
    
    If GetOpenFileName(ofn) Then
        i = InStr(1, out, vbNullChar, vbBinaryCompare)
        If i Then GetFile = Left$(out, i - 1)
    End If
End Function
Цитата Сообщение от CharlyChaplin Посмотреть сообщение
Вопрос 2:
Допустим, имеется простенькая процедура работы с файлом:

...

Предположим, на форме есть кнопка паузы. Каким образом приостановить работу с файлом и продолжить после отжатия паузы? Естественно, чтобы форма не "замерзала", т.е. Sleep не подойдёт.
Думаю, для вопроса № 2 подойдёт создание новой темы № 2 с более подробным объяснением сути работы программы.
3
182 / 33 / 3
Регистрация: 28.05.2015
Сообщений: 148
29.08.2016, 06:24  [ТС]
Подскажите какова разница между.
Visual Basic
1
2
out = String(260, 0)
ofn.lpstrFile = out
и
Visual Basic
1
2
out = String(260, 0)
ofn.lpstrFile = StrPtr(out)
Для чего делать указатель на адрес переменной, если я правильно понял значение StrPtr.
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18030 / 7733 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
29.08.2016, 12:01
В том что первая структура - это OPENFILENAMEA (ANSI), а вторая OPENFILENAMEW (Unicode).
Юникодные параметры передаются по указателю. См. MSDN. Префикс lp - это long pointer.
2
182 / 33 / 3
Регистрация: 28.05.2015
Сообщений: 148
30.08.2016, 04:40  [ТС]
Цитата Сообщение от Dragokas Посмотреть сообщение
В том что первая структура - это OPENFILENAMEA (ANSI), а вторая OPENFILENAMEW (Unicode).
Юникодные параметры передаются по указателю. См. MSDN. Префикс lp - это long pointer.
Ну никак не получается!:-( На такой мелочи застрял!

Вот пример:

*** модуль ***
Кликните здесь для просмотра всего текста
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
Option Explicit
Option Base 0
 
Public Const INVALID_HANDLE_VALUE = -1
Private Const GENERIC_WRITE = &H40000000
Private Const GENERIC_READ = &H80000000
Private Const FILE_ATTRIBUTE_NORMAL = &H80
Private Const CREATE_NEW = 1
Private Const CREATE_ALWAYS = 2
Private Const OPEN_EXISTING = 3
Private Const OPEN_ALWAYS = 4
Private Const TRUNCATE_EXISTING = 5
 
Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, _
   lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, _
   lpNumberOfBytesRead As Long, ByVal lpOverlapped As Long) As Long
 
Public Declare Function CloseHandle Lib "kernel32" ( _
  ByVal hObject As Long) As Long
 
Private Declare Function WriteFile Lib "kernel32" ( _
  ByVal hFile As Long, lpBuffer As Any, _
  ByVal nNumberOfBytesToWrite As Long, _
  lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Long) As Long
 
Private Declare Function CreateFile Lib "kernel32" _
  Alias "CreateFileA" (ByVal lpFileName As String, _
  ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, _
  ByVal lpSecurityAttributes As Long, _
  ByVal dwCreationDisposition As Long, _
  ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) _
  As Long
 
Declare Function FlushFileBuffers Lib "kernel32" ( _
  ByVal hFile As Long) As Long
 
Public Function ap_OpenFileReadOnly(sFileName As String) As Long
' Wrapper around Windows API fn to open a file for read only
' Returns INVALID_HANDLE_VALUE (-1) if it fails.
   ap_OpenFileReadOnly = CreateFile(sFileName, GENERIC_READ, _
                        0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
End Function
 
Public Function ap_OpenFileWrite(sFileName As String) As Long
' Wrapper around Windows API fn to open a file for writing
' Returns INVALID_HANDLE_VALUE (-1) if it fails.
' Warning: Will overwrite existing file, if it exists
   ap_OpenFileWrite = CreateFile(sFileName, GENERIC_WRITE, _
                        0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)
End Function
 
Public Function ap_CloseFile(fHandle As Long) As Boolean
' Flush the file buffers to force writing of the data.
    Dim fSuccess As Long
    fSuccess = FlushFileBuffers(fHandle)
    fSuccess = CloseHandle(fHandle)
    ap_CloseFile = (fSuccess <> 0)
End Function
 
Public Function ap_PutByte(fHandle As Long, byt As Byte) As Boolean
' Writes a single byte to an open file with handle <fHandle>
' Returns True if successful; false if fails
    Dim fSuccess As Long
    Dim lBytesToWrite As Long
    Dim lBytesWritten As Long
    lBytesToWrite = 1
    fSuccess = WriteFile(fHandle, byt, lBytesToWrite, lBytesWritten, 0)
    'Check to see if successful writing the data
    ap_PutByte = (fSuccess <> 0)
End Function
 
Public Function ap_GetBytes(fHandle As Long, aBytes() As Byte, _
    lBytesToRead As Long) As Boolean
' Reads n bytes from open file
    Dim fSuccess As Long
    Dim lBytesRead As Long
    fSuccess = ReadFile(fHandle, aBytes(0), lBytesToRead, lBytesRead, 0)
    ap_GetBytes = (fSuccess <> 0)
End Function
 
Public Function ap_PutBytes(fHandle As Long, aBytes() As Byte, _
    lBytesToWrite As Long) As Boolean
' Writes n bytes to open file
    Dim fSuccess As Long
    Dim lBytesWritten As Long
    fSuccess = WriteFile(fHandle, aBytes(0), lBytesToWrite, lBytesWritten, 0)
    ap_PutBytes = (fSuccess <> 0)
End Function

*** форма ***
Кликните здесь для просмотра всего текста
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
Option Base 1
Option Explicit
 
Private Type OPENFILENAME
    lStructSize As Long
    hwndOwner As Long
    hInstance As Long
    lpstrFilter As Long
    lpstrCustomFilter As Long
    nMaxCustFilter As Long
    nFilterIndex As Long
    lpstrFile As Long
    nMaxFile As Long
    lpstrFileTitle As Long
    nMaxFileTitle As Long
    lpstrInitialDir As Long
    lpstrTitle As Long
    flags As Long
    nFileOffset As Integer
    nFileExtension As Integer
    lpstrDefExt As Long
    lCustData As Long
    lpfnHook As Long
    lpTemplateName As Long
End Type
 
Private Declare Function GetOpenFileName Lib "comdlg32.dll" Alias "GetOpenFileNameW" (pOpenfilename As OPENFILENAME) As Long
 
Private Sub Form_Load()
    Dim sFileIn$
    Dim sFileOut$
    
    Me.Show
    sFileIn$ = GetFile(Me.hwnd, App.Path)
    sFileOut$ = sFileIn$ & "_"
    
    If ap_OpenFileReadOnly(sFileIn$) < 0 Then MsgBox "Не могу открыть.": End
    If ap_OpenFileWrite(sFileOut$) < 0 Then MsgBox "Не могу записать.": End
End Sub
 
Public Function GetFile(ByVal hwnd As Long, Optional InitDir As String) As String
    On Error Resume Next
    Dim ofn As OPENFILENAME
    Dim Title As String, out As String, tmp$
    Dim Filter As String, i As Long, m As Long
    InitDir = "C:\Users\Acid\Desktop\BlowFish"
    Dim Arr() As String
    
    ofn.nMaxFile = 260
    out = String(260, 0)
    Title = "Введите путь..."
    Filter = "Все файлы" & vbNullChar & "*.*" & vbNullChar
    ofn.hwndOwner = hwnd
    ofn.lpstrTitle = StrPtr(Title)
    ofn.lpstrFile = StrPtr(out)
    ofn.lStructSize = Len(ofn)
    ofn.lpstrFilter = StrPtr(Filter)
    ofn.lpstrInitialDir = StrPtr(InitDir)
    
    ReDim Arr(Len(out))
    If GetOpenFileName(ofn) Then
        For m = 1 To Len(out) - 1
            Arr(m) = AscW(Mid$(out, m, 1))
            tmp$ = tmp$ + ChrW$(Arr(m))
        Next m
        i = InStr(1, out, vbNullChar, vbBinaryCompare)
        If i Then GetFile = Left$(out, i - 1)
    End If
End Function


Для отладки я поместил все символы в массив Arr(). Также в out сидит само название файла. Насколько я вижу, тип String в Visual Basic автоматически преобразовывает все символы в <255. И не может содержать в себе явные символы из таблицы Unicode. Хотя я точно не знаю. Сегодня загрузил на другом компе WinXP и тот же файл автоматически преобразовался в <255. То есть вместо 2012-01-30 План работы дейтрейдера на бирже NYSE ПРОЕКТ.pdf получил 2012-01-30 План работы деи?треи?дера на бирже NYSE ПРОЕКТ.pdf. А в Win7 это название отображается корректно.

В общем задача вот какая: необходимо обнаружить, что в имени сидят символы с кодами > 255 и создать новый файл с добавлением постфикса с таким же именем, чтобы содержал Unicode. В данный момент пример, построенный с вашей помощью, уважаемый Dragokas, показывает, что не может ни открыть, ни создать файл с Unicode.:-(

Конечно можно было бы ругаться на каждый "чих" и говорить пользователю, что такой файл нужно переименовать. Но хочется, избавить его от таких проблем. Ведь тот же самый WinRar или 7z нормально всё обрабатывает.
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18030 / 7733 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
30.08.2016, 17:32
Лучший ответ Сообщение было отмечено CharlyChaplin как решение

Решение

Цитата Сообщение от CharlyChaplin Посмотреть сообщение
Насколько я вижу, тип String в Visual Basic автоматически преобразовывает все символы в <255
Нет. Там хранится в юникоде. Можете сами проверить в редакторе памяти, например, WinHex-e. Получаете адрес переменной (StrPtr). WinHex -> Tools -> Open Memory. Navigation -> Goto Offset.

Цитата Сообщение от CharlyChaplin Посмотреть сообщение
Для отладки я поместил все символы в массив Arr().
Соответственно, массив у Вас тоже будет состоять из двухбайтовых чисел.

Цитата Сообщение от CharlyChaplin Посмотреть сообщение
То есть вместо 2012-01-30 План работы дейтрейдера на бирже NYSE ПРОЕКТ.pdf получил 2012-01-30 План работы деи?треи?дера на бирже NYSE ПРОЕКТ.pdf.
А смотрите через что? Окно отладки / и локальных переменных? Эти окна тоже ANSI.

Цитата Сообщение от CharlyChaplin Посмотреть сообщение
А в Win7 это название отображается корректно.
У меня на Win7 и Win10 тоже со знаками "?", т.к. там символы за пределами ASCII. Возможно, у Вас нормально видно в Win7 из-за шрифтов, но проблема решается не так.

Цитата Сообщение от CharlyChaplin Посмотреть сообщение
необходимо обнаружить, что в имени сидят символы с кодами > 255
Юникод - это не только символы > 255, но и < 0.

Цитата Сообщение от CharlyChaplin Посмотреть сообщение
с добавлением постфикса с таким же именем, чтобы содержал Unicode.
Непонятен ни смысл этого действия, ни способ реализации.

Цитата Сообщение от CharlyChaplin Посмотреть сообщение
В данный момент пример, построенный с вашей помощью, уважаемый Dragokas, показывает, что не может ни открыть, ни создать файл с Unicode.:-(
Я не помогал с примером открытия файла. Это Вы сами дописали.

Не работает, потому что Вы всё еще используете ANSI-версию функции:
Цитата Сообщение от CharlyChaplin Посмотреть сообщение
Private Declare Function CreateFile Lib "kernel32" _
* Alias "CreateFileA"
Цитата Сообщение от CharlyChaplin Посмотреть сообщение
ap_OpenFileReadOnly = CreateFile(sFileName, GENERIC_READ, _
* * * * * * * * * * * * 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
CreateFile может не разрешить Вам открыть файл ни на чтение, ни на запись, если Вы не расшариваете для других доступ, если в этот момент файл уже открыт кем-то ещё. Это может быть даже Ваш (или чей-то) антивирус, которой просто решил параллельно открыть тот же файл на чтение.

Добавлено через 1 минуту
Вот мой модуль с базовыми файловыми операциями (чтение, запись, листинг, проверка размера, диски, типы, x64 переадресация, проверка на существование файла). Можете воспользоваться в качестве примера из него.

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

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
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
'
' modFile module by Alex Dragokas
'
 
Option Explicit
 
Const MAX_PATH As Long = 260&
Const MAX_FILE_SIZE As Currency = 104857600@
 
Enum VB_FILE_ACCESS_MODE
    FOR_READ = 1
    FOR_READ_WRITE = 2
    FOR_OVERWRITE_CREATE = 4
End Enum
 
Enum CACHE_TYPE
    USE_CACHE
    NO_CACHE
End Enum
 
Private Type LARGE_INTEGER
    LowPart As Long
    HighPart As Long
End Type
 
Private Type FILETIME
   dwLowDateTime As Long
   dwHighDateTime As Long
End Type
 
Private Type WIN32_FIND_DATA
    dwFileAttributes As Long
    ftCreationTime As FILETIME
    ftLastAccessTime As FILETIME
    ftLastWriteTime As FILETIME
    nFileSizeHigh As Long
    nFileSizeLow As Long
    dwReserved0 As Long
    dwReserved1 As Long
    lpszFileName(MAX_PATH) As Integer
    lpszAlternate(14) As Integer
End Type
 
Private Type SECURITY_ATTRIBUTES
    nLength As Long
    lpSecurityDescriptor As Long
    bInheritHandle As Long
End Type
 
Private Type VS_FIXEDFILEINFO
    dwSignature As Long
    dwStrucVersionl As Integer
    dwStrucVersionh As Integer
    dwFileVersionMSl As Integer
    dwFileVersionMSh As Integer
    dwFileVersionLSl As Integer
    dwFileVersionLSh As Integer
    dwProductVersionMSl As Integer
    dwProductVersionMSh As Integer
    dwProductVersionLSl As Integer
    dwProductVersionLSh As Integer
    dwFileFlagsMask As Long
    dwFileFlags As Long
    dwFileOS As Long
    dwFileType As Long
    dwFileSubtype As Long
    dwFileDateMS As Long
    dwFileDateLS As Long
End Type
 
Private Declare Function PathFileExists Lib "Shlwapi.dll" Alias "PathFileExistsW" (ByVal pszPath As Long) As Long
Private Declare Function GetFileAttributes Lib "kernel32.dll" Alias "GetFileAttributesW" (ByVal lpFileName As Long) As Long
Private Declare Function FindFirstFile Lib "kernel32.dll" Alias "FindFirstFileW" (ByVal lpFileName As Long, lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function FindNextFile Lib "kernel32.dll" Alias "FindNextFileW" (ByVal hFindFile As Long, lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function FindClose Lib "kernel32.dll" (ByVal hFindFile As Long) As Long
Private Declare Function CreateFile Lib "kernel32.dll" Alias "CreateFileW" (ByVal lpFileName As Long, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As Long) As Long
'Private Declare Function SHFileExists Lib "shell32.dll" Alias "#45" (ByVal szPath As String) As Long
Private Declare Function Wow64DisableWow64FsRedirection Lib "kernel32.dll" (OldValue As Long) As Long
Private Declare Function Wow64RevertWow64FsRedirection Lib "kernel32.dll" (ByVal OldValue As Long) As Long
Private Declare Function GetDriveType Lib "kernel32.dll" Alias "GetDriveTypeW" (ByVal nDrive As Long) As Long
Private Declare Function GetLogicalDrives Lib "kernel32" () As Long
Private Declare Function GetFileSizeEx Lib "kernel32.dll" (ByVal hFile As Long, lpFileSize As Any) As Long
Private Declare Function SetFilePointer Lib "kernel32.dll" (ByVal hFile As Long, ByVal lDistanceToMove As Long, lpDistanceToMoveHigh As Long, ByVal dwMoveMethod As Long) As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, ByVal lpBuffer As Long, ByVal nNumberOfBytesToRead As Long, lpNumberOfByConstesRead As Long, ByVal lpOverlapped As Long) As Long
Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, ByVal lpBuffer As Long, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Long) As Long
Private Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExW" (ByVal hKey As Long, ByVal lpSubKey As Long, ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As Long) As Long
Private Declare Function RegQueryValueExLong Lib "advapi32.dll" Alias "RegQueryValueExW" (ByVal hKey As Long, ByVal lpValueName As Long, ByVal lpReserved As Long, ByRef lpType As Long, szData As Long, ByRef lpcbData As Long) As Long
Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long
Private Declare Function memcpy Lib "kernel32.dll" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long) As Long
Private Declare Function GetWindowsDirectory Lib "kernel32.dll" Alias "GetWindowsDirectoryW" (ByVal lpBuffer As Long, ByVal uSize As Long) As Long
Private Declare Function lstrlen Lib "kernel32.dll" Alias "lstrlenW" (ByVal lpString As Long) As Long
Private Declare Function lstrcpy Lib "kernel32.dll" Alias "lstrcpyW" (ByVal lpStringDest As Long, ByVal lpStringSrc As Long) As Long
Private Declare Function GetLongPathNameW Lib "kernel32" (ByVal lpszShortPath As Long, ByVal lpszLongPath As Long, ByVal cchBuffer As Long) As Long
Private Declare Function GetFileVersionInfo Lib "version.dll" Alias "GetFileVersionInfoW" (ByVal lptstrFilename As Long, ByVal dwHandle As Long, ByVal dwLen As Long, lpData As Any) As Long
Private Declare Function GetFileVersionInfoSize Lib "version.dll" Alias "GetFileVersionInfoSizeW" (ByVal lptstrFilename As Long, lpdwHandle As Long) As Long
Private Declare Function VerQueryValue Lib "version.dll" Alias "VerQueryValueW" (pBlock As Any, ByVal lpSubBlock As Long, lplpBuffer As Long, puLen As Long) As Long
 
 
Const FILE_SHARE_READ           As Long = &H1&
Const FILE_SHARE_WRITE          As Long = &H2&
Const FILE_SHARE_DELETE         As Long = 4&
Const FILE_READ_ATTRIBUTES      As Long = &H80&
Const OPEN_EXISTING             As Long = 3&
Const CREATE_ALWAYS             As Long = 2&
Const GENERIC_READ              As Long = &H80000000
Const GENERIC_WRITE             As Long = &H40000000
Const FILE_ATTRIBUTE_DIRECTORY  As Long = &H10&
Const INVALID_HANDLE_VALUE      As Long = &HFFFFFFFF
Const ERROR_SUCCESS             As Long = 0&
Const INVALID_FILE_ATTRIBUTES   As Long = -1&
Const NO_ERROR                  As Long = 0&
Const FILE_BEGIN                As Long = 0&
Const FILE_CURRENT              As Long = 1&
Const FILE_END                  As Long = 2&
Const INVALID_SET_FILE_POINTER  As Long = &HFFFFFFFF
 
Const DRIVE_FIXED               As Long = 3&
Const DRIVE_RAMDISK             As Long = 6&
 
Const HKEY_LOCAL_MACHINE        As Long = &H80000002
Const KEY_QUERY_VALUE           As Long = &H1&
Const RegType_DWord             As Long = 4&
 
Const ch_Dot                    As String = "."
Const ch_DotDot                 As String = ".."
Const ch_Slash                  As String = ""
Const ch_SlashAsterisk          As String = "\*"
 
Private lWow64Old               As Long
Private DriveTypeName           As New Collection
Private arrPathFolders()        As String
Private arrPathFiles()          As String
Private Total_Folders           As Long
Private Total_Files             As Long
 
 
 
Public Function FileExists(ByVal sFile$, Optional bUseWow64 As Boolean) As Boolean
    On Error GoTo ErrorHandler:
    Dim Redirect As Boolean
    
    sFile = Trim$(sFile)
    If Len(sFile) = 0 Then Exit Function
    If Left$(sFile, 2) = "" Then Exit Function 'DriveType = "REMOTE"
    
    ' use 2 methods for reliability reason (both supported unicode pathes)
    Dim Ex(1) As Boolean
    Dim ret As Long
    
    Dim WFD     As WIN32_FIND_DATA
    Dim hFile   As Long
    
    If Not bUseWow64 Then Redirect = ToggleWow64FSRedirection(False, sFile)
    
    ret = GetFileAttributes(StrPtr(sFile))
    If ret <> INVALID_HANDLE_VALUE And (0 = (ret And FILE_ATTRIBUTE_DIRECTORY)) Then Ex(0) = True
 
    hFile = FindFirstFile(StrPtr(sFile), WFD)
    Ex(1) = (hFile <> INVALID_HANDLE_VALUE) And Not CBool(WFD.dwFileAttributes And vbDirectory)
    FindClose hFile
 
    ' // here must be enabling of FS redirector
    If Redirect Then Call ToggleWow64FSRedirection(True)
 
    FileExists = Ex(0) Or Ex(1)
    Exit Function
ErrorHandler:
    ErrorMsg Err, "modFile.FileExists", "File:", sFile$
    If inIDE Then Stop: Resume Next
End Function
 
Public Function FolderExists(ByVal sFolder$, Optional ForceUnderRedirection As Boolean) As Boolean
    On Error GoTo ErrorHandler:
    
    Dim ret As Long
    sFolder = Trim$(sFolder)
    If Len(sFolder) = 0 Then Exit Function
    If Left$(sFolder, 2) = "" Then Exit Function 'network path
    
    '// FS redirection checking
    
    ret = GetFileAttributes(StrPtr(sFolder))
    FolderExists = CBool(ret And vbDirectory) And (ret <> INVALID_FILE_ATTRIBUTES)
    
    '// FS redirection enambling
    
    Exit Function
ErrorHandler:
    ErrorMsg Err, "modFile.FolderExists", "Folder:", sFolder$, "Redirection: ", ForceUnderRedirection
    If inIDE Then Stop: Resume Next
End Function
 
 
Public Sub GetDriveTypeNames()
    On Error GoTo ErrorHandler
    Dim lr As Long
    Dim i  As Long
    Dim DT As String
 
    For i = 65& To 90&
 
      lr = GetDriveType(StrPtr(Chr$(i) & ":"))
 
      Select Case lr
        Case 3&
            DT = "FIXED"
        Case 2&
            DT = "REMOVABLE"
        Case 5&
            DT = "CDROM"
        Case 4&
            DT = "REMOTE"
        Case 0&
            DT = "UNKNOWN"
        Case 1&
            DT = "DISCONNECTED" '"NO_ROOT_DIR"
        Case 6&
            DT = "RAMDISK"
        Case Else
            DT = "UNKNOWN"
      End Select
 
      DriveTypeName.Add DT, Chr$(i)
 
    Next
 
    Exit Sub
ErrorHandler:
    ErrorMsg Err, "modFile.GetDriveTypeNames", "Drive:", Chr$(i)
End Sub
 
 
Function FileLenW(Path As String) As Currency ', Optional DoNotUseCache As Boolean
    On Error GoTo ErrorHandler
    
    Dim lr          As Long
    Dim hFile       As Long
    Dim FileSize    As Currency
 
    hFile = CreateFile(StrPtr(Path), FILE_READ_ATTRIBUTES, FILE_SHARE_READ, ByVal 0&, OPEN_EXISTING, ByVal 0&, ByVal 0&)
    
    If hFile Then
        lr = GetFileSizeEx(hFile, FileSize)
        If lr Then
            If FileSize < 10000000000@ Then FileLenW = FileSize * 10000&
        End If
        CloseHandle hFile: hFile = 0&
    End If
    Exit Function
ErrorHandler:
    ErrorMsg Err, "modFile.FileLenW", "File:", Path, "hFile:", hFile, "FileSize:", FileSize, "Return:", lr
End Function
1
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18030 / 7733 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
30.08.2016, 17:36
Продолжение:

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

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
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
Public Function OpenW(FileName As String, Access As VB_FILE_ACCESS_MODE, retHandle As Long, Optional MountToMemory As Boolean) As Boolean '// TODO: MountToMemory
    
    Dim FSize As Currency
 
    If Access And (FOR_READ Or FOR_READ_WRITE) Then
        If Not FileExists(FileName) Then
            retHandle = INVALID_HANDLE_VALUE
            Exit Function
        End If
    End If
        
    If Access = FOR_READ Then
        retHandle = CreateFile(StrPtr(FileName), GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE Or FILE_SHARE_DELETE, ByVal 0&, OPEN_EXISTING, ByVal 0&, ByVal 0&)
    ElseIf Access = FOR_OVERWRITE_CREATE Then
        retHandle = CreateFile(StrPtr(FileName), GENERIC_WRITE, FILE_SHARE_READ, ByVal 0&, CREATE_ALWAYS, ByVal 0&, ByVal 0&)
    ElseIf Access = FOR_READ_WRITE Then
        retHandle = CreateFile(StrPtr(FileName), GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ, ByVal 0&, OPEN_EXISTING, ByVal 0&, ByVal 0&)
    Else
        'WriteCon "Wrong access mode!", cErr
    End If
 
    OpenW = (INVALID_HANDLE_VALUE <> retHandle)
    
    ' ограничение на максимально возможный файл для открытия ( > 100 МБ )
    If OpenW Then
        If Access And (FOR_READ Or FOR_READ_WRITE) Then
            FSize = LOFW(retHandle)
            If FSize > MAX_FILE_SIZE Then
                CloseHandle retHandle
                retHandle = INVALID_HANDLE_VALUE
                OpenW = False
                '"Не хочу и не буду открывать этот файл, потому что его размер превышает безопасный максимум"
                Err.Clear: ErrorMsg Err, "modFile.OpenW: " & "Trying to open too big file" & ": (" & (FSize \ 1024 \ 1024) & " MB.) " & FileName
            End If
        End If
    Else
        ErrorMsg Err, "modFile.OpenW: Cannot open file: " & FileName
        Err.Raise 75 ' Path/File Access error
    End If
 
End Function
 
                                                                  'do not change Variant type at all or you will die ^_^
Public Function GetW(hFile As Long, pos As Long, Optional vOut As Variant, Optional vOutPtr As Long, Optional cbToRead As Long) As Boolean
                                                                  
    'On Error GoTo ErrorHandler
    
    Dim lBytesRead  As Long
    Dim lr          As Long
    Dim ptr         As Long
    Dim vType       As Long
    Dim UnknType    As Boolean
    
    pos = pos - 1   ' VB's Get & SetFilePointer difference correction
    
    If INVALID_SET_FILE_POINTER <> SetFilePointer(hFile, pos, ByVal 0&, FILE_BEGIN) Then
        If NO_ERROR = Err.LastDllError Then
            vType = VarType(vOut)
            
            If 0 <> cbToRead Then   'vbError = vType
                lr = ReadFile(hFile, vOutPtr, cbToRead, lBytesRead, 0&)
                
            ElseIf vbString = vType Then
                lr = ReadFile(hFile, StrPtr(vOut), Len(vOut), lBytesRead, 0&)
                If Err.LastDllError <> 0 Or lr = 0 Then Err.Raise 52
                
                vOut = StrConv(vOut, vbUnicode)
                If Len(vOut) <> 0 Then vOut = Left$(vOut, Len(vOut) \ 2)
            Else
                'do a bit of magik :)
                memcpy ptr, ByVal VarPtr(vOut) + 8, 4& 'VT_BYREF
                Select Case vType
                Case vbByte
                    lr = ReadFile(hFile, ptr, 1&, lBytesRead, 0&)
                Case vbInteger
                    lr = ReadFile(hFile, ptr, 2&, lBytesRead, 0&)
                Case vbLong
                    lr = ReadFile(hFile, ptr, 4&, lBytesRead, 0&)
                Case vbCurrency
                    lr = ReadFile(hFile, ptr, 8&, lBytesRead, 0&)
                Case Else
                    UnknType = True
                    Err.Clear: ErrorMsg Err, "modFile.GetW. type #" & VarType(vOut) & " of buffer is not supported.": Err.Raise 52
                End Select
            End If
            GetW = (0 <> lr)
            If 0 = lr And Not UnknType Then Err.Clear: ErrorMsg Err, "Cannot read file!": Err.Raise 52
        Else
            Err.Clear: ErrorMsg Err, "Cannot set file pointer!": Err.Raise 52
        End If
    Else
        Err.Clear: ErrorMsg Err, "Cannot set file pointer!": Err.Raise 52
    End If
    
'    Exit Function
'ErrorHandler:
'    AppendErrorLogFormat Now, err, "modFile.GetW"
'    Resume Next
End Function
 
Public Function PutW(hFile As Long, pos As Long, vInPtr As Long, cbToWrite As Long, Optional doAppend As Boolean) As Boolean
    On Error GoTo ErrorHandler
    
    Dim lBytesWrote  As Long
    
    pos = pos - 1   ' VB's Get & SetFilePointer difference correction
    
    If doAppend Then
        If INVALID_SET_FILE_POINTER = SetFilePointer(hFile, 0&, ByVal 0&, FILE_END) Then Exit Function
    Else
        If INVALID_SET_FILE_POINTER = SetFilePointer(hFile, pos, ByVal 0&, FILE_BEGIN) Then Exit Function
    End If
    
    If NO_ERROR = Err.LastDllError Then
    
        If WriteFile(hFile, vInPtr, cbToWrite, lBytesWrote, 0&) Then PutW = True
        
    End If
    
    Exit Function
ErrorHandler:
    ErrorMsg Err, "modFile.PutW"
End Function
 
Public Function LOFW(hFile As Long) As Currency
    On Error GoTo ErrorHandler
    Dim lr          As Long
    Dim FileSize    As Currency
    
    If hFile Then
        lr = GetFileSizeEx(hFile, FileSize)
        If lr Then
            If FileSize < 10000000000@ Then
                LOFW = FileSize * 10000&
            Else
                Err.Clear
                ErrorMsg Now, "File is too big. Size: " & FileSize
            End If
        End If
    End If
ErrorHandler:
End Function
 
Public Function CloseW(hFile As Long) As Long
    CloseW = CloseHandle(hFile)
End Function
 
Public Function ToggleWow64FSRedirection(bEnable As Boolean, Optional PathNecessity As String, Optional OldStatus As Boolean) As Boolean
    'Static lWow64Old        As Long    'Warning: do not use initialized variables for this API !
                                        'Static variables is not allowed !
                                        'lWow64Old is now declared globally
    'True - enable redirector
    'False - disable redirector
 
    'OldStatus: current state of redirection
    'True - redirector was enabled
    'False - redirector was disabled
 
    'Return value is:
    'true if success
 
    Static IsNotRedirected  As Boolean
    Dim lr                  As Long
 
    OldStatus = Not IsNotRedirected
 
    If Not bIsWin64 Then Exit Function
 
    If Len(PathNecessity) <> 0 Then
        If StrComp(Left$(PathNecessity, Len(sWinDir)), sWinDir, vbTextCompare) <> 0 Then Exit Function
    End If
 
    If bEnable Then
        If IsNotRedirected Then
            lr = Wow64RevertWow64FsRedirection(lWow64Old)
            ToggleWow64FSRedirection = (lr <> 0)
            IsNotRedirected = False
        End If
    Else
        If Not IsNotRedirected Then
            lr = Wow64DisableWow64FsRedirection(lWow64Old)
            ToggleWow64FSRedirection = (lr <> 0)
            IsNotRedirected = True
        End If
    End If
End Function
 
 
Public Function GetExtensionName(Path As String) As String  'вернет .ext
    Dim pos As Long
    pos = InStrRev(Path, ".")
    If pos <> 0 Then GetExtensionName = Mid$(Path, pos)
End Function
 
' Является ли файл форматом PE EXE
Public Function isPE_EXE(Optional FileName As String, Optional FileHandle As Long) As Boolean
    On Error GoTo ErrorHandler
 
    Dim hFile          As Long
    Dim PE_offset      As Long
    Dim MZ(1)          As Byte
    Dim pe(3)          As Byte
    Dim FSize          As Currency
  
    If FileHandle = 0& Then
        OpenW FileName, FOR_READ, hFile
    Else
        hFile = FileHandle
    End If
    If hFile <> INVALID_HANDLE_VALUE Then
        FSize = LOFW(hFile)
        If FSize >= &H3C& + 4& Then
            GetW hFile, 1&, , VarPtr(MZ(0)), ((UBound(MZ) + 1&) * CLng(LenB(MZ(0))))
            If (MZ(0) = 77& And MZ(1) = 90&) Or (MZ(1) = 77& And MZ(0) = 90&) Then  'MZ or ZM
                GetW hFile, &H3C& + 1&, PE_offset
                If PE_offset And FSize >= PE_offset + 4 Then
                    GetW hFile, PE_offset + 1&, , VarPtr(pe(0)), ((UBound(pe) + 1&) * CLng(LenB(pe(0))))
                    If pe(0) = 80& And pe(1) = 69& And pe(2) = 0& And pe(3) = 0& Then isPE_EXE = True   'PE NUL NUL
                End If
            End If
        End If
        If FileHandle = 0& Then CloseW hFile: hFile = 0&
    End If
    
    'If Len(FileName) <> 0& Then PE_EXE_Cache.Add FileName, isPE_EXE
    Exit Function
    
ErrorHandler:
    ErrorMsg Err, "Parser.isPE_EXE", "File:", FileName
    'On Error Resume Next
    'If Len(FileName) <> 0& Then PE_EXE_Cache.Add FileName, isPE_EXE
    If FileHandle = 0& Then
        If hFile <> 0 Then CloseW hFile: hFile = 0&
    End If
End Function
Вложения
Тип файла: zip modFile.bas.zip (6.1 Кб, 16 просмотров)
1
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18030 / 7733 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
30.08.2016, 17:36
Продолжение:

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

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
'main function to list folders
 
' Возвращает массив путей.
' Если ничего не найдено - возвращается неинициализированный массив. Используйте SafeArrayGetDim()
Public Function ListSubfolders(Path As String, Optional Recursively As Boolean = False) As String()
    Dim bRedirected As Boolean
    'прежде, чем использовать ListSubfolders_Ex, нужно инициализировать глобальные массивы.
    ReDim arrPathFolders(100) As String
    'при каждом вызове ListSubfolders_Ex следует обнулить глобальный счетчик файлов
    Total_Folders = 0&
    
    If bIsWin64 Then
        If StrBeginWith(Path, sWinDir) Then
            ToggleWow64FSRedirection False
            bRedirected = True
        End If
    End If
    
    'вызов тушки
    Call ListSubfolders_Ex(Path, Recursively)
    If Total_Folders > 0 Then
        Total_Folders = Total_Folders - 1
        ReDim Preserve arrPathFolders(Total_Folders)      '0 to Max -1
        ListSubfolders = arrPathFolders
    End If
    
    If bRedirected Then ToggleWow64FSRedirection True
End Function
 
 
Private Sub ListSubfolders_Ex(Path As String, Optional Recursively As Boolean = False)
    On Error GoTo ErrorHandler
    'On Error Resume Next
    Dim SubPathName     As String
    Dim PathName        As String
    Dim hFind           As Long
    Dim l               As Long
    Dim lpSTR           As Long
    Dim fd              As WIN32_FIND_DATA
    
    'Local module variables:
    '
    ' Total_Folders as long
    ' arrPathFolders() as string
    
    Do
        If hFind <> 0& Then
            If FindNextFile(hFind, fd) = 0& Then FindClose hFind: Exit Do
        Else
            hFind = FindFirstFile(StrPtr(Path & ch_SlashAsterisk), fd)  '"\*"
            If hFind = INVALID_HANDLE_VALUE Then Exit Do
        End If
        
        l = fd.dwFileAttributes And &H600& ' мимо симлинков
        Do While l <> 0&
            If FindNextFile(hFind, fd) = 0& Then FindClose hFind: hFind = 0: Exit Do
            l = fd.dwFileAttributes And &H600&
        Loop
    
        If hFind <> 0& Then
            lpSTR = VarPtr(fd.dwReserved1) + 4&
            PathName = Space(lstrlen(lpSTR))
            lstrcpy StrPtr(PathName), lpSTR
        
            If fd.dwFileAttributes And vbDirectory Then
                If PathName <> ch_Dot Then  '"."
                    If PathName <> ch_DotDot Then '".."
                        SubPathName = Path & "" & PathName
                        If UBound(arrPathFolders) < Total_Folders Then ReDim Preserve arrPathFolders(UBound(arrPathFolders) + 100&) As String
                        arrPathFolders(Total_Folders) = SubPathName
                        Total_Folders = Total_Folders + 1&
                        If Recursively Then
                            Call ListSubfolders_Ex(SubPathName, Recursively)
                        End If
                    End If
                End If
            End If
        End If
        
    Loop While hFind
    
    Exit Sub
ErrorHandler:
    ErrorMsg Err, "modFile.ListSubfolders", "Folder:", Path
    Resume Next
End Sub
 
'main function to list files
 
Public Function ListFiles(Path As String, Optional Extension As String = "", Optional Recursively As Boolean = False) As String()
    Dim bRedirected As Boolean
    'прежде, чем использовать ListFiles_Ex, нужно инициализировать глобальные массивы.
    ReDim arrPathFiles(100) As String
    'при каждом вызове ListFiles_Ex следует обнулить глобальный счетчик файлов
    Total_Files = 0&
    
    If bIsWin64 Then
        If StrBeginWith(Path, sWinDir) Then
            ToggleWow64FSRedirection False
            bRedirected = True
        End If
    End If
    
    'вызов тушки
    Call ListFiles_Ex(Path, Extension, Recursively)
    If Total_Files > 0 Then
        Total_Files = Total_Files - 1
        ReDim Preserve arrPathFiles(Total_Files)      '0 to Max -1
        ListFiles = arrPathFiles
    End If
    
    If bRedirected Then ToggleWow64FSRedirection True
End Function
 
 
Private Sub ListFiles_Ex(Path As String, Optional Extension As String = "", Optional Recursively As Boolean = False)
    'Example of Extension:
    '".txt" - txt files
    'empty line - all files (by default)
 
    On Error GoTo ErrorHandler
    'On Error Resume Next
    Dim SubPathName     As String
    Dim PathName        As String
    Dim hFind           As Long
    Dim l               As Long
    Dim lpSTR           As Long
    Dim fd              As WIN32_FIND_DATA
    
    'Local module variables:
    '
    ' Total_Files as long
    ' arrPathFiles() as string
    
    Do
        If hFind <> 0& Then
            If FindNextFile(hFind, fd) = 0& Then FindClose hFind: Exit Do
        Else
            hFind = FindFirstFile(StrPtr(Path & ch_SlashAsterisk), fd)  '"\*"
            If hFind = INVALID_HANDLE_VALUE Then Exit Do
        End If
        
        l = fd.dwFileAttributes And &H600& ' мимо симлинков
        Do While l <> 0&
            If FindNextFile(hFind, fd) = 0& Then FindClose hFind: hFind = 0: Exit Do
            l = fd.dwFileAttributes And &H600&
        Loop
    
        If hFind <> 0& Then
            lpSTR = VarPtr(fd.dwReserved1) + 4&
            PathName = Space(lstrlen(lpSTR))
            lstrcpy StrPtr(PathName), lpSTR
        
            If fd.dwFileAttributes And vbDirectory Then
                If PathName <> ch_Dot Then  '"."
                    If PathName <> ch_DotDot Then '".."
                        SubPathName = Path & "" & PathName
                        If Recursively Then
                            Call ListFiles_Ex(SubPathName, Extension, Recursively)
                        End If
                    End If
                End If
            Else
                If inArray(GetExtensionName(PathName), SplitSafe(Extension, ";"), , , 1) Or Len(Extension) = 0 Then
                    SubPathName = Path & "" & PathName
                    If UBound(arrPathFiles) < Total_Files Then ReDim Preserve arrPathFiles(UBound(arrPathFiles) + 100&) As String
                    arrPathFiles(Total_Files) = SubPathName
                    Total_Files = Total_Files + 1&
                End If
            End If
        End If
    Loop While hFind
    
    Exit Sub
ErrorHandler:
    ErrorMsg Err, "modFile.ListFiles_Ex", "File:", Path
    Resume Next
End Sub
 
Public Function GetLocalDisks$()
    Dim lDrives&, i&, sDrive$, sLocalDrives$
    lDrives = GetLogicalDrives()
    For i = 0 To 26
        If (lDrives And 2 ^ i) Then
            sDrive = Chr$(Asc("A") + i) & ":"
            Select Case GetDriveType(StrPtr(sDrive))
                Case DRIVE_FIXED, DRIVE_RAMDISK: sLocalDrives = sLocalDrives & Chr$(Asc("A") + i) & " "
            End Select
        End If
    Next i
    GetLocalDisks = Trim$(sLocalDrives)
End Function


Примеры:

Кликните здесь для просмотра всего текста
Это не Stand-alone модуль, так что если решите просто подключить к проекту, остальные ошибки сами исправите, вроде отсутствия функции отладки ошибок ErrorMsg .

Пример использования чтения / записи м.б. несколько сложен, так что вот он:
(хотя в целом он дублирует функции VB Open / Get / Put)

Чтение 10 букв из файла в строковую переменную (без доп. проверок на длину файла) (без обработчика ошибок):

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
dim FileName As String
Dim hFile          As Long
 
FileName = "c:\temp\test.txt"
 
if OpenW (FileName, FOR_READ, hFile) then
 
  sBuf = String(10, 0)
 
  GetW hFile, 1&, sBuf
 
  CloseW hFile
 
end if
GetW hFile, 1&, sBuf

Вместо sBuf можно подставлять и другие типы данных (функция GetW сама подстраивается), как и оригинальная VB Get.
Также можно читать в массив байт. Синтаксис будет несколько другой:

Visual Basic
1
2
3
4
5
6
7
GetW hFile, 1&, , указатель на 0-й элемент массива, размер массива в байтах
 
например,
 
Dim aBuf(1) as byte
...
GetW hFile, 1&, , varptr(aBuf(0)), (UBound(aBuf) + 1&) * CLng(LenB(aBuf(0)))
Использование обработчиков ошибок обязательно. GetW запрограммирована выбрасывать ошибки, как и оригинальная функция.

Запись в файл:

PutW hFile, StartPos, lpArray, cbBytes, (bool)doAppend

StartPos - начальный байт, куда писать (начинается с 1, как у классического VB Put)
lpArray - указатель на массив байт
cbBytes - кол-во байт для записи
doAppend - (опционально). true - если нужно дописать данные в конец файла.

Пример записи в файл текста в формате UTF-16LE (без обработчика ошибок):

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
dim FileName As String
Dim hFile          As Long
Dim sText as string
Dim sBOM as string
Dim b()     As Byte
 
FileName = "c:\temp\test.txt"
sBOM = ChrW$(-257)
sText = "Пример"
 
b() = sBOM & sText
 
if OpenW (FileName, FOR_WRITE, hFile) then
 
  PutW hFile, 1&, VarPtr(b(0)), UBound(b) + 1
 
  CloseW hFile
 
end if
1
182 / 33 / 3
Регистрация: 28.05.2015
Сообщений: 148
31.08.2016, 08:51  [ТС]
Спасибо большое, Dragokas.

Да... с API-шками я практически не работал. Тут целый массив новой для меня информации.:-)
0
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
01.05.2024, 20:49
Цитата Сообщение от Dragokas Посмотреть сообщение
Filter = "Музыкальные файлы" & vbNullChar & "*.mp3;.wav;*.ac3;*.flac" & vbNullChar & _
        "Все файлы" & vbNullChar & "*.*" & vbNullChar
В MSDN кстати написано что последняя строка буфера должна заканчиваться двумя символами NULL а у тебя только один. https://learn.microsoft.com/en... nfilenamew

Добавлено через 2 часа 52 минуты
Итак продолжим спор, я хочу доказать что я прав наглядными примерами.

В твоём примере твой код выглядит так:

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
Option Explicit
 
Private Type OPENFILENAME
    lStructSize As Long
    hwndOwner As Long
    hInstance As Long
    lpstrFilter As Long
    lpstrCustomFilter As Long
    nMaxCustFilter As Long
    nFilterIndex As Long
    lpstrFile As Long
    nMaxFile As Long
    lpstrFileTitle As Long
    nMaxFileTitle As Long
    lpstrInitialDir As Long
    lpstrTitle As Long
    flags As Long
    nFileOffset As Integer
    nFileExtension As Integer
    lpstrDefExt As Long
    lCustData As Long
    lpfnHook As Long
    lpTemplateName As Long
End Type
 
Private Declare Function GetOpenFileName Lib "comdlg32.dll" Alias "GetOpenFileNameW" (pOpenfilename As OPENFILENAME) As Long
 
Private Sub Form_Load()
    MsgBox GetFile(Me.hwnd, App.Path)
End Sub
 
Public Function GetFile(ByVal hwnd As Long, Optional InitDir As String) As String
    Dim ofn As OPENFILENAME
    Dim Title As String, out As String
    Dim Filter As String, i As Long
    
    ofn.nMaxFile = 260
    out = String(260, 0)
    Title = "Открыть файл"
    Filter = "Музыкальные файлы" & vbNullChar & "*.mp3;.wav;*.ac3;*.flac" & vbNullChar & _
        "Все файлы" & vbNullChar & "*.*" & vbNullChar
    ofn.hwndOwner = hwnd
    ofn.lpstrTitle = StrPtr(Title)
    ofn.lpstrFile = StrPtr(out)
    ofn.lStructSize = Len(ofn)
    ofn.lpstrFilter = StrPtr(Filter)
    ofn.lpstrInitialDir = StrPtr(InitDir)
    
    If GetOpenFileName(ofn) Then
        i = InStr(1, out, vbNullChar, vbBinaryCompare)
        If i Then GetFile = Left$(out, i - 1)
    End If
End Function
Мой вариант немного переделанный будет выглядеть так:

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
Option Explicit
 
Private Type OPENFILENAME
    lStructSize As Long
    hwndOwner As Long
    hInstance As Long
    lpstrFilter As String
    lpstrCustomFilter As String
    nMaxCustFilter As Long
    nFilterIndex As Long
    lpstrFile As String
    nMaxFile As Long
    lpstrFileTitle As String
    nMaxFileTitle As Long
    lpstrInitialDir As String
    lpstrTitle As String
    flags As Long
    nFileOffset As Integer
    nFileExtension As Integer
    lpstrDefExt As String
    lCustData As Long
    lpfnHook As Long
    lpTemplateName As String
End Type
 
Private Declare Function GetOpenFileName Lib "comdlg32.dll" Alias "GetOpenFileNameW" (ByVal pOpenfilename As Long) As Long
 
Private Sub Form_Load()
    MsgBox GetFile(Me.hwnd, App.Path)
End Sub
 
Public Function GetFile(ByVal hwnd As Long, Optional InitDir As String) As String
    Dim ofn As OPENFILENAME
    Dim i As Long
    
    ofn.nMaxFile = 260
    ofn.hwndOwner = hwnd
    ofn.lpstrTitle = "Открыть файл"
    ofn.lpstrFile = Space$(260)
    ofn.lStructSize = Len(ofn)
    ofn.lpstrFilter = "Музыкальные файлы" & vbNullChar & "*.mp3;.wav;*.ac3;*.flac" & vbNullChar & "Все файлы" & vbNullChar & "*.*" & vbNullChar & vbNullChar
    ofn.lpstrInitialDir = InitDir
    
    If GetOpenFileName(VarPtr(ofn)) Then
        i = InStr(1, ofn.lpstrFile, vbNullChar)
        If i Then GetFile = Left$(ofn.lpstrFile, i - 1)
    End If
End Function
Получается на 5 строк кода меньше. Обращаю внимание на то, что в моём коде НЕ нужно объявлять дополнительные переменные:

Visual Basic
1
2
Dim Title As String, out As String
Dim Filter As String
А так же в моём коде НЕ нужно писать потом StrPtr постоянно присваивать одно другому... Мой код легче и понятнее.
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18030 / 7733 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
01.05.2024, 20:52
Какой спор? Прекрати некропостить, писать чушь, мешать юникодные функции с ансишными структурами и не отвлекай меня по мелочам.
Отписался от темы.
0
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
01.05.2024, 20:56
Dragokas, я тебе только что ДОКАЗАЛ что не нужно переделывать структуру на As Long, а тем более говорить что структура ансишная или не ансишная это неправильно, они одинаковые на самом деле.

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

[ODBC] Строка '(нет данных)' задает ошибочный путь. Проверьте, что путь задан правильно и имеет
Ребят, подскажите, есть программка написанная на Delphi (к исходникам доступа нет :( ). В ней залочено подключение к БД (mdb) через ODBC....

Узнать путь к dll из самой dll
Собственно вопрос в названии темы. Тут проблема вот в чем, dll запускается из mq4/mq5 программы, где пути к dll явно не прописываются ...

Как заставить программу использовать \system32\shell32.dll, а не \путь к проге\Interop.Shell32.dll
Это неудобно для Portable программы..

COMDLG32.OCX не используется и выдает ошибку
Всем привет!!! Сделал форму в Excel 2003 и кинул на нее CommonDialogControl. Перед этим скачал COMDLG32.OCXи зарегил его как полагается....

Путь поиска dll
Подскажите пожалуйста как добавить путь поиска dll библиотек? SetDllDirectory добавляет только один путь. ( это не подходит), а...


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

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru