VBA Shell strips quotes from PowerShell command line - excel

I'm trying to convert windows CRLF newline to UNIX LF newline with a POWERSHELL command. I would like a VBA macro to do that.
So far my code is:
Sub conversiontoUNIX()
Dim wsh As Object
Set wsh = VBA.CreateObject("WScript.Shell")
Dim waitOnReturn As Boolean: waitOnReturn = True
Dim windowStyle As Integer: windowStyle = 1
Dim file As String, listfichiers As Variant, outputfolder As String, replace As String, command_shell As Variant
outputfolder = Environ("USERPROFILE") & "\Downloads\" & "run_param_" & Format(Date, "dd_mm_yy")
listfichiers = listfiles(outputfolder)
For filx = LBound(listfichiers) To UBound(listfichiers)
file = outputfolder & "\" & listfichiers(filx)
Requst = "PowerShell -noexit -Command (Get-Content " & file & ") -join ""`n"" > " & file & ""
command_shell = Shell(Requst, vbNormalFocus)
Next filx
End Sub
I run into an error:
How can i manage to run my code ?
Best regards,
Jouvzer

You need backslashes to preserve quotes around `n in command line:
Requst = "PowerShell -noexit -Command (Get-Content " & file & _
") -join \""`n\"" > " & file & ""

The error message indicates that the "" was removed and the backtick-newline character is not understood. Try adding another pair of double quotes around the
`n

Related

Powershell Command in VBA

I'm trying to run a powershell command to unzip some files, but running in to some issues figuring out the correct syntax. The following doesn't error out, and even when I run the command in powershell itself it doesn't display an error (but also doesn't work). Does anyone know what I'm doing wrong?
Dim command As String: Set wsh = VBA.CreateObject("WScript.Shell")
Dim wsh As Object
Dim waitOnReturn As Boolean: waitOnReturn = True
Dim windowStyle As Integer: windowStyle = 7
Dim pdfPath As String
pdfPath = ThisWorkbook.Path & "\PDFTemp\"
command = "Powershell -Command" & Chr(32) & "{Expand-Archive -LiteralPath" & Chr(32) & _
"'" & frmMerge.txtBoxFile2.Value & "'" & Chr(32) & "-DestinationPath" & Chr(32) & "'" & pdfPath & "'" & "}"
wsh.Run command, windowStyle, waitOnReturn
Thanks so much for your help!
You can remove a lot of parts from that concatenation.
This worked for me (also adjusted the command a little):
Sub Unzipper()
Dim command As String, wsh As Object, waitOnReturn As Boolean, windowStyle As Integer
Dim pdfPath As String, zipPath As String
waitOnReturn = True
windowStyle = 7
zipPath = "C:\Tester\PDF_files.zip" 'frmMerge.txtBoxFile2.Value
pdfPath = "C:\Tester\PDFTemp\" 'ThisWorkbook.Path & "\PDFTemp\"
command = "Powershell Expand-Archive -LiteralPath " & _
"'" & zipPath & "' -DestinationPath '" & pdfPath & "'"
Set wsh = VBA.CreateObject("WScript.Shell")
wsh.Run command, windowStyle, waitOnReturn
End Sub

Can't get WSCript.Shell object's Run method to work

I set up the following test procedure.
Private Sub TryPDF()
Dim oShell As Object
Dim App As String
Dim SrcPath As String
Dim Fn As String
App = "C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe "
SrcPath = Environ("UserProfile") & "\Downloads\"
Fn = "20200509_Order_of_08_05_2020.PDF"
Shell App & SrcPath & Fn, vbNormalFocus ' opens the file
Set oShell = CreateObject("WSCript.Shell")
oShell.Run App & SrcPath & Fn, vbNormalFocus, True ' error -2147024894
Set oShell = Nothing
End Sub
The Shell command in the middle works, thereby proving that app and files exist as and where specified. However, I want the Wait property of the WSCript.Shell object and therefore want to open the file using the line oShell.Run App & SrcPath & Fn, vbNormalFocus, True. I have tested it as shown and without some and any parameters, which should just open the Acrobat Reader when totally stripped, and I always get the same error, "Method 'Run' of object 'IWshShell3' failed".
What am I doing wrong?
You have to escape the spaces in your paths (app and file) by surrounding them with double-Quotes, as the command-line uses them as argument separators. That would make
C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe
C.\Program a file named Program located on C: and that doesn't exists!
"C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe"
will work as expected on command-line.
For some reasons VBA.Shell can handle the spaces in the apppath, but WScript.Shell can't.
Both will fail on not quoted paths to file, if they contain spaces.
My prefered quoting-style is the Chr(34) function
CommanQuoted = Chr(34) & "C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe" & Chr(34) & " " & Chr(34)
& "...\Downloads\20200509_Order_of_08_05_2020.PDF" & Chr(34)
as it is far better readable than the also useable double double-quote
CommandQuoted = """C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe"" ""...\Downloads\20200509_Order_of_08_05_2020.PDF"""
Or you can create a constant that returns a double quote
Const dquote As String = """"
CommandQuoted = dquote & "C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe" & dquote & " " & dquote
& "...\Downloads\20200509_Order_of_08_05_2020.PDF" & dquote
Private Sub OpenPDFWithWScripShell()
Dim oShell As Object
Dim AppPathQuoted As String
Dim SrcPathQuoted As String
Dim FileName As String
Dim shellCommand As String
AppPathQuoted = Chr(34) & "C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe" & Chr(34)
FileName = "20200509_Order_of_08_05_2020.PDF"
SrcPathQuoted = Chr(34) & Environ("UserProfile") & "\Downloads\" & FileName & Chr(34)
shellCommand = AppPathQuoted & " " & SrcPathQuoted
Debug.Print shellCommand
Set oShell = CreateObject("WSCript.Shell")
oShell.Run shellCommand, vbNormalFocus, True
Set oShell = Nothing
End Sub

Using 'wsh.Run' in VBA with spaces in filepath

I am having trouble with using the WSH.run command and escaping the spaces in the filepath - it works fine without spaces! I have tried using double, triple and quadruple quotation marks around each parameter/filepath but it does not like the filepath when the cmd shell is called from the VBA script. This is the script without any escaping:
Dim strFilePath As String
Dim xslFilePath As String
Dim RetVal
Dim wsh As Object
Set wsh = VBA.CreateObject("WScript.Shell")
firstFilePath = "C:\Program Files\myprogram.exe"
secondFilePath = "C:\Program Files\stylesheet.xsl"
strfilepath = "D:\outputfiles\out.xls"
outpath = Mid(strFilePath, InStrRev(strFilePath, "\") + 1)
outfile = Left(strFilePath, InStrRev(strFilePath, ".") - 1)
logfile = outfile & "_errors.log"
cmd1 = firstFilePath & " -s:" & strFilePath & " -xsl:" & secondFilePath & " -o:" & outfile & ".csv > " & logfile & " 2>&1"
wsh.Run "cmd /c /s" & cmd1, 2, True
When I run the following via the command-line with the escaped filepaths the command completes successfully, so I am not sure why this is not working in Excel when it is called with the same escaping applied?
"C:\Program Files\myprogram.exe" -s:"D:\outputfiles\out.xls" -xsl:"C:\Program Files\stylesheet.xsl" -o:"D:\outputfiles\out.csv" > "D:\outputfiles\out_errors.log" 2>&1
Any advice or help appreciated.
Use this for your cmd1 line
cmd1 = """""" & firstFilePath & """ -s:""" & strFilePath & """ -xsl:""" & secondFilePath & """ -o:""" & outfile & ".csv"" > """ & logfile & """ 2>&1"""

Capture Output of WScript Shell Object

This code upload a file to a FTP Server using Putty
Dim wsh As Object
Dim waitOnReturn As Boolean
Dim windowStyle As Integer
Dim cstrSftp As String
Dim strCommand As String
Dim pUser As String
Dim pPass As String
Dim pHost As String
Dim pFile As String
Dim pRemotePath As String
Dim site As String
Dim resp As String
Set wsh = VBA.CreateObject("WScript.Shell")
'Wait the execution to finish
waitOnReturn = True
'Show the window
windowStyle = 1
'Variables
cstrSftp = """" & Application.ActiveWorkbook.Path & "\pscp.exe" & """"
site = "http://mysite/"
pUser = "user"
pPass = "password "
pHost = "ftp.mysite"
pRemotePath = "/home/"
pFile = """" & Application.ActiveWorkbook.Path & "file.png" & """"
'Command string
strCommand = "cmd /c echo n | " & cstrSftp & " -sftp -l " & pUser & " -pw " & pPass & " " & pFile & " " & pHost & ":" & pRemotePath
'Run the command
wsh.Run strCommand, windowStyle, waitOnReturn
Since the storage server is not reliable I need to capture the output to know if the upload worked. And, if it doesn't I need to know what was the message.
I thought of using the command " > C:\output.txt" to capture the output. Like this
strCommand = strCommand & " > " & """" "C:\output.txt" & """"
When the upload works my output file works too. But, when the upload doesn't work, nothing is written in the output file.
For example, when I get the message Fatal: Server unexpectedly closed network connection nothing is written in the output file. But I need to know what is the exactly messaged given.
Example for using exec to retrieve output, maybe this is useful in your case
Sub TestExec()
Dim wsh As New WshShell
Dim s As String
s = wsh.Exec("cmd /c Dir C:\ ").StdOut.ReadAll
Debug.Print s
End Sub

Access VB - Shell string problems

Trying to create the string for use with the Shell command in Access VB. The string works if written in full but if I try to use variables in the string the command does not work even if the use of variables produces exactly the full string, (in the immediate window), that works.
I suspect something is going on in the interpretation of the string version of the code but can't work out what.
Here's the code, I have used CHR(34) to produce the quotation marks that I want to show in the string. Suggestions would be so much appreciated - I don't have much hair left!
Private Sub temp()
Dim strFilePath As String
Dim strFileName As String
Dim strZipFilename As String
Dim strPDFfilename As String
Dim strShellString As String
Dim shell As Object
Dim result As Long
Set shell = CreateObject("WScript.shell")
strFilePath = "E:\Documents\Excel Spreadsheets\Roz Theremas\Access\PDFs"
strFileName = "17-03-31temp"
strZipFilename = strFilePath & "\" & strFileName & ".zip"
strZipFilename = Chr(34) & strZipFilename & Chr(34)
strPDFfilename = strFilePath & "\" & strFileName & ".pdf"
strPDFfilename = Chr(34) & strPDFfilename & Chr(34)
strShellString = Chr(34) & Chr(34) & Chr(34) & "C:\Program Files\7-Zip\7z.exe" & Chr(34) & Chr(34) & " a -tzip " & Chr(34) & strZipFilename & Chr(34) & " " & Chr(34) & strPDFfilename & Chr(34) & Chr(34)
'Non Working shell command
result = shell.Run(strShellString, 0, False)
'Working shell command
result = shell.Run("""C:\Program Files\7-Zip\7z.exe"" a -tzip ""E:\Documents\Excel Spreadsheets\Roz Theremas\Access\PDFs\17-03-31temp.zip"" ""E:\Documents\Excel Spreadsheets\Roz Theremas\Access\PDFs\17-03-31temp.pdf""", 0, False)
'Immediate Window output of strShellString
' """C:\Program Files\7-Zip\7z.exe"" a -tzip ""E:\Documents\Excel Spreadsheets\Roz Theremas\Access\PDFs\17-03-31temp.zip"" ""E:\Documents\Excel Spreadsheets\Roz Theremas\Access\PDFs\17-03-31temp.pdf"""
End Sub
My hair is saved - I worked out the answer! So, for posterity here it is.
I modified strFilePath to put quotes around the two word folder names and removed quotations from around the strZipFilename and strPDFFilename lines. I guess Shell was suffering from a surfeit of quotes.
Whilst modifying it I added a password to the zip file and changed the false to true at the end of the string command so that it would return an error code.
Thanks to anyone who spent time trying to work out what I had done.
Public Sub temp()
Dim strFilePath As String
Dim strFileName As String
Dim strZipFilename As String
Dim strPDFfilename As String
Dim strPassword As String
Dim shell As Object
Dim result As Long
Set shell = CreateObject("WScript.shell")
strPassword = "frog"
strFilePath = "E:\Documents\""Excel Spreadsheets""\""Roz Theremas""\Access\PDFs"
strFileName = "17-03-31temp"
strZipFilename = strFilePath & "\" & strFileName & ".zip"
strPDFfilename = strFilePath & "\" & strFileName & ".pdf"
result = shell.Run("""C:\Program Files\7-Zip\7z.exe"" a -tzip " & "-p" & strPassword & " " & strZipFilename & " " & strPDFfilename, 0, True)

Resources