2016-11-14 147 views
1

我一直在嘗試執行從VBA獲取輸入參數fileName的PowerShell功能(countLines)。我提到了thisthis的一些答案,但他們不適合我。以下是我嘗試做相同的(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函數,我將很高興。

回答

1

基本上有在你嘗試了兩個錯誤:

  • powershell "D:\Temp\fileReader.ps1";countLines -fileName ...
    這可不行,因爲當你調用父上下文功能的腳本文件在子上下文中執行。您需要dot-source文件才能使其內容在當前上下文中可用。
  • Set WshShellExec = WshShell.Run(strCommand)
    在這裏你很困惑的RunExec方法。前者返回一個整數(外部命令的退出代碼),後者返回一個對象(並且只有該對象提供對外部進程的訪問StdIn,StdOutStdErr)。由於您嘗試使用關鍵字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 
+0

哎呀...對不起,我的壞...我會盡快編輯它...謝謝指出 – Rishi

+0

這工作! :)而且你隱含地解決了我忘記問的一個疑問,那就是如何阻止PowerShell窗口自動關閉。我無法確定路徑沒有得到解決的問題,你正確地指出了這一點......布拉沃爲這樣一個很好的描述性答案!我需要做大量的閱讀...... – Rishi

+0

如果您可以指定如何正確捕獲我的VBA中的PowerShell函數的返回值,那將會很棒。正如您已經指出的那樣,使用上面的返回值實際上會將我退出代碼,所以這對我不起作用。 – Rishi