【发布时间】: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