VBA not assigning object to variable - vba

I am, perhaps foolishly, running an old and complex MDB (originally written in Access 2003, where everything worked smoothly for about a decade under good old XP) with lots of VBA in Access 2013 under WINE (well, Crossover Linux). Most things work, surprisingly, but I have a strange problem with automation. The following code launches an instance of Word that can be seen in task manager, but doesn't assign any object to oWord. It fails at oWord.Visible=True with error 91 and oWord is Nothing.
Dim oWord As Word.Application
Set oWord = CreateObject("Word.Application")
oWord.Visible = True
I've tried early binding and late binding and more or less every line of code that can possibly be used to start Word. Using New Word.Application (or New anything) instantly crashes Access and WiNE's crash report is beyond me. I have exactly the same problem with automating Adobe Acrobat Pro, so this isn't about Office: Acrobat starts, but no object is assigned and I get error 91. Both programs launch happily from Shell. CreateObject is not always failing, either: oddly elsewhere in the database I have no problems with
Dim HttpReq As Object
Set HttpReq = CreateObject("MSXML2.XMLHTTP.6.0")
(but it fails without the version number).
I don't think this is to do with references, either, though I can list them if anyone thinks it's worth it.
Sorry this post is all over the place, but, to summarise.
I think my problem is probably with one of the dlls that WINE uses, and the advice I want is about which dll is likely to cause these particular problems if it is corrupt or incorrect. Then I can try different versions, maybe extract a clean copy from a Win 7 ISO (I've tried several copies of oleaut32.dll, which can be a sore subject with WINE, to no effect save that you can't run VBA at all with WINE's builtin version). I don't want to reinstall Office 2013 because it's so twitchy about activation under WINE. I don't want to risk blowing a perfectly valid licence testing it in a new wineprefix/bottle. I have a separate installation on a second workstation that's doing exactly the same thing. I'm running Lubuntu 18.04 LTS with WINE 3.0.5 and Crossover Linux 18; the wineprefixes are emulating Win 7.
Any help would be very, very gratefully received. I know this is a quixotic project, but so much works perfectly that this is really frustrating. Thank you.

Related

Creating an instance of Visio in vba when 2 versions are installed

I have the below code to create an instance of Visio from Excel. It works on machines where I have a single version of Visio installed, but on some machines I have 2 versions (2010 and 2016) installed. On these machines it fails to run with the error "Method 'Visible' of object 'IVApplication' failed". When I check AppVisio its empty, and I am guessing it is because both applications are visio.exe. Is there a way to create the object from a specific path, or any way to createobject when 2 versions are installed?
Set AppVisio = CreateObject("visio.application")
AppVisio.Visible = False
Set docsObj = AppVisio.Documents
There are some options I believe.
Solution 1 (I would recommend this one). Install only Visio 2010 on your development machine (and uninstall 2016). It's safest to have the lowest version you want your app to run with on your dev machine anyways. Add a reference to Visio 2010's type library in Excel. Remove the reference to Visio 21016 type library. Visio versions are upward-compatible, so the code should run properly even on the machine with Visio 2016.
Solution 2. Use late binding. Remove the reference to the Visio from your excel project altogether and use only script-like access. In this case, you will lose auto-completion though. If your app is not a big one, that should not be an issue.
Solution 3. (if you want to run a specific version). You can start the Visio application from the program files (like any other executable), and then connect to it using "GetObject(...)" instead of "CreateObject(...)"
BTW, there is a better way to run Visio as invisible app (without flashing):
Set appVisio = CreateObject("Visio.InvisibleApp")
If you early-bind it by adding a reference (Tools | References) to the desired version then Diming your object as that type, you'll be guaranteed which version you're using.
Dim visioApplication as Visio.Application
Set visioApplication = new Visio.Application
However, that may not be the full solution if your company is mid-upgrade and some folks have the new version and some the older version. You'd get run-time issues on the machines that don't have your chosen version.
To solve that issue, you could create MyApp2010 and MyApp2016, each linking to the appropriate version of Visio, but that becomes a bit of a maintenance nightmare for you...
Early-binding does add loads of benefits like IntelliSense and turning most run-time errors into compile-time errors, so it's probably still worth it.

MSCOMCTLocx registering but still showing as 'Missing'

I am using VBA hosted in a drafting program called MicroStation. I have been using MSCOMCTL for the last few years to use controls such as Tab Views and ListViews. I have come back from a work trip and found my home PC to have a Windows Updated and im assuming that its broken it as i have found many articles relating to similar problems.
MSCOMCTL will register and says it has succeed, but still shows as missing in the VBA IDE. Usually i can just use the regsvr32 command and it will work no problems.
I have researched alot and have found a heap of solutions, but none work for me. The main one seems to be to run.
regsvr32 c:\windows\syswow64\regtlib.ocx
But i cant find regtlib.ocx on my Windows 10 - 64 Bit PC.
With this VBA Program, the company where it is deployed is very restricted on what the users can do so im hoping to find an alternative to MSCOMCTL but still within VBA that i can somehow package / compile within my VBA file and doesnt need to be installed onto the PC. Either that or a solution to get the file working. I have been reading article after article and trying a heap of things over the past few days but nothing has worked. It seems at the moment that my best option is to redesign the forms without the Tab Control and List Views. But i find this crazy as they are microsoft files.
Thanks in advance!
So far i have tried the below (plus a couple more escape me at this time)
*Replacing MSCOMCTL.ocx with a downloaded version (backed up the original just in case)
*Replacing MSCOMCTL.ocx with a version installed with Office 2013, located under the program files x86/office/root etc.
*Registering MSCOMCTL in safemode to ensure it wasn't in use.
*Searching the C drive for regtlib.ocx as that has been known to fix it.
*I did find an alternative, but requires various files to be installed onto the PC which wouldn't work in this case with the company's restrictions
*I know this is not a new issue, but most of the posts are a few years old and their solutions (usually re-registering the file) have not worked for me.
Thanks everyone. Problem has been solved. It was a combination of a couple of things based on dbmitch's answer.
By unchecking the missing control, closing down the host program and rebooting. Then opening up the VBA file and searching for the "Microsoft Common Controls" and selecting it. Even though the text was the exact same as the "Missing" one it seems to have done the trick.
I did do that step, but didn't close down the program and start again in between.
Thanks for your help guys!

WiX behaving badly on XP machine with windows update issues

My WiX bundle behaves very badly on a specific XP machine (x86). It stalls for six minutes during the "initializing" phase (before any bundled installers are run). From the logs it seems extremely likely it is due to the dodgy state of windows update on the machine:
[090C:0FC0][2018-03-27T19:31:17]i358: Pausing automatic updates.
[090C:0FC0][2018-03-27T19:37:23]w308: Automatic updates could not be paused due to error: 0x80080005. Continuing...
[090C:0FC0][2018-03-27T19:37:23]i360: Creating a system restore point.
I am using WiX v3.10 to make the bundle. I can find very similar situations from google search but the solution always revolves around updating the target machine. I need this installer to work as expected regardless. When I test a regular msi on the same machine it goes through fine.
Is there any way I can mitigate this issue? E.g. can I stop the WiX bundle from trying to pause windows update or something similar? The fact that the installer doesn't even notify what the issue is is extremely problematic, any user is likely to be confused.
The whole point of this WiX installer is to make an install package portable and simple but this actually seems LESS portable than just the msi...
Update: Also tried building the bundle with WiX 3.11 but got same problem. Though now it produces an actual error rather than installing regardless, which I suppose is an improvement.
UPDATE: after looking in the WiX source code it looks like WiX's Burn feature is making a few calls to Microsoft.Update.AutoUpdate (%SystemRoot%\System32\usoapi.dll - %SystemRoot%\SysWOW64\wuapi.dll) and a few other COM objects here and there.
See towards the bottom (screenshot) for a hot COM tip to quickly get an overview of different COM object models.
It must be this AutoUpdate call which hangs causing a timout along the lines of what is described in this blog. I believe you can find the exact source code location by searching for hr = WuaPauseAutomaticUpdates(); in the elevation.cpp WiX Burn source file (Github link). The actual calls to the COM object are in wuautil.cpp.
I am not familiar with the Windows Update Agent Object Model, but I suppose you could try to call the Pause function in a test VBScript just to see what kind of error you get on your problem system (if any). I can't see how you would get anything but a lockup on your problem system, so maybe try first on your main box? This is obviously at your own risk. I would assume a reboot or a call to Resume will continue the process as normal. I also see a call to SystemInformation.RebootRequired in the C++ code, which I have also added to the VBScript:
Set autoupdate = CreateObject("Microsoft.Update.AutoUpdate")
autoupdate.Pause()
MsgBox Err.Number & " " & Err.Description
Set sys = CreateObject("Microsoft.Update.SystemInfo")
MsgBox sys.RebootRequired
' autoupdate.Resume() ' Enable to resume AutoUpdate
Set sys = Nothing
Set autoupdate = Nothing
Let's face it: Windows Update is broken on your XP machine - isn't it? Maybe the WiX guys can add a shorter timeout? I am not sure what is better - 1) to shorten the timeout, 2) to remove the whole call or 3) to just bomb out telling the user that Windows Update is broken? Frankly the latter would probably alert the user to something very serious (often malware).
UPDATE: as you state yourself, Windows Update is almost certainly broken on this particular machine. I would try the MSI properties suggested below for testing, and then zap Windows Update as suggested here (same link as below) (techical).
But wait, maybe a malware check is in order, before wasting time on anything else?
Maybe try this free Sysinternals tool? Checks all running processes by hash using almost 70 scanning engines (no heuristics though). Fire up all you got (only running processes are checked)
Go File => Show Details for All Processes and then elevate to get to scan system processes as well. Now click "System" to scan drivers for example (*.sys files).
Often a great way to get your system admin to agree to rebuild a problematic machine for everyone. Suddenly you go from "deployment problem" to "machine specific problem" - and it is out of your hair. GIGO problem.
Nicely formatted and phrased question BTW. And just for reference: Sysinternals.
Workaround?
I have never seen this, but I have seen some MSI files suddenly pausing for a long time whilst installing whereas they would install quickly during test installs just minutes before.
My guess is that this could be related to system restore and the creation of a restore point at certain "intervals". I am not sure what algorithm is used to determine when such a restore point is created and not, but I wrote an answer many years ago on the issue of speeding up MSI installations: How can I speed up MSI package install and uninstall?
As you will see, you can disable the creation of a restore point for your setup by setting an appropriate command line involving the property MSIFASTINSTALL (and a few other tweaks - please just read the linked serverfault.com answer). I would try this to see if your setup stops locking up / hanging.
Causes?
Some hits from the web:
Could it be that Windows Updates is also trying to create a restore point at the same time as your MSI-package? Setup hang when trying to disable windows updates (PhilDW)
Could it be that the Windows Update feature is corrupted?
Similar issue: WiX Toolset installs VC++ redistributable (x86) 2015 too slowly
I would first try the MSI properties mentioned as a "workaround" above, and if that doesn't work, I would try to see if fixing Windows Update as explained in the link directly above works. Crucially I would also let Windows Update complete its task of installing all available updates before running your bundle again.
Hot Tip (COM)
I don't like to recommend commercial tools, but we all need some quick tricks and quick wins at times - which is what this is about. Get hold of VbsEdit and use its light weight object browser to quickly see details from any COM object model. Just do a CreateObject and you will instantly see the object model in the object browser to the right in the application window (View => Object Browser if it is not there).
Just type in something like this:
Set installer = CreateObject("WindowsInstaller.Installer")
I find this to be a time-saver when I need to deal with legacy COM stuff and Visual Studio is very sluggish. I just have the VbsEdit trial version, and it allows basic editing. And let's throw in a rant: why on earth do they not make a Javascript version? I am missing something - as usual :-).
Throwing in a second screen shot to show a more interesting object model information tidbit:
Should you want to try it, here are some other CreateObject statements you can try:
Set autoupdate = CreateObject("Microsoft.Update.AutoUpdate")
Set fso = CreateObject("Scripting.FileSystemObject")
Set scriptshell = CreateObject ("WScript.Shell")
Set dictionary = CreateObject("Scripting.Dictionary")
Set shell = CreateObject("Shell.Application")

Change on Visual basic 6 application, exe crashes

For my customer i had to do a change in a visual basic 6 application running on a windows xp computer.
It's nothing special, just communicating with a plc and functions as a user interface.
My changes work absolute perfect in developer environment(IDE), but when i create the exe it crashes when opening some forms or pressing some buttons. Some stuff works, and some stuff crashes.
Compiler in develop doesn't give any errors even after full compile!
I found some "bugs" by iterating the code and this really is just deleting some variables. (that already existed + It isn't a programmable error) The compiler doesn't give an error, just the exe crashes on it.
An example from bug that crashed:
sub On form_load()
Some code
Global_String_Variabel = "Something"
some code
End sub
By deleting the global string variable just in this form, it didn't crash any more.
It's weird because this peace of code already existed, works perfectly fine in develop but not in .exe
Does somebody have any idea why this could happen?
If I understand your question correctly, the program runs on your development machine both in IDE and compiled in both states, with the string assign and without, yet works only without on the client's machine. Something like this happened to me many years ago, and while it may not be your problem, you might at least be able to rule it out. The client may have a virus scanner that erroneously thinks that a segment of your code is malware. Just adding another line like x = x or something else benign can sometimes fix it.
You may also need to look further into other differences, like other things they have/run that you don't.
Not that it should matter but are you declaring the variable somewhere and using Option Explicit?

Error 48 loading dll after rebuilding code, MSADO-related

I am getting confusing and seemingly inconsistent results with one ActiveX DLL trying to create an instance of another.
Everything worked until we rebuilt our entire codebase, something which had never done since taking it over a few years ago. We previously just built pieces as we needed them.
The problem is occurring in multiple places, but here is a representative example:
Dim objMid As MiddlePiece.clsMyClass
Set objMid = CreateObject("MiddlePiece.clsMyClass")
This is hitting an error (48: Error in loading DLL) on the CreateObject line. I tried changing around the code and came up with the following results.
Dim objMid As MiddlePiece.clsMyClass
Set objMid = New MiddlePiece.clsMyClass
That gives me error 48 again.
Dim objMid As Object
Set objMid = New MiddlePiece.clsMyClass
That also gives error 48.
Dim objMid As Object
Set objMid = CreateObject("MiddlePiece.clsMyClass")
That one actually works.
Can anyone explain what the real difference is between these, and why only the last one works now, whereas at least the first one was working before?
I think I understand the difference between early and late binding, and that only the last example is an instance of late binding, but I've checked and confirmed that on both the build PC and the test machine, the registry contains the same version of MiddlePiece.dll, so I'm not clear on why this would fail.
The problem seems to stem from the fact that MiddlePiece.dll was built with Microsoft ActiveX Data Objects. There have been numerous issues related to this ever since we moved from Windows XP to Windows 7. The msado26.tlb library no longer worked for us, so we had to change our references to that library to refer to msado60_Backcompat.tlb instead. That seemed to work for a while, but we've since had more trouble with two different versions of msado15.dll. The newest version is breaking code in both VB6 and C++.
We replaced all references to msado60_backcompat.tlb with references to msado26.tlb, essentially undoing a "fix" we first implemented when we transitioned to Windows 7 about two years ago. This is basically all due to problems introduced by Microsoft. A good starting place to research the issue, for those who care to know is here. This allowed us to rebuild everything on the Windows 7 machine and resolve multiple issues.