I am attempting to create a dll from a WSDL file for accessing a web service within a VBA application. When using the compiled library I can't call the class methods i need, only the methods with similar names which are built in the proxy to build the main request/response.
This is the procedure I have tried:
Generate proxy classes in vb.net using svcutil.exe
Compile proxy classes to dll library using vbc.exe
Register dll using regasm.exe
Add reference to tlb file from within VBA (Excel)
call method from within VBA after defining an instance of the class
Svcutil "https://deltek.XXXXXX.com/Vision/visionws.asmx?wsdl" /language:vb /syncOnly
vbc /t:library /out:DeltekVisionOpenAPIWebService.dll DeltekVisionOpenAPIWebService.vb
regasm /codebase /tlb DeltekVisionOpenAPIWebService.dll
An extract of the generated vb file:
Option Strict Off
Option Explicit On
<System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0"), _
System.ServiceModel.ServiceContractAttribute([Namespace]:="http://tempuri.org/Deltek.Vision.WebServiceAPI.Server/DeltekVisionOpenAPIWebServi"& _
"ce", ConfigurationName:="DeltekVisionOpenAPIWebServiceSoap")> _
Public Interface DeltekVisionOpenAPIWebServiceSoap
'CODEGEN: Generating message contract since element name ConnInfoXML from namespace http://tempuri.org/Deltek.Vision.WebServiceAPI.Server/DeltekVisionOpenAPIWebService is not marked nillable
<System.ServiceModel.OperationContractAttribute(Action:="http://tempuri.org/Deltek.Vision.WebServiceAPI.Server/DeltekVisionOpenAPIWebServi"& _
"ce/UpdateOpportunity", ReplyAction:="*")> _
Function UpdateOpportunity(ByVal request As UpdateOpportunityRequest) As UpdateOpportunityResponse
End Interface
Partial Public Class DeltekVisionOpenAPIWebServiceSoapClient
Inherits System.ServiceModel.ClientBase(Of DeltekVisionOpenAPIWebServiceSoap)
Implements DeltekVisionOpenAPIWebServiceSoap
<System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)> _
Function DeltekVisionOpenAPIWebServiceSoap_UpdateOpportunity(ByVal request As UpdateOpportunityRequest) As UpdateOpportunityResponse Implements DeltekVisionOpenAPIWebServiceSoap.UpdateOpportunity
Return MyBase.Channel.UpdateOpportunity(request)
End Function
Public Function UpdateOpportunity(ByVal ConnInfoXML As String, ByVal DataXML As String) As String
Dim inValue As UpdateOpportunityRequest = New UpdateOpportunityRequest()
inValue.Body = New UpdateOpportunityRequestBody()
inValue.Body.ConnInfoXML = ConnInfoXML
inValue.Body.DataXML = DataXML
Dim retVal As UpdateOpportunityResponse = CType(Me,DeltekVisionOpenAPIWebServiceSoap).UpdateOpportunity(inValue)
Return retVal.Body.UpdateOpportunityResult
End Function
End Class
I expect to be able to call the class methods that relate to the web service calls, but the only methods that are available (returned by autocomplete/don't error as not defined when called) are the methods used to build the request and response as defined in the interface.
Edit:
Somehow missed that regasm was reporting this error, but not sure how to address it:
Type library exporter warning processing 'DeltekWebAPI.DeltekVisionOpenAPIWebServiceSoapClient, DeltekVisionOpenAPIWebService'. Warning: Type library exporter encountered a type that derives from a generic class and is not marked as [ClassInterface(ClassInterfaceType.None)]. Class interfaces cannot be exposed for such types. Consider marking the type with [ClassInterface(ClassInterfaceType.None)] and exposing an explicit interface as the default interface to COM using the ComDefaultInterface attribute.
Related
I have a two .NET assemblies which are registered as COM+ components and I'm testing them from a regular console application test harness;
Dim objFirst As New MyFirstComponent() 'COM+ initialisation
Dim RC As Boolean = objFirst.GetValue()
The method call is executed successfully. This is the definition of
MyFirstComponent;
<ProgId("MyFirstComponent")> _
<Guid("...")> _
<ClassInterface(ClassInterfaceType.None)> _
<Transaction(TransactionOption.Supported)> _
Public Class MyFirstComponent
Inherits ServicedComponent
Implements IMyFirstComponent
Public Function GetValue() As Boolean Implements
IMyFirstComponent.GetValue
Dim objSecond As New MySecondComponent() 'COM+ initialisation
Dim RC As Boolean = objSecond.GetValue()
Return RC
End Function
End Class
At the point where MySecondComponent is initialised, I get a
RemotingException with the following message;
"Cannot load type 'MySecondComponent', ..., Version=...,
Culture=neutral,
PublicKeyToken=...'
All assemblies are strongly named too. I cannot work out why I can
successfully fire a method call to the first component, but when it tries
to subsequently load up the second component itself, it can't resolve the
type.
As a sidenote, if I run the code from the body of "GetValue()" in my test
harness, it executes as expected. The problem seems to only crop up once
things have moved into the realm of COM+ components calling other COM+
components.
I implemented a .NET DLL with COM visibility (VB.NET):
Public Class Processer Implements IProcesser
Public Sub processASpecificThing(ByVal param As String) _
Implements IProcesser.processAThing
' [...]
End Sub
End Class
Below the Interface definition. For some reasons I exposed a method with a different name in the interface.
Imports System.Runtime.InteropServices
Imports System.ComponentModel
<InterfaceType(ComInterfaceType.InterfaceIsDual)> _
Public Interface IProcesser
Sub processAThing(ByVal param As String)
End Interface
The project is configured to set the Assembly as COM visible. If I understood correctly InterfaceIsDual let the Interface be visible at early binding as well as at late binding.
In a VB6 project, this works:
Dim aProcesser as IProcesser
Set aProcesser = New Processer
aProcesser.processAThing "param" ' Call by the *Interface* method name
In a VB6 project or an ASP classic VBScript page, this fails:
Dim aProcesser
Set aProcesser = CreateObject("ProcessLib.Processer")
' Call by the *Interface* method name
aProcesser.processAThing "param" ' [FAIL]
' Call by the *Interface* method name
aProcesser.processASpecificThing "param" ' [SUCCESS]
The failing line leads to the error message:
Object Doesn't Support this Property or Method
The real context of this question is an ASP classic page. I use a late binding to avoid adding a METADATA header in the ASP file (I believe it's the only way, but not tested yet).
Sounds like the interface is not accessible. Why does that problem occur and how could I make the interface accessible with ?
I have been attempting to load a DLL using Reflector
Imports System.Reflection
I have a simple DLL file written in c++ using /CLR (this is the entire file)
using namespace System;
namespace ASSEMBLE{
public class REM{
public:
int VALUE(){
return 100;
}
};
};
And inside my VB.net butten click event i have
Dim dllPath As String = "C:\Users\richard\Documents\Visual Studio 2012\Projects\link\link\bin\Release\dlltest.dll"
' load the assembly
Dim assembly1 As System.Reflection.Assembly = Assembly.LoadFrom(dllPath)
' get the type
Dim t As Type = assembly1.GetType("ASSEMBLE.REM")
' create an instance and add it.
Dim c As Object = Activator.CreateInstance(t)
MsgBox(t.InvokeMember("VAULE", BindingFlags.Default Or BindingFlags.InvokeMethod, Nothing, c, {}))
When event triggered (ie. i load the dll) i get the error:
Method 'ASSEMBLE.REM.VALUE' not found
Using:
<DllImport("DLL.dll")> Public Shared Function VALUE() As Integer
End Function
is not an option. I need to load the DLL after runtime.
Your REM class is an unmanaged class, and therefore reflection cannot see its methods. Using the /CLR compile option does not automatically force all classes to be managed. It just allows you to have managed classes in your project.
To allow the call to InvokeMember, you need to make REM a managed class. This can be done by adding ref to the class declaration like so:
public ref class REM{
...
};
I have some functions in my VB.NET DLL which I can 'hide' from my VB6 app by using the following:
<Runtime.InteropServices.ComVisible(False)> _
But is there a way to make a function ONLY visible to COM clients and not to .NET assemblies?
This way I can use Shared methods for the .NET side avoiding the need for an instance declaration.
You might be able to achieve what you want by using Explicit Interface Implementation. You can declare an interface that will be used by COM clients and another one for .NET clients, leaving all methods private in your implementation class. The code may look like this:
Imports System.Runtime.InteropServices
Public Interface ITestInterface
<ComVisible(True)> _
Sub MyTestMethod()
End Interface
<ComVisible(True)> _
Public Class TestClass
Implements ITestInterface
Private Sub MyTestMethod() Implements ITestInterface.MyTestMethod
End Sub
End Class
I have to say that I do not understand what you mean with: "This way I can use Shared methods for the .NET side avoiding the need for an instance declaration. "
I want to create a COM DLL using VSS 2010 and need to register to Registry. My aim is I want use that created DLL like "Excel.Application", "Word.Application", "Wscript.Shell" kind-of.
I want to create instance using CreateObject / New OleObject methods and use the same in my Scripting (VBScript or JavaScript).
Any one help me to create a COM object and how to register it?
I tried to create COM Object and tried to register using RegSvr32.exe. It says "dll was loaded but no entry point found. Make sure valid dll or ocx"
Here is my code for your ref...
<ComClass(ComClass1.ClassId, ComClass1.InterfaceId, ComClass1.EventsId)> _
Public Class ComClass1
Public Const ClassId As String = "b3b13b6c-6de5-47cb-ad6f-0ae5c7ce5c59"
Public Const InterfaceId As String = "68536b50-1b47-42d5-970f-d3d34b56d681"
Public Const EventsId As String = "413fa5c3-76fa-44d0-b753-1f3d3f52dbaf"
' A creatable COM class must have a Public Sub New() with no parameters,
' otherwise, the class will not be
' registered in the COM registry and cannot be created
' via CreateObject.
Public Sub New()
MyBase.New()
End Sub
Public Sub Test1()
Console.WriteLine("Test1....")
End Sub
End Class
Thanks,
Shanmugavel.C
Create a CLass Library
Inside the .vb file, Create a Interface first.
Create class by inheriting from Interface.
Create Strong Name under "Signing" TAB of Properties.
Enable the "Register for Com Interop" under "compile" TAB of Properties
Enter the Assembly Information.
Build the Solution.
After this,
Goto "Visual Studio 2010 Command Prompt"
Navigate to dll path
Register the dll using "regasm" like regasm test.dll /tlb:test.tlb
Now Registry Entries will be done under CLSID and Interface. Then
Export to GAC(Global Assembly Cache ie. C:\Windows\Microsoft.Net\Assembly) using "gacutil.exe" like gacutil /i test.dll
That's all.... We can use the COM application....
Refer the links:
http://www.codeproject.com/KB/COM/nettocom.aspx
http://www.15seconds.com/issue/040721.htm