PNG/ICO/CUR/ANI изображения в стандартных контролах VB6.

Тема в разделе "VB", создана пользователем Thetrik, 10 фев 2019.

  1. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    860
    Не поленился. Посмотрел на небольшом семпле:
    Код (Text):
    1. Private Sub UserForm_Click()
    2.     Dim z As Long
    3.  
    4.     For z = 0 To 10
    5.         ListBox1.AddItem z
    6.     Next
    7.  
    8. End Sub
    Проверяем P-код для этой функции в 2003 ворде:
    Код (Text):
    1.  
    2. 00 02 00 15 F5 00 00 00 00 04 78 FF F5 0A 00 00
    3. 00 FE 64 70 FF 45 00 00 24 27 3C FF 04 78 FF 4D
    4. 5C FF 03 40 04 6C FF 21 0D 90 01 00 00 08 6C FF
    5. 0D 48 02 01 00 1A 6C FF 35 3C FF 00 0A 04 78 FF
    6. 66 70 FF 17 00 00 00 13
    Проверяем в 2010:
    Код (Text):
    1.  
    2. 00 02 00 15 F5 00 00 00 00 04 78 FF F5 0A 00 00
    3. 00 FE 64 70 FF 45 00 00 24 27 3C FF 04 78 FF 4D
    4. 5C FF 03 40 04 6C FF 21 0D 90 01 00 00 08 6C FF
    5. 0D 48 02 01 00 1A 6C FF 35 3C FF 00 0A 04 78 FF
    6. 66 70 FF 17 00 00 00 13
    Никаких глобальных изменений нет. Конечно это простой семпл, но как видно глобальных изменений в структуре p-кода нет (те же самые 1-2-х байтные опкоды и данные). Я конечно допускаю что новые p-коды возможно и добавляются, но что ломают старые - я сомневаюсь (конечно если дело не касается каких-то дыр).

    Хорошо, если можешь приведи пример несовместимых пи-кодов, в одной версии он делал одно, в другой другое (не x64 версии).

    Ну и? Любой in-proc сервер к примеру исполняется в контексте какого-то хост процесса. От этого он лишается интеграции с COM? Я изначально говорил что нет другого такого ЯП с такой COM ориентированностью/интеграцией.

    Ну COM ориентированность от этого ни куда не уходит. В VBA или VBS класс как был COM-классом так он и остался, как ты его подсоединишь к другим это уже детали реализации. Делать динамическую библиотеку на VBA - это вообще бессмысленно и невозможно, но пользоваться COM объектами of VBA - никто не запрещает. Тоже самое и в вбс. Что ты ожидаешь увидеть в реестре вместо длл? Путь к скрипту? Ну это нонсенс. Мы говорим о технологии, о том что VBA/VBS/VB6 - это одна технология, под технологией я уже выше написал что подразумевается.

    Ну это вообще не проблема для COM, есть же OBJREF моникеры.

    Ничего не нужно, объекты сами декрементируют счетчики при выходе из процедуры. Option Explicit тут вообще не причем. При использовании голого API тебе и в дотнете придется закрывать все руками (ну там хендлы и т.п.), если не инкапсулировать все в классы, тогда ресурсы автоматом в деструкторе освобождаются детерминированно.

    Да, объект может держать открытые файлы и т.п. которые я намериваюсь использовать после освобождения объекта.

    Да причем тут GC.Collect? Я вообще из чистого C юзаю твои объекты, я следую только правилам COM, как и множество COM вещей в винде. Создал какой-нить стрим на базе файла с помощью твоего дотнетовского COM класса, поработал - хочу удалить, вызываю Release. А файл блокирован. Это хорошо что я могу запросить IDisposable и принудительно перед Release вызвать Dispose, но что если мы уже имеем скомпилированное приложение которое уже работает а нам нужно к нему плагин такой написать?

    Нет, проблема как раз с высвобождением ресурсов:
    Ну и циклические ссылки тоже не так часто используются, а где используются там они разрешаются по разному в том числе и через слабые ссылки.
     
  2. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.241
    это надо качать разные версии офисов и ставить их на виртуалки, никакой спор в интернетах не стоит таких усилий))...

    да, но не в контексте моего процесса, процесса в котором я его инициализирую...

    ну чисто формально есть registration free com, который может быть подгружен по манифесту, а в манифесте может быть путь к скрипту... ну и опять же чисто формально дотнетовские ком объекты регистрируются в реестре, как библиотека mscoree.dll и дополнительный путь к DLL или EXE файлу дотнетовского COM-объекта... и система это нормально воспринимает...

    ну окей, это интересно, можешь мне поподробнее расписать, как мне создать COM-объект на VBS, и как его зарегать правильно, чтобы он был доступен по DCOM с другой машины? мне интересно попробовать... я правильно понимаю, что для вызова через DCOM объекта необходимо, чтобы он был зарегистрирован на обеих машинах, на клиенте и на сервере?

    при этом в интернетах их рекомендуют принудительно выставлять в nothing...

    ну так какие проблемы, я не понимаю, я же говорил уже про using стейтмент:
    Код (Text):
    1.  
    2. using(var fil = new FileStream(/* ... */)) {
    3.     // Хендл файла открыт здесь
    4. }
    5. // Хендл файла закрыт здесь, детерминированно
    6. // даже если в блоке произошло исключение
    7.  
    если ты нормально программироуешь свой COM-объект на дотнете, то у тебя нет проблем со сборщиком мусора...

    нет никаких проблем с освобождением ресурсов, если ты программируешь нормально...

    да, но для этого программист должен знать про циклы в принципе и про слабые ссылки... GC решает эту проблема автоматически...
     
  3. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    860
    Ну вообще-то необязательно. Как ты собираешься к примеру 32 битную ActX Dll использовать в 64 битном приложении (и на оборот)? COM это позволяет.

    К примеру in-proc сервер зарегистрированный в реестре/через reg-free должен быть исполняемым файлом, и иметь предопределенный набор предопределенных функций (DllGetClassObject/DllCanUnloadNow...) которые и обеспечивают возможность породить объект. Для реализации в скрипте нужно колхозить новый метод, ну и траблы с регистрацией и т.п.

    Ну вот пример (для создания моникера и пампа используется VB6 т.к. API недоступно из скриптов, для вба это не нужно):
    Код (Text):
    1. Option Explicit
    2.  
    3. Private m_bRunning  As Boolean
    4.  
    5. Public Function RegisterObject( _
    6.                 ByVal cObj As Object) As String
    7.     Dim cMoniker    As IMoniker
    8.     Dim cBind       As IBindCtx
    9.     Dim pStr        As Long
    10.    
    11.     Set cBind = CreateBindCtx()
    12.     Set cMoniker = CreateObjrefMoniker(cObj)
    13.    
    14.     cMoniker.GetDisplayName ObjPtr(cBind), 0, pStr
    15.    
    16.     RegisterObject = SysAllocString(pStr)
    17.    
    18.     CoGetMalloc(1).Free pStr
    19.    
    20. End Function
    21.  
    22. Public Sub Pump()
    23.     Dim tMsg    As Win32.MSG
    24.     Dim lRet    As Long
    25.    
    26.     m_bRunning = True
    27.    
    28.     Do While m_bRunning
    29.        
    30.         lRet = GetMessage(tMsg, 0, 0, 0)
    31.         If lRet = -1 Or lRet = 0 Then Exit Do
    32.        
    33.         TranslateMessage tMsg
    34.         DispatchMessage tMsg
    35.        
    36.     Loop
    37.    
    38. End Sub
    39.  
    40. Public Sub Unregister()
    41.     m_bRunning = False
    42. End Sub
    Код (Text):
    1. Dim cReg
    2. Dim cFso
    3. Dim cFile
    4. Dim cShObj
    5.  
    6. ' // Создаем регистратор
    7. Set cReg = CreateObject("CVBSRegistrator.CRegistrator")
    8. ' // Создаем текстовый файл с данными регистрации
    9. Set cFso = CreateObject("Scripting.FileSystemObject")
    10. Set cFile = cFso.CreateTextFile("moniker.txt")
    11. ' // Создаем наш расшаренный объект
    12. Set cShObj = New CShared
    13.  
    14. ' // Регистрируем его
    15. cFile.Write cReg.RegisterObject(cShObj)
    16.  
    17. Set cFile = Nothing
    18. Set cFso = Nothing
    19.  
    20. ' // Запускаем памп. (можно просто вызвать к примеру MsgBox)
    21. cReg.Pump
    22.  
    23. Class CShared
    24.  
    25.     Public Sub Quit()
    26.     ' // Выход из пампа
    27.         cReg.Unregister
    28.     End Sub
    29.    
    30.     Public Sub ShowMessage(sTest)
    31.     ' // Показать сообщение
    32.         MsgBox(sTest)
    33.     End Sub
    34. End Class
    Запускаем этот "сервер" и в папке появляется файл с текстом, его можно передать на целевую машину чтобы она могла коннектится к серверу:
    upload_2019-2-14_20-4-12.png

    Для примера, запускаем другую машину и из VB6 делаем GetObject с этим моникером, все можем вызывать удаленно методы:
    Код (Text):
    1. Dim z As Object
    2.    
    3. Set z = GetObject("objref:xxxx")
    4.    
    5. z.ShowMessage "Hello Rel!"
    6.    
    7. z.quit
    upload_2019-2-14_20-5-27.png

    На целевой машине вызывается метод VBS объекта:

    upload_2019-2-14_20-6-22.png

    Также все корректно, освобождается.

    Это равносильно вызову Release при использовании CComPtr в плюсах - абсолютно не имеет смысла, но и ничего плохого не происходит, другое дело - хороший стиль.

    Смотри, приведу сценарий, ты меня не понимаешь либо я что-то не пойму:
    Есть COM либа которая олицетворяет некий архив, в ней есть класс CArch. Данная библиотека написана на дотнете.
    Из клиентского кода я вызываю CArch::Open, код открывает файл архива;
    Я читаю/пишу туда файл открыт на монопольный доступ чтобы никто не мог модифицировать файл;
    Я удаляю COM объект. Файл должен освободится, т.к. я хочу зашифровать его к примеру.
    По правилам COM после того как последняя ссылка на объект освобождена, объект удаляется, но в твоем случае это не так и файл по прежнему заблокирован пока сборщик мусора не вызовет финализатор.

    Ну решения так до сих пор нет.

    Ценой недетерминированного освобождения? В некоторых случаях это неприемлимо.