p align="left">Приложение 2B было протестировано на 2х компьютерах: А) компьютер с Windows-95 Реально тестирование проводилось еще и на третьем компьютере с системой Windows-98, однако ее поведение ничем не отличалось от Windows-95, за исключением уже отмеченного нюанса в реализации функций DefineDosDevice и QueryDosDevice. и Windows 3.11 + Win32s диск A -- 3.5”, дискета не вставлена диск C -- EIDE HDD, том “Bootable” диск D -- SCSI HDD, под Windows 3.11 доступен через ASPI драйвер, том “SCSI_VOL” диск E -- IDE CD-ROM, диск не вставлен Б) компьютер с Windows NT диск A -- 3.5”, дискета не вставлена диск C -- SCSI HDD, диск D -- IDE CD-ROM, диск не вставлен Всего было выполнено 6 тестов -- запускались 16ти и 32х разрядные версии приложения в среде Windows 3.11 + Win32s, Windows-95 и Windows NT Server 4.0. Результаты тестов следующие: Среда Windows 3.11+Win32s, 16ти разрядное приложение: ******** GET VOLUME INFORMATION ******** Root: A:\ type=REMOVABLE volume='' ***** NO VOLUME INFORMATION! Root: C:\ type=FIXED volume='' serial=00000000 maximal component length=12 cluster=16384 total=822272K free=71712K file system ='' flags=CASE_PRESERVED Root: D:\ type=FIXED volume='' serial=00000000 maximal component length=12 cluster=32768 total=1065792K free=45408K file system ='' flags=CASE_PRESERVED Root: E:\ type=REMOTE volume='' ***** NO VOLUME INFORMATION! ******** READ DOS DEVICES MAP ******** NOTE: DefineDosDevice() is not implemented! 16ти разрядное приложение пытается обратиться к дискам в функции access (в эмуляции GetVolumeInformation), что для дисков A (гибкий диск) и E (CD-ROM) приводит к системному сообщению об ошибке “Cannot read from drive ...”; Локальный CD-ROM распознается как сетевое устройство. Среда Windows 3.11+Win32s, 32х разрядное приложение: ******** GET VOLUME INFORMATION ******** Root: A:\ type=REMOVABLE volume='' ***** NO VOLUME INFORMATION! Root: C:\ type=FIXED volume='BOOTABLE' serial=00000000 maximal component length=12 cluster=16384 total=822272K free=71728K file system ='FAT' flags= Root: D:\ type=RAM DISK volume='SCSI_VOL' serial=00000000 maximal component length=12 cluster=32768 total=1065792K free=45408K file system ='FAT' flags= Root: E:\ type=CD-ROM volume='SCSI_VOL' serial=00000000 maximal component length=12 cluster=0 total=0K free=0K file system ='FAT' flags= ******** READ DOS DEVICES MAP ******** NOTE: DefineDosDevice() is not implemented! Реакция приложения совершенно другая (используются функции, входящие в реализацию Win32 API, а не их эмуляция нашим приложением). При обращении к диску A генерируется сообщение об ошибке, При обращении к диску E (CD-ROM) функция GetVolumeInformation (причем именно ее реализация в Win32s, а не ее эмуляция у нас) дает сообщение об ошибке и сообщает, что информация о томе успешно (?!) получена, после чего следует попытка узнать свободное пространство на отсутствующем диске E -- с еще одним сообщением об ошибке (вместо сообщения “no volume information”). Характерно, что тип диска E -- CD-ROM -- определен корректно, файловая система -- CDFS (файловая система CD дисков) почему-то распознана как FAT, а метку тома позаимствовали у предыдущего диска Такое поведение типично для MSCDEX.EXE, который обеспечивает доступ к дискам с CDFS в среде MS-DOS; при отсутствии диска MSCDEX часто использует данные, оставшиеся в кэше от предыдущего диска, может быть даже от того, который был раньше вставлен, либо вообще от другого. Это, кстати, может приводить к ошибке -- при попытке проверить наличие какого-либо конкретного файла на томе с CDFS вы можете получить положительный ответ, даже если том вообще отсутствует в приводе! При проверке наличия файла на CD-ROM лучше не просто проверять его наличие, а открывать и выполнять чтение небольшого фрагмента, что бы убедиться в действительном присутствии файла.. Кроме того, SCSI диск, доступный через ASPI, был распознан как RAM DISK. Среда Windows 95, 16ти разрядное приложение: ******** GET VOLUME INFORMATION ******** Root: A:\ type=REMOVABLE volume='' ***** NO VOLUME INFORMATION! Root: C:\ type=FIXED volume='' serial=00000000 maximal component length=12 cluster=16384 total=822272K free=70208K file system ='' flags=CASE_PRESERVED Root: D:\ type=FIXED volume='' serial=00000000 maximal component length=12 cluster=32768 total=1065792K free=45408K file system ='' flags=CASE_PRESERVED Root: E:\ type=REMOTE volume='' ***** NO VOLUME INFORMATION! ******** READ DOS DEVICES MAP ******** NOTE: DefineDosDevice() is not implemented! Уже неплохо -- результаты совпадают с тем, что было получено для 16ти разрядного приложения в среде Windows 3.11, реакция на получение информации об отсутствующем диске такая-же -- сообщение об ошибке. Среда Windows 95, 32х разрядное приложение: ******** GET VOLUME INFORMATION ******** Root: a:\ type=REMOVABLE volume='' ***** NO VOLUME INFORMATION! Root: c:\ type=FIXED volume='BOOTABLE' serial=0E3219D9 maximal component length=255 cluster=16384 total=822272K free=69696K file system ='FAT' flags=CASE_PRESERVED UNICODE Root: d:\ type=FIXED volume='SCSI_VOL' serial=025511DA maximal component length=255 cluster=32768 total=1065792K free=45408K file system ='FAT' flags=CASE_PRESERVED UNICODE Root: e:\ type=CD-ROM volume='' ***** NO VOLUME INFORMATION! ******** READ DOS DEVICES MAP ******** NOTE: DefineDosDevice() is not implemented! Пожалуй, самый приличный результат. Все срабатывает корректно и без сообщений о критических ошибках, даже если не использовать функцию SetErrorMode. Типы дисков и файловые системы определяются корректно. Среда Windows NT, 16ти разрядное приложение: ******** GET VOLUME INFORMATION ******** Root: A:\ type=REMOVABLE volume='' ***** NO VOLUME INFORMATION! Root: C:\ type=FIXED volume='' serial=00000000 maximal component length=12 cluster=32768 total=999968K free=615136K file system ='' flags=CASE_PRESERVED Root: D:\ type=REMOTE volume='' serial=00000000 maximal component length=12 cluster=16384 total=601632K free=0K file system ='' flags=CASE_PRESERVED ******** READ DOS DEVICES MAP ******** NOTE: DefineDosDevice() is not implemented! Поведение приложения вполне соответствует обычному 16ти разрядному приложению в среде Windows 3.x, но вот полный размер диска, превышающий 1Г определяется с ошибкой -- диск C на 1.33Г был определен как диск размером 999М. Среда Windows NT, 32х разрядное приложение: ******** GET VOLUME INFORMATION ******** Root: A:\ type=REMOVABLE volume='' ***** NO VOLUME INFORMATION! Root: C:\ type=FIXED volume='' serial=00AE5141 maximal component length=255 cluster=512 total=1405655K free=615143K file system ='NTFS' flags=CASE_PRESERVED CASE_SENSITIVE UNICODE ACL MAY_COMPRESS Root: D:\ type=CD-ROM volume='ASART3' serial=E2F025BC maximal component length=221 cluster=2048 total=601644K free=0K file system ='CDFS' flags=CASE_SENSITIVE ******** READ DOS DEVICES MAP ******** DISPLAY1 = \Device\Video0 NDIS = \Device\Ndis DISPLAY2 = \Device\Video1 Z: = \??\C:\WINNT D: = \Device\CdRom0 $VDMLPT1 = \Device\ParallelVdm0 COM1 = \Device\Serial0 COM2 = \Device\Serial10000 PIPE = \Device\NamedPipe UNC = \Device\Mup PhysicalDrive0 = \Device\Harddisk0\Partition0 PRN = \DosDevices\LPT1 A: = \Device\Floppy0 Scsi0: = \Device\ScsiPort0 DC21X41 = \Device\DC21X41 LPT1 = \Device\Parallel0 Scsi1: = \Device\ScsiPort1 C: = \Device\Harddisk1\Partition1 AUX = \DosDevices\COM1 MAILSLOT = \Device\MailSlot NUL = \Device\Null Единственное, что кажется несколько странным, так это сообщение о критической ошибке при попытке вызова GetVolumeInformation для отсутствующего диска, хотя под Windows-95 эта функция работает молча -- она же и так возвращает результат “не удалось”, так зачем же еще давать сообщение? Сообщение об ошибке отключается с помощью SetErrorMode, хотя это и не согласуется с формальным описанием функции. Итого: Если ваше приложение может работать в Windows 3.x с Win32s, то необходимо особенно тщательное тестирование всех операций с файлами и томами, так как реакция системы может существенно отличаться от той, которая будет в случае Windows-95 и Windows NT. Кроме того особое внимание стоит уделить функциям, возвращающим информацию о томе (типа GetVolumeInformation) -- они производят попытку реального обращения к томам, что может привести либо к возникновению сообщений об ошибках либо даже к «зависанию» всего приложения, если работа с томом сопровождается какой-либо ошибкой. Так, например, отдельной проверки и отладки потребуют все случаи работы со сменными дисками (гибкими, компакт-дисками, магнито-оптическими дисками и т.д.) и с сетевыми томами (особенно случаи, когда удаленный компьютер, предоставляющий свои тома в общее пользование, зависает, отключается или происходят какие-либо неполадки в работе сети -- в такой ситуации возможно даже зависание компьютера, с которого производится вызов функции GetVolumeInformation). Работа с каталогами и файлами Win32 API содержит все необходимые функции для работы с каталогами и файлами. При этом набор функций, реализованных в Windows полностью перекрывает обычный набор функций библиотеки времени выполнения, так что необходимость в применении функций последней отпадает. Рассматриваемые здесь функции служат следующим целям: работа с каталогами (создание, удаление, поиск и получение списка файлов); получение и изменение атрибутов файлов; работа с файлами (длинными и короткими именами файлов, копирование, перемещение и удаление файлов); В таком порядке мы и познакомимся с функциями Win32 API. Работа с каталогами Аналогично обычному Windows API в Win32 API используется понятие текущего каталога, в котором должны размещаться файлы, если только в их имени не содержится путь к этим файлам. Иногда возможно задание относительного пути (подробнее см. Работа с файлами, каталогами и томами в Windows API, стр. 1). Вы можете как узнать текущий каталог с помощью функции GetCurrentDirectory, так и сделать текущим какой-либо иной каталог, воспользовавшись функцией SetCurrentDirectory. DWORD GetCurrentDirectory(cchDir, lpszDir); BOOL SetCurrentDirectory(lpszDir); Параметры функций: lpszDir -- буфер, содержащий или получающий имя текущего каталога, cchDir -- максимальное число символов в имени текущего каталога, которые могут уместиться в отведенном буфере. Не забывайте, что длина имени (это полный путь к текущему каталогу) может быть очень большой, поэтому удобно сначала узнать необходимый размер буфера, выделить его и затем получить имя: DWORD nSize; char *pszCurDir; dwSize = GetCurrentDirectory(0, NULL); // возвращается требуемая длина, pszCurDir = new char [ dwSize ]; // включая завершающий `\0' GetCurrentDirectory(dwSize, pszCurDir); При необходимости вы можете создавать или уничтожать каталоги с помощью функций CreateDirectory и RemoveDirectory. Как и в случае функций библиотеки времени выполнения, функция RemoveDirectory может удалить только пустой каталог; в противном случае функция сообщит об ошибке. BOOL CreateDirectory(lpszDir, lpsaSA); BOOL RemoveDirectory(lpszDir); Параметр lpSA является указателем на структуру SECURITY_ATTRIBUTES, с помощью которого вы можете управлять доступом к файлам. DWORD GetTempPath(cchBuffer, lpszTempPath); Эта функция дополняет прежние GetTempDrive и GetTempFileName. Она возвращает путь к каталогу, предназначенному для хранения временных файлов.
Страницы: 1, 2, 3, 4, 5, 6, 7
|