Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / WinForms, .Net Framework Новый топик    Ответить
 COM, объект Object, выбрать интерфейс IObject или IObject2 по условию  [new]
Дмитрий77
Member

Откуда:
Сообщений: 4099
Есть такая штука Fax Service Extended COM

Объект FaxServer, ему соответствуют интерфейсы IFaxServer (доступен на XP и выше) и IFaxServer2 (только начиная с Висты),
аналогично
Объект FaxDocument, ему соответствуют интерфейсы IFaxDocument (доступен на XP и выше) и IFaxDocument2 (только начиная с Висты),
ну и в таком духе
Про те которые с "2" на конце сказано:
The IBlaBlaBla2 interface inherits from IBlaBlaBla. IBlaBlaBla2 also has ...

Я здесь когда-то поступил так: сделал универсальный Interop а-ля XP и успешно им пользуюсь на всем подряд (от XP до Win10 с .Net2.0 и Net4.5 - один файл).
Но: мне недоступны IFaxServer2, IFaxDocument2 и соотв. ряд методов, которые хотел бы использовать (на всем что старше XP/2003).

Если я делаю Interop на Win10, то у меня там эти интерфейсы есть, и IBlaBlaBla, и IBlaBlaBla2.
И в принципе он будет работать и на XP.
Но здесь засада.

Типичный код:
    Dim objFaxServer As New FAXCOMEXLib.FaxServer
    Dim objFaxDocument As New FAXCOMEXLib.FaxDocument

    Try
      objFaxServer.Connect("")

На Win10 - работает, на XP - ругается на отсутствующие IFaxServer2, IFaxDocument2 (потому что их там нету, а он по дефолту хочет именно их)

А если вот так:
    Dim objFaxServer As FAXCOMEXLib.IFaxServer
    Dim objFaxDocument As FAXCOMEXLib.IFaxDocument

    objFaxServer = New FAXCOMEXLib.FaxServer
    objFaxDocument = New FAXCOMEXLib.FaxDocument

    Try
      objFaxServer.Connect("")

то на XP уже не ругается, работает также как если б IBlaBlaBla2 в Interop не было.

В то же время корректный вариант на Vista-Win10:
    Dim objFaxServer As FAXCOMEXLib.IFaxServer2
    Dim objFaxDocument As FAXCOMEXLib.IFaxDocument2

    objFaxServer = New FAXCOMEXLib.FaxServer
    objFaxDocument = New FAXCOMEXLib.FaxDocument

    Try
      objFaxServer.Connect("")


А возможно ли как-то сделать грубо такую штуку (универсальную)?

    If(<XP/2003>)
      Dim objFaxServer As FAXCOMEXLib.IFaxServer
      Dim objFaxDocument As FAXCOMEXLib.IFaxDocument
    Else ' >=Vista
      Dim objFaxServer As FAXCOMEXLib.IFaxServer2
      Dim objFaxDocument As FAXCOMEXLib.IFaxDocument2
    End If

    objFaxServer = New FAXCOMEXLib.FaxServer
    objFaxDocument = New FAXCOMEXLib.FaxDocument


Т.е. на какой системе нахожусь код знает,
и в зависимости от этого сказать использовать IBlaBlaBla или IBlaBlaBla2 интерфейс для объекта.
(ну соотв. методы доступные только в IBlaBlaBla2 на XP не вызывать).

Т.е. как мне сказать объекту: ты на XP, используй BlaBlaBla без "2"?
11 сен 17, 03:31    [20785532]     Ответить | Цитировать Сообщить модератору
 Re: COM, объект Object, выбрать интерфейс IObject или IObject2 по условию  [new]
Дмитрий77
Member

Откуда:
Сообщений: 4099
У меня в частном случае прокатила такая конструкция.
Но чет я в написанном не очень уверен (object = OtherObject).


    Dim objFaxServer As Object ' As FaxServer писать нельзя!!!
    Dim objFaxDocument As Object ' As FaxDocument писать нельзя!!!

    If (IsWinVista()) Then
      Dim objFaxServer2 As FAXCOMEXLib.IFaxServer2 = New FAXCOMEXLib.FaxServer
      objFaxServer = objFaxServer2
      Dim objFaxDocument2 As FAXCOMEXLib.IFaxDocument2 = New FAXCOMEXLib.FaxDocument
      objFaxDocument = objFaxDocument2
    Else
      Dim objFaxServer1 As FAXCOMEXLib.IFaxServer = New FAXCOMEXLib.FaxServer
      objFaxServer = objFaxServer1
      Dim objFaxDocument1 As FAXCOMEXLib.IFaxDocument = New FAXCOMEXLib.FaxDocument
      objFaxDocument = objFaxDocument1
    End If

    Try
      objFaxServer.Connect("")

      With objFaxDocument
        'Set the fax body
        If (IsWinVista()) Then
          Dim arr(1) As String
          arr(0) = FileName
          arr(1) = FileName2
          .Bodies = arr 'тестово объединяем 2 файла (доступно только в IFaxDocument2)
        Else
          .Body = FileName
        End If


И как бы понадобится еще глобально в форме (для отслеживания событий), тоже как-то "задваивать" придется
Dim WithEvents g_objFaxServer As FAXCOMEXLib.FaxServer
11 сен 17, 05:46    [20785552]     Ответить | Цитировать Сообщить модератору
 Re: COM, объект Object, выбрать интерфейс IObject или IObject2 по условию  [new]
Изопропил
Member

Откуда:
Сообщений: 30649
Дмитрий77
Dim WithEvents g_objFaxServer As FAXCOMEXLib.FaxServer

а чё в vbnet только динозавроподобная подписка на события?
AddHandler вроде как имеется
11 сен 17, 12:33    [20786341]     Ответить | Цитировать Сообщить модератору
 Re: COM, объект Object, выбрать интерфейс IObject или IObject2 по условию  [new]
Дмитрий77
Member

Откуда:
Сообщений: 4099
Изопропил
а чё в vbnet только динозавроподобная подписка на события?
AddHandler вроде как имеется

Да подумал уже об этом, попробую, счас как бы на стадии проектирования.
Но, за таким "универсальным" кодом надо оч. хорошо следить.
Кейсы, потом если пишешь As Object, то он же методы/свойства не подставляет когда пишешь. Приходится временно менять на As BlaBlaObject

М.б. кстати вариант - разные сборки под XP/2003 и под "все остальное", с ссылками на свой Interop не есть худший.
Они у меня итак разные: XP/2003==.Net 2.0 "все остальное"==.Net 4.5
Но это тоже удовольствие еще то.
Я с Ribbon например так вожусь. Проект веду в .Net 4.5, а когда делаю .Net 2.0, то приходится делать ряд стандартных изменений/комментировать куски кода при конвертации, удалять ссылку, чтоб убрать что касается Ribbon , наловчился, но не оч. удобно.
Одно дело просто в .Net 2.0 конвертануть, другое дело каждый раз править.
Но вести 2 параллельных проекта, еще накладнее, обезательно забудешь чего-нибудь когда-нибудь перенести.

Самое простое во всех этих делах, отказаться вообще от поддержки XP/2003. Но обидно блин, жаба, столько наработок.
11 сен 17, 16:44    [20787617]     Ответить | Цитировать Сообщить модератору
 Re: COM, объект Object, выбрать интерфейс IObject или IObject2 по условию  [new]
Изопропил
Member

Откуда:
Сообщений: 30649
Дмитрий77
М.б. кстати вариант - разные сборки под XP/2003 и под "все остальное", с ссылками на свой Interop не есть худший.

да.
условной компиляцией можно ветки разнести дабы исходник общий был
11 сен 17, 17:42    [20787829]     Ответить | Цитировать Сообщить модератору
 Re: COM, объект Object, выбрать интерфейс IObject или IObject2 по условию  [new]
refreg
Member

Откуда: Саратов
Сообщений: 726
Дмитрий77
Т.е. на какой системе нахожусь код знает,
и в зависимости от этого сказать использовать IBlaBlaBla или IBlaBlaBla2 интерфейс для объекта.
(ну соотв. методы доступные только в IBlaBlaBla2 на XP не вызывать).
Что значит "не вызывать"? Этот функционал на XP скрыт или этот функционал должен обрабатываться особым образом?

Вообще это паттерн стратегия. Делаешь свой интерфейс по действиям который тебе нужны, и приводишь к этому интерфейсу как XP-реализацию, так и Win10 (возможно, понадобятся классы-адаптеры)
При запуске инжектишь ту реализацию, которая требуется.
11 сен 17, 18:32    [20787987]     Ответить | Цитировать Сообщить модератору
 Re: COM, объект Object, выбрать интерфейс IObject или IObject2 по условию  [new]
Дмитрий77
Member

Откуда:
Сообщений: 4099
Дмитрий77
Изопропил
а чё в vbnet только динозавроподобная подписка на события?
AddHandler вроде как имеется

Да подумал уже об этом, попробую,

Попробовал, ничего хорошего.

  Dim WithEvents g_objFaxServer As Object 'FAXCOMEXLib.FaxServer
...
  Private Sub frm1_Load(sender As Object, e As EventArgs) Handles Me.Load
...
    Try
      If sys_WinVista Then
        Dim iFaxServer2 As FAXCOMEXLib.IFaxServer2 = New FAXCOMEXLib.FaxServer
        g_objFaxServer = iFaxServer2
      Else
        Dim iFaxServer1 As FAXCOMEXLib.IFaxServer = New FAXCOMEXLib.FaxServer
        g_objFaxServer = iFaxServer1
      End If
      'g_objFaxServer = New FAXCOMEXLib.FaxServer
      AddHandler CType(g_objFaxServer, FAXCOMEXLib.FaxServer).OnServerShutDown, AddressOf Me.g_objFaxServer_OnServerShutDown
...

  Private Sub TimerMSFax_Tick(sender As Object, e As EventArgs) Handles TimerMSFax.Tick
    If (FaxServerSost = False) AndAlso IsServiceExists("fax") _
     AndAlso (GetServiceStatus("fax") = ServiceControllerStatus.Running) Then
      Try
        'Connect to the local fax server.
        g_objFaxServer.Connect("")
        'Now register for the desired events.
        g_objFaxServer.ListenToServerEvents(FAXCOMEXLib.FAX_SERVER_EVENTS_TYPE_ENUM.fsetFXSSVC_ENDED + _
                                            FAXCOMEXLib.FAX_SERVER_EVENTS_TYPE_ENUM.fsetOUT_QUEUE + _
                                            FAXCOMEXLib.FAX_SERVER_EVENTS_TYPE_ENUM.fsetOUT_ARCHIVE)
        FaxServerSost = True 'успешно подключились к факс-серверу
        Debug.Print("Connected")
        MsgBox("Connected")
      Catch
        'ошибка подключения к факс-серверу
      End Try
    End If
  End Sub

  Private Sub g_objFaxServer_OnServerShutDown(pFaxServer As FAXCOMEXLib.FaxServer) ' Handles g_objFaxServer.OnServerShutDown
    FaxServerSost = False 'произошло отключение от факс-сервера
    Debug.Print("Disconnected")
    MsgBox("Disconnected")
  End Sub


На Win10 оно как бы работает.
А на XP (пробовал на Win2003, пофиг)
строчка c AddHandler выдает
Exeption from HRESULT: 0x80040200

при попытке подписаться на событие, он все равно ассоциирует g_objFaxServer с отсутствующим IFaxServer2,
а если я не сделаю CType/DirectCast/TryCust то хрен он мой Object подпишет на событие.

Поэтому думаю все таки правильно "раздельные exe" со своими Interop для каждого.
Vista-десяточный Interop на XP только гадить будет не здесь так там.
Если б не было нужно событий было бы проще, но это уже обсуждали пару лет назад.

Я б не парился и использовал бы и дальше XP-шный,
но чет я запал на .Bodies/ConnectedSubmit2 (возможность слияния двух документов в один факс, чего нет на XP).
Т.е. напр. в mail2fax есть e-mail с 2-мя attachment, так я второе attachment отсекал, а с этим могу их объединить.

Использовал бы "C/C++ API для Win2000" как я люблю, но сунулся в них и понял, что действительно COMEx умеет много больше как MS вещает. API хороши (и являются единственным вариантом) для Fax Service Provider и для Fax Routing Extension, но для клиентских задач увы нормально не катит.
11 сен 17, 19:38    [20788102]     Ответить | Цитировать Сообщить модератору
 Re: COM, объект Object, выбрать интерфейс IObject или IObject2 по условию  [new]
Изопропил
Member

Откуда:
Сообщений: 30649
Дмитрий77
Если б не было нужно событий было бы проще, но это уже обсуждали пару лет назад.

это проблема синтаксиса старого бейсика
11 сен 17, 22:26    [20788392]     Ответить | Цитировать Сообщить модератору
 Re: COM, объект Object, выбрать интерфейс IObject или IObject2 по условию  [new]
Дмитрий77
Member

Откуда:
Сообщений: 4099
Изопропил
Дмитрий77
Если б не было нужно событий было бы проще, но это уже обсуждали пару лет назад.

это проблема синтаксиса старого бейсика


Ну, а новый синтаксис то есть?
Если он доступен с C#, то должен быть доступен и в VB.Net

Просто при работе с COM, тот синтаксис что я использую в VB.Net, по сути тождественен старому VB6.
При указании as Object (что я должен делать при позднем связывании, а также счас пытался делать за-ради привязки к конкретному интерфейсу), на событие я никак не подпишусь. (Ну, ты кажется чего-то пытался объяснять, как интерфейсы "ручками прописывать", чего-то получилось на простейшем примере, но делать эту огромную работу для "огромной штуки" понятно как минимум того не стоит).

В VB.Net есть AddHandler, но он по сути ничего не дает, т.е. просто Object на событие все равно не подпишешь.
CType/DirectCast/TryCust(object, BlaBlaObject) как я упомянул эквивалентно объявлению as BlaBla с автопривязкой к интерфейсу IBlaBla2 вместо желаемого IBlaBla.
12 сен 17, 00:05    [20788517]     Ответить | Цитировать Сообщить модератору
 Re: COM, объект Object, выбрать интерфейс IObject или IObject2 по условию  [new]
Изопропил
Member

Откуда:
Сообщений: 30649
Дмитрий77,

делай две сборки - волки целы будут и овцы сыты
12 сен 17, 00:09    [20788527]     Ответить | Цитировать Сообщить модератору
 Re: COM, объект Object, выбрать интерфейс IObject или IObject2 по условию  [new]
Дмитрий77
Member

Откуда:
Сообщений: 4099
Изопропил
делай две сборки

Ну так и сделаю. Напишу все под Win10==Vista==Net4.5(с новым Interop, со времен Виста эта кухня уже не менялась, хотя выкидывать ее MS похоже не собирается, любителей факсов по миру таки хватает, тем и живем) , потом урежу под XP==Net2.0(под старый Interop) - c описанием себе в комментариях алгоритма чего урезаю/меняю. Где возможно сразу сделаю case-ы в коде.
12 сен 17, 01:28    [20788587]     Ответить | Цитировать Сообщить модератору
 Re: COM, объект Object, выбрать интерфейс IObject или IObject2 по условию  [new]
Relic Hunter
Member

Откуда: AB
Сообщений: 6250
Дмитрий77,

Не открою Америки если скажу, что есть еще позднее связывание, которое компилятором не проверяется.
12 сен 17, 04:27    [20788629]     Ответить | Цитировать Сообщить модератору
 Re: COM, объект Object, выбрать интерфейс IObject или IObject2 по условию  [new]
Дмитрий77
Member

Откуда:
Сообщений: 4099
Relic Hunter,
Не откроешь. Более того, в случае .Net с его Interop-ами оно можно сказать оптимально.
С одним жирным НО для случая когда надо подписываться на события, о чем вскользь было сказано в частности здесь, чуть выше.
12 сен 17, 04:34    [20788630]     Ответить | Цитировать Сообщить модератору
 Re: COM, объект Object, выбрать интерфейс IObject или IObject2 по условию  [new]
Relic Hunter
Member

Откуда: AB
Сообщений: 6250
Дмитрий77,

А условную компиляцию использовать нельзя?
12 сен 17, 05:01    [20788637]     Ответить | Цитировать Сообщить модератору
 Re: COM, объект Object, выбрать интерфейс IObject или IObject2 по условию  [new]
Дмитрий77
Member

Откуда:
Сообщений: 4099
Relic Hunter
Дмитрий77,
А условную компиляцию использовать нельзя?

Поясни на примере, что имеется ввиду.
Вкладываю на всяк. случай 2 своих Interop-па

1. В папке "XP" -изготовлен 2 года назад, честно говоря уже не помню к каким точно извращениям я прибег, чтобы его сделать.
В общем он .Net 2.0 и "старого образца", работает с любой .Net-версией и на любой OS от XP до Win10 вдоль и поперек, но не поддерживает IBlaBla2 интерфейсы. Проверен временем в продакшн (2+ года).
2. В папке "Vista_Win10" -изготовлен вчера на Win10, также .Net 2.0, поддерживает IBlaBla2, предположительно работоспособен на всем что >=Виста, на XP без танцев с бубном будет пытаться подставлять IBlaBla2 (кот. там нет) и ругаться.

К сообщению приложен файл (Interop.FAXCOMEXLib.zip - 80Kb) cкачать
12 сен 17, 06:14    [20788648]     Ответить | Цитировать Сообщить модератору
 Re: COM, объект Object, выбрать интерфейс IObject или IObject2 по условию  [new]
Antonariy
Member

Откуда: ☭
Сообщений: 66873
Дмитрий77
Кейсы, потом если пишешь As Object, то он же методы/свойства не подставляет когда пишешь. Приходится временно менять на As BlaBlaObject
А что если написать собственный IFaxServer3, который наследует и IFaxServer и IFaxServer2? И написать Dim objFaxServer As IFaxServer3
12 сен 17, 08:24    [20788741]     Ответить | Цитировать Сообщить модератору
 Re: COM, объект Object, выбрать интерфейс IObject или IObject2 по условию  [new]
Дмитрий77
Member

Откуда:
Сообщений: 4099
Antonariy,

Нужен же не
Dim objFaxServer As IFaxServerN
а
 Dim WithEvents g_objFaxServer As FAXCOMEXLib.FaxServer

Забей, только путать, решил уже. 2 сборки: Net4.5 под новый Interop, Net2.0 под старый.
Лучше на смысловую часть кода время потратить, быстрее сделаю, чем на эти изыскания.
12 сен 17, 19:14    [20791072]     Ответить | Цитировать Сообщить модератору
Все форумы / WinForms, .Net Framework Ответить