Програмування на VB6 (FAQ), Різне, Програмні керівництва, статті

 

FAQ (червень-липень 2003)

 

Даний матеріал наданий журналом CODE


 


Програмування на VB6


 


Q. Чи можу я у своїй програмі використовувати процедури написані на інших мовах програмування не включаючи їх в DLL або ActiveX контрол?


 


G.M. Досить дивне питання і я на жаль, не зміг отримати уточнення. Сподіваюся, що Ви, прочитавши ці рядки, напишете мені, і я зможу відповісти на поставлене вами питання.


Але, так чи інакше, я задався метою дослідити поставлену задачу, в результаті чого я виявив один нетривіальний спосіб використання вже скомпільованих функцій, написаних на мові Assembler. Цей метод був знайдений мною у роботі clsASMpic 1.0 на сайті www.pscode.com. Код на мові асемблера написаний Робертом Рейментом (Robert Rayment).


Суть методу полягає в тому, щоб зберігати вже скомпільований код у вигляді константи. Яким чином це реалізується? Нижче приведена змінена мною витримка з коду з моїми поясненнями.









Лістинг – приклад використання збережених функцій


Private Const ASMCode As String = “5589E581EC780000005756538B5D0 …” ‘Шістнадцяткове значення сильно скорочено з метою економії місця


Call LoadMCodeFromString (MyFunc, ASMCode) ‘виклик функції перетворення


‘Так як VB за замовчуванням передає параметри ByRef – ми отримуємо масив MyFunc


Private Function LoadMCodeFromString(asm_code_ARRAY() As Byte, MCODE As String)


    Dim i As Long, aSize As Long


aSize = Len (MCODE) “розмір коду


Debug.Assert Not aSize And 1 “число не може бути парним


    aSize = aSize 2


ReDim Preserve asm_code_ARRAY (0 To aSize – 1) “готуємо масив


    For i = 0 To aSize – 1


asm_code_ARRAY (i) = Val (“& H” & Mid $ (MCODE, i * 2 + 1, 2)) “створюємо масив


    Next


End Function


ptMf = VarPtr (MyFunc (0)) “отримуємо адресу першого елемента, він же і буде адресою нашої процедури


CallWindowProc pMf, … параметри



Як ви можете переконатися – рішення вельми елегантно. Строкова змінна містить код, який потім завантажується в пам’ять у вигляді масиву байтів. Для отримання адреси процедури використовується вбудована функція VB – VarPtr – повертає покажчик на змінну. І звичайний дзвінок за допомогою Win API – CallWindowProc.


Докладніше ви можете розглянути цей приклад на сайті www.pscode.com.


 


 


Q. У моїй програмі я використовую CommonControls. Для підтримки візуальних стилів WindowsXP я додаю до свого e xe файлу – файл exe. manifest. Програма дійсно відображається в стилі XP, але чомусь всі c heck і option зафарбовані чорним кольором. Як цього уникнути?


 


G.M. Щоб ці елементи відображалися на формі в WindowsXP так, якими ви хочете їх бачити досить помістити їх на який-небудь контрол-контейнер, наприклад Frame або Picture.


Q. Як можна дописати в скомпільований exe файл якусь інформацію, так щоб він продовжував запускатися як завжди? І взагалі, чи можна це зробити.


 


G.M. Можна. Дійсно, будь-які записана в кінець exe файлу дані будуть ігноруватися завантажувачем ОС, тому ви можете вільно писати і читати додані дані, за умови, що, він доступний на читання і запис. Наведу простий приклад – ми маємо exe файл певного розміру (відомий заздалегідь) та іншу програму з формою, текстовим полем і кнопкою. Вміст файлу, який ми будемо використовувати як сховище даних, нас не цікавить.









Лістинг form1.frm


Private Sub Command1_Click()


Dim f As Integer


f = FreeFile “отримуємо вільний id


Open “test.exe” For Binary As # f “відкриваємо файл


Put # f, file_size, Text1.Text “Розміщуємо вміст Text1 в кінець файлу


Close #f


End Sub


Тепер відкрийте файл будь-яким редактором і подивіться в його кінець. Ви побачите саме той текст, який був введений в поле Text1. Тепер подвійним клацанням запустите файл – ви переконаєтеся в його працездатності.


Q. Як отримати інформацію про PE файлі з VB? Тобто прочитати заголовки і отримати потрібну інформацію?


 


G.M. Для цього необхідно оголосити відповідні типи, що описують PE заголовки і заповнити їх даними з відкритого файлу. Для прикладу наведу код отримує дані з DOSHEADER і NTHEADER.


Оголошення відповідних структур:









Код для модуля


Public Type IMAGEDOSHEADER


    e_magic As String * 2


    e_cblp As Integer


    e_cp As Integer


    e_crlc As Integer


    e_cparhdr As Integer


    e_minalloc As Integer


    e_maxalloc As Integer


    e_ss As Integer


    e_sp As Integer


    e_csum As Integer


    e_ip As Integer


    e_cs As Integer


    e_lfarlc As Integer


    e_ovno As Integer


    e_res(1 To 4) As Integer


    e_oemid As Integer


    e_oeminfo As Integer


    e_res2(1 To 10)    As Integer


    e_lfanew As Long


End Type


Public Type IMAGE_FILE_HEADER


    Machine As Integer


    NumberOfSections As Integer


    TimeDateStamp As Long


    PointerToSymbolTable As Long


    NumberOfSymbols As Long


    SizeOfOptionalHeader As Integer


    Characteristics As Integer


End Type


Public Type IMAGE_DATA_DIRECTORY


    VirtualAddress As Long


    size As Long


End Type


Public Type IMAGE_OPTIONAL_HEADER


    Magic As Integer


    MajorLinkerVersion As Byte


    MinorLinkerVersion As Byte


    SizeOfCode As Long


    SizeOfInitializedData As Long


    SizeOfUninitializedData As Long


    AddressOfEntryPoint As Long


    BaseOfCode As Long


    BaseOfData As Long


    ImageBase As Long


    SectionAlignment As Long


    FileAlignment As Long


    MajorOperatingSystemVersion As Integer


    MinorOperatingSystemVersion As Integer


    MajorImageVersion As Integer


    MinorImageVersion As Integer


    MajorSubsystemVersion As Integer


    MinorSubsystemVersion As Integer


    Win32VersionValue As Long


    SizeOfImage As Long


    SizeOfHeaders As Long


    CheckSum As Long


    Subsystem As Integer


    DllCharacteristics As Integer


    SizeOfStackReserve As Long


    SizeOfStackCommit As Long


    SizeOfHeapReserve As Long


    SizeOfHeapCommit As Long


    LoaderFlags As Long


    NumberOfRvaAndSizes As Long


    DataDirectory(0 To 15) As IMAGE_DATA_DIRECTORY


End Type


Public Type IMAGE_NT_HEADERS


    Signature As String * 4


    FileHeader As IMAGE_FILE_HEADER


    OptionalHeader As IMAGE_OPTIONAL_HEADER


End Type


“Відповідні змінні


Public DOSHEADER As IMAGEDOSHEADER


Public NTHEADER As IMAGE_NT_HEADERS


‘Нам знадобиться ця функція для копіювання даних в структури


Public Declare Sub CopyMemory Lib “kernel32” Alias “RtlMoveMemory” _


(pDst As Any, pSrc As Any, ByVal ByteLen As Long)


Прочитаємо вміст файлу в масив бінарних даних:









Код для процедури у формі


Dim PEDATA() As Byte


Dim fH As Long


fH = FreeFile “Краще отримувати вільне значення, ніж використовувати число, наприклад 1


Open “c: winntexplorer.exe” For Binary As # fH ‘Не забудьте виправити шлях


ReDim PEDATA (LOF (fH) – 1) “Визначаємо розмір масиву під дані


Get # fH,, PEDATA “Прочитуємо файл


Close #fH


CopyMemory DOSHEADER, DATA(CNT), Len(DOSHEADER)


CopyMemory NTHEADER, DATA(DOSHEADER.e_lfanew), Len(NTHEADER)


‘Всі дані завантажені, тепер можна отримувати будь-яку інформацію


MsgBox “Machine: ” & NTHEADER.FileHeader.Machine & vbCrLf & _


“Minor OS Version: ” & _


NTHEADER.OptionalHeader.MinorOperatingSystemVersion & vbCrLf & _


“Signature: ” & NTHEADER.Signature


У загальному випадку, цей метод підходить для будь-якого файлу, що описується відповідними йому структурами, приватним випадком якого є файл формату PE. В якості вправи рекомендую взяти опис будь-якого формату, наприклад ICO, і спробувати отримати дані з файлів в директорії Windows.


Web – програмування


 


Q. У своєму додатку я використовую глобальну змінну $ _SESSION, де зберігаю дані користувацьких сеансів. Чи не може зломщик передати її вміст у рядку GET запиту?


 


G.M. Подібні питання простіше вирішити самостійно протестувавши свій додаток. Я розумію, що ввело вас в оману. Щоб показати, що ваші побоювання марні, розглянемо такі два приклади. Створимо просте додаток, що виводить вміст змінної в броузер.









Лістинг test1.php


<?


echo @$_SESSION[‘test’];


?>


Запустимо цю програму і передавши подібний GET запит: / test1.php? _SESSION [Test] = Hi. Ви можете переконатися, що він проходить і програма виводить очікуване слово “Hi”. Можливо, що саме це вас і збентежило. Але тепер розглянемо інший приклад:









Лістинг test2.php


<?


session_start();


echo @$_SESSION[‘test’];


?>


Тепер, скільки б ми не натискали Refresh (‘Оновити’) в броузері, придумуючи самі неймовірні GET запити з варіаціями на тему передачі вмісту в $ _SESSION, та й будь-яку іншу подібну зміну, нічого не вийде. Можете спати спокійно, автори PHP передбачили таку маленьку хитрість.


Q. У моєму сценарії на PHP 4.0 обробляється форма містить прапорці вибору. Проблема полягає в тому, що значення передається сценарієм тільки тоді, коли прапорець вибраний. Але хотілося б отримати значення і тоді, коли прапорець не вибраний. Як вирішити це завдання?


G.M. Просто. Так як броузер відправляє значення value прапорця лише якщо він обраний, то можна перед самим елементом checkbox помістити елемент hidden з тим самим значенням name. При цьому, якщо прапорець буде обраний користувачем, то значення цієї змінної візьме вказане в value значення checkbox – PHP підставить змінної $ check1 останнє значення в запиті (GET або POST).









Лістинг form.html


<form action=’test.php’>


  <input type=’hidden’ name=’check1’ value=’0’>


  <input type=’checkbox’ name=’check1’ value=’1’>


<input type=’submit’ name=’submit’ value=’submit’>


</form>



Q. Мені необхідно отримати в моєму сценарії вміст сторінки видається програмою, розташованим на віддаленому хості при передачі йому параметрів. Наприклад: myhost/index.php?page=1.


 


G.M. Завдяки тому, що в PHP передбачена робота з віддаленими файлами так само, як якби вони були розташовані на вашому хості, то можна легко отримати відповідь програми з віддаленого хоста:









Лістинг get_remote_page.php


<?


$content = join(“”, file(“http://vbstreets/index.php?page=news”));


echo $content;


?>


Проектування


 


Q. Чи допоможе популярності нашого веб-сайту оригінальний і нестандартний дизайн. Відмова від стандартних форм?


 


G.M. Як це зазвичай буває – у медалі дві сторони. На перший погляд – оригінальності і нестандартність дизайну безумовно приверне увагу користувачів, але за статистикою, якщо користувач протягом короткого часу не зможе розібратися з тим, як працюють веб-додатки на вашому сайті – він покине ваш ресурс. Тому необхідно знайти оптимальне рішення – поєднати нестандартність і простоту роботи. Уявіть себе початківцям користувачем Інтернету, знайомим лише з простими Windows додатками і не бажає вникати в тонкощі вашого підходу. Оцініть свій ресурс, представивши себе на його місці.


Q. Що краще – використання стандартних елементів веб-форм або використання власних ActiveX елементів і Java аплетів?


G.M. На мій погляд, використання ActiveX і Java, звичайно, сильно розширює функціональність ваших веб-додатків і характеризує ресурс як створений професійними програмістами, але з іншого боку вимагає від клієнта завантаження контролів і апетит і виконання їх. При цьому слід врахувати, що клієнт може мати сильно застарілим «залізом» і «софтом», що зведе всі ваші зусилля нанівець. Особисто я намагаюся використовувати простий HTML скрізь, де це можливо.


Q. Наскільки вигідно використовувати в своїх програмах компоненти, розроблені за принципом «відкритого коду»?


 


G.M. Все залежить від того, яку мету ви переслідуєте. На мою особисту досвіду в подібних компонентах досить часто зустрічаються важко виправні помилки. Тому перш ніж приймати подібне ПО в розгляд – Пройдіть всі етапи тестування і оціните наскільки трудомістким зміна виявлених помилок і приведення до необхідного вам увазі. Зазвичай дуже важко переконати менеджера (або, як це зараз модно, архітектора) проекту, що використання open source компонентів допоможе скоротити витрати на розробку.


Q. Чи необхідна сайту система керування вмістом?


 


G.M. Перш за все подумайте, чи варто на вашому сайті розміщувати подібну систему? Я можу навести кілька варіантів, коли використання такої системи сильно полегшить підтримку ресурсу:


1. Сайт являє собою часто оновлюваний інформаційний портал з великою кількістю інформації


2. Сайт розробляється більш ніж однією людиною – щоб вміст було структуровано, то необхідно розробити правила публікації, або використовувати єдину систему управління контентом.


Якщо ж це домашня сторінка або «візитна картка» – сайти на яких інформація оновлюється вкрай рідко, то установка такої системи невиправдана – ви витратите більше часу на установку, настройку та обслуговування системи.


Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*