Reputation: 2112
I am using Excel VBA to run a simple Powershell script that, when run in Powershell itself, returns one or two file names of some files within a given directory.
I can run this script from my VBA, but the return value is always some random integer. How do I get the script to return the file names that were returned through the Powershell script?
VBA to call script:
Dim weekly As String
weekly = Shell("Powershell ""<location of powershell script.ps1>"" ")
Script:
Get-ChildItem "<directory to search in>" | Where-Object {$_.Name -match "<regex to find file name>"}
If I have missed any details, please ask.
Upvotes: 3
Views: 7391
Reputation: 306
You can use WScript to access StdOut output of a PowerShell script. Use the following code:
Set wShell = CreateObject("WScript.Shell")
Set wShellOutput = wShell.Exec("powershell 'C:\Path\To\file.ps1'")
text_output = wShellOutput.StdOut.ReadAll ()
I would suggest using single quotes instead of double quotes in the .Exec() call, because Windows handles double quotes painfully.
Edit: as noted by @Belladonna, you would need to tell VBA to wait until the PowerShell script finishes (e.g. here WScript.Shell.Exec - read output from stdout).
Upvotes: 1
Reputation: 308
Try this the Powershell function below to run a powershell command and return the output. The code outputs the result of the command to a temporary file, waits for the command to complete, and returns the output.
The Powershell function uses sub WaitFile to wait for the output file to be completed, which signals completion of the powershell command, and uses the Windows sleep function to wait 100ms when polling.
Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Function Powershell(Command As String) As String
'Runs powershell command and returns output
Dim FilePath As String
Dim OutFile As String
Dim fso As Object
'Generate output file name
FilePath = ThisWorkbook.Path
Set fso = CreateObject("Scripting.FileSystemObject")
OutFile = FilePath & "\" & fso.GetTempName()
Set fso = Nothing
'Delete output file if it exists
DelFile OutFile
'Add output file to command
Command = SPrintF("%s | out-file -FilePath %s -Encoding ASCII", Command, OutFile)
'Run command
Shell SPrintF("Powershell ""%s""", Command), vbMinimizedNoFocus
'Wait for temp file to appear
WaitFile OutFile
'Gather results from temp file
Powershell = GetFile(OutFile)
'Delete output file if it exists
DelFile OutFile
End Function
Sub WaitFile(FileName As String, Optional TimeOutSecs As Long = 60)
'Returns entire contents of file
Dim fhan As Long
Dim s As String
Dim StartTime As Date
On Error Resume Next
'Initialise start time
StartTime = Now
'Wait for file to appear (or time out)
Do While FileLen(FileName) = 0
Sleep 100
DoEvents
If DateDiff("s", StartTime, Now) > TimeOutSecs Then Exit Do
Loop
End Sub
Upvotes: 0
Reputation: 26
I know this is way late but I wanted to let anyone else searching for this a way to do this. Have your powershell script write an output file:
Get-ChildItem "Directory to Search" | Select-String -Pattern "what to seach for" | out-file "C:\output.txt"
From there you can write this line by line to a variable:
Sub test()
Dim txtfile, text, textline As String
txtfile = "C:\output.txt"
Open txtfile For Input As #1
Do Until EOF(1)
Line Input #1, textline
text = text & textline
Loop
Close #1
MsgBox text
End Sub
From there you can insert the text into a cell, or if preferred, you can write each line to an array and select each line individually if needed.
Upvotes: 1
Reputation: 4198
It looks like the VBA is simply seeing the exit code that the powershell.exe quits with. Try this:
Get-ChildItem "<directory to search in>" | Where-Object {$_.Name -match "<regex to find file name>"} 2>&1
I believe this will redirect your Powershell output to stdout which the VBA should be able to pick up.
Upvotes: 0