如何验证和使用两个参数已设置,以防获得垃圾数据。

huangapple go评论60阅读模式
英文:

How verify and use two arguments are set so don't get garbage

问题

I'm using arguments for a PowerShell script, but I found that if the second one isn't set, it's getting garbage, although it's possible I'm doing something wrong, since I'm having trouble finding examples with two passed-in arguments. How can I verify that both are set?

This script is called from a very old perl script as shown:

#`"C:\\Program Files\\PowerShell\\\pwsh.exe" -NoProfile -noninteractive -ExecutionPolicy bypass -Command "\\\\wserverp01\\kiosksupport\\Retailer_DeviceSN\\MoveSNToSprdsht_1.0.ps1 $service_report_xls"`;

In my script, MoveSNToSprdsht_1.0.ps1:

$out_pth = ""
$outFilePathExcel_pl = ""
$outFilePathExcel_pl = $Args[0]
$out_pth = $Args[1]  #this is blob scan output dir that we look for the correct date file in
Write-Host "new tab will go to:$($outFilePathExcel_pl)" 
Write-Host "Will get files from:$($out_pth)"  #this had garbage in it, like terminal output from something I ran yesterday that's unrelated

I was thinking maybe I'm not supposed to use $Args[1], and found [this example][1], but it doesn't say what to do in the script with -arg1 and -arg2. I'm using VisualStudioCode to run the PowerShell to test it for now so it's possible I'm executing it from the VSC command line incorrectly as well. When I used the pasted perl line from the old perl script, it worked ok with the first parameter but I've added the second parameter now.

I haven't found in a search how to verify the script arguments are actually set. I tried checking against an empty string, and that didn't work. Something had filled Arg[1] with the garbage, so it failed the check for an empty string.

Update:

So if I used cmdletbinding, would this be good program structure, and would the program be run the normal way?

[cmdletbinding()]
Param ( [Parameter(Mandatory)][string]$outFilePathExcel_pl,  [Parameter(Mandatory)][string]$out_pth="\\wserverp01\support\Retailer_SN\OutputSprdsht\")
    
#and the rest of the program...
Get-ChildItem $out_pth | Foreach-Object {$lastupdatetime=$_.LastWriteTime;$nowtime = get-date; if (($nowtime - $lastupdatetime).totalhours -le 72) {write-host "here2";$excel_File_from = $_.Name;write-host $_.name}}
..

Update2:
Hopefully I'm calling the PowerShell script correctly, below, per comments.

my $resultPS = `"C:\\Program Files\\PowerShell\\\pwsh.exe" -NoProfile -noninteractive -ExecutionPolicy bypass -File "\\\\wserverp01\\support\\Retailer_SN\\MoveSNToSprdsht_1.0.ps1" "-outFilePathExcel_pl $service_report_xls" "-out_pth $cvs_blob_scan_dir"`;

Calling updated PowerShell script:

[cmdletbinding()]
param( [Parameter(Mandatory)][string]$outFilePathExcel_pl,  [Parameter()][string]$out_pth="\\wserverp01\support\Retailer_SN\OutputSprdsht\")
    
Start-Transcript -path '\\wserverp01\support\Retailer_SN\Logs\MoveSNToSprdsht.log' 
#get file location from parameter so put sn tab there
    
Write-Host "new tab will go to:$($outFilePathExcel_pl)" 
Write-Host "Will get scan files from:$($out_pth)"
    
#make sure params are valid paths; non-terminating error if invalid
if(Test-Path $outFilePathExcel_pl)
{
    Write-Host "path for $outFilePathExcel_pl looks good"
}
else 
{
    Write-Error "path for $outFilePathExcel_pl invalid" 
}
if(Test-Path $out_pth)
{
    Write-Host "path for $out_pth looks good"
}
else 
{
    Write-Error "path for $outFilePathExcel_pl invalid"
}
    
Get-ChildItem $out_pth | Foreach-Object {$lastupdatetime=$_.LastWriteTime;$nowtime = get-date; if (($nowtime - $lastupdatetime).totalhours -le 72) {write-host "here2";$excel_File_from = $_.Name;write-host $_.name}}

Update3:

For some reason when I use the named parameters from perl and use them from the PowerShell, I'm getting:

Cannot bind argument to parameter 'Path' because it is an empty string.

when I try to use the variable. Is there a problem with my syntax?

From perl:

my $resultPS = `"C:\\Program Files\\PowerShell\\\pwsh.exe" -NoProfile -noninteractive -ExecutionPolicy bypass -File "\\\\wserverp01\\support\\Retailer_SN\\MoveSNToSprdsht_1.0.ps1" -outFilePathExcel_pl "$service_report_xls" -out_pth "$retailer_blob_scan_dir"`;

Then in MoveSNToSprdsht_1.0.ps1:

[cmdletbinding()]
param( [Parameter(Mandatory)][string]$outFilePathExcel_pl,  [Parameter()][string]$out_pth="\\wserverp01\support\Retailer_SN\OutputSprdsht\")
    
Start-Transcript -path '\\wserverp01\support\Retailer_SN\Logs\MoveSNToSprdsht.log' 
#get file location from parameter so put sn tab there
    
Write-Host "new tab will go to:$($outFilePathExcel_pl)" #need to use below instead of $outFilePathExcel
Write-Host "Will get blob scan files from:$($out_pth)"
    
#make sure params are valid paths; non-terminating error if invalid
if(Test-Path $outFilePathExcel_pl)
{
    Write-Host "path for $outFilePathExcel_pl looks good"
}
else 
{
    Write-Error "path for $outFilePathExcel_pl invalid" 
}
if(Test-Path $out_pth)
{
    Write-Host "path for $out_pth looks good"
}
else 
{
    Write-Error "path for $out_pth invalid"
}
    
[System.String] $excel_File_from = &quot

<details>
<summary>英文:</summary>

I&#39;m using arguments for a PowerShell script, but I found that if the second one isn&#39;t set, it&#39;s getting garbage, although it&#39;s possible I&#39;m doing something wrong, since I&#39;m having trouble finding examples with two passed in arguments.  How can I verify that both are set?

This script is called from a very old perl script as shown:

    #`&quot;C:\\Program Files\\PowerShell\\7\\pwsh.exe&quot; -NoProfile -noninteractive -ExecutionPolicy bypass -Command &quot;\\\\wserverp01\\kiosksupport\\Retailer_DeviceSN\\MoveSNToSprdsht_1.0.ps1 $service_report_xls&quot;`;

In my script, MoveSNToSprdsht_1.0.ps1:

    $out_pth = &quot;&quot;
    $outFilePathExcel_pl = &quot;&quot;
    $outFilePathExcel_pl = $Args[0]
    $out_pth = $Args[1]  #this is blob scan output dir that we look for correct date file in
    Write-Host &quot;new tab will go to:$($outFilePathExcel_pl)&quot; 
    Write-Host &quot;Will get files from:$($out_pth)&quot;  #this had garbage in it, like terminal output from something I ran yesterday that&#39;s unrelated

I was thinking maybe I&#39;m not supposed to use $Args[1], and found [this example][1], but it doesn&#39;t say what to do in the script with -arg1 and -arg2. I&#39;m using VisualStudioCode to run the PowerShell to test it for now so it&#39;s possible I&#39;m executing it from the VSC command line incorrectly as well. When I used the pasted perl line from the old perl script, it worked ok with the first parameter but I&#39;ve added the second parameter now.

I haven&#39;t found in a search how to verify the script arguments are actually set. I tried checking against empty string and that didn&#39;t work. Something had filled Arg[1] with the garbage so it failed the check for empty string.

**Update:**

So if I used cmdletbinding, would this be good program structure, and would the program be run the normal way?


      [cmdletbinding()]
      Param ( [Parameter(Mandatory)][string]$outFilePathExcel_pl,  [Parameter(Mandatory)][string]$out_pth=&quot;\\wserverp01\support\Retailer_SN\OutputSprdsht\&quot;)
    
    #and the rest of the program...
    Get-ChildItem $out_pth | Foreach-Object {$lastupdatetime=$_.LastWriteTime;$nowtime = get-date; if (($nowtime - $lastupdatetime).totalhours -le 72) {write-host &quot;here2&quot;;$excel_File_from = $_.Name;write-host $_.name}}
    ..

**Update2:**
Hopefully I&#39;m calling the powershell script correctly, below, per comments.

			

    my $resultPS = `&quot;C:\\Program Files\\PowerShell\\7\\pwsh.exe&quot; -NoProfile -noninteractive -ExecutionPolicy bypass -File &quot;\\\\wserverp01\\support\\Retailer_SN\\MoveSNToSprdsht_1.0.ps1&quot; &quot;-outFilePathExcel_pl $service_report_xls&quot; &quot;-out_pth $cvs_blob_scan_dir&quot;`;

Calling updated powershell script:

    [cmdletbinding()]
    param( [Parameter(Mandatory)][string]$outFilePathExcel_pl,  [Parameter()][string]$out_pth=&quot;\\wserverp01\support\Retailer_SN\OutputSprdsht\&quot;)
    
    Start-Transcript -path &#39;\\wserverp01\support\Retailer_SN\Logs\MoveSNToSprdsht.log&#39; 
    #get file location from parameter so put sn tab there
    
    Write-Host &quot;new tab will go to:$($outFilePathExcel_pl)&quot; 
    Write-Host &quot;Will get scan files from:$($out_pth)&quot;
    
    #make sure params are valid paths; non-terminating error if invalid
    if(Test-Path $outFilePathExcel_pl)
    {
        Write-Host &quot;path for $outFilePathExcel_pl looks good&quot;
    }
    else 
    {
        Write-Error &quot;path for $outFilePathExcel_pl invalid&quot; 
    }
    if(Test-Path $out_pth)
    {
        Write-Host &quot;path for $out_pth looks good&quot;
    }
    else 
    {
        Write-Error &quot;path for $outFilePathExcel_pl invalid&quot;
    }
    
    Get-ChildItem $out_pth | Foreach-Object {$lastupdatetime=$_.LastWriteTime;$nowtime = get-date; if (($nowtime - $lastupdatetime).totalhours -le 72) {write-host &quot;here2&quot;;$excel_File_from = $_.Name;write-host $_.name}}

**Update3:**

For some reason when I use the named parameters from perl and use them from the powershell, I&#39;m getting 

    Cannot bind argument to parameter &#39;Path&#39; because it is an empty string.

when I try to use the variable. Is there a problem with my syntax?

from perl:

			my $resultPS = `&quot;C:\\Program Files\\PowerShell\\7\\pwsh.exe&quot; -NoProfile -noninteractive -ExecutionPolicy bypass -File &quot;\\\\wserverp01\\support\\Retailer_SN\\MoveSNToSprdsht_1.0.ps1&quot; -outFilePathExcel_pl &quot;$service_report_xls&quot; -out_pth &quot;$retailer_blob_scan_dir&quot;`;

(where the variables are set from an ini file and passed to the script as the parameters, printout before the powershell call look good in perl)

Then in MoveSNToSprdsht_1.0.ps1:

    [cmdletbinding()]
    param( [Parameter(Mandatory)][string]$outFilePathExcel_pl,  [Parameter()][string]$out_pth=&quot;\\wserverp01\support\Retailer_SN\OutputSprdsht\&quot;)
    
    Start-Transcript -path &#39;\\wserverp01\support\Retailer_SN\Logs\MoveSNToSprdsht.log&#39; 
    #get file location from parameter so put sn tab there
    
    Write-Host &quot;new tab will go to:$($outFilePathExcel_pl)&quot; #need to use below instead of $outFilePathExcel############################
    Write-Host &quot;Will get blob scan files from:$($out_pth)&quot;
    
    #make sure params are valid paths; non-terminating error if invalid
    if(Test-Path $outFilePathExcel_pl)
    {
        Write-Host &quot;path for $outFilePathExcel_pl looks good&quot;
    }
    else 
    {
        Write-Error &quot;path for $outFilePathExcel_pl invalid&quot; 
    }
    if(Test-Path $out_pth)
    {
        Write-Host &quot;path for $out_pth looks good&quot;
    }
    else 
    {
        Write-Error &quot;path for $out_pth invalid&quot;
    }
    
    [System.String] $excel_File_from = &quot;&quot;
    
    ############## hours - 72 hours is ok for now so we don&#39;t cut it too close for file timestamp for scan..scan run on weekend, use Monday:
    Get-ChildItem $out_pth | Foreach-Object {$lastupdatetime=$_.LastWriteTime;$nowtime = get-date; if (($nowtime - $lastupdatetime).totalhours -le 72) {write-host &quot;here2&quot;;$excel_File_from = $_.Name;write-host $_.name}}

Maybe I need curly brackets below the cmdlet binding? It the error is complaining about using the empty parameter, not wrong formatting though.

  [1]: https://stackoverflow.com/questions/47051466/call-powershell-script-with-multiple-args-from-command-line



</details>


# 答案1
**得分**: 1

* 在您的 Perl 命令行中`$service_report_xls` 是一个 _Perl_ 变量会被字符串扩展为了*健壮地*传递它将其括在*嵌入的* `&quot;...&quot;` 中需要 `\\&quot;...\\&quot;`原文如此):

```perl
`&quot;C:\\Program Files\\PowerShell\\7\\pwsh.exe&quot; -NoProfile -noninteractive -ExecutionPolicy bypass -Command &quot;\\\\wserverp01\\kiosksupport\\Retailer_DeviceSN\\MoveSNToSprdsht_1.0.ps1 \\&quot;$service_report_xls\\&quot;&quot;`;
  • 然而,即使这样也可能使您的参数受到不希望的解释,因为使用了 -Command PowerShell CLI 参数。对于执行 脚本文件 (*.ps1),更好的选择是使用 -File 参数,它接受将逐字传递的单独参数(有关何时使用 -Command vs. -File 的指导,请参阅此答案):
`&quot;C:\\Program Files\\PowerShell\\7\\pwsh.exe&quot; -NoProfile -NonInteractive -ExecutionPolicy Bypass -File &quot;\\\\wserverp01\\kiosksupport\\Retailer_DeviceSN\\MoveSNToSprdsht_1.0.ps1&quot; &quot;$service_report_xls&quot;`;
  • 为确保不会传递意外的参数给您的 PowerShell 脚本(.ps1),将您的脚本定义为高级脚本,这需要正式声明参数并使用[CmdletBinding()]属性;高级脚本和函数只接受与正式声明的参数绑定的参数;例如:
[CmdletBinding()] # 使脚本成为高级脚本。
param(
  # 强制,第一个位置参数
  [Parameter(Mandatory)]  # 确保始终传递参数。
  [string] $outFilePathExcel_pl,   
  # 可选,第二个位置参数,带有默认值。
  [string] $out_pth = '...'
)
# ...

注意:由于已声明的参数也可以通过名称绑定(最好如此,以便更好地理解概念),例如...\MoveSNToSprdsht_1.0.ps1 -outFilePathExcel_pl c:\some\file.xlsx,建议使用更具描述性的参数名称。

英文:
  • In your Perl command line, $service_report_xls is a Perl variable that gets string-expanded. To pass it robustly, enclose it in embedded &quot;...&quot;, which requires \\&quot;...\\&quot; (sic):
`&quot;C:\\Program Files\\PowerShell\\7\\pwsh.exe&quot; -NoProfile -noninteractive -ExecutionPolicy bypass -Command &quot;\\\\wserverp01\\kiosksupport\\Retailer_DeviceSN\\MoveSNToSprdsht_1.0.ps1 \\&quot;$service_report_xls\\&quot;&quot;`;
  • However, even that can subject your arguments to unwanted interpretation, due to use of the -Command PowerShell CLI parameter. For execution of a script file (*.ps1) the better option is to use the -File parameter, which accepts separate arguments that are passed verbatim (for guidance on when to use -Command vs. -File, see this answer):
`&quot;C:\\Program Files\\PowerShell\\7\\pwsh.exe&quot; -NoProfile -NonInteractive -ExecutionPolicy Bypass -File &quot;\\\\wserverp01\\kiosksupport\\Retailer_DeviceSN\\MoveSNToSprdsht_1.0.ps1&quot; &quot;$service_report_xls&quot;`;
  • To ensure that no unexpected arguments are passed to your PowerShell script (*.ps1), make your script an advanced one, which requires formally declaring parameters and using the [CmdletBinding()] attribute; advanced scripts and functions only accept arguments that bind to formally declared parameters; e.g.:
[CmdletBinding()] # Make the script an advanced one.
param(
# Mandatory, 1st positional parameter
[Parameter(Mandatory)]  # Make sure an argument is always passed.
[string] $outFilePathExcel_pl,   
# Optional, 2nd positional parameter with default value.
[string] $out_pth = &#39;...&#39;
)
# ...

Note: Since declared parameters can also be bound by name (preferably so, for conceptual clarity) - e.g. ...\MoveSNToSprdsht_1.0.ps1 -outFilePathExcel_pl c:\some\file.xlsx - it's better to use more descriptive parameter names.

huangapple
  • 本文由 发表于 2023年3月4日 03:34:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/75631211.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定