【问题标题】:Powershell Global Variable usage as parameter to argumentPowershell 全局变量用作参数的参数
【发布时间】:2020-07-25 01:52:51
【问题描述】:
$global:af_fp = "C:\Path\to\folder\"
Function function-name {
     do things …
     $global:af_fp = $global:af_fp + $variableFromDo_things + "_AF.csv"
}
function-name | ConvertTo-CSV -NoTypeInformation | Add-Content -Path $($af_fp)

以上是 powershell 脚本的通用(和缩写)脚本内容。 每次以这种方式运行脚本时,都会出现以下错误:

Add-Content : Could not find a part of the path 'C:\Users\timeuser\Documents\'.
At C:\Users\timeuser\Documents\get_software.ps1:231 char:51
     + ... ware | ConvertTo-CSV -NoTypeInformation | Add-Content -Path $($af_fp)
     +                                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~
     + CategoryInfo          : ObjectNotFound: (C:\Users\timeuser\Documents\:String) [Add-Content], DirectoryNotFoundException
     + FullyQualifiedErrorId : GetContentWriterDirectoryNotFoundError,Microsoft.PowerShell.Commands.AddContentCommand

当我跑步时

Get-Variable -Scope global

在运行脚本并看到错误后,变量 af_fp 包含我正在寻找的文件名信息,但是,错误显示变量内容以 ':String' 结尾。 更让我困惑的是,如果我注释掉包含 '$global:...' 的行并重新运行相同的脚本,它实际上会使用该行运行并保存文件

function-name | ConvertTo-CSV -NoTypeInformation | Add-Content -Path $($af_fp)

如预期。当然,我必须先运行脚本并观察它的错误,然后使用全局变量声明重新运行脚本并将更新注释掉以使其实际工作。我想运行脚本一次并且仍然得到相同的结果。

仅供参考,我是一个完整的 powershell 菜鸟,但非常熟悉变量范围的概念.....但是为什么这个全局在最初创建和更新时不起作用,但是第二次起作用,当,据我所知,全球的内容和范围保持不变......。任何帮助找到解决这个小问题的方法将不胜感激;我已经尝试过与通过这里和谷歌查询不同的方法........

编辑:不知道为什么这很重要,因为当我将 -Path 的参数显式键入为“C:\path\to\file”时,脚本按预期运行。对原始工作脚本(如下)所做的唯一更改是我包含了全局变量声明,更新了全局变量的内容(接近函数末尾),以及尝试使用全局变量作为-Path 的参数,这就是我省略脚本的原因:

'''

$global:af_fp = "C:\Users\timeuser\Documents\"
Function Get-Software {

  [OutputType('System.Software.Inventory')]

  [Cmdletbinding()] 

  Param( 

    [Parameter(ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] 

    [String[]]$Computername = $env:COMPUTERNAME

  )         

  Begin {

  }

  Process {     

    ForEach ($Computer in  $Computername) { 

      If (Test-Connection -ComputerName  $Computer -Count  1 -Quiet) {

        $Paths = @("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", "SOFTWARE\\Wow6432node\\Microsoft\\Windows\\CurrentVersion\\Uninstall")         

        ForEach ($Path in $Paths) { 

          Write-Verbose  "Checking Path: $Path"

        #  Create an instance of the Registry Object and open the HKLM base key 

          Try { 

            $reg = [microsoft.win32.registrykey]::OpenRemoteBaseKey('LocalMachine', $Computer, 'Registry64') 

          }
          Catch { 

            Write-Error $_ 

            Continue 

          } 

      #  Drill down into the Uninstall key using the OpenSubKey Method 

      Try {

        $regkey = $reg.OpenSubKey($Path)  

        # Retrieve an array of string that contain all the subkey names 

        $subkeys = $regkey.GetSubKeyNames()      

        # Open each Subkey and use GetValue Method to return the required  values for each 

        ForEach ($key in $subkeys) {   

          Write-Verbose "Key: $Key"

          $thisKey = $Path + "\\" + $key 

          Try {  

            $thisSubKey = $reg.OpenSubKey($thisKey)   

            # Prevent Objects with empty DisplayName 

            $DisplayName = $thisSubKey.getValue("DisplayName")

            If ($DisplayName -AND $DisplayName -notmatch '^Update  for|rollup|^Security Update|^Service Pack|^HotFix') {

              $Date = $thisSubKey.GetValue('InstallDate')

              If ($Date) {

                Try {

                  $Date = [datetime]::ParseExact($Date, 'yyyyMMdd', $Null)

                }
                Catch {

                  Write-Warning "$($Computer): $_ <$($Date)>"

                  $Date = $Null

                }

              } 

              # Create New Object with empty Properties 

              $Publisher = Try {

                $thisSubKey.GetValue('Publisher').Trim()

              } 

              Catch {

                $thisSubKey.GetValue('Publisher')

              }

              $Version = Try {

                #Some weirdness with trailing [char]0 on some strings

                $thisSubKey.GetValue('DisplayVersion').TrimEnd(([char[]](32, 0)))

              } 

              Catch {

                $thisSubKey.GetValue('DisplayVersion')

              }

              $UninstallString = Try {

                $thisSubKey.GetValue('UninstallString').Trim()

              } 

              Catch {

                $thisSubKey.GetValue('UninstallString')

              }

              $InstallLocation = Try {

                $thisSubKey.GetValue('InstallLocation').Trim()

              } 

              Catch {

                $thisSubKey.GetValue('InstallLocation')

              }

              $InstallSource = Try {

                $thisSubKey.GetValue('InstallSource').Trim()

              } 

              Catch {

                $thisSubKey.GetValue('InstallSource')

              }

              $HelpLink = Try {

                $thisSubKey.GetValue('HelpLink').Trim()

              } 

              Catch {

                $thisSubKey.GetValue('HelpLink')

              }

              $Object = [pscustomobject]@{
                #Potential Candidate for AssetID in the TIME system
                AssetID         = $Computer
                #String that contains word or word combinations for the product field of CPE WFN; may also contain the valid values necessary for update, edition, language, sw_edition, target_hw/sw fields as well.
                cpeprodinfo     = $DisplayName

                cpeversion      = $Version

                InstallDate     = $Date

                cpevendor       = $Publisher

                UninstallString = $UninstallString

                InstallLocation = $InstallLocation

                InstallSource   = $InstallSource

                HelpLink        = $thisSubKey.GetValue('HelpLink')

                EstimatedSizeMB = [decimal]([math]::Round(($thisSubKey.GetValue('EstimatedSize') * 1024) / 1MB, 2))

              }

              $Object.pstypenames.insert(0, 'System.Software.Inventory')

              Write-Output $Object

            }

          }
          Catch {

            Write-Warning "$Key : $_"

          }   

        }

      }
      Catch { }   

      $reg.Close() 

    }                  

  }
  Else {

    Write-Error  "$($Computer): unable to reach remote system!"

      }
     $global:af_fp = $global:af_fp + $Computer + "_AF.csv"
    } 

  } 
}
Get-Software | ConvertTo-CSV -NoTypeInformation | Add-Content -Path $($af_fp)

''' 请忽略格式 - 无法从复制粘贴中正确缩进并在现场对代码块进行限制.....

注意:我提出的唯一更改是全局声明、函数中的全局变量更新,以及尝试将全局变量用于 -Path 参数...。否则脚本将运行如果我第一次运行它并出错,甚至会按原样运行最后一行.....不确定添加脚本将如何以任何方式、形状或形式提供帮助!

【问题讨论】:

  • [1] 您的代码没有为 $variableFromDo_things 定义任何值。 [2] 您的错误与您的代码不匹配。 ///// 请解决这两个问题...这里的代码应该是问题的“最小但完整”的示例。 [咧嘴一笑]
  • 错误确实与代码匹配,它实际上来自代码的最后一行(阅读错误)
  • 您的错误 = ObjectNotFound: (C:\Users\timeuser\Documents\:String) 但您的第一个代码块 = "C:\Path\to\folder\" ...请注意路径中的差异。您的第二个代码块确实正确显示了它。我会重新编写您的问题以删除具有误导性且现已过时的代码。

标签: powershell global-variables parameter-passing powershell-3.0


【解决方案1】:

稍加努力,Nasir 的解决方案就奏效了!但是,我遇到了一个示例文件,该文件有一种添加参数的方法,该参数启发我对我的 ORIGINAL 进行更改,这也有效:从脚本中完全删除全局变量并在最后添加此代码:

    $file_suffix = '_AF.csv'
    Get-Software | ConvertTo-CSV -NoTypeInformation | Add-Content -Path $env:COMPUTERNAME$file_suffix

通过这种方式,我能够完全完成我打算做的事情!也感谢纳西尔的回复!我也能够按预期完成这项工作!

【讨论】:

    【解决方案2】:

    全局变量通常不受欢迎,因为它们通常会导致脚本质量不佳,并且难以调试问题。

    您的函数似乎返回了一些内容,您需要将其写入文件,该文件的名称也是由同一函数生成的。你可以试试这样:

    function function-name {
      param($PathPrefix)
    
      #do things
    
      [pscustomobject]@{"DoThings_data" = $somevariablefromDoThings; "Filename" = "$($PathPrefix)$($variableFromDo_Things)_AF.csv"}
    }
    
    function-name -PathPrefix "C:\Path\to\folder\" | Foreach-Object { $_.DoThings_data | Export-Csv -Path $_.Filename -NoTypeInformation } 
    

    或者,如果您需要在函数之外进一步处理数据,或者只是让您的函数将 CSV 数据写出,然后返回数据。

    编辑:这只是我从您提供的部分代码中推断出来的。就 Lee_Dailey 而言,是的,请提供更多详细信息。

    【讨论】:

    • 我现在要尝试这种方法,因为,是的,我正在尝试将脚本的内容保存到文件中 - 我省略了其他所有内容,因为如果我将 -Path 显式设置为,脚本将正常运行'C:\path\to\folder'....我对现有脚本所做的唯一更改是全局声明、对声明的更新以及对 -Path 参数使用全局变量的尝试。该问题可以简单地重述为“为什么全局变量正确保存为全局变量,但在尝试用作 -Path 的参数时不起作用”。
    • 嗯,我不能公开投票,因为代表太低了,但这个解决方案也有效!
    • 这里有一个错字:[pscutomobject] --> [pscustomobject]s 不见了)
    猜你喜欢
    • 1970-01-01
    • 2013-08-07
    • 2020-10-28
    • 2022-11-04
    • 2022-11-11
    • 2017-01-20
    • 1970-01-01
    • 1970-01-01
    • 2017-02-01
    相关资源
    最近更新 更多