Страница 2 из 4

Целостность multi-DLL проекта

Добавлено: 13 Октябрь 2021, 20:31
kreator
Дата изменения - это дата последней записи в файл. Она не меняется при копировании и т.д. В GetFileDate это значение вытаскивается по умолчанию (при отсутствии второго параметра). Думаю и в Directory она же.

Целостность multi-DLL проекта

Добавлено: 13 Октябрь 2021, 20:41
Дед Пахом
Если загружать dll с FTP, то дата изменения (вроде бы) меняется на текущую.

Целостность multi-DLL проекта

Добавлено: 13 Октябрь 2021, 20:46
Игорь Столяров
Дед Пахом писал(а): 13 Октябрь 2021, 20:41 Если загружать dll с FTP, то дата изменения (вроде бы) меняется на текущую.
Есть много нюансов с архиваторами, программами резервного копирования и т.д.
И вообще это совсем не правильно определять версию DLL по внешней дате файла.

Целостность multi-DLL проекта

Добавлено: 13 Октябрь 2021, 20:49
Дед Пахом
Есть ещё CRC.

Целостность multi-DLL проекта

Добавлено: 13 Октябрь 2021, 21:23
Игорь Столяров
Достаточно трудно в использовании.

1. Нужно после сборки проекта записывать хеш всех DLL файлов проекта в какой-то лог.
Не очень большая - но всё-таки дополнительная операция.

2. А вот загружать в память все DLL считать их хеш при каждом запуске программы - уже медленно. :(

Правильный путь через WinAPI - надо разбираться с GetFileVersionInfoA().

Целостность multi-DLL проекта

Добавлено: 13 Октябрь 2021, 23:09
kreator
Дед Пахом писал(а): 13 Октябрь 2021, 20:41 Если загружать dll с FTP, то дата изменения (вроде бы) меняется на текущую.
Передавайте архивом.
Вообще загнаться можно. И Api будет врать.

Целостность multi-DLL проекта

Добавлено: 26 Октябрь 2021, 13:50
Игорь Столяров
Дед Пахом писал(а): 13 Октябрь 2021, 16:51 https://stackoverflow.com/questions/940 ... r-exe-file
Ещё раз спасибо, всё сделал по науке. И это была интересная охота ! :)

Когда уже разобрался в вопросе, то понял что элементарную базовую проверку
можно сделать и штатными средствами Clarion (и это решило бы мой вопрос):

Код: Выделить всё

  If System{Prop:ExeVersion,3} <> System{Prop:LibVersion,3} then Message('Houston, we have a problem !').  

Целостность multi-DLL проекта

Добавлено: 26 Октябрь 2021, 16:24
kreator
Круто! Я не знал.

Целостность multi-DLL проекта

Добавлено: 26 Октябрь 2021, 16:26
Дед Пахом
Я знал, но забыл.

Целостность multi-DLL проекта

Добавлено: 04 Ноябрь 2021, 15:34
Игорь Столяров
Пример контроля версий DLL Clarion (и не только).

1. Добавляем где-нибудь в Global Map и линкуем к проекту Version.lib (прикреплён, см. ниже):

Код: Выделить всё

  Module('Windows')
    Glo:memcpy(Long lpDest,Long lpSource,Long nCount),Long,Proc,Name('_memcpy')
  end

  Module('Version.dll')
    WinGetFileVersionInfoSizeA(*CSTRING lptstrFilename, *ULong lpdwHandle),ULONG,PASCAL,RAW,Name('GetFileVersionInfoSizeA')
    WinGetFileVersionInfoA(    *CSTRING lptstrFilename, Long dwHandle, Long dwLen, *String lpData),BOOL,PASCAL,RAW,Name('GetFileVersionInfoA')
    WinVerQueryValueA(*String pBlock, *CSTRING lpSubBlock, *ULong lplpBuffer, *ULong puLen),BOOL,PASCAL,RAW,Name('VerQueryValueA')
  end
2. Пример проверки версии DLL используемой в Вашем проекте (где-нибудь при запуске EXE):

Код: Выделить всё

  ExeVersion# = System{Prop:ExeVersion,3}   ! Версия сборки EXE модуля
  
  If CheckVerDll(ExeVersion#, 'CLAASC.DLL')  Or |
     CheckVerDll(ExeVersion#, 'CLATPS.DLL')  Or |
     CheckVerDll(ExeVersion#, 'CLADOS.DLL')  then Return.
3. И собственно сама процедура проверки (кто найдёт ошибку - тому спасибо !):

Код: Выделить всё

CheckVerDll          PROCEDURE  (Long xVersion_, String xDllName_, Byte xMess_ = 0)
Loc:RetValue         BYTE(False)
Loc:SubBlock         CSTRING('\')
Loc:puLen            ULONG(0)
Loc:Buffer           ULONG
Loc:verHandle        ULONG(0)
Loc:verSize          ULONG
Loc:verData          &STRING
Loc:verFile          CSTRING(256)

Loc:verInfo     Group
dwSignature         Long
dwStrucVersion      Long
dwFileVersionMS     Long
dwFileVersionLS     Long
dwProductVersionMS  Long
dwProductVersionLS  Long
dwFileFlagsMask     Long
dwFileFlags         Long
dwFileOS            Long
dwFileType          Long
dwFileSubtype       Long
dwFileDateMS        Long
dwFileDateLS        Long
                end                
  Code
  
  Loc:verFile = Command('0')  ! Получить папку EXE модуля (может отличаться от текущей папки работы)
  Loc:verFile = LongPath(xExtractFileName(Loc:verFile,1) & xExtractFileName(Loc:verFile,2) & xDllName_)

  Loc:verSize = WinGetFileVersionInfoSizeA(Loc:verFile, Loc:verHandle)

  If Loc:verSize > 0

     Loc:verData &= New(String(Loc:verSize))  ! Создаем буфер для загрузки

     If ~(Loc:verData &= NULL)                ! Если буфер удачно создан
        If WinGetFileVersionInfoA(Loc:verFile,0,Loc:verSize,Loc:verData) <> 0        ! Получить данные о версии
           If WinVerQueryValueA(Loc:verData,Loc:SubBlock,Loc:Buffer,Loc:puLen) <> 0  ! Получить адрес структуры версии
              If Loc:puLen = 52

                 Glo:memcpy(address(Loc:verInfo), Loc:Buffer, Loc:puLen)  ! Копируем кусок памяти в Loc:verInfo

                 If (Loc:verInfo.dwSignature = 0FEEF04BDh) and |  ! Проверка сигнатуры структуры версии
                    (Sub(LongToHex(Loc:verInfo.dwFileVersionLS,False),5,4) <> Sub(LongToHex(xVersion_,False),5,4))

                    Message('Нарушена целостность библиотек программы !|' & |
                            'Различные версии сборки EXE и DLL файлов программы.||' & |
                            LongPath(Command('0')) & '|Версия: 0x' & Sub(LongToHex(xVersion_,False),5,4)         & '  ( ' & |
                              Clip(Left(xVersion_)) & ' )||' & |
                            Loc:verFile  & '|Версия: 0x' & Sub(LongToHex(Loc:verInfo.dwFileVersionLS,False),5,4) & '  ( ' & |
                              Evaluate('0' & Sub(LongToHex(Loc:verInfo.dwFileVersionLS,False),5,4) & 'h') & ' )||'        & |
                            'Выполните пожалуйста переустановку программы.', 'У нас проблема',Icon:Exclamation,'&1. Закрыть')
                            
                    Loc:RetValue = True  ! Не совпадение версий DLL и EXE
                 end

                 ! Просмотр содержимого Loc:verInfo при отладке
                 !Message(Loc:verFile           & '||' & |
                 !        'Signature = '        & LongToHex(Loc:verInfo.dwSignature       , False) & '|' & |
                 !        'StrucVersion = '     & LongToHex(Loc:verInfo.dwStrucVersion    , False) & '|' & |
                 !        'FileVersionMS = '    & LongToHex(Loc:verInfo.dwFileVersionMS   , False) & '|' & |
                 !        'FileVersionLS = '    & LongToHex(Loc:verInfo.dwFileVersionLS   , False) & '|' & |
                 !        'ProductVersionMS = ' & LongToHex(Loc:verInfo.dwProductVersionMS, False) & '|' & |
                 !        'ProductVersionLS = ' & LongToHex(Loc:verInfo.dwProductVersionLS, False) & '|' & |
                 !        'FileFlagsMask = '    & LongToHex(Loc:verInfo.dwFileFlagsMask   , False) & '|' & |
                 !        'FileFlags = '        & LongToHex(Loc:verInfo.dwFileFlags       , False) & '|' & |
                 !        'FileOS = '           & LongToHex(Loc:verInfo.dwFileOS          , False) & '|' & |
                 !        'FileType = '         & LongToHex(Loc:verInfo.dwFileType        , False) & '|' & |
                 !        'FileSubtype = '      & LongToHex(Loc:verInfo.dwFileSubtype     , False) & '|' & |
                 !        'FileDateMS = '       & LongToHex(Loc:verInfo.dwFileDateMS      , False) & '|' & |
                 !        'FileDateLS = '       & LongToHex(Loc:verInfo.dwFileDateLS      , False))

              end  ! If Loc:puLen = 52
           end  ! If WinVerQueryValueA(
        elsIf xMess_ then Message('Ошибка WinGetFileVersionInfo !','У нас проблема',Icon:Exclamation,'&1. Закрыть')
        end  ! If WinGetFileVersionInfoA(

        Dispose(Loc:verData)
     end  ! If ~(Loc:verData &= NULL)

  elsIf xMess_ then Message('Ошибка GetFileVersionInfoSize !','У нас проблема',Icon:Exclamation,'&1. Закрыть')
  end  ! If Loc:verSize > 0

  Return Loc:RetValue
3.jpg

Целостность multi-DLL проекта

Добавлено: 05 Ноябрь 2021, 11:48
gopstop2007
Игорь Столяров писал(а): 04 Ноябрь 2021, 15:34 Пример контроля версий DLL Clarion (и не только).
Огромное спасибо за Ваш код. :ty:
Надеюсь у админа найдется возможность докинуть в FAQ

Целостность multi-DLL проекта

Добавлено: 05 Ноябрь 2021, 11:58
Игорь Столяров
gopstop2007 писал(а): 05 Ноябрь 2021, 11:48 Надеюсь у админа найдется возможность докинуть в FAQ
В разделе FAQ - ответы на базовые вопросы, а это что-то вроде игры в напёрстки с WinAPI ... ;)
Хотя, конечно, вызывает недоумение, почему SV считает, что работа приложения с разными версиями DLL - это нормально. :(
На мой субъективный взгляд, Run-Time должен проверять прилинковые DLL при запуске приложения и рубить запуск при
обнаружении "солянки сборной мясной" ... :) Что в общем-то и делает обсуждаемый пример ... :)

Целостность multi-DLL проекта

Добавлено: 05 Ноябрь 2021, 15:35
kreator
Я помню времена, когда как раз dll разных сборок работали, а одной нет. Если у SV было бы всё чётко, то да. А так косячат не по-детски. Другое дело свои dll. А есть ещё сторонние dll. Совершенно не базовый вопрос, ИМХО.

Целостность multi-DLL проекта

Добавлено: 05 Ноябрь 2021, 16:01
Игорь Столяров
kreator писал(а): 05 Ноябрь 2021, 15:35 Если у SV было бы всё чётко, то да
Я часто читаю на ClarionHUB советы вернуть какую-то DLL из прошлого релиза или наоборот, подсунуть из нового.
Есть просто знатные купажисты, работающие методом тыка ... но проблема в том, что Clarion - это не OpenSource.
Фиг его знает, что изменено в версиях на самом деле и где это вылезет. Я против таких слепых замесов. :(
Возможные результаты - см. в первом сообщении этой темы. ;)

Целостность multi-DLL проекта

Добавлено: 09 Ноябрь 2021, 19:57
Игорь Столяров
Если эта тема кому-нибудь интересна, то здесь можно усугубить.
Вот такая функция позволяет построить список используемых компонентов проекта, как в серьёзный программах. ;)

Код: Выделить всё

GetVerDll            PROCEDURE  (String xDllName_,Byte xMess_ = 0)  ! ,Byte
Loc:RetValue         BYTE(False)
Loc:SubBlock         CSTRING(256)
Loc:puLen            ULONG(0)
Loc:Buffer           ULONG
Loc:verHandle        ULONG(0)
Loc:verSize          ULONG
Loc:verData          &STRING
Loc:verFile          CSTRING(256)
Loc:LTmp             ULONG
Loc:LangCharset      STRING(8)
Loc:verInfo          CSTRING(256),DIM(2,8)
Loc:Count            BYTE

  Code
  Loc:verFile = Command('0')
  Loc:verFile = LongPath(xExtractFileName(Loc:verFile,1) & xExtractFileName(Loc:verFile,2) & xDllName_)

  Loc:verSize = WinGetFileVersionInfoSizeA(Loc:verFile, Loc:verHandle)

  If Loc:verSize > 0

     Loc:verData &= New(String(Loc:verSize))  ! Создаем буфер для загрузки

     If ~(Loc:verData &= NULL)                ! Если буфер удачно создан
        If WinGetFileVersionInfoA(Loc:verFile,0,Loc:verSize,Loc:verData) <> 0        ! Получить данные о версии

           Loc:SubBlock = '\VarFileInfo\Translation'
           If WinVerQueryValueA(Loc:verData,Loc:SubBlock,Loc:Buffer,Loc:puLen) <> 0  ! Получить структуру версии

              If Loc:puLen = 4  ! Размер буфера 4 byte

                 Glo:memcpy(address(Loc:LTmp), Loc:Buffer, Loc:puLen)
                 Loc:LangCharset = LongToHex(Loc:LTmp,False)
                 Loc:LangCharset = Loc:LangCharset[5:8] & Loc:LangCharset[1:4]

                 Loop Loc:Count = 1 to 8 by 1

                   Loc:verInfo[1,(Loc:Count)] = Choose(Loc:Count,'CompanyName',      |
                                                                 'FileDescription',  |
                                                                 'FileVersion',      |
                                                                 'InternalName',     |
                                                                 'LegalCopyright',   |
                                                                 'OriginalFileName', |
                                                                 'ProductName',      |
                                                                 'ProductVersion')

                   Loc:SubBlock = '\StringFileInfo\' & Loc:LangCharset & '\' & Loc:verInfo[1,(Loc:Count)]

                   If WinVerQueryValueA(Loc:verData,Loc:SubBlock,Loc:Buffer,Loc:puLen) <> 0

                      If Loc:puLen <= Size(Loc:verInfo[2,(Loc:Count)])
                         Glo:memcpy(address(Loc:verInfo[2,(Loc:Count)]), Loc:Buffer, Loc:puLen)
                      else
                         Loc:verInfo[2,(Loc:Count)] = 'Превышение размера: ' & Clip(Left(Loc:puLen))
                      end
                   end  ! If WinVerQueryValueA(
                 end  ! Loop Loc:Count = 1 to 8 by 1

                 Message(Loc:verFile      & '||' & |
                         Loc:verInfo[1,1] & ' = ' & Loc:verInfo[2,1] & '|' & |
                         Loc:verInfo[1,2] & ' = ' & Loc:verInfo[2,2] & '|' & |
                         Loc:verInfo[1,3] & ' = ' & Loc:verInfo[2,3] & '|' & |
                         Loc:verInfo[1,4] & ' = ' & Loc:verInfo[2,4] & '|' & |
                         Loc:verInfo[1,5] & ' = ' & Loc:verInfo[2,5] & '|' & |
                         Loc:verInfo[1,6] & ' = ' & Loc:verInfo[2,6] & '|' & |
                         Loc:verInfo[1,7] & ' = ' & Loc:verInfo[2,7] & '|' & |
                         Loc:verInfo[1,8] & ' = ' & Loc:verInfo[2,8])
                      
              end  ! If Loc:puLen = 4
           end  ! If WinVerQueryValueA(

        elsIf xMess_ then Message('Ошибка WinGetFileVersionInfo !','У нас проблема',Icon:Exclamation,'&1. Закрыть')
        end  ! If WinGetFileVersionInfoA(

        Dispose(Loc:verData)
     end  ! If ~(Loc:verData &= NULL)

  elsIf xMess_ then Message('Ошибка GetFileVersionInfoSize !','У нас проблема',Icon:Exclamation,'&1. Закрыть')
  end  ! If Loc:verSize > 0

  Return Loc:RetValue  ! Потом вернём успешность выполнения
1.jpg
2.jpg

P/S: По прежнему готов выпить пива за здоровье того, кто видит в этом коде ошибку. 8)