Shell hitting Run-Time error '5' trying to call R script in Access VBA - vba

I made a simplified version of my code that directly highlights the issue.
I have read dozens of similar issues/solution.
Part of my workflow in VBA in Microsoft Access involves calling an R script that does some logic and returns information to a table in the same database.
It was working until we moved the location of the R installation to a new drive. Changing the path to this new install location does not work. No other code is changed.
cmd = "C:\R\bin\i386\Rscript.exe C:\R\test.R"
Debug.Print cmd
Shell cmd
I get
runtime error '5'
I am using the immediate window to check the paths are correct and copying them into RUN to verify that they do work.
The above outputs:
C:\R\bin\i386\Rscript.exe C:\R\test.R
It works in RUN.
The first thing I found when searching online is to add more (") as shell can handle them weirdly:
cmd = """C:\R\bin\i386\Rscript.exe""" & " " & """C:\R\test.R"""
Or any iterations of using "s in different places, output:
"C:\R\bin\i386\Rscript.exe" "C:\R\test.R"
Same error but works in RUN. I also tried them all successfully in CMD.
It seems just Shell refuses to launch R from that path. I have moved it elsewhere on my C drive with same effect.
I cannot recreate the original R installation path as that shared drive is now completely dead.
EDIT:
I changed to using ShellExecute simply to try and make Notepad ++ open, again works in cmd.
Set objShell = CreateObject("Shell.Application")
objShell.ShellExecute "C:\N\notepad++.exe", "C:\R\test_in.csv", "", "open", 1
This time I hit a "suspicious macro error" that leads me to believe that it may be an antivirus setting (macros are enabled in Access) blocking Shell from calling anything.

After days of testing I have found the solution, hopefully this can help anyone else in a similar situation. Windows Defender only blocks shell calls to non-Microsoft products, so I nested a call to PowerShell within the call to Shell:
Shell ("powershell.exe C:\R\bin\i386\Rscript.exe C:\R\test.R")
Take note you need to play around with the "s a lot ot get it working, my actual pipeline has more arguments and I had to enclose them in 5 sets of "s for it to pass through to powershell properly. IE:
Dim codePath As String: codePath = """""\\example\example"""""

Try these variations using Start or a second Command:
cmd = "Start C:\R\bin\i386\Rscript.exe C:\R\test.R"
or:
cmd = "cmd /c ""C:\R\bin\i386\Rscript.exe C:\R\test.R"""

Related

How to call java object in VBA with classpath

We use a CMD to call a PowerShell script. In the PowerShell script, a Java program is called. Both files are in the same directory. I want this all replaced by VBA within Microsoft Access. I have found several related topics but I can't decide whether it is possible or not based on these topics. Topics like Launch jar file from VBA code
The CMD contains the following code:
SET CLASSPATH=.\yyyyy.jar
powershell .\startscript.ps1
The PowerShell script contains the following sample:
& java '-Djavax.net.ssl.trustStore="zzzz.keystore"' com.router.router.router.Router -user:... etc.
We also run the same Java program in a different setting, only with the use of one .CMD-file. This is made like:
SET USR=user
SET CLASSPATH=.\yyyyy.jar
java -Djavax.net.ssl.trustStore=zzzz.keystore com.router.router.router.Router -user:%USR% etc.
Preferably both PowerShell and CMD become obsolete and the parameters like "-user" are fed with variables from the VBA code.
Does someone have a usable link, example or code? Please advice.
What you are trying to do is to run a command via the command line. It just happens that this command runs java, as far as the VBA code is concerned it may run anything that the shell would understand.
A sample code to run a command via a shell in VBA is the following (note there are many ways and it's super easy to find these samples on internet, I'm just using the first one I found):
Dim wsh As Object
Set wsh = VBA.CreateObject("WScript.Shell")
Dim waitOnReturn As Boolean: waitOnReturn = False
Dim windowStyle As Integer: windowStyle = 1
wsh.Run "cmd.exe /S /C " & yourCommand
... where yourCommand is the litteral string you would run in your command prompt. Now, it's all about string concatenation in VBA. Following your sample (and adding the username directly from VBA):
user = Environ("UserName")
yourCommand = "java -Djavax.net.ssl.trustStore=zzzz.keystore com.router.router.router.Router -user:" & user
(please note that I replaced %USR% - which asks the shell to retrieve the username - with a variable user that I've defined in VBA, even though in this specific example, the function Environ is asking environment variables so it's still asking it to a shell).

CMD file executed from VBA leads to different results

PROBLEM IS SOLVED ALREADY
this should be fairly simple, but I can't figure out what's wrong.
I have a cmd file in V:\something\XYZ.cmd, which takes 1 parameter.
When I execute it manually, e.g. Windows-Explorer and double-click the cmd, I get my result.
Now I have a XLSM file on my Desktop and a macro should invoke this cmd instead.
Problem is, when executed that way, I get some "file-not-found errors" in the cmd itself.
So how could I simulate the manual execution of the cmd.
There must be some path related problem...
This is how I execute from VBA:
Call Shell("cmd.exe /c " & "V:\something\XYZ.cmd" & " " & someParameter, vbNormalFocus)
I tried to put a
ChDir "V:\something\"
right before the call, but that doesn't change anything...
Where's the problem?
thank you, I just found the error myself:
There was a %root% used inside the script, this was the error. Changed it to absolute path, now it works

Call .reg File from Excel-VBA script

I want to call a .reg File out of my VBA script. I'm using Office/Excel 2013.
I know Excel can't run these files by itself, so i need to call the file via shell. The code i wrote doesn't work:
Sub deactivateHyperlinkWarnings()
Dim x
x = Shell("cmd /C C:\TEMP\DisableHyperlinkWarnings.reg")
End Sub
I found this piece of code somewhere on the web, but its not working. I don't even get an error message. The .reg File is located in C:\TEMP
What do i need to write to make it work?
Plus: Is it possible to suppress the MessageBoxes that are displayed when i run the .reg-File? When i start the file manually, i need to Hit "OK" like 3 Times. The people who are working with the Excelsheet later on shouldn't be seeing these things.
Instead of running cmd try to run reg. So in your case it should be x = Shell("reg import C:\TEMP\DisableHyperlinkWarnings.reg")
More info here

Launching Ruby script with command line flag from VB .NET

This question might seem easy, yet there seems to be a tiny tricky moment I cannot bypass.
In a nutshell, I am launching a ruby/watir web automation script from a VB .NET app. The script can work with webdrivers for IE, FF and Chrome. In case of first two it is simple. In case of Chrome it needs to launch the .rb file with --log-path flag.
Here is my code:
Dim chromeStarter As New ProcessStartInfo(generatedScripts(i))
Dim args As String = " --log-path=" & testRunPath & "\chromedriver.log"
If isChrome = True Then
chromeStarter.Arguments = args
Process.Start(chromeStarter)
Else
Process.Start(chromeStarter)
End If
Problem: Indeed it launches the correct .rb file, yet does not take flag into account.
I tried passing both file name and flag as a single string to Process.Start and it didn't work as well.
Flag works fine when script is manually run from cmd.
Thanks in advance for your advice!

WMI remote process to copy file

Long story short, my application needs to copy a file to a remote target where UNC connections TO the target might not be possible. However UNC connections FROM the target and BACK to the server will always be possible. So the plan was to use WMI to start a remote command shell (cmd) and use the copy command to grab the file. But this doesn't work. The following command works fine when executed manually from the command line of the target:
copy \\192.168.100.12\c$\remotefile.txt c:\localfile.txt
But when I try this same command as part of the InputParameters("CommandLine") it does not work, and produces no error. Note that I can use WMI to connect to the target and remote execution works just fine as I can start calc.exe etc. Here is the code that doesn't work:
Dim ConnectionOptions As New System.Management.ConnectionOptions
With ConnectionOptions
.Username = "target\Administrator"
.Password = "password"
End With
Dim ManagementScope As New System.Management.ManagementScope("\\192.168.100.11\root\cimv2", ConnectionOptions)
Try
ManagementScope.Connect()
MsgBox("connected")
Dim ManagementPath As New System.Management.ManagementPath("Win32_Process")
Dim ManagementOptions As New System.Management.ObjectGetOptions
Dim ManagementClass As New System.Management.ManagementClass(ManagementScope, ManagementPath, ManagementOptions)
Dim InputParameters As System.Management.ManagementBaseObject = ManagementClass.GetMethodParameters("Create")
InputParameters("CommandLine") = "cmd /c copy \\192.168.100.12\c$\remotefile.txt c:\localfile.txt"
Dim OutputParameters As System.Management.ManagementBaseObject = ManagementClass.InvokeMethod("Create", InputParameters, Nothing)
MsgBox("done")
Catch ex As Exception
MsgBox(ex.Message)
End Try
Any ideas why this isn't working? Or does anyone have a better way of doing what I'm trying to do?
Frank you should actually give yourself credit since the method you created is likely the first ever to get around WMI limitations of remote file copy! I did 3 weeks of searching for info/workaround and yours is the only one that works! If I had any points I would vote for your solution...
I created a fully working VBS & WMI script based on your method:
InputParameters("CommandLine") = "cmd /c echo myFTPCommands > c:\ftpscript.txt"
where you replace myFTPCommands as needed with whatever script you want to go into the file c:\ftpscript.bat (or .vbs, .ps1, or whatever you like). If you couldn't fit enough text in the one-line script, then append with the same method using >>. Now, you can use XCOPY, PSEXEC, COPY, or anything else to run the script you just created on the remote host's file system.
Here's my fully fleshed out VBScript using your method. Thanks again. :)
HTH,
Lizz
For security reasons, most methods of programatically connecting to a remote machine and telling it to copy a file to itself from another machine are blocked. One thing that finally worked for me is FTP. Using the above code I can do something like this:
InputParameters("CommandLine") = "ftp -s:c:\ftpscript.txt"
Which causes the ftp commandline utility to run on the remote machine, using c:\ftpscript.txt to get a list of commands from. Since there is no way to copy the ftp script file to the target (again, no UNC connection), I can first do:
InputParameters("CommandLine") = "cmd /c echo myFTPCommands > c:\ftpscript.txt"
And this works :)
UPDATE: Never thought to use XCOPY and it works perfectly:
InputParameters("CommandLine") = "cmd /c echo F | xcopy remotefile localfile"
UPDATE: XCOPY worked yesterday, now it doesn't. NOTHING has changed, so I am at a complete loss for explanation.