如何使用VBA传递参数来执行PowerShell功能
问题描述:
我一直在尝试执行从VBA获取输入参数fileName
的PowerShell功能(countLines
)。我提到了this和this的一些答案,但他们不适合我。以下是我尝试做相同的(fname
是我送的参数包含代码的下面一行VBA程序的VBA变量):如何使用VBA传递参数来执行PowerShell功能
的fileReader.ps1
内容是:
function countLines {
param([string]$logFile);
#The directory path may differ for others according to the machine's source code repository
$scriptPath = Resolve-Path "..\..\testFolder";
$varHolder = -join($scriptPath, "\logFileCount.txt");
$linesb4Exec = Get-Content $logFile;
$nLines = $linesb4Exec.Count;
Clear-Content $varHolder
$nLines | Out-File $varHolder
#For second attempt, I am adding the following too
#echo $nLines;
}
第一次尝试:
Call Shell("powershell -ExecutionPolicy Unrestricted ""D:\Temp\fileReader.ps1"";countLines -fileName """ & fname & """", vbMaximizedFocus))
第二次尝试:
Dim strCommand As Variant, WshShell As Variant, WshShellExec As Variant, output As Variant
strCommand = "powershell -command ""& { . ""D:\Temp\fileReader.ps1"";countLines -logFile """ & fname & """ }"""
Set WshShell = CreateObject("WScript.Shell")
Set WshShellExec = WshShell.Run(strCommand)
output = WshShellExec.StdOut.ReadAll
使用这个,我得到一个错误:类型不匹配。
第三次尝试(我想在我的PowerShell文件硬编码的一切,删除功能,只是运行的代码块):
Call Shell("powershell -ExecutionPolicy Bypass -file ""D:\Temp\fileReader.ps1""", vbMaximizedFocus)
和改变上述的PowerShell脚本:
$logFile = "C:\somepath\Logs\Log.txt";
$varHolder = "D:\testing\testFolder\logFileCount.txt";
$linesb4Exec = Get-Content $logFile;
$nLines = $linesb4Exec.Count;
Clear-Content $varHolder
$nLines | Out-File $varHolder
这似乎工作。
如果有人能够帮助我使用VBA调用任何具有参数的PowerShell函数,我将很高兴。
答
基本上有在你尝试了两个错误:
-
powershell "D:\Temp\fileReader.ps1";countLines -fileName ...
这可不行,因为当你调用父上下文功能的脚本文件在子上下文中执行。您需要dot-source文件才能使其内容在当前上下文中可用。 -
Set WshShellExec = WshShell.Run(strCommand)
在这里你很困惑的Run
和Exec
方法。前者返回一个整数(外部命令的退出代码),后者返回一个对象(并且只有该对象提供对外部进程的访问StdIn
,StdOut
和StdErr
)。由于您尝试使用关键字Set
指定整数返回值,因此只能在将对象分配给变量时使用,因此会出现类型不匹配。
如果您想坚持使用-Command
并点击文件,那么您第二次尝试的命令行是正确的方法。使用单引号PowerShell的脚本块内,以避免quotefusion并与Shell
功能执行命令行:
cmd = "powershell -ExecutionPolicy Bypass -Command ""&{. 'D:\Temp\fileReader.ps1';countLines -logFile '" & fname & "'}"""
Shell cmd
随着中说,如果函数是在脚本中的唯一代码,它会是简单的参数化脚本,直接从它运行的代码:
[CmdletBinding()]
Param(
[string]$LogFile
)
$scriptPath = Resolve-Path "..\..\testFolder"
$varHolder = Join-Path $scriptPath "logFileCount.txt"
@(Get-Content $logFile).Count | Out-File $varHolder
使用参数-File
像这样运行脚本:
cmd = "powershell -ExecutionPolicy Bypass -File ""D:\Temp\fileReader.ps1"" -LogFile """ & fname & """"
Shell cmd
请注意,路径..\..\testFolder
与您当前的工作目录相关,而不是脚本的位置。后者使用$MyInvocation.MyCommand.Path
。
如果有什么不工作参数-NoExit
添加到命令行(所以不会自动关闭PowerShell窗口),并调用Shell
功能与选项vbNormalFocus
在前台运行的过程。
cmd = "powershell -ExecutionPolicy Bypass -NoExit -File ""D:\Temp\fileReader.ps1"" -LogFile """ & fname & """"
Shell cmd, vbNormalFocus
哎呀...对不起,我的坏...我会尽快编辑它...谢谢指出 – Rishi
这工作! :)而且你隐含地解决了我忘记问的一个疑问,那就是如何阻止PowerShell窗口自动关闭。我无法确定路径没有得到解决的问题,你正确地指出了这一点......布拉沃为这样一个很好的描述性答案!我需要做大量的阅读...... – Rishi
如果您可以指定如何正确捕获我的VBA中的PowerShell函数的返回值,那将会很棒。正如您已经指出的那样,使用上面的返回值实际上会将我退出代码,所以这对我不起作用。 – Rishi