我一直在尝试执行从VBA获取输入参数countLines
的PowerShell函数(fileName
)。我已经提到了this和this的一些答案,但它们对我不起作用。以下是我尝试做同样的事情(fname
是一个VBA变量,我将其作为参数发送到包含以下代码行的VBA例程中):
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函数,我将很高兴。
答案 0 :(得分:1)
你的尝试基本上有两个错误:
powershell "D:\Temp\fileReader.ps1";countLines -fileName ...
Set WshShellExec = WshShell.Run(strCommand)
Run
和Exec
方法。前者返回一个整数(外部命令的退出代码),后者返回WshScriptExec
个对象(只有该对象提供对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窗口不会自动关闭),并使用选项vbNormalFocus
调用Shell
函数在前台运行该过程。
cmd = "powershell -ExecutionPolicy Bypass -NoExit -File ""D:\Temp\fileReader.ps1"" -LogFile """ & fname & """"
Shell cmd, vbNormalFocus