DLL question...not sure where this should go

Blake81

Well-known member
Joined
Feb 23, 2006
Messages
304
Location
Georgia, USA
Programming Experience
1-3
I've tried to write a DLL with VB and now I just need to double check that it's written properly. I'd like to use this DLL in a mIRC script where I would give it a string (zip code) and it would return the weather for that zip. You don't need to check all the lines dealing with the XML. I've used those lines successfully in another Windows application I made. I just need to make sure that this is set up correctly to put that information into a variable and return a value. Here's the code
VB.NET:
[SIZE=2][COLOR=#0000ff]Imports[/COLOR][/SIZE][SIZE=2] System.Xml
[/SIZE][SIZE=2][COLOR=#0000ff]Public[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Class[/COLOR][/SIZE][SIZE=2] Class1
[/SIZE][SIZE=2][COLOR=#0000ff]Public[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Function[/COLOR][/SIZE][SIZE=2] GetWeather([/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] zip [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]String[/COLOR][/SIZE][SIZE=2])
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] retzip [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]String[/COLOR][/SIZE][SIZE=2] = [/SIZE][SIZE=2][COLOR=#800000]""
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] xmldocument [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] System.Xml.XmlDocument
xmldocument = [/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] System.Xml.XmlDocument
xmldocument.Load([/SIZE][SIZE=2][COLOR=#800000]"http://xoap.weather.com/weather/local/"[/COLOR][/SIZE][SIZE=2] + zip + [/SIZE][SIZE=2][COLOR=#800000]"?cc=*&dayf=5&prod=xoap&par=1017300893&key=268086eb4218acff"[/COLOR][/SIZE][SIZE=2])
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] Xnodes [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.Xml.XmlNodeList
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] Xnode [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.Xml.XmlNode
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] Xname [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]String
[/COLOR][/SIZE][SIZE=2]Xname = xmldocument.SelectSingleNode([/SIZE][SIZE=2][COLOR=#800000]"/weather/loc/dnam"[/COLOR][/SIZE][SIZE=2]).InnerText
Xnode = xmldocument.SelectSingleNode([/SIZE][SIZE=2][COLOR=#800000]"/weather/cc"[/COLOR][/SIZE][SIZE=2])
Xnodes = Xnode.ChildNodes
[/SIZE][SIZE=2][COLOR=#0000ff]For[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Each[/COLOR][/SIZE][SIZE=2] Xnode [/SIZE][SIZE=2][COLOR=#0000ff]In[/COLOR][/SIZE][SIZE=2] Xnodes
[/SIZE][SIZE=2][COLOR=#0000ff]If[/COLOR][/SIZE][SIZE=2] Xnode.Name = [/SIZE][SIZE=2][COLOR=#800000]"tmp"[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Then
[/COLOR][/SIZE][SIZE=2]retzip = retzip + Xnode.InnerText + [/SIZE][SIZE=2][COLOR=#800000]" "
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]ElseIf[/COLOR][/SIZE][SIZE=2] Xnode.Name = [/SIZE][SIZE=2][COLOR=#800000]"flik"[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Then
[/COLOR][/SIZE][SIZE=2]retzip = retzip + [/SIZE][SIZE=2][COLOR=#800000]"Feels Like: "[/COLOR][/SIZE][SIZE=2] + Xnode.InnerText() + [/SIZE][SIZE=2][COLOR=#800000]" "
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]ElseIf[/COLOR][/SIZE][SIZE=2] Xnode.Name = [/SIZE][SIZE=2][COLOR=#800000]"t"[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Then
[/COLOR][/SIZE][SIZE=2]retzip = retzip + Xnode.InnerText()
[/SIZE][SIZE=2][COLOR=#0000ff]ElseIf[/COLOR][/SIZE][SIZE=2] Xnode.Name = [/SIZE][SIZE=2][COLOR=#800000]"wind"[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Then
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] XWindList [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.Xml.XmlNodeList
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] Xwind [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.Xml.XmlNode
Xwind = Xnode.SelectSingleNode([/SIZE][SIZE=2][COLOR=#800000]"/weather/cc/wind"[/COLOR][/SIZE][SIZE=2])
XWindList = Xwind.ChildNodes
[/SIZE][SIZE=2][COLOR=#008000]'Dim Windstring As String = Nothing
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] WindGust [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]String
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] WindSpeed [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]String
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]For[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Each[/COLOR][/SIZE][SIZE=2] Xwind [/SIZE][SIZE=2][COLOR=#0000ff]In[/COLOR][/SIZE][SIZE=2] XWindList
[/SIZE][SIZE=2][COLOR=#0000ff]If[/COLOR][/SIZE][SIZE=2] Xwind.Name = [/SIZE][SIZE=2][COLOR=#800000]"t"[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Then
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] WindDir [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]String[/COLOR][/SIZE][SIZE=2] = [/SIZE][SIZE=2][COLOR=#800000]"Wind: From "[/COLOR][/SIZE][SIZE=2] + Xwind.InnerText
[/SIZE][SIZE=2][COLOR=#0000ff]If[/COLOR][/SIZE][SIZE=2] WindGust = [/SIZE][SIZE=2][COLOR=#800000]"N/A"[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Then
[/COLOR][/SIZE][SIZE=2]retzip = retzip + WindDir + WindSpeed + [/SIZE][SIZE=2][COLOR=#800000]" "
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Else
[/COLOR][/SIZE][SIZE=2]retzip = retzip + WindDir + WindSpeed + [/SIZE][SIZE=2][COLOR=#800000]" Gusting to "[/COLOR][/SIZE][SIZE=2] + WindGust + [/SIZE][SIZE=2][COLOR=#800000]" MPH"
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]If
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]ElseIf[/COLOR][/SIZE][SIZE=2] Xwind.Name = [/SIZE][SIZE=2][COLOR=#800000]"s"[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Then
[/COLOR][/SIZE][SIZE=2]WindSpeed = [/SIZE][SIZE=2][COLOR=#800000]" at "[/COLOR][/SIZE][SIZE=2] + Xwind.InnerText + [/SIZE][SIZE=2][COLOR=#800000]" MPH"
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]ElseIf[/COLOR][/SIZE][SIZE=2] Xwind.Name = [/SIZE][SIZE=2][COLOR=#800000]"gust"[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Then
[/COLOR][/SIZE][SIZE=2]WindGust = Xwind.InnerText
[/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]If
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Next
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]If
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Next
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Return[/COLOR][/SIZE][SIZE=2] retzip
[/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Function
End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Class
[/COLOR][/SIZE]

I also need to ask how to use this dll. The mIRC help says the syntax is:
$dll(filename, procname, data)
What is procname in this case or how do I find it? I tried using the GUID, but that didn't work. Thanks for any help. I tried using regsvr32 to register the dll and got a message saying that it was loaded, but "the DllRegisterServer entry point was not found. This file can not be registered."
 
Last edited:
Oi, I am of absolutely no help in this but I will post my thoughts anyway :) Also interested in finding this stuff out.

Would procname (procedure name?) not just be GetWeather? Filename is (oviously?) the DLL name. And data then the string for the zip?

A question: since it says procname - are you sure you can use functions which return a value? a procedure returns bugger all so that might cause a problem (unless there is '$dll(filename,funcname,data,return)' or something?)

Im assuming that the 'entry point' being referred to is the point where GetWeather is and since it cant be found the DLL cant be registered correctly.

As far as a DLL being well-formed there is nothing special. It's just normal code encapsulated into one file which can be used as a tool by programs.

Let me know if you've resolved this problem or if any of the above actually makes sense.
 
Thanks for your suggestions. One of the examples in the mIRC help files talked about using the mIRC $com command to call non-standard DLLs. I've tried this with just about every variation I can think of using $dll and $com and haven't hit on anything that works yet. I think I should be able to use $dll though. I posted once on the message boards for mIRC about this and they said I could use $dll to send text. For example, this DLL will take a zip code as a string and return the weather for that zip (when it works), so in mIRC, I should be able to type "//echo -a $dll(weather.dll,GetWeather,12345) (just put a number where zip would be) and it should echo the weather for that zip in mIRC. I've added a reference to this DLL to a Windows form in VB and it works there, so I know I have that right at least. It's just odd that I'm not able to register the DLL with COM using regsvr32 or the mIRC command "/comreg". I've also been reading something about using a DEF file with your DLL, and I'm not sure what that's about. I also read something about "exporting" your functions in the DLL. The example was in C# I think, so I couldn't follow it. I'm going to keep looking into this. I'll let you know if I find anything.
 
I found some other things in the mIRC help which I'm not sure how to use. Apparently, the DLL has to have a certain format and use certain parameters. This is from the help:
Technical notes
This section contains technical information for programmers who want to create DLLs for use with mIRC.
The routine in the DLL being called must be of the form:
int __stdcall procname(HWND mWnd, HWND aWnd, char *data, char *parms, BOOL show, BOOL nopause)
mWnd is the handle to the main mIRC window.
aWnd is the handle of the window in which the command is being issued, this might not be the currently active window if the command is being called by a remote script.
data is the information that you wish to send to the DLL. On return, the DLL can fill this variable with the command it wants mIRC to perform if any.
parms is filled by the DLL on return with parameters that it wants mIRC to use when performing the command that it returns in the data variable.
Note: The data and parms variables can each hold 900 chars maximum.
show is FALSE if the . prefix was specified to make the command quiet, or TRUE otherwise.
nopause is TRUE if mIRC is in a critical routine and the DLL must not do anything that pauses processing in mIRC, eg. the DLL should not pop up a dialog.
The DLL can return an integer to indicate what it wants mIRC to do:
0 means that mIRC should /halt processing
1 means that mIRC should continue processing
2 means that it has filled the data variable with a command which it wants mIRC to perform, and has filled parms with the parameters to use, if any, when performing the command.
3 means that the DLL has filled the data variable with the result that $dll() as an identifier should return.
Note: You may need to create a .def file with the procedure names exported when compiling your DLL.
I'm not sure about those window parameters or how to create the .def file.
 
I figured this DLL thing out for mIRC! I thought I had done this before but I guess I hadn't. In the properties page for the class library, under Compile, make sure you check the box that says "Register for COM Interop". After I did that and built the project, I actually had a DLL file and a TLB, which I didn't have before. I had read somewhere earlier today about putting the files in the system32 folder, and I'm not sure if that's necessary, but I put them there and in my mIRC directory. After that, I found my DLL in the registry and found the progid (still not sure what procid is). $com works just fine for me though because mine is a non-standard DLL. I then typed /comreg weather.dll in mIRC and it successfully registered. mIRC help has four different "methods" that can be used when calling the DLL, or a combination of any of them, so I used these two lines, after typing /comopen weather weather.GWeather.

var %a = $com(weather,GetWeather,3,bstr,30117)
echo -a $com(weather).result

I used 3 as the method number, because it was a combination of 1 and 2. The methods (according to mIRC help) are:

method - Combination of the following values added together:
1 = DISPATCH_METHOD
2 = DISPATCH_PROPERTYGET
4 = DISPATCH_PROPERTYPUT
8 = DISPATCH_PROPERTYPUTREF

I put those two lines into an alias and it returned the weather for that zip code! I'm really happy to finally get a DLL working for mIRC, because it will shorten my scripts considerably, while adding alot of potential. Thanks for the help, UncleRonin.
 
Thanks for the tips Blake81! Just tested this stuff with success.

Clarifying a few things hopefully:
If you "Register for COM Interop" all is taken care of regarding registering the com dll in registry, no need to copy the dll/tlb anywhere, nor use the comreg command in mIrc. Not sure if mIrc is capable of registering .Net COM DLL as type libraries, anyway this can also be done with "regasm /tlb" manually if this path is chosen.

The default ProgID is your application namespace and class name for example ClassLibrary1.Class1. This can be overridden with the ProgId attribute like this:
VB.NET:
Imports System.Runtime.InteropServices
<ProgId("myProg.ID")> _
Public Class Class1
  Function sayhello() As String 
    Return "hello"
  End Function
End Class
For example this script below will use that dll by opening, accessing and closing it. I put it in Aliases window in Script Editor and it is called simply by typing "/test" in a channel (and it appears I say "Hello" in channel):
VB.NET:
test {
  comopen johnh myProg.ID
  if ($comerr) {
    echo comopen failed
    halt
  }
  var %a = $com(johnh,sayhello,1)
  /say $com(johnh).result
  comclose johnh
}
 
Thanks for more information about registering DLLs. I wasn't sure if I really needed to be copying the other files that came with the DLL project, but I pretty much figured out that I just need the DLL. I have this script completely finished for mIRC. It's a weather script that lets you look up the weather for any US zip code. You just have to send me a mIRC notice saying "!weather <zip code here>" and my script will send you a notice back with the results. Here's an example of the output you would get back:

Your weather for Carrollton, GA (30117)--Temp: 72 Feels Like: 72 Conditions: Partly Cloudy Wind From: E at 5 MPH Gusting to: N/A MPH


If you're interested in seeing it, here's the mIRC code for this. The DLL made it really nice for keeping the script small while allowing it to do a lot.
VB.NET:
on 1:NOTICE:!weather*:*:{
  if ($com(weather)) {    
    var %zip = $2
    noop $com(weather,GetWeather,3,bstr,%zip)
    var %weather = $com(weather).result
    notice $nick %weather
    echo -a $nick %weather
  }
  else {
    comopen weather weather.GWeather
    var %zip = $2
    noop $com(weather,GetWeather,3,bstr,%zip)
    var %weather = $com(weather).result
    notice $nick %weather 
    echo -a $nick %weather
  }
}
And in case you're wondering, there is a /comopen line for this. I just have it in the "ON START" event for mIRC, not directly with this script. JohnH was right about the syntax though. The comopen line is just "comopen weather weather.GWeather".
 
Found this old thread that I had posted, because I'm having problems doing this again. I don't have my DLL anymore, so I'm trying to recreate it. I registered for COM Interop, but nothing happens when I try to open the COM connection in mIRC. Any suggestions would be appreciated.

VB.NET:
Imports System.Xml
Public Class weather
    Public Function GetWeather(ByVal zip As String)
        Dim retzip As String = ""
        Dim xmldocument As New System.Xml.XmlDocument
        xmldocument = New System.Xml.XmlDocument
        xmldocument.Load("http://xoap.weather.com/weather/local/" + zip + "?cc=*&dayf=5&prod=xoap&par=1017300893&key=268086eb4218acff")
        Dim Xnodes As System.Xml.XmlNodeList
        Dim Xnode As System.Xml.XmlNode
        Dim Xname As String
        Xname = xmldocument.SelectSingleNode("/weather/loc/dnam").InnerText
        Xnode = xmldocument.SelectSingleNode("/weather/cc")
        Xnodes = Xnode.ChildNodes
        For Each Xnode In Xnodes
            If Xnode.Name = "tmp" Then
                retzip = retzip + Xnode.InnerText + " "
            ElseIf Xnode.Name = "flik" Then
                retzip = retzip + "Feels Like: " + Xnode.InnerText() + " "
            ElseIf Xnode.Name = "t" Then
                retzip = retzip + Xnode.InnerText()
            ElseIf Xnode.Name = "wind" Then
                Dim XWindList As System.Xml.XmlNodeList
                Dim Xwind As System.Xml.XmlNode
                Xwind = Xnode.SelectSingleNode("/weather/cc/wind")
                XWindList = Xwind.ChildNodes
                'Dim Windstring As String = Nothing
                Dim WindGust As String
                Dim WindSpeed As String
                For Each Xwind In XWindList
                    If Xwind.Name = "t" Then
                        Dim WindDir As String = "Wind: From " + Xwind.InnerText
                        If WindGust = "N/A" Then
                            retzip = retzip + WindDir + WindSpeed + " "
                        Else
                            retzip = retzip + WindDir + WindSpeed + " Gusting to " + WindGust + " MPH"
                        End If
                    ElseIf Xwind.Name = "s" Then
                        WindSpeed = " at " + Xwind.InnerText + " MPH"
                    ElseIf Xwind.Name = "gust" Then
                        WindGust = Xwind.InnerText
                    End If
                Next
            End If
        Next
        Return retzip
    End Function
End Class
 
Back
Top