Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Function PowerShell-导出Csv:无法将参数绑定到参数';InputObject';因为它是空的_Function_Powershell_Csv - Fatal编程技术网

Function PowerShell-导出Csv:无法将参数绑定到参数';InputObject';因为它是空的

Function PowerShell-导出Csv:无法将参数绑定到参数';InputObject';因为它是空的,function,powershell,csv,Function,Powershell,Csv,我正在使用我在网上找到的一个PowerShell函数,它非常有效。在将其合并到针对给定域中的Windows服务器使用的脚本中时,我将输出导出为.csv。它确实可以工作,但是在脚本运行的整个过程中,我发现了关于“InputObject”的错误,我只是想清理一下,但我不知道问题出在哪里。感谢您的帮助。下面是我使用的函数,然后是我使用该函数的脚本,然后是我得到的错误 功能 Function Get-LocalGroupMembership { <# .SYNOPSIS

我正在使用我在网上找到的一个PowerShell函数,它非常有效。在将其合并到针对给定域中的Windows服务器使用的脚本中时,我将输出导出为.csv。它确实可以工作,但是在脚本运行的整个过程中,我发现了关于“InputObject”的错误,我只是想清理一下,但我不知道问题出在哪里。感谢您的帮助。下面是我使用的函数,然后是我使用该函数的脚本,然后是我得到的错误

功能

Function Get-LocalGroupMembership {
    <#
        .SYNOPSIS
            Recursively list all members of a specified Local group.

        .DESCRIPTION
            Recursively list all members of a specified Local group. This can be run against a local or
            remote system or systems. Recursion is unlimited unless specified by the -Depth parameter.

            Alias: glgm

        .PARAMETER Computername
            Local or remote computer/s to perform the query against.
            
            Default value is the local system.

        .PARAMETER Group
            Name of the group to query on a system for all members.
            
            Default value is 'Administrators'

        .PARAMETER Depth
            Limit the recursive depth of a query. 
            
            Default value is 2147483647.

        .PARAMETER Throttle
            Number of concurrently running jobs to run at a time

            Default value is 10

        
    #>
    [cmdletbinding()]
    Param (
        [parameter(ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
        [Alias('CN','__Server','Computer','IPAddress')]
        [string[]]$Computername = $env:COMPUTERNAME,
        [parameter()]
        [string]$Group = "Administrators",
        [parameter()]
        [int]$Depth = ([int]::MaxValue),
        [parameter()]
        [Alias("MaxJobs")]
        [int]$Throttle = 10
    )
    Begin {
        $PSBoundParameters.GetEnumerator() | ForEach {
            Write-Verbose $_
        }
        #region Extra Configurations
        Write-Verbose ("Depth: {0}" -f $Depth)
        #endregion Extra Configurations
        #Define hash table for Get-RunspaceData function
        $runspacehash = @{}
        #Function to perform runspace job cleanup
        Function Get-RunspaceData {
            [cmdletbinding()]
            param(
                [switch]$Wait
            )
            Do {
                $more = $false         
                Foreach($runspace in $runspaces) {
                    If ($runspace.Runspace.isCompleted) {
                        $runspace.powershell.EndInvoke($runspace.Runspace)
                        $runspace.powershell.dispose()
                        $runspace.Runspace = $null
                        $runspace.powershell = $null                 
                    } ElseIf ($runspace.Runspace -ne $null) {
                        $more = $true
                    }
                }
                If ($more -AND $PSBoundParameters['Wait']) {
                    Start-Sleep -Milliseconds 100
                }   
                #Clean out unused runspace jobs
                $temphash = $runspaces.clone()
                $temphash | Where {
                    $_.runspace -eq $Null
                } | ForEach {
                    Write-Verbose ("Removing {0}" -f $_.computer)
                    $Runspaces.remove($_)
                }             
            } while ($more -AND $PSBoundParameters['Wait'])
        }

        #region ScriptBlock
            $scriptBlock = {
            Param ($Computer,$Group,$Depth,$NetBIOSDomain,$ObjNT,$Translate)            
            $Script:Depth = $Depth
            $Script:ObjNT = $ObjNT
            $Script:Translate = $Translate
            $Script:NetBIOSDomain = $NetBIOSDomain
            Function Get-LocalGroupMember {
                [cmdletbinding()]
                Param (
                    [parameter()]
                    [System.DirectoryServices.DirectoryEntry]$LocalGroup
                )
                # Invoke the Members method and convert to an array of member objects.
                $Members= @($LocalGroup.psbase.Invoke("Members"))
                $Counter++
                ForEach ($Member In $Members) {                
                    Try {
                        $Name = $Member.GetType().InvokeMember("Name", 'GetProperty', $Null, $Member, $Null)
                        $Path = $Member.GetType().InvokeMember("ADsPath", 'GetProperty', $Null, $Member, $Null)
                        # Check if this member is a group.
                        $isGroup = ($Member.GetType().InvokeMember("Class", 'GetProperty', $Null, $Member, $Null) -eq "group")
                        If (($Path -like "*/$Computer/*")) {
                            $Type = 'Local'
                        } Else {$Type = 'Domain'}
                        New-Object PSObject -Property @{
                            Computername = $Computer
                            Name = $Name
                            Type = $Type
                            ParentGroup = $LocalGroup.Name[0]
                            isGroup = $isGroup
                            Depth = $Counter
                        }
                        If ($isGroup) {
                            # Check if this group is local or domain.
                            #$host.ui.WriteVerboseLine("(RS)Checking if Counter: {0} is less than Depth: {1}" -f $Counter, $Depth)
                            If ($Counter -lt $Depth) {
                                If ($Type -eq 'Local') {
                                    If ($Groups[$Name] -notcontains 'Local') {
                                        $host.ui.WriteVerboseLine(("{0}: Getting local group members" -f $Name))
                                        $Groups[$Name] += ,'Local'
                                        # Enumerate members of local group.
                                        Get-LocalGroupMember $Member
                                    }
                                } Else {
                                    If ($Groups[$Name] -notcontains 'Domain') {
                                        $host.ui.WriteVerboseLine(("{0}: Getting domain group members" -f $Name))
                                        $Groups[$Name] += ,'Domain'
                                        # Enumerate members of domain group.
                                        Get-DomainGroupMember $Member $Name $True
                                    }
                                }
                            }
                        }
                    } Catch {
                        $host.ui.WriteWarningLine(("GLGM{0}" -f $_.Exception.Message))
                    }
                }
            }

            Function Get-DomainGroupMember {
                [cmdletbinding()]
                Param (
                    [parameter()]
                    $DomainGroup, 
                    [parameter()]
                    [string]$NTName, 
                    [parameter()]
                    [string]$blnNT
                )
                Try {
                    If ($blnNT -eq $True) {
                        # Convert NetBIOS domain name of group to Distinguished Name.
                        $objNT.InvokeMember("Set", "InvokeMethod", $Null, $Translate, (3, ("{0}{1}" -f $NetBIOSDomain.Trim(),$NTName)))
                        $DN = $objNT.InvokeMember("Get", "InvokeMethod", $Null, $Translate, 1)
                        $ADGroup = [ADSI]"LDAP://$DN"
                    } Else {
                        $DN = $DomainGroup.distinguishedName
                        $ADGroup = $DomainGroup
                    }         
                    $Counter++   
                    ForEach ($MemberDN In $ADGroup.Member) {
                        $MemberGroup = [ADSI]("LDAP://{0}" -f ($MemberDN -replace '/','\/'))
                        New-Object PSObject -Property @{
                            Computername = $Computer
                            Name = $MemberGroup.SamAccountName[0]
                            Type = 'Domain'
                            ParentGroup = $NTName
                            isGroup = ($MemberGroup.Class -eq "group")
                            Depth = $Counter
                        }
                        # Check if this member is a group.
                        If ($MemberGroup.Class -eq "group") {              
                            If ($Counter -lt $Depth) {
                                If ($Groups[$MemberGroup.name[0]] -notcontains 'Domain') {
                                    Write-Verbose ("{0}: Getting domain group members" -f $MemberGroup.name[0])
                                    $Groups[$MemberGroup.name[0]] += ,'Domain'
                                    # Enumerate members of domain group.
                                    Get-DomainGroupMember $MemberGroup $MemberGroup.Name[0] $False
                                }                                                
                            }
                        }
                    }
                } Catch {
                    $host.ui.WriteWarningLine(("GDGM{0}" -f $_.Exception.Message))
                }
            }
            #region Get Local Group Members
            $Script:Groups = @{}
            $Script:Counter=0
            # Bind to the group object with the WinNT provider.
            $ADSIGroup = [ADSI]"WinNT://$Computer/$Group,group"
            Write-Verbose ("Checking {0} membership for {1}" -f $Group,$Computer)
            $Groups[$Group] += ,'Local'
            Get-LocalGroupMember -LocalGroup $ADSIGroup
            #endregion Get Local Group Members
        }
        #endregion ScriptBlock
        Write-Verbose ("Checking to see if connected to a domain")
        Try {
            $Domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
            $Root = $Domain.GetDirectoryEntry()
            $Base = ($Root.distinguishedName)

            # Use the NameTranslate object.
            $Script:Translate = New-Object -comObject "NameTranslate"
            $Script:objNT = $Translate.GetType()

            # Initialize NameTranslate by locating the Global Catalog.
            $objNT.InvokeMember("Init", "InvokeMethod", $Null, $Translate, (3, $Null))

            # Retrieve NetBIOS name of the current domain.
            $objNT.InvokeMember("Set", "InvokeMethod", $Null, $Translate, (1, "$Base"))
            [string]$Script:NetBIOSDomain =$objNT.InvokeMember("Get", "InvokeMethod", $Null, $Translate, 3)  
        } Catch {Write-Warning ("{0}" -f $_.Exception.Message)}         
        
        #region Runspace Creation
        Write-Verbose ("Creating runspace pool and session states")
        $sessionstate = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
        $runspacepool = [runspacefactory]::CreateRunspacePool(1, $Throttle, $sessionstate, $Host)
        $runspacepool.Open()  
        
        Write-Verbose ("Creating empty collection to hold runspace jobs")
        $Script:runspaces = New-Object System.Collections.ArrayList        
        #endregion Runspace Creation
    }

    Process {
        ForEach ($Computer in $Computername) {
            #Create the powershell instance and supply the scriptblock with the other parameters 
            $powershell = [powershell]::Create().AddScript($scriptBlock).AddArgument($computer).AddArgument($Group).AddArgument($Depth).AddArgument($NetBIOSDomain).AddArgument($ObjNT).AddArgument($Translate)
           
            #Add the runspace into the powershell instance
            $powershell.RunspacePool = $runspacepool
           
            #Create a temporary collection for each runspace
            $temp = "" | Select-Object PowerShell,Runspace,Computer
            $Temp.Computer = $Computer
            $temp.PowerShell = $powershell
           
            #Save the handle output when calling BeginInvoke() that will be used later to end the runspace
            $temp.Runspace = $powershell.BeginInvoke()
            Write-Verbose ("Adding {0} collection" -f $temp.Computer)
            $runspaces.Add($temp) | Out-Null
           
            Write-Verbose ("Checking status of runspace jobs")
            Get-RunspaceData @runspacehash   
        }
    }
    End {
        Write-Verbose ("Finish processing the remaining runspace jobs: {0}" -f (@(($runspaces | Where {$_.Runspace -ne $Null}).Count)))
        $runspacehash.Wait = $true
        Get-RunspaceData @runspacehash
    
        #region Cleanup Runspace
        Write-Verbose ("Closing the runspace pool")
        $runspacepool.close()  
        $runspacepool.Dispose() 
        #endregion Cleanup Runspace    
    }
}

Set-Alias -Name glgm -Value Get-LocalGroupMembership
我得到的错误

$Servers = Get-ADComputer `
    -searchbase ‘OU=RDS Servers,OU=Production,OU=Servers,DC=xxx,DC=xxxx,DC=xxx’ `
    -properties OperatingSystem -Filter * | `
    Where-Object {$_.operatingsystem -Like "*Windows*"} | select name 

foreach ($Server in $Servers) {
    Get-LocalGroupMembership -Computername $Server.Name | `
        Export-Csv D:\Scripts\ServerLocalAdmin\Reports\LocalAdmins.csv `
        -Append -NoTypeInformation 
}
Export-Csv : Cannot bind argument to parameter 'InputObject' because it is null.
At D:\Scripts\ServerLocalAdmin\ServerLocalAdmin.ps1:5 char:87
+ ... rver.Name | Export-Csv D:\Scripts\ServerLocalAdmin\Reports\LocalAdmin ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Export-Csv], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.Exp 
   ortCsvCommand
 
Export-Csv : Cannot bind argument to parameter 'InputObject' because it is null.
At D:\Scripts\ServerLocalAdmin\ServerLocalAdmin.ps1:5 char:87
+ ... rver.Name | Export-Csv D:\Scripts\ServerLocalAdmin\Reports\LocalAdmin ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Export-Csv], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.Exp 
   ortCsvCommand

由于您正在遍历包含服务器的对象,而我们无法访问该数据,因此您可能应该尝试在foreach循环中添加一个输出,以查看对象中的哪些项是问题所在。
听起来好像Get-LocalGroupMembership正在为您的某些服务器返回空值。

您只需更改以下内容:

foreach ($Server in $Servers)
{
    Get-LocalGroupMembership -Computername $Server.Name |
    Export-Csv D:\Scripts\ServerLocalAdmin\Reports\LocalAdmins.csv -Append -NoTypeInformation
}
为此:

foreach ($Server in $Servers)
{
    $localMembership = Get-LocalGroupMembership -Computername $Server.Name
    
    if($localMembership)
    {
        $localMembership | Export-Csv D:\Scripts\ServerLocalAdmin\Reports\LocalAdmins.csv -Append -NoTypeInformation
    }
}
或者这个:

foreach ($Server in $Servers)
{
    $localMembership = Get-LocalGroupMembership -Computername $Server.Name
    
    if(-not $localMembership){continue}

    $localMembership | Export-Csv D:\Scripts\ServerLocalAdmin\Reports\LocalAdmins.csv -Append -NoTypeInformation
}
正如@Zucchini提供的答案中所述,您得到的错误是,因为函数为您的一些服务器返回了
$null
值。要重现错误,您可以尝试:

PS /~> $null | Export-Csv test.csv
Export-Csv : Cannot bind argument to parameter 'InputObject' because it is null.
At line:1 char:9
+ $null | Export-Csv test.csv
+         ~~~~~~~~~~~~~~~~~~~
...
值得一提的是,在每次循环迭代时将结果附加到CSV是非常低效的,脚本的磁盘I/O越少,其运行速度就越快:)

因此,这是如何使脚本运行得更快的一个示例:


$result = [system.collections.generic.list[pscustomobject]]::new()

foreach ($Server in $Servers)
{
    $localMembership = Get-LocalGroupMembership -Computername $Server.Name
    
    if($localMembership)
    {
        $result.Add($localMembership)
    }
}

$result | Export-Csv D:\Scripts\ServerLocalAdmin\Reports\LocalAdmins.csv -NoTypeInformation
编辑: 下面是一个工作示例,函数在任何地方都返回空值

$result = [system.collections.generic.list[pscustomobject]]::new()

foreach ($Server in $Servers)
{
    $localMembership = Get-LocalGroupMembership -Computername $Server.Name
    
    foreach($i in $localMembership|?{$_})
    {
        $result.Add([pscustomobject]@{
            Name=$i.Name
            Depth=$i.Depth
            ParentGroup=$i.ParentGroup
            Type=$i.Type
            ComputerName=$i.ComputerName
            isGroup=$i.isGroup
        })
    }
}

$result | Export-Csv D:\Scripts\ServerLocalAdmin\Reports\LocalAdmins.csv -NoTypeInformation

我明天会尝试一下,并让你知道,我感谢你的帮助。所以我仔细阅读了你的每一条建议。首先,我得到了与我的原始脚本相同的问题。对于第二个建议,我也得到了同样的行为。对于您提到的第三个建议,我没有发现任何错误,但是输出不正确。它看起来像下面的…“Count”、“Length”、“LongLength”、“Rank”、“SyncRoot”、“IsReadOnly”、“IsFixedSize”、“IsSynchronized”、“178”、“178”、“178”、“178”、“1”、“System.Object[]”、“False”、“True”、“False”、“False”、“185”、“185”、“1”、“System.Object[]”、“False”、“True”、“False”我将尝试并测试从一个csv文件(我知道正在连接)中运行的服务器列表。我正在测试的OU总共有13台服务器。最终,我将运行另一个包含近1500台服务器的OU。我知道有些问题可能是WinRM。这是一场试图确保允许通过多个子网和防火墙进行连接的战斗。我将与我们的网络团队在这方面进行更多的合作。在导入我知道是从.csv文件连接的服务器时,我也会遇到同样的错误。因此,对于无法连接的服务器来说,这似乎不是一个问题。这一定是我假设的函数本身。最后,我知道它是有效的,我只是希望通过消除错误来加快速度。我曾经在我所有的服务器上运行过一次,大约需要12个小时。总的来说,这个功能是惊人的打破了所有用户添加到本地管理组。