如何使用PowerShell查找集合成员身份信息

时间:2013-06-07 15:47:03

标签: powershell csv collections sccm computer-name

我有以下代码,但我不断收到“无效的命名空间”错误,我很确定我输入了正确的信息。

如果你有另一种方法,也可以接受。

Param(
    $SiteCode,
    $SourceFile,
    $Destination = "$env:USERPROFILE\DESKTOP\Computers.csv"
)


$Computers = Get-Content $SourceFile
$EmptyArray = @()

foreach($computer in $computers)
{
    $ResourceIDQuery = Get-WmiObject -Namespace "root\sms\site_$SiteCode" -Class SMS_R_SYSTEM -Filter "Name='$computer'"

    $CollectionQuery = Get-WmiObject -Namespace "root\sms\site_$SiteCode" -Class SMS_CollectionMember_a -filter "ResourceID='$($ResourceIDQuery.ResourceId)'"

    foreach($Item in $CollectionQuery)
    {
        $DObject = New-Object PSObject
            $Dobject | Add-Member -MemberType NoteProperty -Name "Computer" -Value $computer 
            $Dobject | Add-Member -MemberType NoteProperty -Name "ResID" -Value $($ResourceIDQuery.ResourceId)
            $Dobject | Add-Member -MemberType NoteProperty -Name "CollID" -Value $($Item.CollectionId)
            $Dobject | Add-Member -MemberType NoteProperty -Name "DirectOrNot" -Value $($Item.IsDirect)
        $EmptyArray += $Dobject
    }
}

$EmptyArray | ConvertTo-Csv -NoTypeInformation | Out-File $Destination

2 个答案:

答案 0 :(得分:1)

而不是连接到每台计算机并提取信息(慢)从数据库直接获取它....

[CmdletBinding()]
param ( 
        [string] $hosts = "",
        [string] $sccmsrv = "",
        [Parameter(Mandatory=$False,Position=3)]
        [string] $path = ""
    )

$usage =  "USAGE: List-AdvertCollMembershipSCCM.ps1 -sccmsrv SCCMSERVER -hosts 'host1 host2 host3' -path 'c:\temp\Outfile.csv'"

if ($host -and $sccmsrv){

Write-Host ""       
Write-Host -ForegroundColor Yellow "SCCM Server: $sccmsrv"
Write-Host -ForegroundColor Yellow "Looking at hosts: $hosts"


  #### Function for executing a SQL query with integrated authentication  
  function execSQLQuery ([string]$fSQLServer, [string]$db, [string]$query){  
    $objConnection = New-Object System.Data.SqlClient.SqlConnection  
    $objConnection.ConnectionString = "Server = $fSQLServer; Database = $db; trusted_connection=true;"  
    $SqlCmd = New-Object System.Data.SqlClient.SqlCommand $query, $objConnection  
    trap {Write-Host -ForegroundColor 'red' "($sqlsrv/$db not accessible)";continue}   
    $SqlCmd.Connection.Open()  

    if ($SqlCmd.Connection.State -ine 'Open') {  
       $SqlCmd.Connection.Close()  
       return  
    }  
    $dr = $SqlCmd.ExecuteReader()  

    #get the data  
    $dt = new-object "System.Data.DataTable"  
    $dt.Load($dr)  
    $SqlCmd.Connection.Close()  
    $dr.Close()  
    $dr.Dispose()  
    $objConnection.Close()  
    return $dt  
  }  

  # read the SCCM site name of the SCCM site server  
  $site = (gwmi -ComputerName $sccmsrv -Namespace root\sms -Class SMS_ProviderLocation).sitecode  

  # enumerating SQL server name for the given SCCM site server  
  $sccmCompquery = gwmi -q "Select distinct SiteSystem, Role, SiteCode FROM SMS_SiteSystemSummarizer where role = 'SMS SQL Server' and siteCode = '$site' ORDER BY SiteCode" -namespace "root\sms\site_$site" -ComputerName $sccmsrv  
  [string]$tmpstr = [regex]::Match($sccmCompquery.sitesystem, "\\\\\w+\\$")  
  $sccmSQLServer = $tmpstr.replace("\", "")  
  $objColl = @()  

  #### Collate the host list.  
  $hostlist = @($Input)  
  if ($hosts) {  
    if($hosts -imatch " "){  
       $hostsArr = @($hosts.split(" "))
       $hostlist += $hostsArr  
    }  
    else{  
       $hostlist += $hosts  
    }  
  }  

  # going through the list of hosts  
  foreach($srv in $hostlist){  
    $memberQuery = "SELECT dbo.v_FullCollectionMembership.Name AS 'Hostname', dbo.v_GS_SYSTEM.ResourceID, dbo.v_Collection.Name AS 'Collection Name', dbo.v_Collection.CollectionID, dbo.v_FullCollectionMembership.IsDirect "  
    $memberQuery += "FROM dbo.v_FullCollectionMembership INNER JOIN dbo.v_Collection ON dbo.v_FullCollectionMembership.CollectionID = dbo.v_Collection.CollectionID INNER JOIN dbo.v_GS_SYSTEM ON dbo.v_FullCollectionMembership.ResourceID = dbo.v_GS_SYSTEM.ResourceID "  
    $memberQuery += "WHERE (LOWER(dbo.v_FullCollectionMembership.Name) = LOWER('$srv'))"  

    # running sql query to enumerate list of collections the computer is member of  
    $membership = execSQLQuery $sccmSQLServer "SMS_$site" $memberQuery  

    # if we have a result, go through it and build an object collection with the computer name and the collection(s) it is member of  
    if($membership){  
       foreach($enumColl in $membership){

        $sObject = $enumColl | select Hostname, ResourceID, "Collection Name", CollectionID, IsDirect
        $objColl +=$sObject

       }  
    }  
  }


if ($objColl){
    if ($path){
        $objColl | ft -AutoSize
        Write-Host -ForegroundColor Yellow "Exporting to results to: $path"
        $objColl | Export-Csv $path -NoTypeInformation
    }
    else{
    $objColl | ft -AutoSize
    Write-Host -ForegroundColor Green "Use the -path argument in the command line to export output to csv to display"
    Write-Host -ForegroundColor Green "the 'IsDirect' Information"
    Write-Host ""
    }
}
Else {
    foreach ($Hostname in $hostlist){
    Write-Host ""
    Write-Host -ForegroundColor Yellow "The host $hostname is not a member of any collection"
    }
Write-Host -ForegroundColor Yellow "Check you have entered the correct hostname and try again"
}
}
else {

    Write-Host ""
    Write-Host -ForegroundColor Yellow $usage
}

执行: -

PS C:\> ListSCCMCollections.ps1 -sccmsrv SCCMSERVER -hosts host1,host2,host3 -path "c:\temp\Outfile.csv"

PS C:\> Get-Content hostlist.txt | ListSCCMCollections.ps1 -sccmsrv SCCMSERVER -path c:\temp\Outfile.csv

直接从SQL获取所需信息: -

SELECT     dbo.v_FullCollectionMembership.Name AS 'Hostname', dbo.v_GS_SYSTEM.ResourceID, dbo.v_Collection.Name AS 'Collection Name', dbo.v_Collection.CollectionID, 
                      dbo.v_FullCollectionMembership.IsDirect
FROM         dbo.v_FullCollectionMembership INNER JOIN
                      dbo.v_Collection ON dbo.v_FullCollectionMembership.CollectionID = dbo.v_Collection.CollectionID INNER JOIN
                      dbo.v_GS_SYSTEM ON dbo.v_FullCollectionMembership.ResourceID = dbo.v_GS_SYSTEM.ResourceID
WHERE     (LOWER(dbo.v_FullCollectionMembership.Name) = LOWER('Hostname'))

此脚本可与SCCM数据库上的任何SQL查询一起使用。您需要做的就是更新脚本中的SQL查询。即$ memberQuery数组(如果你将查询分散到如下所示的几行,请务必在每行的末尾留一个空格,除了最后一行)。

例如;如果您希望脚本显示分配了实时广告的客户端集合,请将$ memberQuery数组中的SQL查询更改为: -

$memberQuery = "SELECT dbo.v_FullCollectionMembership.Name AS 'Hostname', dbo.v_GS_SYSTEM.ResourceID, dbo.v_Collection.Name AS 'Collection Name',dbo.v_Collection.CollectionID, dbo.v_FullCollectionMembership.IsDirect, dbo.v_Advertisement.AdvertisementID, dbo.v_Advertisement.AdvertisementName "  
$memberQuery += "FROM dbo.v_FullCollectionMembership INNER JOIN dbo.v_Collection ON dbo.v_FullCollectionMembership.CollectionID = dbo.v_Collection.CollectionID INNER JOIN dbo.v_GS_SYSTEM ON dbo.v_FullCollectionMembership.ResourceID = dbo.v_GS_SYSTEM.ResourceID INNER JOIN dbo.v_Advertisement ON dbo.v_Collection.CollectionID = dbo.v_Advertisement.CollectionID "  
$memberQuery += "WHERE (LOWER(dbo.v_FullCollectionMembership.Name) = LOWER('$srv'))"  

和$ sObject变量: -

$sObject = $enumColl | select Hostname, ResourceID, "Collection Name", CollectionID, IsDirect, AdvertisementID, AdvertisementName

使用实时建议查看客户端集合的完整脚本(执行与以前相同): -

[CmdletBinding()]
param ( 
        [string] $hosts = "",
        [string] $sccmsrv = "",
        [Parameter(Mandatory=$False,Position=3)]
        [string] $path = ""
    )

$usage =  "USAGE: List-AdvertCollMembershipSCCM.ps1 -sccmsrv SCCMSERVER -hosts 'host1 host2 host3' -path 'c:\temp\Outfile.csv'"

if ($host -and $sccmsrv){

Write-Host ""       
Write-Host -ForegroundColor Yellow "SCCM Server: $sccmsrv"
Write-Host -ForegroundColor Yellow "Looking at hosts: $hosts"


  #### Function for executing a SQL query with integrated authentication  
  function execSQLQuery ([string]$fSQLServer, [string]$db, [string]$query){  
    $objConnection = New-Object System.Data.SqlClient.SqlConnection  
    $objConnection.ConnectionString = "Server = $fSQLServer; Database = $db; trusted_connection=true;"  
    $SqlCmd = New-Object System.Data.SqlClient.SqlCommand $query, $objConnection  
    trap {Write-Host -ForegroundColor 'red' "($sqlsrv/$db not accessible)";continue}   
    $SqlCmd.Connection.Open()  

    if ($SqlCmd.Connection.State -ine 'Open') {  
       $SqlCmd.Connection.Close()  
       return  
    }  
    $dr = $SqlCmd.ExecuteReader()  

    #get the data  
    $dt = new-object "System.Data.DataTable"  
    $dt.Load($dr)  
    $SqlCmd.Connection.Close()  
    $dr.Close()  
    $dr.Dispose()  
    $objConnection.Close()  
    return $dt  
  }  

  # read the SCCM site name of the SCCM site server  
  $site = (gwmi -ComputerName $sccmsrv -Namespace root\sms -Class SMS_ProviderLocation).sitecode  

  # enumerating SQL server name for the given SCCM site server  
  $sccmCompquery = gwmi -q "Select distinct SiteSystem, Role, SiteCode FROM SMS_SiteSystemSummarizer where role = 'SMS SQL Server' and siteCode = '$site' ORDER BY SiteCode" -namespace "root\sms\site_$site" -ComputerName $sccmsrv  
  [string]$tmpstr = [regex]::Match($sccmCompquery.sitesystem, "\\\\\w+\\$")  
  $sccmSQLServer = $tmpstr.replace("\", "")  
  $objColl = @()  

  #### Collate the host list.  
  $hostlist = @($Input)  
  if ($hosts) {  
    if($hosts -imatch " "){  
       $hostsArr = @($hosts.split(" "))
       $hostlist += $hostsArr  
    }  
    else{  
       $hostlist += $hosts  
    }  
  }  

  # going through the list of hosts  
  foreach($srv in $hostlist){  
    $memberQuery = "SELECT dbo.v_FullCollectionMembership.Name AS 'Hostname', dbo.v_GS_SYSTEM.ResourceID, dbo.v_Collection.Name AS 'Collection Name',dbo.v_Collection.CollectionID, dbo.v_FullCollectionMembership.IsDirect, dbo.v_Advertisement.AdvertisementID, dbo.v_Advertisement.AdvertisementName "  
    $memberQuery += "FROM dbo.v_FullCollectionMembership INNER JOIN dbo.v_Collection ON dbo.v_FullCollectionMembership.CollectionID = dbo.v_Collection.CollectionID INNER JOIN dbo.v_GS_SYSTEM ON dbo.v_FullCollectionMembership.ResourceID = dbo.v_GS_SYSTEM.ResourceID INNER JOIN dbo.v_Advertisement ON dbo.v_Collection.CollectionID = dbo.v_Advertisement.CollectionID "  
    $memberQuery += "WHERE (LOWER(dbo.v_FullCollectionMembership.Name) = LOWER('$srv'))"  

    # running sql query to enumerate list of collections the computer is member of  
    $membership = execSQLQuery $sccmSQLServer "SMS_$site" $memberQuery  

    # if we have a result, go through it and build an object collection with the computer name and the collection(s) it is member of  
    if($membership){  
       foreach($enumColl in $membership){

        $sObject = $enumColl | select Hostname, ResourceID, "Collection Name", CollectionID, IsDirect, AdvertisementID, AdvertisementName
        $objColl +=$sObject

       }  
    }  
  }
if ($objColl){
    if ($path){
        $objColl | ft -AutoSize
        Write-Host -ForegroundColor Yellow "Exporting to results to: $path"
        $objColl | Export-Csv $path -NoTypeInformation
    }
    else{
    $objColl | ft -AutoSize
    Write-Host -ForegroundColor Green "Use the -path argument in the command line to export output to csv to display"
    Write-Host -ForegroundColor Green "the header 'AdvertisementName'"
    Write-Host ""
    }
}
Else {
    foreach ($Hostname in $hostlist){
    Write-Host ""
    Write-Host -ForegroundColor Yellow "The host $hostname is not a member of any collection with live advertisements"
    }
Write-Host -ForegroundColor Yellow "Check you have entered the correct hostname and try again"
}
}
else {

    Write-Host ""
    Write-Host -ForegroundColor Yellow $usage
}

答案 1 :(得分:1)

如果从安装了 SCCM控制台的工作站连接到SCCM并且每个其他SCCM cmdlet都工作,请尝试Get-WmiObject:

Get-WmiObject -Namespace "root\sms\site_$SiteCode" ... 

您将收到错误:

“Get-WmiObject : Invalid namespace …”

在这种情况下,您应指定参数ComputerName并指向安装SCCM的服务器:

Get-WmiObject -ComputerName "SCCMserver" -Namespace "root\sms\site_$SiteCode" ... 

希望它有所帮助,我浪费了几分钟。