繁体   English   中英

Powershell 全局变量用作参数的参数

[英]Powershell Global Variable usage as parameter to argument

$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 包含我正在寻找文件名的信息,但是,错误显示变量内容以“:字符串”结尾。 更让我困惑的是,如果我注释掉包含 '$global:...' 的行并重新运行相同的脚本,它实际上会使用该行运行并保存文件

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

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

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

编辑:不确定为什么这很重要,因为当我将 -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)

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

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

全局变量通常不受欢迎,因为它们通常会导致糟糕的脚本,难以调试问题。

似乎您的 function 返回了一些内容,您需要将其写入文件,其名称也由相同的 function 生成。 你可以尝试这样的事情:

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 } 

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM