Создать по CLSID

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
SSecurity
Служба безопасности
Аватара пользователя
 
Сообщения: 1283
Зарегистрирован: 19.08.2003 (Вт) 1:11
Откуда: Россия, Мурманск

Создать по CLSID

Сообщение SSecurity » 13.03.2009 (Пт) 10:42

Добрый день, уважаемые форумчане!

Теребит меня такой интересный вопрос, как создать экземпляр объекта при позднем связывании зная его CLSID. Воспользовавшись поиском нашел тему, из которой построил модуль, который не очень работать хочет:)

Код: Выделить всё
Option Explicit
Private Type GUID
    Data1 As Long
    Data2 As Long
    Data3 As Long
    Data4 As Long
    Data5(5) As Byte
End Type
Private Declare Sub CoCreateInstance Lib "ole32" (rclsid As GUID, ByVal pUnkOuter As IUnknown, ByVal dwClsContext As Long, riid As GUID, ppv As Object)

Private Function CreateObjectFromCLSID(CLSID As GUID) As IUnknown
    Dim IID_Unknown As GUID
    'IID_Unknown = CLSID
    IID_Unknown.Data4 = CLSID.Data4
    IID_Unknown.Data5(5) = CLSID.Data5(5)
    CoCreateInstance CLSID, Nothing, 5, IID_Unknown, CreateObjectFromCLSID
End Function

Function CreateObjectEx(ByVal Data As String) As Object
    On Error Resume Next
    Dim wa As Object, WordCLSID As GUID
    Dim tmp() As String
    Dim I As Byte
   
    Set CreateObjectEx = Nothing
    tmp = Split(Replace$(Replace$(Data, "{", ""), "}", ""), "-")
    If UBound(tmp) <> 4 Then Exit Function
    WordCLSID.Data1 = CDec("&h" & tmp(0))
    WordCLSID.Data2 = CDec("&h" & tmp(1))
    WordCLSID.Data3 = CDec("&h" & tmp(2))
    WordCLSID.Data4 = CDec("&h" & tmp(3))
    If Len(tmp(4)) <> 12 Then Exit Function
    For I = 0 To 5
      WordCLSID.Data5(I) = CDec("&h" & Mid$(tmp(4), I * 2 + 1, 2))
    Next I
    Set CreateObjectEx = CreateObjectFromCLSID(WordCLSID)
End Function


тестировал на самописном ActiveX Control'е - экземпляр создается и управляется, при тестировании на Тёмычевской :) (прошу прощения) обёртке к GDI+ результат CreateObjectEx Is Nothing :)

синтаксис проверки такой

Код: Выделить всё
Sub CheckThis()
  On error resume next
  Dim X as object
  Set X = CreateObjectEx("{6ACDABF7-4CAC-46CA-82C8-2A251E677080}")
  Debug.Print "по CLSID: " & IIF(X is Nothing, "не создалось:(","создалось чё-та")
  Set X = Nothing
  Set X = CreateObject("prjGDIplus.Global")
  Debug.Print "по PROGID: " & IIF(X is Nothing, "не создалось:(","создалось чё-та")
  Set X = Nothing
End Sub


Пожалуйста, подскажите как правильнее создавать объект по CLSID .. а то неуникальность PROGID мешается:)

Заранее благодарен за ответы...

С Уважением,
Сергей
Программист - это маленький Бог, а все его ошибки - это самостоятельные творения:)
Так задумано:)

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16489
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Создать по CLSID

Сообщение Хакер » 13.03.2009 (Пт) 11:22

как создать экземпляр объекта при позднем связывании зная его CLSID

Зачем упоминать "позднее связывание"? Это какое-то массовое заблуждение, мне кажется: народ думает, что есть какая-то связь между поздним/ранним связыванием и тем, каким способом создаётся объект. А связи никакой.

Во-первых, чем для создания объекта по CLSID тебя не устраивает New?

Во-вторых, должно быть не
Код: Выделить всё
Private Type GUID
    Data1 As Long
    Data2 As Long
    Data3 As Long
    Data4 As Long
    Data5(5) As Byte
End Type

а
Код: Выделить всё
Public Type T_UUID
    data1               As Long
    data2               As Integer
    data3               As Integer
    data4(7)            As Byte
End Type


В-третьих, вот это какой-то бред:
Код: Выделить всё
    IID_Unknown.Data4 = CLSID.Data4
    IID_Unknown.Data5(5) = CLSID.Data5(5)

Должно быть так:
Код: Выделить всё
.data4(0) = &HC0
.data4(7) = &H46


В-четвыртых:
Set CreateObjectEx = Nothing

Нафиг не надо. Компилятор, вобщем-то, всё равно уберёт.

В-пятых:
Код: Выделить всё
    tmp = Split(Replace$(Replace$(Data, "{", ""), "}", ""), "-")
    If UBound(tmp) <> 4 Then Exit Function
    WordCLSID.Data1 = CDec("&h" & tmp(0))
    WordCLSID.Data2 = CDec("&h" & tmp(1))
    WordCLSID.Data3 = CDec("&h" & tmp(2))
    WordCLSID.Data4 = CDec("&h" & tmp(3))
    If Len(tmp(4)) <> 12 Then Exit Function
    For I = 0 To 5
      WordCLSID.Data5(I) = CDec("&h" & Mid$(tmp(4), I * 2 + 1, 2))
    Next I

Это кошмар. Мало того, что оно совершенно неправильное, так даже если бы было правильным: для этой цели есть функция CLSIDFromString.

В-шестых:
А зачем хранить CLSID-ы в виде строк?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

SSecurity
Служба безопасности
Аватара пользователя
 
Сообщения: 1283
Зарегистрирован: 19.08.2003 (Вт) 1:11
Откуда: Россия, Мурманск

Re: Создать по CLSID

Сообщение SSecurity » 13.03.2009 (Пт) 11:39

Хакер писал(а):
как создать экземпляр объекта при позднем связывании зная его CLSID

Зачем упоминать "позднее связывание"? Это какое-то массовое заблуждение, мне кажется: народ думает, что есть какая-то связь между поздним/ранним связыванием и тем, каким способом создаётся объект. А связи никакой.

потому что в референсах я ничего не пишу и при запуске программа вообще не подозревает что будет использовать а потом узнает :)

Хакер писал(а):Во-первых, чем для создания объекта по CLSID тебя не устраивает New?

Пример можно посмотреть?

Хакер писал(а):Во-вторых, должно быть не
Код: Выделить всё
Private Type GUID
    Data1 As Long
    Data2 As Long
    Data3 As Long
    Data4 As Long
    Data5(5) As Byte
End Type

а
Код: Выделить всё
Public Type T_UUID
    data1               As Long
    data2               As Integer
    data3               As Integer
    data4(7)            As Byte
End Type


брал отсюда и все работало
viewtopic.php?f=49&t=26330&p=6612863&hilit=clsid#p6612948

Хакер писал(а):В-третьих, вот это какой-то бред:
Код: Выделить всё
    IID_Unknown.Data4 = CLSID.Data4
    IID_Unknown.Data5(5) = CLSID.Data5(5)

Должно быть так:
Код: Выделить всё
.data4(0) = &HC0
.data4(7) = &H46


это применительно к моему коду :))) по темычевским мотивам

Хакер писал(а):В-четвыртых:
Set CreateObjectEx = Nothing

Нафиг не надо. Компилятор, вобщем-то, всё равно уберёт.

Для меня полезнее знать ...


Хакер писал(а):В-пятых:
Код: Выделить всё
    tmp = Split(Replace$(Replace$(Data, "{", ""), "}", ""), "-")
    If UBound(tmp) <> 4 Then Exit Function
    WordCLSID.Data1 = CDec("&h" & tmp(0))
    WordCLSID.Data2 = CDec("&h" & tmp(1))
    WordCLSID.Data3 = CDec("&h" & tmp(2))
    WordCLSID.Data4 = CDec("&h" & tmp(3))
    If Len(tmp(4)) <> 12 Then Exit Function
    For I = 0 To 5
      WordCLSID.Data5(I) = CDec("&h" & Mid$(tmp(4), I * 2 + 1, 2))
    Next I

Это кошмар. Мало того, что оно совершенно неправильное, так даже если бы было правильным: для этой цели есть функция CLSIDFromString.

про функцию спасибо ... что подсказал ... посмотрю использование ... но в рамках ранее созданного примера работало :)

Хакер писал(а):В-шестых:
А зачем хранить CLSID-ы в виде строк?

[/quote]
потому что они ко мне приходят строками ... по сети
Программист - это маленький Бог, а все его ошибки - это самостоятельные творения:)
Так задумано:)

Vi
Постоялец
Постоялец
 
Сообщения: 739
Зарегистрирован: 25.01.2002 (Пт) 11:03
Откуда: Россия, Ижевск

Re: Создать по CLSID

Сообщение Vi » 13.03.2009 (Пт) 11:48

SSecurity писал(а):Теребит меня такой интересный вопрос, как создать экземпляр объекта при позднем связывании зная его CLSID. Воспользовавшись поиском нашел тему, из которой построил модуль, который не очень работать хочет:)
...
Пожалуйста, подскажите как правильнее создавать объект по CLSID .. а то неуникальность PROGID мешается:)

Проще всего подсоединить библиотеку типов, которая даст для имени или объекта реальный CLSID, и создать нужный объект средствами VB.
Код: Выделить всё
Dim o As Object
Set o = New <lib>.<obj>            ' создаем через CLSID
Set o = CreateObject(<lib>.<obj>)  ' создаем через ProgID

вместо нежелательного раннего связывания
Код: Выделить всё
Dim o As <lib>.<obj>
Set o = New <lib>.<obj>            ' создаем через CLSID
Set o = CreateObject(<lib>.<obj>)  ' создаем через ProgID
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! (с) КВН

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16489
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Создать по CLSID

Сообщение Хакер » 13.03.2009 (Пт) 11:54

SSecurity писал(а):потому что в референсах я ничего не пишу и при запуске программа вообще не подозревает что будет использовать а потом узнает :)

Но ты упомянул позднее связывание рядом с "созданием объекта". Зачем?

SSecurity писал(а):Пример можно посмотреть?

Код: Выделить всё
Set AnyRef = New AnyCoClassDeclaredInTypelibrary



брал отсюда и все работало
viewtopic.php?f=49&t=26330&p=6612863&hilit=clsid#p6612948

Там три средних поля — Integer'ные, у тебя же — Long'овые.

это применительно к моему коду :))) по темычевским мотивам

Не понял.

Для меня полезнее знать ...

Что знать? :?

но в рамках ранее созданного примера работало :)

Не могло.

потому что они ко мне приходят строками ... по сети

:shock:
Это очень странная архитектура. Программа создаёт объекты тех классов, каких ей скажут по сети... Это вероятно ещё и большая дыра в безопасности.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

SSecurity
Служба безопасности
Аватара пользователя
 
Сообщения: 1283
Зарегистрирован: 19.08.2003 (Вт) 1:11
Откуда: Россия, Мурманск

Re: Создать по CLSID

Сообщение SSecurity » 13.03.2009 (Пт) 12:05

Vi писал(а):
SSecurity писал(а):Теребит меня такой интересный вопрос, как создать экземпляр объекта при позднем связывании зная его CLSID. Воспользовавшись поиском нашел тему, из которой построил модуль, который не очень работать хочет:)
...
Пожалуйста, подскажите как правильнее создавать объект по CLSID .. а то неуникальность PROGID мешается:)

Проще всего подсоединить библиотеку типов, которая даст для имени или объекта реальный CLSID, и создать нужный объект средствами VB.
Код: Выделить всё
Dim o As Object
Set o = New <lib>.<obj>            ' создаем через CLSID
Set o = CreateObject(<lib>.<obj>)  ' создаем через ProgID

вместо нежелательного раннего связывания
Код: Выделить всё
Dim o As <lib>.<obj>
Set o = New <lib>.<obj>            ' создаем через CLSID
Set o = CreateObject(<lib>.<obj>)  ' создаем через ProgID


Что-то я наверно очень сильно торможу:)) но не мог бы привести код как я могу создать к примеру экземпляр Excel.Sheet зная о нем только CLSID: {00020820-0000-0000-C000-000000000046}. И получив CLSID в текстовом виде - к примеру из текстового файла, после запуска программы
Программист - это маленький Бог, а все его ошибки - это самостоятельные творения:)
Так задумано:)

SSecurity
Служба безопасности
Аватара пользователя
 
Сообщения: 1283
Зарегистрирован: 19.08.2003 (Вт) 1:11
Откуда: Россия, Мурманск

Re: Создать по CLSID

Сообщение SSecurity » 13.03.2009 (Пт) 12:16

Хакер писал(а):
SSecurity писал(а):потому что в референсах я ничего не пишу и при запуске программа вообще не подозревает что будет использовать а потом узнает :)

Но ты упомянул позднее связывание рядом с "созданием объекта". Зачем?

SSecurity писал(а):Пример можно посмотреть?

Код: Выделить всё
Set AnyRef = New AnyCoClassDeclaredInTypelibrary



брал отсюда и все работало
viewtopic.php?f=49&t=26330&p=6612863&hilit=clsid#p6612948

Там три средних поля — Integer'ные, у тебя же — Long'овые.

это применительно к моему коду :))) по темычевским мотивам

Не понял.

Для меня полезнее знать ...

Что знать? :?

но в рамках ранее созданного примера работало :)

Не могло.

потому что они ко мне приходят строками ... по сети

:shock:
Это очень странная архитектура. Программа создаёт объекты тех классов, каких ей скажут по сети... Это вероятно ещё и большая дыра в безопасности.



1. Потому что емко ... надо было знак припинания поставить :)))
2. у меня лонговые потому что я разбивал CLSID на 5 чисел .... FFFF = 65535 а Integer поменьше будет. и поэтойже причине у меня последнее число записано как 6 байтовых
3. Пока у меня ворд не открылся по его CLSID я тоже думал что не должно ... но открылся.
4. По поводу безопасности - я для примера сказал ... дырка дыркой, но эта дырка мне нужна - понятно что CLSID не открытым текстом передается ... но тем не менее он там есть :)
Любое обновление ПО - это бомба для пользователя:)
Последний раз редактировалось SSecurity 13.03.2009 (Пт) 12:22, всего редактировалось 1 раз.
Программист - это маленький Бог, а все его ошибки - это самостоятельные творения:)
Так задумано:)

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16489
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Создать по CLSID

Сообщение Хакер » 13.03.2009 (Пт) 12:16

Он не смог бы. Он как и я не знал, что CLSID приходит в виде строчки по сети.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

SSecurity
Служба безопасности
Аватара пользователя
 
Сообщения: 1283
Зарегистрирован: 19.08.2003 (Вт) 1:11
Откуда: Россия, Мурманск

Re: Создать по CLSID

Сообщение SSecurity » 13.03.2009 (Пт) 12:26

Хакер писал(а):Он не смог бы. Он как и я не знал, что CLSID приходит в виде строчки по сети.

Если так смущае слово сеть ... давай считать что есть текстовый файл в нем список CLSID которые нужно создать ... для примера пусть он один будет ... а может их 20...30 ... да сколько угодно.

Но единственное что нам известно это стринговое значение CLSID.
Код: Выделить всё
Private Declare Function CLSIDFromString Lib "OLE32" (ByVal lpszCLSID ​As Long, pclsid As GUID) As Long

Если я правильно понимаю - то вот эта функция переведет стринг в удобоваримый
Программист - это маленький Бог, а все его ошибки - это самостоятельные творения:)
Так задумано:)

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16489
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Создать по CLSID

Сообщение Хакер » 13.03.2009 (Пт) 12:36

2. у меня лонговые потому что я разбивал CLSID на 5 чисел .... FFFF = 65535 а Integer поменьше будет. и поэтойже причине у меня последнее число записано как 6 байтовых
3. Пока у меня ворд не открылся по его CLSID я тоже думал что не должно ... но открылся.

Ты что-то путаешь или придумываешь.

Вот типовой UUID:
{9C9066EA-854F-4e79-B820-FCD1D0D44D6F}

Задача: создать в памяти 16-байтовую структуру, содержающую заданные байты. Если делать тем кривым способом, которым делаешь ты, то надо:
  • 9C9066EA поместить в 4-байтовую переменную (в Long)
  • 854F в 2-х байтовую (в Integer)
  • 4e79 в 2-х байтовую (в Integer)
  • B820 в 2-х байтовую (в Integer)
  • FCD1D0D44D6F в 6-байтовую (в массив из 6 байтов)

У тебя сначала строчка "{9C9066EA-854F-4e79-B820-FCD1D0D44D6F}" разделится таким образом:
"9C9066EA", "854F", "4e79", "B820", "FCD1D0D44D6F"
Далее ты делаешь вот что:
В Long-овую Data1 записываешь &h9C9066EA (правильно)
В Long-овую Data2 записываешь &h0000854F (неправильно!)
В Long-овую Data3 записываешь &h00004e79 (неправильно!)
В Long-овую Data4 записываешь &h0000B820 (неправильно!)
В массив загоняешь оставшиеся байты FC, D1, D0, D4, 4D, 6F (правильно).

В итоге у тебя в памяти получается следующее:
EA66909C4F850000794E000020B80000FCD1D0D44D6F

тогда как должно быть:
EA66909C4F85794E20B8FCD1D0D44D6F

Ты посмотри, у тебя суммарный размер структуры больше, чем 16 байт. И что ты мне говоришь, что у тебя что-то работает?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

SSecurity
Служба безопасности
Аватара пользователя
 
Сообщения: 1283
Зарегистрирован: 19.08.2003 (Вт) 1:11
Откуда: Россия, Мурманск

Re: Создать по CLSID

Сообщение SSecurity » 13.03.2009 (Пт) 12:52

ничего я не путаю просто CDec возращает не то значение:)))

Код: Выделить всё
Debug.Print "&h8", &H8, CDec("&h8")
Debug.Print "&h8F", &H8F, CDec("&h8f")
Debug.Print "&h8FF", &H8FF, CDec("&h8ff")
Debug.Print "&h8FFF", &H8FFF, CDec("&h8fff")


результат
Код: Выделить всё
&h8            8             8
&h8F           143           143
&h8FF          2303          2303
&h8FFF        -28673         36863


я так понимаю после 2^15-1 заполняются значения -2^15+1 а CDec выдает число привышающее 2^15, в этом петрушка и сидит:) щас верну integer в описании + недочеты указанные выше подправлю и попробую запустить.

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

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16489
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Создать по CLSID

Сообщение Хакер » 13.03.2009 (Пт) 12:59

CDec возвращает singned long, просто принт — signed int.
Если скастовать 36863 к типу signed int то будет -28673.

Поиграйся с TDC.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

SSecurity
Служба безопасности
Аватара пользователя
 
Сообщения: 1283
Зарегистрирован: 19.08.2003 (Вт) 1:11
Откуда: Россия, Мурманск

Re: Создать по CLSID

Сообщение SSecurity » 13.03.2009 (Пт) 13:00

Вообщем всем спасибо и в особенности Хакеру и Vi.
Обертка запустилась, файлики препросмотра создались:)
Вот итоговый урезанный код:)

Код: Выделить всё
Option Explicit
Private Type GUID
   Data1 As Long
   Data2 As Integer
   Data3 As Integer
   Data4(0 To 7) As Byte
End Type

Private Declare Sub CoCreateInstance Lib "ole32" (rclsid As GUID, ByVal pUnkOuter As IUnknown, ByVal dwClsContext As Long, riid As GUID, ppv As Object)
Private Declare Function CLSIDFromString Lib "ole32.dll" (ByVal lpsz As Long, rguid As GUID) As Long

Private Function CreateObjectFromCLSID(clsid As GUID) As IUnknown
    Dim IID_Unknown As GUID
    IID_Unknown.Data4(0) = &HC0
    IID_Unknown.Data4(7) = &H46
    CoCreateInstance clsid, Nothing, 5, IID_Unknown, CreateObjectFromCLSID
End Function

Function CreateObjectEx(ByVal Data As String) As Object
    Dim WordCLSID As GUID
    Dim A As Long
    A = CLSIDFromString(StrPtr(Data), WordCLSID)
    Set CreateObjectEx = CreateObjectFromCLSID(WordCLSID)
End Function
Программист - это маленький Бог, а все его ошибки - это самостоятельные творения:)
Так задумано:)

SSecurity
Служба безопасности
Аватара пользователя
 
Сообщения: 1283
Зарегистрирован: 19.08.2003 (Вт) 1:11
Откуда: Россия, Мурманск

Re: Создать по CLSID

Сообщение SSecurity » 13.03.2009 (Пт) 13:04

Хакер писал(а):CDec возвращает singned long, просто принт — signed int.
Если скастовать 36863 к типу signed int то будет -28673.
Поиграйся с TDC.


Спасибо, Хакер.
Код: Выделить всё
Print &H8FFF, CInt ("&H8FFF")

вернул что нужно :)
Программист - это маленький Бог, а все его ошибки - это самостоятельные творения:)
Так задумано:)

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16489
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Создать по CLSID

Сообщение Хакер » 13.03.2009 (Пт) 13:16

Код: Выделить всё
print "0xFACA"; " = "; &hFACA%; "="; &HFACA&
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: AhrefsBot, Yandex-бот и гости: 15

    TopList