@Linda-chan

Тег программизм в блоге Linda-chan

Linda-chan

Ранее я писала, что по какой-то причине вызов встроенной функции DateAdd() в VB3 прекрасно работал в Windows 3.11, но выдавал ошибку «File not found» в 32-разрядных виндах.
Неожиданно в Пойнте мне посоветовали помониторить процесс:
#orvhfn/#3
По-началу я скептически отнеслась к этой идее, поскольку Win16 приложения в 32-битных виндах работают в виртуальной машине и даже своего процесса не имеют. Мало ли, как оно там внутрях работает. Но, подумав, всё же решила попробовать, тем более, что ранее меня всё равно посещала такая идея.
Взяла FileMon (ProcMon более жёстко по отношению к ресурсам системы действует, и у меня комп как-то даже вешался от него), отфильтровала NTVDM.EXE, и посмотрела, что происходит при запуске тестовой программы. С первого раза ничего такого почему-то не заметила, а вот со второго увидела, что какой-то MSAFINX.DLL активно разыскивается в PATH, но не обнаруживается. Глянула – действительно, в системном каталоге такого файла нет, зато он есть в системном каталоге Windows 3.11. В описании – «Finance And Miscellaneous Functions for Microsoft Visual Basic». В экспортах – в том числе CIDATEADD.
Скопировала файл прямо в папку к программе, и всё неожиданно заработало OO
Решила выяснить, что это за файл такой. Поискала в каталоге с VB3 упоминания этого файла, и нашла их не только в PACKING.LST (полный список всех файлов дистрибутива с пояснениями и разбивкой на оригинальные дискеты, где их можно найти), но и в VB.HLP. Поискала в самой справке VB3, ну и в числе прочего нашла ту самую функцию DateAdd(), а в её описании, в самом конце – пояснение:

Distribution Note
When you create and distribute applications that use this function in your code, you should install the file MSAFINX.DLL in the customer's Microsoft Windows \SYSTEM directory. The Visual Basic Setup Kit provides tools to help you write setup programs that install your applications.

Полагаю, что дело было так. В прочих виндах я VB3 таскаю прямо каталогом без какой-либо установки, разве что VBRUN*.DLL закидываю в системный каталог. Поэтому нужного файла у меня не оказалось. А вот в Windows 3.11 я прямо всё устанавливала с образов дискет, чтобы у меня группа в Диспетчере программ появилась и всё такое прочее. Ну и файл тоже установился. А столь важную пометку я никогда не читала потому, что я и так знаю, как работает функция, и в VB6 она не требует никаких дополнительных библиотек. Вот и получилось то, что получилось =_=

Linda-chan

Спросила у Утки: «VB3 DateAdd error "File not found"».
Среди бесконечных ссылок на обсуждения VBA в Access неожиданно попался вопрос на форуме, где у человека такая ошибка именно в VB3. Правда, он говорит как-то туманно, звучит так, словно у него ошибка и в Windows 3.11, и в Windows 98, а на другой машине под Windows 98 ошибки нет. В то время как у меняя ошибка во всех 32-разрядных системах, а в Windows 3.11 – нет. Но ведь то, что я ищу! Правда, ответ на свой вопрос человек так и не получил.
Зато я получила ответ от ИИ ассистента в Утке. ИИ не знает о такой проблеме, но, опираясь на текст ошибки рекомендует переустановить программу, переустановить VB3, переустановить винду. Или написать свою реализацию DateAdd()! Я уже приготовилась читать пространные объяснения реализации типа Date и математики, связанной с ним, но вместо этого ИИ выдал мне функцию, которая принимает аргументы как DateAdd(), в Select Case смотрит, какая буква, обозначающая интервал, передана в функцию, и вызывает нативную DateAdd(), но с проставленной ручками буквой. Я сначала не поняла, что происходит, а, когда поняла, – просто охренела.
Но окончательно меня добил один из последних вариантов ответа, который предлагал почитать документацию фразой «Seek help».

Linda-chan

В Windows XP DateDiff() из программы на VB3 выдаёт ошибку «File not found» OO

Linda-chan

С парсингом данных счётчиков производительности и вычислением значений из этих данных, вроде как разобралась. А всё из-за вот этого фрагмента из MSDN:

Windows NT: To obtain the time elapsed since the computer was started, look up the System Up Time counter in the performance data in the registry key HKEY_PERFORMANCE_DATA. The value returned is an 8 byte value.

Оказалось, что WMI иногда сходит с ума и выдаёт странные значения, ну вот я и заинтересовалась...

Linda-chan

Разбираюсь со счётчиками производительности Windows. При чём самым хардкорным методом, без дотнет обёрток, без DPH.DLL, а прямо через реестр с парсингом двоичных данных. И это пипец, надо сказать ^^'
Пробовала спрашивать нейросети, но те либо откровенную дичь несут, либо всё к тем же обёрткам отсылают. Один запрос вообще выдал мне некий скелет, куда нейросеть предложила самостоятельно дописать код, который меня и интересовал.
Поэтому пришлось читать и страдать. Страдать в основном потому, что там нет шортката, быстрого кода, который можно написать для решения конкретной задачи и не разбираться со всем остальным. Разбираться таки придётся ^^'

Linda-chan

В заголовочнике winperf.h обнаружились константы:
• PERF_DETAIL_NOVICE
• PERF_DETAIL_ADVANCED
• PERF_DETAIL_EXPERT
• PERF_DETAIL_WIZARD

Linda-chan

Кстати о переполнении. Если просто приплюсовать к переменной единичку и словить ошибку переполнения, у переменной останется тоже самое значение. Тоесть это только в цикле старший бит переворачивается.

Linda-chan

Поняла, в чём проблема. Если цикл идёт от 1 до 3, то на выходе из него переменная будет равна 4. Никогда раньше не использовала переменную из цикла после выхода из него, так что не задумывалась об этом. Судя по документации, в конце итерации значение переменной плюсуется, после чего проверяется: если переменная меньше или равна конечному значению, то выполняется следующая итерация, иначе – выход. Тоесть, условием выхода является превышение конечного значения, а, если конечное значение – самое большое для данного типа переменной, то происходит переполнение. Ну и самое большое значение Long – 0x7FFFFFFF, а самое маленькое – 0x80000000, так что понятно, почему у меня переменная как бы перескакивала к началу цикла.

Linda-chan

Столкнулась с неожиданной проблемой.
Есть тип данных Long, который принимает значения от -2'147'483'648 до 2'147'483'647. Если взять пустой цикл от меньшего к большему, то оно сначала пробегает все значения, а потом случается ошибка 6 – «Overflow». Значение переменной из цикла в этот момент равняется -2'147'483'648.
Что характерно, в VBA та же история.
Ещё интересно, что, если вписать значение -2'147'483'648 в редакторе кода, то он автоматом в конце впишет «#», тоесть укажет, что это значение типа Double. Если подставить «&», тоесть, что это Long, то редактор начнёт выдавать ошибку «Expected: expression». А вот с -2'147'483'647 уже всё в порядке.
Наверняка, не связано, но всё равно забавно.

Linda-chan

Ещё с нулевых у меня был код на VC++, который форматировал Double в удобочитаемый вид. Сначала он делает так:

sprintf(TXT, "%lf", dblByaka);

На выходе получается что-то в духе «123.456789», а потом TXT пизается в GetNumberFormat(), который уже форматирует этот текст в то, что задано в региональных настройках (или что укажешь в специальной структуре).
Недавно вдруг обнаружилось, что в Windows 2000 и ниже этот код возвращает пустую строку при очень маленьких значениях dblByaka. Начала разбираться и выяснила, что sprintf() выдаёт мне «0,000000123» вместо «0.000000123». Тоесть именно в этом случае он ставит запятую вместо точки, как это происходит во всех остальных случаях. А вот в Windows XP и выше такого не наблюдается. Мистика.

Linda-chan

Требую Бейсикпанк – жанр и мир, в котором все программы написаны на тех или иных диалектах Бейсика!

Linda-chan

Dollars that make your program run faster

https://www.aivosto.com/articles/stringopt.html
Речь про «Mid$() vs Mid()», а не то, что вы подумали.

Linda-chan

Попутно выяснила занятное. У функции DeviceIOControl(), которая позволяет давать команды устройствам и получать от них всякие данные (как раз через неё пишутся и читаются данные reparse point), есть такие параметры: входной буфер с размером, выходной буфер с размером, сколько было записано в выходной буфер, ну и ссылка на OVERLAPPED для асинхронной операции. Буферы опциональны в зависимости от устройства и команды, параметр, возвращающий количество записанного, – тоже, ну и OVERLAPPED. Ну, у меня при записи в reparse point операция синхронная и используется только входной буфер, поэтому в функцию передаю только входной буфер и его размер, а всё остальное – NULL. Ну и программа в результате вылетает. Оказалось, что, если параметр, принимающий OVERLAPPED, установлен в NULL, то параметр, принимающий количество записанного в выходной буфер, должен ссылаться на актуальную переменную, даже если выходной буфер – тоже NULL. Оказывается, Microsoft не только не добавила проверку этого параметра, но и использовала его значение где-то внутрях функции, о чём указала в документации. В общем, не делайте так =_=

Linda-chan

Короче, написала я прототип программы, которая данные хранит в reparse point. И оно работает: появляется файл длиной ноль байт, который, поскольку система не знает, что это такое, можно только удалить. Написать код, который вытащит эти данные, разумеется, – задача тривиальная, тоесть для маскировки подходит мало, но тут именно что нужно писать код или искать очень специальную утилиту, ибо никакими блокнотами такие файлы не открываются.

Linda-chan

А вот интересно... Можно ли сделать кастомную reparse point так, чтобы хранить в ней какие-то свои данные, не связанные с файловой системой? Типа как маскировка данных в файловых потоках, только ещё круче, что прямо код надо писать, чтобы вытащить эти данные.
// Возможно, этот пост содержит часть ответа на вопрос из предыдущего.

Linda-chan

Написала код, который изучает симлинк (на самом деле – reparse point) и выдаёт то, на что симлинк ссылается. Проверила – работает. Почти приступила к применению, но тут заметила, что в некоторых случаях код работает неправильно, выдаёт странные результаты. Начала изучать двоичные данные, которые парсит программа, и поняла, что что-то с ними не так: одни поля налезают на другие, хотя в других случаях всё с полями нормально. Начала копаться в MSDN. Оказалось, что документация про всему этому есть, но какая-то туманная, везде недосказанность, функций всего ничего, объясняются только общие концепции. Продолжила копать и повторно открыла для себя раздел «Open Specifications», в котором предельно чётко описаны все структуры, которые в этих самых reparse points используются. И оказалось, что в MSDN была описана одна структура, а в реальности используются другие структуры, по одной на каждый тип симлинков. А та, что описана в MSDN – вообще для сторонних реализаций. В итоге код придётся переписывать и снова всё тестировать. Но я всё равно не понимаю, чего Microsoft так тряслись над этими reparse points так, словно это пентагоновский секрет?

Linda-chan

Почему структура GUID не соответствует текстовому виду этого самого GUID?

Linda-chan

Узнала, что JavaScript поддерживает запись двоичных чисел как «0b10101010». В смысле, в принципе поддерживает двоичные числа.

Linda-chan

Не, я знаю, что For Each, не смотря на использование варианта, работает быстрее, чем просто For с индексом, но чтобы настолько... Коллекция, 240 тысяч элементов типа Long, с которым в цикле производятся действия (коллекция перегоняется в массив). For с индексом пережёвывает коллекцию за тридцать-сорок секунд. For Each проносится по коллекции за 0.12 секунд.

Linda-chan

Научилась делать ботов-уведомляторов для телеграмки на VB. Документация по API, конечно, написана в лучших традициях Роберта Гейла. Особенно порадовало описание отправки картинок и файлов на сервер, типа, можно указать URL, можно указать ID, а можно «КАК БРОУЗЕР ЗАГРУЖАЕТ КАРТИНКИ НА САЙТ». Я час ломала голову, пока не додумалась, что оно в отправляемой форме хочет имя файла, даже если это имя потом нигде не будет использоваться.

Добавить пост

Вы можете выбрать до 10 файлов общим размером не более 10 МБ.
Для форматирования текста используется Markdown.