2

I have to write a program in Visual Studio 2013, but it doesn't work, so I started testing all the possibilities with Microsoft Excel and its developement playground. I started with the following version (provided by the company supplying the program I need to use):

Sub Main()

    Dim XServer As X2000.Server
    Dim XApp As X2000.Application
    Dim XSR As X2000.ScriptRoutines

    Set XServer = New X2000.Server
    Set XApp = XServer.AppConnection()    '<- This actually fires the application
    XApp.Visible = True

    Set XSR = XApp.ScriptCommands
    XSR.DATA_FILENAME = "C:\X2000\myFile.x"    ' <- Code blocks here

End Sub

This basically starts the application X2000.exe, connects my code to it, and then executes the DATA_FILENAME assignation routine, by loading myFile.x in the program. I need to start the application, because at that point its license is checked, and I don't have any other option to work with.

Now, in this version, the code was blocking at the last line by saying "A dll is missing" without any other information. I tried late-binding the ScriptRoutines object by doing the following:

Dim XServer As X2000.Server
Dim XApp As X2000.Application
Dim XSR As Object

Set XServer = New X2000.Server
Set XApp = XServer.AppConnection()
XApp.Visible = True

XSR = CreateObject("XApp.ScriptCommands")

This doesn't work as well, but did give me a piece of information more: "ActiveX control couldn’t load the object". I did a little research, and found out, through "Dependancy Walker", that X2000.exe was depending on MSVBVM60.DLL, which was missing in the system32 folder. Curious though, because my system is 64bit, Excel is too, and I tried the code on VS2013 by using a 32bit compatibility and still the code didn't work.
I installed the service pack from Microsoft, where this file was contained, only to find out, that system32 was left untouched... sysWoW64 instead had already a MSVBVM60.DLL, therefore I suspected that X2000.exe was written only to work with 32bit systems: I was wrong.

A colleague of mine could execute the same program written in MATLAB code:

function [Data,eng_or_met] = Read_X2000_File_BB_2(sFileName)

XServer = actxserver('X2000.server');
XApp = XServer.AppConnection;
XApp.Visible = 1;
objX2000 = XApp.ScriptCommands;
objX2000.data_filename = "C:\X2000\myFile.x";

delete(XServer);

This code works thanks to the actxserver function, which I believe to handle this compatibility problem.

How can I do the same with Excel/VS2013?

EDIT:

I tried with the code suggested by omegastripes:

Dim XSR As Object
Set XSR = CreateObjectx86("XApp.ScriptCommands") ' create ActiveX via x86 mshta host

being CreateObjectx86 the function linked here. I tried both the If / Else conditions and at the end the object is not created anyway, both with:

Set CreateObjectx86 = oWnd.CreateObjectx86(sProgID)

and

Set CreateObjectx86 = CreateObject(sProgID)

The last line is what gets executed if I don't change the code (therefore not #If Win64).

EDIT:

As per the first answer to this question, I also tried:

Dim XServer As Object
Dim XApp As X2000.Application
Dim XSR As X2000.Script

Set XServer = CreateObject("X2000.Server")
Set XApp = XServer.AppConnection()
XApp.Visible = True
Set XSR = X2000.ScriptCommands

Only to find out I get the same error.

Noldor130884
  • 974
  • 2
  • 16
  • 40
  • Chances are actxserver is doing exactly the same thing but the context is different. If your app was written using VB6, then you must have MSVBVM60.dll somewhere. Run this: https://www.microsoft.com/en-us/download/details.aspx?id=24417 also check this https://blogs.msdn.microsoft.com/deva/2009/12/30/development-is-visual-basic-6-0-runtime-still-supported/ and if your app was built using a localized version of VB6, make sure you install localized VB6 support binaries – Simon Mourier Aug 23 '17 at 08:36
  • *I installed the service pack from Microsoft, where this file was contained* <- I already ran the file you linked me to. I cannot be sure that `X2000` was made with localized VB6, but it it were, I'd guess that'd be the standard version, that comes with every VB6, since the company providing `X2000` is from U.S.A. – Noldor130884 Aug 23 '17 at 09:16
  • if it's from USA, I don't think you'd need anything localized indeed. What I would do is use sysinternal's procmon tool and monitor files (filter by your program's exe name). This could help you determine the missing ones. It may be a satellite file, or one you didn't think of. – Simon Mourier Aug 23 '17 at 10:06
  • I'm not familiar with it, but I guess I could try... if I only were an admin -_- – Noldor130884 Aug 23 '17 at 10:53
  • @Noldor130884 I guess you are testing with 64-bit Office version, while MATLAB is 32-bit version, and ActiveX is written for 32-bit applications only, so it's working in MATLAB on x64 OS via WoW64. You may try late binding using [this method](https://stackoverflow.com/a/38134477/2165759). – omegastripes Aug 23 '17 at 14:17
  • @omegastripes I am not really sure (right now I cannot check), but I think MATLAB too should be 64bit. Anyway, could you elaborate on that solution? I don't think I understood how to create a `X2000.Server` with that late binding... – Noldor130884 Aug 24 '17 at 06:14
  • Checked: MATLAB too is 64bit – Noldor130884 Aug 28 '17 at 10:46
  • I'm aware you've found a workaround. I *think* I know what the issue is. But first, three questions in order to check. 1) Is a UAC prompt displayed when you run the first version of your code? 2) Does copying `MSVBVM60.DLL` from `sysWoW64` to `system32` enable the code to run correctly? 3) Does your workaround still work using `Dim XApp As X2000.Application`? – robinCTS Aug 30 '17 at 03:51
  • Well, I'm all ears :) I always appreciate someone who can teach me something. About your questions: 1) No UAC prompt is displayed. 2) No. I tried that before already. Dependancy Walker highlighted several DLL not found at that point. 3) No it doesn't – Noldor130884 Aug 30 '17 at 05:26

1 Answers1

1

I apparently solved the issue. Inspired by Hans Passant, I Dimed the XServer as the only object depending on the reference to X2000.exe:

Dim XServer As X2000.Server
Dim XApp As Object
Dim XSR As Object

Set XServer = New X2000.Server
Set XApp = XServer.AppConnection
XApp.Visible = True
Set XSR = XApp.ScriptCommands

XSR.DATA_FILENAME = "C:\foo.x" 

DATA_FILENAME is actually a "ScriptCommand" that gets executed.

Simple as that. Yet I have no idea why this works.

Noldor130884
  • 974
  • 2
  • 16
  • 40