I need to dynamically call web service! For this I made simple web service Service1.asmx
Then I created the proxy class for the Service1 Web Service, I use the WSDL.exe utility and following command at the command prompt:
wsdl /language:VB /out:myclass.vb http://localhost:3245/Service1.asmx?WSDL
This command create class myclass.vb. That class I include in my Windows Application project, but when I do this I get lot of errors.
This is the how created class look like:
Imports System
Imports System.ComponentModel
Imports System.Diagnostics
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.Xml.Serialization
'
'This source code was auto-generated by wsdl, Version=2.0.50727.1432.
'
'''<remarks/>
<System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.1432"), _
System.Diagnostics.DebuggerStepThroughAttribute(), _
System.ComponentModel.DesignerCategoryAttribute("code"), _
System.Web.Services.WebServiceBindingAttribute(Name:="Service1Soap", [Namespace]:="http://tempuri.org/")> _
Partial Public Class Service1
Inherits System.Web.Services.Protocols.SoapHttpClientProtocol
Private HelloWorldOperationCompleted As System.Threading.SendOrPostCallback
'''<remarks/>
Public Sub New()
MyBase.New
Me.Url = "http://localhost:3245/Service1.asmx"
End Sub
'''<remarks/>
Public Event HelloWorldCompleted As HelloWorldCompletedEventHandler
'''<remarks/>
<System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/HelloWorld", RequestNamespace:="http://tempuri.org/", ResponseNamespace:="http://tempuri.org/", Use:=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle:=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)> _
Public Function HelloWorld() As String
Dim results() As Object = Me.Invoke("HelloWorld", New Object(-1) {})
Return CType(results(0),String)
End Function
'''<remarks/>
Public Function BeginHelloWorld(ByVal callback As System.AsyncCallback, ByVal asyncState As Object) As System.IAsyncResult
Return Me.BeginInvoke("HelloWorld", New Object(-1) {}, callback, asyncState)
End Function
'''<remarks/>
Public Function EndHelloWorld(ByVal asyncResult As System.IAsyncResult) As String
Dim results() As Object = Me.EndInvoke(asyncResult)
Return CType(results(0),String)
End Function
'''<remarks/>
Public Overloads Sub HelloWorldAsync()
Me.HelloWorldAsync(Nothing)
End Sub
'''<remarks/>
Public Overloads Sub HelloWorldAsync(ByVal userState As Object)
If (Me.HelloWorldOperationCompleted Is Nothing) Then
Me.HelloWorldOperationCompleted = AddressOf Me.OnHelloWorldOperationCompleted
End If
Me.InvokeAsync("HelloWorld", New Object(-1) {}, Me.HelloWorldOperationCompleted, userState)
End Sub
Private Sub OnHelloWorldOperationCompleted(ByVal arg As Object)
If (Not (Me.HelloWorldCompletedEvent) Is Nothing) Then
Dim invokeArgs As System.Web.Services.Protocols.InvokeCompletedEventArgs = CType(arg,System.Web.Services.Protocols.InvokeCompletedEventArgs)
RaiseEvent HelloWorldCompleted(Me, New HelloWorldCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState))
End If
End Sub
'''<remarks/>
Public Shadows Sub CancelAsync(ByVal userState As Object)
MyBase.CancelAsync(userState)
End Sub
End Class
'''<remarks/>
<System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.1432")> _
Public Delegate Sub HelloWorldCompletedEventHandler(ByVal sender As Object, ByVal e As HelloWorldCompletedEventArgs)
'''<remarks/>
<System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.1432"), _
System.Diagnostics.DebuggerStepThroughAttribute(), _
System.ComponentModel.DesignerCategoryAttribute("code")> _
Partial Public Class HelloWorldCompletedEventArgs
Inherits System.ComponentModel.AsyncCompletedEventArgs
Private results() As Object
Friend Sub New(ByVal results() As Object, ByVal exception As System.Exception, ByVal cancelled As Boolean, ByVal userState As Object)
MyBase.New(exception, cancelled, userState)
Me.results = results
End Sub
'''<remarks/>
Public ReadOnly Property Result() As String
Get
Me.RaiseExceptionIfNecessary
Return CType(Me.results(0),String)
End Get
End Property
End Class
And some of errors are:
Type 'System.Web.Services.WebServiceBindingAttribute' is not defined. C:\Documents and Settings\Owner\My Documents\Visual Studio 2008\Projects\WindowsApplication3\WindowsApplication3\class.vb 16 2 WindowsApplication3
Error 4 Type 'System.Web.Services.Protocols.SoapHttpClientProtocol' is not defined. C:\Documents and Settings\Owner\My Documents\Visual Studio 2008\Projects\WindowsApplication3\WindowsApplication3\class.vb 18 14 WindowsApplication3
etc....
Update:
I'm doing this because this service need to be on server and this windows application only call this web service from server. The problem is that I need to write address of server in some kind of config file and later read that address and then call web service! So I can't simple add web reference, because I need to read address of server where service is run from config file.
Any idea?
You must to add reference to System.Web.Services assembly.
For your convenience, you can also to right-click your Visual Studio 2008 project, click "Add Service Reference", "Advanced..." and "Add Web Reference..."
If you are using VS 2005 adding a web reference allows you to specify the URL behavior of the web reference. By setting this to 'dynamic' it will store the url in the config file of the application, there by allowing you to change it if necessary.
Related
So, I'm working on converting this code from VB.NET to C#:
Public Class Form1
Const filesplit As String = "|split|"
Dim stub, opt() As String
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
On Error Resume Next
FileOpen(1, Application.ExecutablePath, OpenMode.Binary, OpenAccess.Read, OpenShare.Shared)
stub = Space(LOF(1))
FileGet(1, stub)
FileClose(1)
opt = Split(stub, filesplit)
End Sub
End Class
I've used a series of online converters, and they don't really work for me.
How do I do it? I'm trying to understand VB.NET source code so I can use it in.
Those methods are in the Microsoft.VisualBasic Namespace.
So you could just add a reference to that in your project and then use virtually the exact same code with a small amount of extra qualification on the methods used:
using Microsoft.VisualBasic; //add this statement
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
string filesplit = "|split|";
string stub;
string[] opt;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
FileSystem.FileOpen(1, Application.ExecutablePath, OpenMode.Binary, OpenAccess.Read, OpenShare.Shared);
stub = Strings.Space(Convert.ToInt32(FileSystem.LOF(1)));
FileSystem.FileGet(1, ref stub);
FileSystem.FileClose(1);
opt = Strings.Split(stub, filesplit);
}
}
}
However you should really look into using the File.xxx methods in the System.IO namespace in both your VB.NET and C# code going forward, but this will get it working for you.
Use File.Open. That should get you what you want.
Your VB code is essentially doing this:
// The using clause ensures the StreamReader is properly disposed after the closing block.
using (StreamReader sr = File.OpenText(Application.ExecutablePath))
{
stub = sr.ReadToEnd();
opt = stub.Split(filesplit).ToArray();
}
This assumes filesplit is a char, string or something like Environment.NewLine
Basically you would use :
Dim content = File.ReadAllText("c:\temp\MyTest.txt")
However it would be more correct to use:
Dim path As String = "c:\temp\MyTest.txt"
If File.Exists(path) Then
Dim content = File.ReadAllText(path)
Rem do something with content
End If
I have a task to establish a communication with a Motorola SNAPI Scan Engine device as a vb.net project. I have been referring the sample source code in C# from Motorola as well as the Snapi Documentation. The device responds correctly for a SNAPI_Init call, but subsequently, it fails to process a following SNAPI_Connect call. Please assist. Thanks.
http://www.motorolasolutions.com/web/Business/Products/Bar%20Code%20Scanning/Bar%20Code%20Scanners/Fixed%20Mount%20Scanners/MiniScan%204400/_Documents/Static%20Files/SnapiProgrammersGuide_7137001.pdf
`
`**My vb.net code:**
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Text
Imports System.IO
Imports System.Threading
Imports System.Runtime.InteropServices
Imports System.Collections.ObjectModel
Imports System.Collections.Specialized
Imports System.Windows.Forms
Imports System
Imports Scan_2d_7mar.SnapiDLL
Public Class Form1
'Declaration
Dim status As Integer
Dim xstatus As Integer
Dim num_device As Integer
Dim m_hWnd As Integer = Me.Handle.ToInt32
Dim devicehandle(8) As Integer
Dim sernum() As String
'obtain and populate the s/n for this scanner
Public sb As New System.Text.StringBuilder(100)
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
status = SnapiDLL.SNAPI_Init(m_hWnd, devicehandle, num_device)
TextBox1.Text = devicehandle(0)
TextBox2.Text = num_device
TextBox3.Text = m_hWnd
If ((status = 0) And num_device) Then 'Assuming one scanner found during call to SNAPI_Init
Dim y() As Byte
xstatus = SNAPI_GetSerialNumber(devicehandle(0), y)
xstatus = SnapiDLL.SNAPI_Connect(devicehandle(0))
TextBox2.Text = sb.ToString(4, sb.Length - 4)
TextBox1.Text = xstatus
Else
TextBox1.Text = 9
End If
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
End Sub
End Class
I have an application that uses Process.Start to execute an exe. It works fine for all the .exe that I have tested except when the .exe has a configuration file where it gets a connectionstring, when this happens I get a System.NullReferenceException. this is my code.
to execute the exe:
string eucApp = #"C:\Temp\app.exe"
startInfo = new ProcessStartInfo(eucApp);
using (Process execProcess = Process.Start(startInfo))
{
execProcess.WaitForExit();
}
then the exe starts and the first thing that does is get the a connection string with this code line
strCadena = ConfigurationManager.ConnectionStrings("ConnectionString")
If I replace this with the connectionstring like this, it works fine
strCadena = "Data Source=HostName;Initial Catalog=MyDB;Integrated security=True"
I would remove the config file and put its values into the .exe code but the trouble is that I have more than 500 .exe's that uses config files so if any one knows a way to avoide this please tell me!
thanks for your help. I figured out the problem. Somehow the .exe was pointing to the app.config of the aplication that start's the process. I added this class to the .exe that is developed in VB .Net
Imports System.Configuration
Imports System.Reflection
Public Class AppConfig
Implements IDisposable
Public Shared Function Change(ByVal path As String) As AppConfig
Return New ChangeAppConfig(path)
End Function
Public Overridable Sub Dispose() Implements IDisposable.Dispose
End Sub
Private Class ChangeAppConfig
Inherits AppConfig
Private ReadOnly oldConfig As String = AppDomain.CurrentDomain.GetData("APP_CONFIG_FILE").ToString
Private disposedValue As Boolean
Public Sub New(ByVal path As String)
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", path)
ResetConfigMechanism()
End Sub
Public Overrides Sub Dispose()
If (Not disposedValue) Then
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", oldConfig)
ResetConfigMechanism()
disposedValue = True
End If
GC.SuppressFinalize(Me)
End Sub
Private Shared Sub ResetConfigMechanism()
GetType(ConfigurationManager).GetField("s_initState", BindingFlags.NonPublic Or BindingFlags.Static).SetValue(Nothing, 0)
GetType(ConfigurationManager).GetField("s_configSystem", BindingFlags.NonPublic Or BindingFlags.Static).SetValue(Nothing, Nothing)
Dim assemblies() As Type = GetType(ConfigurationManager).Assembly.GetTypes()
For Each assembly As Type In assemblies
If (assembly.FullName = "System.Configuration.ClientConfigPaths") Then
assembly.GetField("s_current", BindingFlags.NonPublic Or BindingFlags.Static).SetValue(Nothing, Nothing)
Exit For
End If
Next
End Sub
End Class
End Class
I call Change function at the begining of the program
AppConfig.Change(Application.StartupPath & "\app.exe.Config")
This way it take the right config file
I'm trying to create a COM class with one method that will cast an object to a specific interface on behalf of VBScript.
This is the method signature I'm using:
public object GetInterface(object unknown, string iid)
I thought this would be possible because if the method explicitly declares the return type as :
public IRequestedInterface GetInterface(object unknown, string iid)
Then VBScript gets the reference to the desired interface.
So I tried just casting to the interface
return (IRequestedInterface)unknown;
Unfortunately, VBScript gets a reference to the default interface instead of the requested interface.
I have tried getting round this by creating a custom marshaller using ICustomMarshaler.
I thought this would work because the method MarshalManagedToNative returns a IntPtr.
Because of this I thought that if i just returned the IntPtr to the interface
return Marshal.GetComInterfaceForObject(unknown, typeof(IRequestedInterface));
it would work. But, obviously, it didn't have the desired effect :(
So does anybody know if it is posible and how you would do it?
EDIT:
I thought it would be helpful to add a concrete example (although it is contrived) to explain why I haven't accepted that VBScript will always get the default interface. I'm still clinging to my hope.
Below you will find the contents of 3 files, 'TestLib.cs', 'Build.cmd' and 'Test.vbs'. These hopefully demonstrate why I still think it 'should' be possible.
Note: I have tested this on Windows XP SP3 (x86).
TestLib.cs
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
[assembly: ComVisible(false)]
[assembly: Guid("64e20009-c664-4883-a6e5-1e36a31a0fd8")]
[assembly: AssemblyVersion("2012.06.*")]
[ComVisible(true)]
[Guid("EB77C7B1-D1B9-4BB3-9D63-FBFBD56C9ABA")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IPerformQi
{
[DispId(1000)]
object GetInterface(object unknown, string iid);
[DispId(2000)]
IRequested GetIRequested(object unknown);
}
[ComVisible(true)]
[Guid("7742BC0A-8719-483E-B1DF-AE9CD9A958DC")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IDefault
{
[DispId(1000)]
void SayHello(string name);
}
[ComVisible(true)]
[Guid("FFF34296-2A06-47D4-B09C-B93B63D5CC53")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IRequested
{
[DispId(1000)]
void SayGoodbye(string name);
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ComDefaultInterface(typeof(IPerformQi))]
[Guid("222BB88D-B9FA-4F23-8DB3-BA998F4E668B")]
[ProgId("TestLib.PerformQi")]
public class PerformQi : IPerformQi
{
object IPerformQi.GetInterface(object unknown, string iid)
{
if(iid == "FFF34296-2A06-47D4-B09C-B93B63D5CC53")
return (IRequested)unknown;
throw new Exception("Unable to find inteface");
}
IRequested IPerformQi.GetIRequested(object unknown)
{
return (IRequested)unknown;
}
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ComDefaultInterface(typeof(IDefault))]
[Guid("174ABED6-3325-4878-89E3-BF8BD1107488")]
[ProgId("TestLib.Test")]
public class Test : IDefault, IRequested
{
void IDefault.SayHello(string name)
{
MessageBox.Show(string.Format("Hello '{0}'", name));
}
void IRequested.SayGoodbye(string name)
{
MessageBox.Show(string.Format("Goodbye '{0}'", name));
}
}
Build.cmd
"%windir%\Microsoft.Net\Framework\v4.0.30319\csc.exe" /out:TestLib.dll /target:library /r:System.Windows.Forms.dll TestLib.cs
"%windir%\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe" TestLib.dll /codebase /tlb:TestLib.tlb
PAUSE
Test.vbs
Dim oPerformQi 'As TestLib.PerformQi
Dim oTest 'As TestLib.Test
Dim oTest2 'As IRequested
Dim oTest3 'As IRequested
Set oPerformQi = CreateObject("TestLib.PerformQi")
Set oTest = CreateObject("TestLib.Test")
Call oTest.SayHello("Robert")
Set oTest2 = oPerformQi.GetIRequested(oTest)
'Note: This works
Call oTest2.SayGoodbye("Robert")
Set oTest3 = oPerformQi.GetInterface(oTest, "FFF34296-2A06-47D4-B09C-B93B63D5CC53")
'Note: This does not work
Call oTest3.SayGoodbye("Robert")
Using the call oPerformQi.GetIRequested(oTest) makes the call to oTest3.SayGoodbye("Robert") work. This makes me think you are not limited to just the default interface in VBS.
Perhaps .Net is not capable of returning the specified interface because of an implicit cast on the return value? Ideally I would use generics for this, but as we all know COM does not support genrics.
Under this restriction is there any other way that you can think of to achieve this?
EDIT 2:
I have found that I can achieve this using VB6, below is the code for the class.
Option Explicit
Public Function GetInterface(ByVal oUnknown As Object, ByVal IID As String) As Variant
Dim oIRequested As IRequested
If IID = "FFF34296-2A06-47D4-B09C-B93B63D5CC53" Then
Set oIRequested = oUnknown
Set GetInterface = oIRequested
Else
Err.Raise 1, , "Unable to find inteface"
End If
End Function
I would still like to find a C# version if anybody can shed some light on the subject i would appreciate it.
In order to have multiple IDispatch-derived interfaces implemented on a single object, to be accessible from scripting environment you should rather implement IDispatchEx and have its methods called once a call from script is taking place.
The problem you are facing is caused by the fact that script queries for your IDispatch first, and both your IDispatch-derived interfaces return the same "main" IDispatch leaving no chance for methods of other interfaces to be accessible.
When VBS host is about to call a method on your object, it first queries IDispatchEx. If found, the calls are delivered via IDispatchEx::InvokeEx and your COM Class can internally route the call to the proper IDispatch implementation, both private or forward to external/inner object.
In case IDispatchEx is not found, it looks for IDispatch and there you are in trouble because it sees only your "main" interface. That is, the workaround for you is to implement IDispatchEx. You can do it either way: implement right on your COM class, or instead create a proxy class to accept scripting calls via IDispatchEx::InvokeEx and forward to correct IDispatch in your code.
Example: Both A and B classes implement IX and IY interfaces, B additionally implements IDispatchEx. Interface methods are IX::X1, IY::Y1.
On Error Resume Next
Set A = CreateObject("Test.A")
WScript.Echo A.X1 ' Success, via IX::Invoke
WScript.Echo A.Y1 ' Failure, A's IDispatch is IX's parent and does not have Y1 method
Set B = CreateObject("Test.B")
WScript.Echo B.X1 ' Success, via IDispatchEx::InvokeEx
WScript.Echo B.Y1 ' Success, via IDispatchEx::InvokeEx
Ok so I have an assembly, written in C#, using Visual Studio 2010.
This Assembly contains one class, which contains one method which returns the word Result, the code is below:
using System.Runtime.InteropServices;
namespace TestDLL
{
public class Class1
{
[ComVisible(true)]
public string TestMethod()
{
return "Result";
}
}
}
The output section in the Build tab on the properties window looks like so:
When I click on Build, I get a DLL file and a TLB file. I can add this TLB file to Microsoft Access simply by browsing to it.
Now, in Access I have a button and a label. I want to make the Caption property of my label equal to the result of testMethod. I'm thinking I need to do something similar to below but I'm not sure, any help would be much appreciated:
Private Sub btnMain_Click()
Dim tm As TestDLL
Dim foo As String
foo = tm.testMethod
lblBarr.Caption = foo
End Sub
Thankyou
Maybe next will work:
Private Sub btnMain_Click()
Dim tm As TestDLL.Class1
Dim foo As String
Set tm = New TestDLL.Class1
foo = tm.testMethod
lblBarr.Caption = foo
End Sub