VBA Excel command doesn't work when called with Shell, but works when copy-pasted to cmd directly - excel

I'm trying to run a program with an input file.
Dim command, cfx5_exe_path, cfx_file_folder, cfx_file_name As String
command = cfx5_exe_path & " -cfx " & cfx_file_folder & cfx_file_name & ".cfx "
Shell command
so it gives an error.
the resulting value of the command in the debugger is
"c:\"Program Files"\"ANSYS Inc"\v150\CFX\bin\cfx5pre.exe -cfx c:\Users\Username\Arbeit\Programming\A321_tail_flow.cfx"
If I copy-paste that into windows cmd directly and remove first/last quotation signs, then it works perfectly.
What is the problem with Shell?

The documentation says:
If the Shell function successfully executes the named file, it returns the task ID of the started program. The task ID is a unique number that identifies the running program. If the Shell function can't start the named program, an error occurs.
and it gives a small example:
Sub test()
Dim RetVal
Dim command As String
command = "C:\WINDOWS\CALC.EXE"
RetVal = Shell(command, 1)
End Sub
Here I get Error 53: file not found as calc on Windows 7 resides somewhere else. Do you get this error?
Providing the right path to calc starts the program and returns a unique ID.
However, quoting a part of the correct path will throw the error:
command = "C:\WINDOWS\""SYSTEM32""\CALC.EXE"
but quoting the full path does not:
command = """C:\WINDOWS\SYSTEM32\CALC.EXE"""
So you must remove all embedded quotes and then quote the full path once.

Related

How to enter the user path and directly assign to the command prompt

Right now, I need to create a VBA macro wherein I need to open the cmd.exe then, it will ask the user to enter the path of the file they need to open. Then, the path should be put in the command line. As of now, I already open the location of the cmd.exe and added an inputbox function to enter the path. But, I don't know how to put the value of the path in my command line. Sorry if this seems trivial. I am new to VBA coding.
Private Sub CommandButton22_Click()
Call Shell("cmd.exe /S /K" & "perl a.pl c:\temp", vbNormalFocus)
Dim path As String
path = InputBox("Enter a file path", "Title Here")
Open path For Output As #1
Close #1
End Sub
So, for example the user enter the path: C:\Users\aaa\Desktop\Files\
In command prompt, it should look like this:
<C:\Windows\System32>**cd C:\Users\aaa\Desktop\Files**
Is it possible to do that in VBA?
Thank you.

Using VBA to run WinSCP script

I am able to download files from SFTP in CMD window, by using following code:
WinSCP.com
# Connect to the host and login using password
open user:pw#address
# get all the files in the remote directory and download them to a specific local directory
lcd C:\Users\xx\Desktop
get *.xlsx
# Close and terminate the session
exit
I searched online and found out that I can put these codes in a bat file and use
Call Shell("cmd.exe /c C:\Users\xx\Desktop\WinSCPGet.bat", 1)
However, only the first line of the bat file WinSCP.com is being executed. It will pop up the cmd window, showing this, without doing anything else.
How to execute all the lines at one time?
Thanks
The code you have is not a Windows batch file. It's one Windows command followed by WinSCP commands. The first command runs winscp.com application, which then sits and waits for input. If you eventually close it, Windows command interpreter (cmd.exe) will carry on executing the remaining commands, failing most, as they are not Windows commands. See also WinSCP script not executing in batch file and WinSCP FAQ Why are some WinSCP scripting commands specified in a batch file not executed/failing?
So you either have to save the commands (open to exit) to a WinSCP script file (say script.txt) and execute the script using the /script switch:
Call Shell("C:\path\winscp.com /ini=nul /script=c:\path\script.txt")
Alternatively, specify all commands on WinSCP command line, using the /command switch:
Call Shell("C:\path\winscp.com /ini=nul /command ""open user:pw#address"" ""lcd C:\Users\xx\Desktop"" ""get *.xlsx"" ""exit""")
Regarding the quotes: With the /command switch, you have to enclose each command to double-quotes. In VBA string, to use a double-quote, you have to escape it by doubling it.
Also note that you generally should use the /ini=nul switch to isolate the WinSCP script run from your WinSCP configuration. This way you can also make sure that the script will run on other machines. Your script won't, as it lacks the -hostkey switch to verify the SSH host key fingerprint. Using the /ini=nul will help you realize that.
You can have WinSCP GUI generate complete command-line (including the -hostkey) for you.
See also Automating file transfers to SFTP server with WinSCP.
I like this small and compact procedure, and use it in my own projects. No temp-files required. Fast and reliable.
Parse a string src (an absolute filepath) to uploadImageByFTP. Etc. C:\Users\user\Desktop\image.jpg, and the file will be uploaded.
Replace:
<username> with FTP-User
<password> with FTP-Password
<hostname> with FTP-hostname (etc. example.com)
<WinSCP.com path> with path on your WinSCP-client (etc. C:\Program Files (x86)\WinSCP\WinSCP.com. Caution: WinSCP.com and not WinSCP.exe)
<FTP-path> with path on your FTP-client (etc. /httpdocs/wp-content/uploads)
Sub uploadImageByFTP(src As String)
Dim script As Object: Set script = VBA.CreateObject("WScript.Shell")
Dim waitOnReturn As Boolean: waitOnReturn = True
Dim windowStyle As Integer: windowStyle = 1
'Not empty
If (src <> vbNullString) Then
'Execute script
script.Run _
"""<WinSCP.com path>"" " + _
"/ini=nul " + _
"/command " + _
"""open ftp://<username>:<password>#<hostname>/"" " + _
"""cd <FTP-path>"" " + _
"""put " & """""" & src & """""" & """ " + _
"""close"" " + _
"""exit""", windowStyle, waitOnReturn
End If
End Sub
WScript.Shell is more powerful than the default Shell(), as you can append a waitOnReturn-command; this tells VBA, that further execution isn't allowed before the file(s) have been uploaded to the FTP-server.
Change windowStyle to 0, if you don't like the command prompt to open on each execution.

execute nodejs command from wscript.run in classic asp

I'm trying to execute a nodejs command from a vbscript/classic asp page. I'm starting with lessc (less compiler) but need to use other commands too.
nodejs is installed, and I installed lessc in the global namespace (e.g. npm install -g less) I can (at the server cmd prompt) issue lessc and it works.
at the server command prompt, I can issue a command that executes lessc, such as:
lessc D:\webs\player\Layout\less\app.less > D:\webs\player\Layout\less\app.css
but when I execute it thusly inside vbscript:
dim path : path = "D:\webs\player\Layout\less\"
dim shell : shell = server.createobject("WScript.Shell")
dim errCode : errCode = shell.Run("lessc " & path & "\app.less > " & path & "\app.css", 0, true)
response.write errCode
then it does nothing. Substituting the command so that it runs CMD ahead of lessc goes one step forward: it creates a zero byte output file (app.css):
dim errCode : errCode = shell.Run("CMD /C lessc " & path & "\app.less > " & path & "\app.css", 0, true)
So it looks like it's not finding lessc, even though it's defined in the path variable; ECHO %PATH% at the servers command prompt shows the path where lessc is located. So I tried executing the full path to lessc and even that doesn't seem to work ( no errors, no output ):
dim errCode : errCode = shell.Run("CMD /C C:\Users\Administrator\AppData\Roaming\npm\lessc " & path & "\app.less > " & path & "\app.css", 0, true)
.. frustrated now .. I tried piping the output of lessc itself to a file, and it outputs a zero byte file. So it's doing something, just not executing lessc.
call shell.Run("CMD /C C:\Users\Administrator\AppData\Roaming\npm\lessc > c:\temp\lessc.txt", 0, true)
Just how do you get path variables to work in a shell.run anyway? is there a better way to execute a nodejs command server side from in vbscript/classic asp? it's going to be one of those stupid little things I always forget when working with IIS, isn't it?
Well, after a day of mucking about, I came across a github project that has a compressed node and less combo as a standalone package, that is easy to execute just using Shell.Run and you don't have to muck about with environment variables at all.
https://github.com/duncansmart/less.js-windows
So, answered my own question.

How to create a triple nested command line string for Shell function in VBA?

I need to create a VBA Macro in Excel.
The task is that when a button is clicked a command will be executed in cmd.
The command to be executed is rfrompcb and it takes the path of a file as argument so there is the first level string which wraps the path up as it contains spaces. As this command is to be executed in cmd there is the second level string, which is the argument for cmd command, i.e. cmd /c "rfrompcb ""file_path""" (I hope I have got this one right). Then since it is to be called by Shell in VBA there is the third level string which wraps the cmd command and serves as the argument for Shell.
My question is: How many double quotation marks should there be? I am quite confused about what the final command line string would look like. Can anyone show me how to construct such string? Or is there another way to do it which involves less string nesting?
Thanks.
You would only need to quote file_path, for example:
shell environ$("COMSPEC") & " /c dir ""c:\program files\"" /b"
environ$("COMSPEC") just returns the full path for cmd.exe.
If the executable path you wish to run does not need to be quoted then to pass it an argument that does need to be quoted:
Shell Environ$("COMSPEC") & " /c rfrompcb ""file path"""
If the exe path does need to be quoted you need to wrap it all in another pair of quotes so it looks like:
cmd.exe /c ""c:\path to\rfrompcb" "file path""
Which can be done:
Shell Environ$("COMSPEC") & " /c """"c:\path to\rfrompcb"" ""file path"""""

How do I write to a text file using AppleScript?

So, that's it. How can I write to a text file using AppleScript?
I've tried googling around, but answers seem to be years old and I'm not really sure what should be the preferred idiom this days.
on write_to_file(this_data, target_file, append_data) -- (string, file path as string, boolean)
try
set the target_file to the target_file as text
set the open_target_file to ¬
open for access file target_file with write permission
if append_data is false then ¬
set eof of the open_target_file to 0
write this_data to the open_target_file starting at eof
close access the open_target_file
return true
on error
try
close access file target_file
end try
return false
end try
end write_to_file
Interfacing with it can be cleaned up with the following...
my WriteLog("Once upon a time in Silicon Valley...")
on WriteLog(the_text)
set this_story to the_text
set this_file to (((path to desktop folder) as text) & "MY STORY")
my write_to_file(this_story, this_file, true)
end WriteLog
A short version in pure AppleScript:
set myFile to open for access (choose file name) with write permission
write "hello world" to myFile
close access myFile
It seems there is no native one command solution. Instead you have to open and later close the file.
#JuanANavarro.
When using the shell you should use quoted form of for the TEXT and the file path.
This will help stop errors with spaces in file names and characters like apostrophes in the text for example.
set someText to "I've also learned that a quick hack, if one only wants to spit a bit of text to a file, is to use the shell."
set textFile to "/Users/USERNAME/Desktop/foo.txt"
do shell script "echo " & quoted form of someText & " > " & quoted form of textFile
The above script works fine.
If I did not have & quoted form of someText
but instead I had & someText I would get the following error.
error "sh: -c: line 0: unexpected EOF while looking for matching `''
sh: -c: line 1: syntax error: unexpected end of file" number 2
The apostrophes in "I've" is seen as part of the command.
If I had
set textFile to "/Users/USERNAME/Desktop/some foo.txt" as my file path ( note the space.) And did not have & quoted form of textFile but instead I had & textFile
Then when the file was written out it would write to a file named "some" and not "some foo.txt"
I've also learned that a quick hack, if one only wants to spit a bit of text to a file, is to use the shell.
do shell script "echo TEXT > some_file.txt"
For me running do shell script was too slow on a PowerBook G4 when executed in a loop 300000 times ;), but of course that's quicker to write which sometimes makes sense. You would also want to escape shell characters like this:
do shell script "echo " & quoted form of foobar & " >> some_file.txt"
and for aesthetic reasons I would use
tell me to do shell script "#..."
but I haven't verified yet (what I believe) that if "do shell script" is in a block of "tell Finder" for example it is Finder process that creates a subshell. With "tell me to do shell script" at least Script Editor log looks better for me. ;)

Resources