

InterviewSolution
1. |
Solve : Return array from ActiveX exe? |
Answer» I have an activex exe written in vb6 that I am accessing using vbscript. I have a sub in this activex exe with a parameter that needs to return an array. I tried using a function to return a variant type array, but it would not allow access to the array in vbscript. Basically, I just need to figure out a way to pass an array or a collection from my vb6 exe to my vbscript. I have seen examples, but none of them will work for me probably because most of them are talking about ASP. and use Redim() to turn it into an array in the routine. That fixed it ReDim Preserve aparently doesn't work the first time. I had to start it out by using ReDim keyNames(0) to make the variant into an array. I also decided to make it into a function instead of a sub. I removed the msgboxes because they don't ever display, I even made a new sub with a msgbox in it and it didn't work. There's only one small problem left with the "keyName = Space(KEY_LENGTH)". In the console, it shows all the extra spaces after the key name. I figure that's because there is no null termination CHARACTER, but it's weird because it displays fine in a msgbox (no extra spaces). So I have two final questions. Why won't msgboxes display from the activex exe? And how do I get rid of the trailing spaces in the console? Thanks so much for your help I was at this for three hours. Code: [Select]Public Function EnumKeys(strSection As String, keyName As String) As Variant Dim hKey As Long Dim keyNames As Variant Dim section As Long Dim i As Long 'FORCE IT TO TURN VARIANT INTO ARRAY ReDim keyNames(0) ' Convert from string to the section code section = GetSection(strSection) ' Open the key. If RegOpenKeyEx(section, keyName, 0, KEY_ALL_ACCESS, hKey) <> ERROR_SUCCESS Then Exit Function End If ' Enumerate keyName = Space(KEY_LENGTH) While RegEnumKey(hKey, i, keyName, KEY_LENGTH) = ERROR_SUCCESS ReDim Preserve keyNames(i) '<---- NOT GOOD ENOUGH. WON'T FORCE IT TO BE ARRAY FIRST TIME keyNames(i) = keyName keyName = Space(KEY_LENGTH) i = i + 1 Wend ' Close the key. RegCloseKey (hKey) EnumKeys = keyNames End Function Here is the vbscript: Code: [Select]Option Explicit Dim reg Dim keys Dim values Dim i Dim io Set io = CreateObject("wshshell.IO") Set reg = CreateObject("wshshell.Registry") keys = reg.EnumKeys("HKLM", "SYSTEM\CurrentControlSet\Services") values = reg.EnumValues("HKLM", "SYSTEM\CurrentControlSet\Services\Tcpip") For i = 0 to Ubound(keys) wscript.stdout.writeline keys(i) Next AnyKey For i = 0 to Ubound(values) wscript.stdout.writeline values(i) Next AnyKey Set io = Nothing Set reg = Nothing Sub AnyKey() wscript.stdout.writeline "Press any key to continue. . ." wscript.sleep 200 While io.GetKeysASCII = 0 wscript.sleep 50 Wend End Sub Quote from: Linux711 on November 04, 2010, 08:01:45 AM There's only one small problem left with the "keyName = Space(KEY_LENGTH)". In the console, it shows all the extra spaces after the key name. I figure that's because there is no null termination character, but it's weird because it displays fine in a msgbox (no extra spaces).The MsgBox() Function Calls MessageBoxA(), As I'm sure you are aware. When VB passes the String to MessageBoxA, it (converts it to ASCII from the native VB Unicode) and then tacks a null character on the end. Since your string probably have a null character (as returned from the Registry function) Messagebox only displays up to that first null character. The Console, However, does not work this way. The Console is written to using WriteFile(), which basically takes a data block, a size, and then writes it to the handle. In this case, WScript.Echo() passes in the string, and the string length; so ALL of the string gets written. (Note that null characters usually just appear as spaces in the console). The solution? Use something like: Code: [Select]Struse = Left$(struse,instr(struse,vbnullchar)-1) before returning it from the EXE. Quote Why won't msgboxes display from the activex exe?Don't know. It works fine for me. Make sure "unattended Execution" isn't checked in the Project properties, Msgbox is ignored if that option is set on compilation. [/quote] Quote Thanks so much for your help I was at this for three hours.You're Welcome EDIT: Actually, now that I think about it, you may find this class useful. As you can see from the comments, I wasn't the original author; however, It is heavily modified from the original version, I fixed several bugs, made it independent of a Module that was originally required, and probably most interesting, I switched the APIs from using the ANSI version (RegReadKeyExA, for example) to using the Wide (Unicode) versions (RegReadKeyExW) when it detects it's running on a NT platform. Essentially, it wraps almost all the Registry manipulation functions. I've found it quite useful. That being said, I'm not sure how well it would work with VBScript, since there is a lot of strong typing and ByRef Arguments as well in the various public methods. It might make creating your versions easier I guess. Example- Code: [Select]'Declarations: Private mReg as cRegistry '------------------------------------------------------------------- 'Class Initialize should have this: Private Sub Class_Initialize() Set mReg = new cRegistry End Sub 'and then your EnumKeys Function could be changed as well: Public Function EnumKeys(strSection As String, keyName As String) As Variant Dim returnvar as Variant Dim sCount as Long,sKeys() as String if mReg.EnumerateSections(sKeys, sCount) Then Redim returnvar(0 to sCount-1) 'only problem is the fact that it now has to be "CONVERTED" to the variant array... For I = 1 to sCount returnvar(I-1) = sKeys(I) Next I End If EnumKeys = returnvar End Function It's far from perfect; the strong typing of byRef Arguments means it wouldn't work directly with VBScript, at least not without helper functions, and 1 based arrays? what was I thinking.... Actually, no, I'll just blame the original author for that . But it might be helpful. |
|