2017-06-02 18 views
1

我在2個遠程服務器上的COM應用程序中安裝了COM + dll。我從其中一臺服務器中導出了非排隊代理,並將其安裝在客戶端計算機上。在運行時在VB6中創建非排隊的遠程COM對象指定服務器

我希望能夠指定COM對象在運行時實例化的遠程服務器 - 代理安裝包含我從中導出代理的計算機的遠程服務器名稱,因此只需在客戶端上創建代理就會始終調用我從中導出的機器,因爲它是代理屬性的一部分。

代理服務器沒有排隊,所以我不能使用調用GetObject的方法,使用PathName如queue:ComputerName=Server01/new:ComClass.Class

對於將始終調用它們從中導出的遠程服務器的非排隊代理,我只使用CreateObject(objectName),它將使用代理屬性中的遠程服務器名稱。

經過一番搜索,我找到了一個解決方案(在我的自我回答下面),但有沒有一種更簡單的方法在VB6中做到這一點,而無需使用ole32.dll函數?

編輯:在測試@ Bob77提出的解決方案的評論中,使用服務器名稱參數調用CreateObject沒有任何影響。只使用概述的CreateRemoteObject方法實際上調用指定服務器上的COM組件。

這可能是因爲客戶端調用來自IIS進程,並且遠程服務器的COM +應用程序的用戶身份不同。

+1

爲什麼不直接在「CreateObject」調用的第二個參數中提供服務器名稱?這就是它的原因。 – Bob77

+1

@ Bob77:我相信這是在這裏尋找的答案。考慮到語言的過時程度,查找VB6調用的文檔可能是一個相當大的挑戰。 –

+0

@ Bob77我們使用代理服務器組件,因爲服務器組件必須以特定的用戶身份在COM +應用程序中運行,而代理服務器可以在IIS進程中實例化。我真的不知道我的解決方案是使用IIS用戶身份還是遠程COM +應用程序標識 - 查找有用的VB6文檔是一場噩夢! –

回答

0

這可以使用ole32.dll庫中的CoCreateInstanceEx函數完成。

首先聲明從ole32.dll所需要的功能和相應的數據結構:

Private Type SERVER_STRUCTURE 
    reserved1 As Long 
    pServer  As Long 
    AuthInfo As Long 
    reserved2 As Long 
End Type 

Private Type MULTI_QI 
    pIID  As Long 
    pInterface As Object 
    hResult  As Long 
End Type 

Private Declare Function CLSIDFromProgID Lib "ole32.dll" _ 
       (progid As Any, clsid As Any) As Long 

Private Declare Function OleInitialize Lib "ole32.dll" _ 
       (ByVal Nullptr As Long) As Long 

Private Declare Function CoCreateInstanceEx Lib "ole32.dll" _ 
       (clsid As Any, ByVal pUnkOuter As Long, _ 
        ByVal Context As Long, server As SERVER_STRUCTURE, _ 
        ByVal nElems As Long, mqi As MULTI_QI) As Long 

我然後使用此功能,取入對象名稱和服務器名稱,並返回該對象的一個​​實例,這將是一個代理到所需的服務器:

Private Function CreateRemoteObject(ByVal ObjectName As String, _ 
        ByVal ByVal serverName As String) As Object 

    Dim clsid(256) As Byte 
    Dim progid() As Byte 
    Dim server() As Byte 
    Dim queryInterface As MULTI_QI 
    Dim serverStructure As SERVER_STRUCTURE 
    Dim refiid(16) As Byte 
    Dim longReturnCode As Long 
    Dim errorString As String 

    errorString = "" 

    GetInterfaceIDforIDispatch refiid()  ' set an interface ID for IDispatch 
    queryInterface.pIID = VarPtr(refiid(0)) ' point to the interface ID 
    progid = ObjectName & Chr$(0)   ' specify the object to be launched 
    server = serverName & Chr$(0)   ' specify the server 
    OleInitialize 0       ' initialise OLE 
    longReturnCode = CLSIDFromProgID(progid(0), clsid(0)) ' get the CLSID for the object 

    If longReturnCode <> 0 Then 
     errorString = "Unable to obtain CLSID from progid " & ObjectName 
     App.LogEvent errorString, vbLogEventTypeError 
     Exit Function 
    End If 

    ' point to server name and invoke a remote instance of the desired object 
    serverStructure.pServer = VarPtr(server(0)) 
    longReturnCode = CoCreateInstanceEx(clsid(0), 0, 16, serverStructure, 1, queryInterface) 

    If longReturnCode <> 0 Then 
     errorString = "CoCreateInstanceEx failed with error code " & Hex$(longReturnCode) 
     App.LogEvent errorString, vbLogEventTypeError 
     Exit Function 
    End If 

    ' Pass back object ref 
    Set CreateRemoteObject = queryInterface.pInterface 
End Function 

Private Sub GetInterfaceIDforIDispatch(p() As Byte) 
    ' fills in the well-known IID for IDispatch into the byte array p. 

    p(1) = 4 
    p(2) = 2 
    p(8) = &HC0 
    p(15) = &H46 
End Sub