Running a batch file in a network directory using VBA - excel

I have a .bat file calling from VBA, it is working when I use a local folder as path (example as C:\Users\cthoud01\Desktop\my scripts\scripts).
However, I got an error if I use a path from a network directory (example - H:\scripts). I also tried replacing the path as """H:\scripts\""" but continue to get the same error. I would like to hear from our experts if there is any way around to make this work.
Below is the error message I receive:
VBA Code I am using:
Sub test()
Dim wsh As Object
Set wsh = VBA.CreateObject("WScript.Shell")
Dim waitOnReturn As Boolean: waitOnReturn = True
Dim WindowStyle As Integer: WindowStyle = 1
Dim errorCode As Long
Dim pth As String
errorCode = wsh.Run("cmd.exe /k cd """ & "H:\scripts\" & """ && DeleteMatrix.bat", WindowStyle, waitOnReturn)
If errorCode <> 0 Then
MsgBox "fail, please retry"
End
End If
End Sub

errorCode = wsh.Run("cmd.exe /k cd /d """ & "H:\scripts\" & """ && DeleteMatrix.bat", WindowStyle, waitOnReturn)
Look at the extra /d.
In MSDos each drive had a current directory.
C:\>cd D:\dog
C:\>Copy *.* D:
would copy files into the d:\dog directory. This makes typing easier. There were no mouses or menus.
Windows only has the concept of current directory (and it's per program).
So MSDos batch files run unchanged in CMD you have to tell windows you don't want MSDos behaviour with the CD command by using /d.
Likewise CMD simulates a default drive per directory.
This is what it looks like in the process's environment block
=C:=C:\Users\David Candy\Desktop\Editor\EditorSdi
=D:=d:\~MSSETUP.T

Related

open .exe in VBA excel and write in the input window

I have to run an .exe in VBA Excel and write in the input window "in.txt" "out.txt" in order to make the process automatic inside a macro. I tried to use shell but it works asynchrounous and I also don't know how to tell her to write inside the .exe.
I've also tried with SendKeys but apperently it doesen't work.
How could I make the VBA calling my .exe, open it, write inside the command window of the .exe, wait for the output and use it to go on?
thank you in advance
here are two attempts (both failed):
Sub write()
prog = Shell("C:\Users\arancia\Pictures\Camera Roll\axtur\axtur\AXTUR_64.exe", 1)
Application.Run "'AXTUR&EXCEL.xlsm'!inserisci_dati_input"
SendKeys.send "in.txt~", True
SendKeys.send "out.txt~", True
SendKeys "%{F4}", True
End Sub
Sub StartExeWithArgument()
Dim strProgramName As String
Dim strArgument As String
strProgramName = "C:\Users\arancia\Pictures\Camera Roll\axtur\axtur\AXTUR_64.exe"
strArgument = "in.txt~out.txt~"
Call Shell("""" & strProgramName & """ """ & strArgument & """", vbNormalFocus)
End Sub
One solution would be to write a batch file that includes all the parameters and then run the batch.
I have used WshShell (Windows scripting host) to run batch files to do what you want in the past but WshShell does not work on our computers since the Nov 2020 updates. WshShell allows you to wait for the outcome of the external program.
One way I found to go around it is to write a simple text file at the end of the batch and wait for it to show up. This is crude but it works.
In the code below, I write a simple batch file in the folder of the Excel sheet. The last line of the batch writes the content of the folder in a text file. The Do Until loop waits for the text file to show up in 1 second increments. When the code resumes after the loop, the text file is deleted. If you write the command line you would type in cmd instead of "echo Hello World" this should work.
You need to reference the Microsoft Scripting Runtime (scrrun) to use the file system object.
Good Luck!
Public Sub RunBatch()
Dim i As Integer
Dim k As Integer
Dim xlWB As Workbook
Dim fso1 As New FileSystemObject
Dim BatFile As Object
Dim IsDone As Boolean
Dim OutFileName As String
Set xlWB = ThisWorkbook
OutFileName = xlWB.Path & "\" & "HW.bat"
Set BatFile = fso1.CreateTextFile(OutFileName)
BatFile.WriteLine "cd /d " & xlWB.Path
BatFile.WriteLine "echo Hello World"
BatFile.WriteLine "dir > Done.txt"
BatFile.Close
IsDone = False
Call Shell(OutFileName, vbNormalFocus)
Do Until IsDone
If fso1.FileExists(xlWB.Path & "\Done.txt") Then IsDone = True
Application.Wait (Now + TimeValue("00:00:01"))
Loop
fso1.DeleteFile (OutFileName)
End Sub

Combination of text file not generate after running cmd from VBA EXCEL

I tried to run Command in CMD from excel VBA to combine file to the only single file but its not wrok. And that command work properly when I run directly in folder
Excel VBA 2013
Sub CombineFiles()
Dim wsh As Object
Set wsh = VBA.CreateObject("WScript.Shell")
Dim waitOnReturn As Boolean: waitOnReturn = True
Dim windowStyle As Integer: windowStyle = 1
wsh.Run "D:\Excel\FT\cmd.bat"
End Sub
MY Code Inside CMD
copy *.txt combined.txt
I expect to get the combination of all text file into single file named Combined.txt
Within your .bat file, you need to change the directory to point to the folder location of the .txt files:
d:
cd\Excel\FT
copy *.txt combined.txt
PAUSE
or
copy D:\Excel\FT\*.txt D:\Excel\FT\combined.txt
PAUSE
I have added a pause so you can see the result of the running bat file, if you wish you can remove the pause command.

Open file - security warning when running a .bat file in vba excel

I am having an issue finding/understanding how to solve the following issue when running a .bat file in VBA in Excel. I am getting an Open File - Security Warning prompt when I try and execute it.
The issue is i don't have administrative privileges, so I can't set .bat files as being ignored from this prompt, and this .bat file is one that I created myself so I don't understand why my computer is flagging it as potentially harmful.
If anyone could explain a workaround, and why such an issue arises despite it being a custom generated .bat file, I would greatly appreciate it. By a workaround I mean modifying the code I currently have to deal with this problem, without having to go through Administrators.
Below is the snippet of code pertaining to the problem, thanks:
sub test()
'some stuff
Open MY_FILENAME For Output As #FileNumber
Print #FileNumber, FileContents
Print #FileNumber, "exit"
Close #FileNumber
'run batch file
Dim wsh As Object
Set wsh = VBA.CreateObject("WScript.Shell")
Dim waitOnReturn As Boolean: waitOnReturn = True
Dim windowStyle As Integer: windowStyle = 1
Dim rtn As Integer
rtn = wsh.Run(Chr(34) & MY_FILENAME & Chr(34), windowStyle, waitOnReturn)
end sub
I should add that if run the shell like so I have no issues:
rtn = Shell(MY_FILENAME, vbNormalFocus)
Except that the code will continue running despite the shell not closing and completing its execution. I need the shell to halt until it has executed it's task.

VBA SendKeys to specific window

I have a spreadsheet that summarizes usage of a server. The spreadsheet references a text file that is updated when I have VBA send some commands to the Linux server through the Windows command prompt (and Cygwin). My problem is that the only way I have found to execute commands in Cygwin is through the SendKeys command. This results in two problems:
I have to trust that the user will not click somewhere until the script is done running.
I have to hardcode the amount of time to wait for the command to be executed before the next command can be sent.
I would (and did) try creating a bash file to run in Cygwin, but I don't know of a way to do this that also allows the user to enter their password to log into the Linux server. I am currently getting the user's password from a UserForm that is run before the main code is executed. This password is then saved to a "very hidden" worksheet that is deleted when the application is closed.
I am currently using the following script to run the commands:
Public Sub test()
' Declare Variables
Dim cmd As String
Dim ret As Double
Dim LastRow As Integer
Dim PssWrd As String
PssWrd = Worksheets("PssWrd").Range("A1").Value
' Run Linux Commands
cmd = "C:\cygwin\Cygwin.bat"
ret = Shell(cmd, vbMinimizedFocus)
wait 0.02
cmd = "ssh " & Worksheets("Settings").Range("LOGIN") & "~" ' Format: user#hostname
SendKeys cmd
cmd = PssWrd & "~"
SendKeys cmd
wait 2.78
cmd = "{(} date ; fs ; qstat ; date {)} > & zout &~"
SendKeys cmd
cmd = "exit~"
SendKeys cmd
wait 0.5
cmd = "exit~"
SendKeys cmd
wait 5
' Update PivotTable and other data
End Sub
Public Sub wait(PauseTime As Double)
Dim Start As Double
Dim Finish As Double
Dim TotalTime As Double
Start = Timer ' Set start time
Do While Timer < Start + PauseTime
DoEvents ' Yield to other processes
Loop
Finish = Timer ' Set end time
TotalTime = Finish - Start ' Calculate total time
End Sub
Is there any way to at least send the keystrokes to a specific window instead of just the active window? Any help would be greatly appreciated, and any additional necessary information will be readily provided.
Okay. I think I found the solution. Thanks for all the help (#anishsane) pointing me in the right direction! Here is my updated code:
Public Sub test()
' Declare Variables
Dim cmd As String
Dim ret As Double
Dim LastRow As Integer
Dim PssWrd As String
Dim WshShell As Object
Dim plink_object As Object
PssWrd = Worksheets("PssWrd").Range("A1").Value
' Run Linux Commands
Set WshShell = CreateObject("WScript.Shell")
On Error Resume Next
Set plink_object = WshShell.Run("""C:\Program Files (x86)\PuTTY\plink.exe"" -ssh " & Worksheets("Settings").Range("LOGIN") & " -pw " & PssWrd & " ""(date; fs; qstat; date) > &zout&""", 7, True)
On Error GoTo 0
' Update PivotTable and other data
End Sub
Evidently, in VBA the WScript is not needed. Also, wshshell.exec seems to fail at some point because the commands never get executed (though PuTTY/Plink is started). For some reason, the WshShell.Run command resulted in the "Run-time error '424': Object required" error, but the essential part of the commands still get executed properly, so I just have the error being ignored. I also figured out how to execute my command all in one line so I don't have to worry about the stdIn.Write command that wasn't working before. I could use the Shell() command, but I need to make sure that the command has finished executing (via the bWaitOnReturn option) to make sure I have the most up-to-date file when the update script runs. Having said that, I believe that since I am having Linux write out the output of the command to a file, the file hasn't finished updating when VBA says the command has finished executing. However, I believe I've figured out a means to check that the last line of text is formatted correctly in the file (since it should be the date), so that shouldn't be a problem.

Shell code doesn`t run in XP environment if processing many files

This VBA code I wrote runs in Windows 7 but not in XP.
Public Function WShellRun(command As String)
Dim wShell As Object
Dim waitOnReturn As Boolean: waitOnReturn = True
Dim windowStyle As Integer: windowStyle = 0
Dim errorCode As Integer
Dim wExec, rslt As String
Set wShell = CreateObject("Wscript.Shell")
wShell.CurrentDirectory = ActiveWorkbook.Path
On Error GoTo WinXpMode
errorCode = wShell.Run(command, windowStyle, waitOnReturn)
If errorCode <> 0 Then
MsgBox "SHELL COULDN`T STARTED " & errorCode, vbCritical, "SHELL ERROR"
Exit Function
End If
Set wShell = Nothing
Exit Function
WinXpMode:
Set wExec = wShell.Exec("%ComSpec% /c " & command) ''(1) execute DOS
Do While wExec.Status = 0 ''(2) wait until response
DoEvents
Loop
'rslt = wExec.StdOut.ReadAll ''(3) show result
'MsgBox rslt
Set wExec = Nothing
Set wShell = Nothing
End Function
I thought WSH doesn't run on XP so I wrote a GOTO to which the code would flow when something happened to the script. But when I run it in XP environment, the WinXPMode part and the upper part runs parallel that it freezes the flow of the program (I think).
I have two questions.
Is there any way to upgrade the code to work in both Windows 7 and XP so I don't have to worry about the environment.
Is there any way to check what is wrong with the code or the system?
I found that when I run the .jar for few files (10 or 20 file names), it goes without any problem. After that I tried for many files like 100 file names. Then it showed me an error that it can't output file (can't write file), which doesn't show up in Windows 7.

Resources