Visual Basic 6.0 cannot compile Collection on Windows 7 - windows

I'll try to be brief: We have code written in Visual Basic 6.0 that I am trying to compile on a Windows 7 64-bit computer. (Previously this was compiled on an old XP computer.) Most of the code seems to compile correctly, however certain code that has Attributes, like the NewEnum, are not honoring the VB attribute. Here is an example:
The VB6 method looks like this:
Public Property Get NewEnum() As IUnknown
Attribute NewEnum.VB_UserMemId = -4
Attribute NewEnum.VB_MemberFlags = "40"
'this property allows you to enumerate
'this collection with the For...Each syntax
Set NewEnum = mCol.[_NewEnum]
End Property
This is default Enumerator that is created when you use the Class Builder Utility.
However, the Attribute elements are not honored when the code is compiled. Using the OLE View program, it shows that the Attributes are ignored.
The XP computer produces the following snippet:
[id(0xfffffffc), propget, hidden]
HRESULT NewEnum([out, retval] IUnknown** );
But the Windows 7 computer generates:
[id(0x68030000), propget]
HRESULT NewEnum([out, retval] IUnknown** );
I have attempted to set the Visual Basic application to run in XP (Service Pack 3) Compatibility mode and this has not helped.
Because of the size and complexity of our application we cannot port it from VB6 to .NET at this time, and we need to get it to compile. Does anyone know how to properly configure VB6 so that it will properly compile a collection?

Related

Printers info not refreshing while debugging

I'm having trouble debugging a specific printer paperbin problem. I seems that VB6 does not refresh/update the printer info while debugging. I have narrowed it down to a simple piece of code.
Private Sub Form_Load()
Dim prt As Printer
For Each prt In Printers
AddOutput prt.DeviceName
AddOutput "Paperbin: " & prt.PaperBin
Next
End Sub
This code loops through all the printers and shows their names and paperbin values. The AddOutput procedure adds it to a Textbox. When I run this code from the VB6 IDE the paperbin value is the same for all printers. When I compile this code to an executable and run it then the output shows the correct paperbin values.
I found out that when I add a watch to the the prt object and collapse the information that the paperbin is correctly updated. From that moment on the VB6 IDE uses that specific paperbin value for all printers.
Why is the VB6 IDE giving the wrong value while the compiled version is giving the right value?
I have tested this code on Windows 7.
Update
Looping by index make no difference, so using For i = 0 to Printers.Count -1 has the same problem as using For each prt in Printers.
Other properties are also affected. Properties like PrintQuality, PaperSize and Duplex do not update. Properties DeviceName and Port are updating correctly.
While it's rare to stumble upon something that looks like a platform bug, but it seems to be one in this case. I recommend installing the latest service pack (which for VB6 is Service Pack 6) to ensure that you have the latest bugfixes. I suspect (though it is just a guess) that the reason it worked when complied but not in the IDE is that when compiled it used the VB6 runtime built in to newer versions of Windows (which includes the current service packs), but in the IDE it used the IDE's runtime (which you've indicated was not yet patched).

800a0ad error in VBS, Windows 7 32

I wrote a simple ActiveX Dll object with C++ & ATL (VS2010) for using in VBS scripting engine embedded in a SCADA system. It's just a code carcass now, just interfaces with stubs, no dependencies. Every interface designed to be called from client side have dual interface.
I can see this object from OLE/COM Object Viewer and can instantiate it from there. I've got no problem with instantiating this ActiveX object using C#'s interop services for debug purposes.
However, when i'm trying to instantiate this from wscript (vbs) I get this 800a0ad error.
The operating system is Windows 7 (32 bit), not x64.

GTKmm on Windows (porting) - sigc::mem_fun returning errors from VC++ Express 2010 about deducing template arguments

I am trying to port my GTKmm application developed in Linux into Windows. I have a treeview with multiple selections and I need to get those selections into an std::vector. The code I use (and that works fine in Linux) is this:
std::vector<Gtk::TreeModel::iterator> rows;
mp_FileDetailsTree->treeSelection()->selected_foreach_iter(
sigc::mem_fun(rows, &std::vector<Gtk::TreeModel::iterator>::push_back)
);
On Windows, however, (Visual C++ Express 2010) I get a lot of this error (repeated quite a bit):
error C2784: 'sigc::bound_const_volatile_mem_functor7<T_return,T_obj,T_arg1,T_arg2,T_arg3,T_arg4,T_arg5,T_arg6,T_arg7> sigc::mem_fun(T_obj &,T_return (__thiscall T_obj2::* )(T_arg1,T_arg2,T_arg3,T_arg4,T_arg5,T_arg6,T_arg7) volatile const)' : could not deduce template argument for 'overloaded function type' from 'overloaded function type'
c:\devel\gtkmm\include\sigc++-2.0\sigc++\functors\mem_fun.h(6196) : see declaration of 'sigc::mem_fun'
Right at the sigc::mem_fun line.
Any idea how I can fix this? Googling has turned up nothing useful :(. I'm using GTKmm 2.22 (full Windows installer).
Directly using std::vector::push_back as a signal handler is rather ambitious. I'm not surprised that the compiler is confused.
I would just use a regular signal handler method and call vector::push_back() inside that method.

TYPE_E_CANTLOADLIBRARY when using a COM object on a separate thread on Windows 2003 x64 only

I have a Windows Forms app (compiled as x86) accessing a COM object. It gives me the following error, only on Windows 2003 x64, when the code is run on a separate thread:
Exception during creation of IDoc:Unable to cast COM object of type 'PTISG.COM.TeklogixQueue.QueueClass' to interface type 'PTISG.COM.TeklogixQueue._Queue'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{3CBD7297-27D8-11D6-B75D-00902761DFA4}' failed due to the following error: Error loading type library/DLL. (Exception from HRESULT: 0x80029C4A (TYPE_E_CANTLOADLIBRARY))
And the code looks like this:
Private Sub Button3_Click(...)
If _separateThreadCheckBox.Checked Then
Dim t As Thread
t = New Thread(AddressOf Me.CreateQueue)
t.Start()
Else
Me.CreateQueue()
End If
End Sub
And CreateQueue() looks something like this:
Dim q As New TeklogixQueue.Queue
q.Object = .... 'Has to use the object
I've tried the same code on different OS and here's the result:
Windows 7 x64. Works.
Windows 2008 x64. Works.
Windows 2003 R2 Server Standard x64.
Fails.
If I don't execute the code on a separate thread, then it works on all platforms.
I've used ProcessMonitor to capture the registry reads for that interface id, and here's one difference between Windows 2003 vs. Windows 7:
Windows 2003:
"1:09:13.2616131 PM","IDocSend.exe","2704","RegOpenKey","HKCU\Software\Classes\Wow6432Node\Interface{3CBD7297-27D8-11D6-B75D-00902761DFA4}","NAME NOT FOUND",""
"1:09:13.2616360 PM","IDocSend.exe","2704","RegOpenKey","HKCR\Wow6432Node\Interface{3CBD7297-27D8-11D6-B75D-00902761DFA4}","SUCCESS",""
"1:09:13.2617100 PM","IDocSend.exe","2704","RegQueryKey","HKCR\Wow6432Node\Interface{3CBD7297-27D8-11D6-B75D-00902761DFA4}","SUCCESS","Query: Name"
Windows 7:
"1:10:01.6212010 PM","IDocSend.exe","4548","RegOpenKey","HKCU\Software\Classes\Wow6432Node\Interface{3CBD7297-27D8-11D6-B75D-00902761DFA4}","NAME NOT FOUND","Desired Access: Read","32-bit"
"1:10:01.6212518 PM","IDocSend.exe","4548","RegOpenKey","HKCR\Wow6432Node\Interface{3CBD7297-27D8-11D6-B75D-00902761DFA4}","SUCCESS","Desired Access: Read","32-bit"
"1:10:01.6212927 PM","IDocSend.exe","4548","RegSetInfoKey","HKCR\Wow6432Node\Interface{3CBD7297-27D8-11D6-B75D-00902761DFA4}","SUCCESS","KeySetInformationClass: KeySetHandleTagsInformation, Length: 0","32-bit"
"1:10:01.6213324 PM","IDocSend.exe","4548","RegQueryKey","HKCR\Wow6432Node\Interface{3CBD7297-27D8-11D6-B75D-00902761DFA4}","SUCCESS","Query: Name","32-bit"
Note on Windows 7, there's an extra "RegSetInfoKey" call.
Also, if I don't run on a separate thread, there's nothing captured in ProcessMonitor. Dunno why.
Anyone has an idea why this fails on a separate thread?
Thanks,
Harold

CoCreateInstance fails with 0x80040154 on ITaskBarList3

Does anyone have any idea why CoCreateInstance would be failing on ITaskBarList3 on Windows 7 64-bit? The error code is 0x80040154, which is Class Not Registered.
The calling code (VB6) is:
Public Const IID_ITaskbarList3 = "{EA1AFB91-9E28-4B86-90E9-9E9F8A5EEFAF}"
Public Const CLSID_TaskbarList3 = "{EA1AFB91-9E28-4B86-90E9-9E9F8A5EEFAF}"
'....
Dim IID As GUID_API
Dim CLSID As GUID_API
Dim iTaskBarVB3 As ShellLib.ITaskbarList3
rc = CLSIDFromString(StrPtr(CLSID_TaskbarList3), CLSID)
rc = IIDFromString(StrPtr(IID_ITaskbarList3), IID)
rc = CoCreateInstance(CLSID, 0, CLSCTX_SERVER, IID, iTaskBarVB3)
The returns from CLSIDFromString and IIDFromString are both 0 (Success). I can find the string in the registry. Since my taskbar is obviously working just fine, I know the interface is able to be called by other processes just fine.
ITaskBarList3 is declared in a typelib compiled using mktyplib.exe. I've double checked the GUID values, and they match those in the SDK.
Any help would be greatly appreciated.
The most likely reason is that the calling code is 32-bit and the COM server is 64-bit and therefore can't be loaded as an in-proc server.
A possible solution could be to create a COM+ application for the COM server to force its creation as an out-proc server. However this will not help if the COM server is meant to supply an ActiveX control.
I'm also surprised to see the class id being equal to the interface id - it's common practice to have them different. Since you are not the developer of the component implementing that interface but only the consumer it's likely that you just misplaced the class id with the interface id and this is the reason why your client program is not working. You should find the class id of the class implementing the ITaskBarList3 interface and use it as the class id.
CLSID_TaskbarList3 doesn't exist! It's simply,
CLSID_TaskbarList = "{56FDF344-FD6D-11D0-958A-006097C9A090}"
which indeed has a different GUID than the IID_TaskbarList3 IID.
In COM you have typically one class implementing one or more interface. There doesn't generally exist a new class for every interface.
The ClassID wasn't the problem, as this worked correctly about a week ago. I was previously compiling on Windows Vista, 32-bit.
I've now updated my system to Windows 7, 64-bit. The problem isn't a matter of 32/64-bit compatibility. The TaskBar is accessible through Wow64, and I am able to call the interface just fine from a 32-bit ATL DLL.
I did some more searching, and I found a number of references on the web regarding problems with actxprxy.dll on 64-bit windows. This is the DLL where the interfaces appear to reside, according to OLE Viewer.
Anyways, some people have had luck with various combinations of .reg scripts and unregistering/re-registering the files. Unfortunately, I'm not one of those people.
I've decided to save myself the headache, and just wrote a small DLL using ATL, and I have the VB code calling that. Works fine in that setup...
Thanks again for your help.

Resources