Powershell scrip to run a query in multiple servers - powershell

Trying to run the following query in multiple databases but receiving the following error : Invoke-SqlCmd : Value cannot be null.
$query = #' SQL SCRIPT ' #
$csvFilePath = 'PATH FOR CSV FILE'
$serverlist = echo (list of servers )
$queryresults = $null
$InvokeParams = #{
SERVER = $serverlist
Database = 'TEST DATABASE'
Username = 'username '
Password = 'password1'
Query = $query
QueryTimeout = 100
}
foreach($server in $serverlist)
{
write-host "Executing query against server: " $server
$queryResults = Invoke-SqlCmd #InvokeParams -Erroraction stop
}
write-host "Saving Query Results in CSV format..."
$queryResults | export-csv $csvFilePath -NoTypeInformation
write-host "Converting CSV output to Excel..."
Do I always have to specify parameters ? What if my query is about creating a table for example ?

Related

PowerShell - Run function against multiple records from SQL query to send one email

I am trying to run a PowerShell script where I query a list of servers and run a custom Get-TimeZone function and then send an email to a list of recipients with the data in a table format.
I was able to get the script to work correctly if I write the server list to a text file and then run the function against the list from the text file, but I am wanting to skip the step of writing to a text file and run the function directly against the returned list of servers from the query.
##This works via text file
$SQLInstance = "SQLInstance"
$Database = "DatabaseName"
$ServerQuery = "SELECT em.ServerName FROM dbo.EnvironmentMap AS em ORDER BY em.ServerName;"
$serverFile = "D:\Powershell\Misc\TimeZoneServers.txt"
If ( Test-Path $serverFile ) { Remove-Item $serverFile }
$servers = Invoke-DbaQuery -SqlInstance $SQLInstance -Database $Database -Query $ServerQuery
foreach ($server in $servers.ServerName)
{
$server | Out-File -FilePath $serverFile -Append
}
$serverNames = Get-Content $serverFile
$TimeZoneInfo = Get-TimeZone -ComputerName $serverNames | Select ComputerName, TimeZone | Sort-Object ComputerName, TimeZone | ConvertTo-Html | Out-String
$messageParameters = #{
Subject = "SQL Server Time Zone Information"
Body = $TimeZoneInfo
From = "noreply#companyX.com"
To = "email1#companyX.com"
SmtpServer = "smtp.companyX.com"
}
Send-MailMessage #messageParameters -BodyAsHtml
In my attempt to remove the text file creation, the script does run but it sends an email with a single value for each of the servers that is returned.
##Sends multiple emails
$SQLInstance = "SQLInstance"
$DatabaseName = "DatabaseName"
$TimeZoneQuery = "SELECT em.ServerName FROM dbo.EnvironmentMap AS em ORDER BY em.ServerName;"
$serverList = Invoke-DbaQuery -SqlInstance $SQLInstance -Database $DatabaseName -Query $TimeZoneQuery
foreach ( $server in $serverList )
{
$TimeZoneInfo = Get-TimeZone -ComputerName $server.ServerName | Select ComputerName, TimeZone | Sort-Object ComputerName, TimeZone | ConvertTo-Html | Out-String
$messageParameters = #{
Subject = "SQL Server Time Zone Information"
Body = $TimeZoneInfo
From = "noreply#companyX.com"
To = "email1#companyX.com"
SmtpServer = "smtp.companyX.com"
}
Send-MailMessage #messageParameters -BodyAsHtml
}
I understand why the code now sends multiple emails - but I cannot figure out where or if I need a foreach loop to have the function run for each of the servers that are returned in the query.
Any advice on how I can have one email sent that would contain all of the servers returned from the query?
Thanks,

Function to check DB in remote server - Timeout question

I am writing a function in PowerShell that will do the following when given some parameter:
Get Credetials to connect to remote SQL Server
Open SQL Connection with given parameters. If Opening connection takes longer than value in $sqlconnectionTimeout, it will report a log file with Timeout error
A query will be introduce in a specific DB from Remote Server. If executing command takes longer than value in $sqlCommandTimeout, it will report a log file with error.
The function will create a html file with connectivity result (True or False). If True, the script will check log reports within last 5 minutes. Connectivity will be True if no logs are found. If False, a log will be created and saved in a specific folder.
About the Timeout variables, No matter what I put in the variable, The Connection is opened and the command is executed. Even If I put 0 forcing it to output a timeout error. The connection is opened and the query executed.
My question is: What am I missing here so that Timeout takes effect when executing the function?
Thanks for your help
This is the Code:
# Editing Variables
$user = "userName"
$DatabaseName = "SampleDB"
$query = "INSERT INTO [SampleDB].[dbo].[HealthChecks]([DateTime],[Source],[User]) VALUES (CURRENT_TIMESTAMP, ##SERVERNAME, CURRENT_USER)"
#Set timeout when stablishing connection (Default = 15)
$sqlConnectionTimeout = 3
#Set timeout when executing sql command (Default = 30)
$sqlCommandTimeout = 3
# 1. R-etrieve the data
function Test-SqlConnection
{
param(
[Parameter(Mandatory)]
[string]$serverURL,
[Parameter(Mandatory)]
[string]$DatabaseName,
[Parameter(Mandatory)]
[string]$user,
[Parameter(Mandatory)]
[string]$query,
[Parameter(Mandatory=$False)]
[string]$sqlConnectionTimeout,
[Parameter(Mandatory=$False)]
[string]$sqlCommandTimeout
)
try
{
$logTime = (Get-Date -Format "hh-mm_dd-MM-yyyy")
$reportPath = "C:\Logs\DBLogs\"
$DBCheckPath = "C:\inetpub\wwwroot\UptimeRobot\"
# Obtain Credentials without revealing password in script
$userName = $user
$passwordFile = "C:\Utilities\keys\password.txt"
$keyFile = "C:\Utilities\keys\aes.key"
$key = Get-Content $keyFile
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $userName, (Get-Content $passwordFile | ConvertTo-SecureString -Key $key)
# Open Connection to DB
$userName = $Credential.UserName
$password = $Credential.GetNetworkCredential().Password
$connectionString = "Data Source={0};database={1};User ID={2};Password={3};Connection Timeout={4}" -f $serverURL,$DatabaseName,$userName,$password,$sqlConnectionTimeout
$sqlConnection = New-Object System.Data.SqlClient.SqlConnection $ConnectionString
$sqlConnection.Open()
#3. P-repare the UpdateRequest
$sqlCommand = New-Object System.Data.SQLClient.SQLCommand
$sqlCommand.CommandTimeout = $sqlCommandTimeout
$sqlCommand.Connection = $sqlConnection
$sqlCommand.CommandText = $query
$res = $sqlCommand.ExecuteNonQuery()
# 4. S-end reports to log file in JSon format
$sqlLogs = Get-Childitem $reportPath -filter *.json | Where-Object {$_.LastWriteTime -gt [datetime]::Now.AddMinutes(-5)}
if($res -eq 1)
{
if($sqlLogs.count -gt 0)
{
$connectivityResult = #{
DBServer = $ServerFriendlyName
DataCenter = $dataCenter
Connectivity = $False
}
}else
{
$connectivityResult =#{
DBServer = $ServerFriendlyName
DataCenter = $dataCenter
Connectivity = $True
}
}
$connectivityResult | ConvertTo-Json -Compress | Out-File -Encoding utf8 -LiteralPath ($DBCheckPath + "DBCheck.html")
}
##TODO: Only report Connectivity Serviceable= $false when there are two logs with $false value within 5 minutes.
}catch
{
$errorMessage = $_.Exception
## Only return $false if the exception was thrown because it can't connect for some reason. Otherwise
## throw the general exception
if ($errorMessage -match 'The server was not found' -or 'timeout')
{
$connectivityResult = #{
DBServer = $ServerFriendlyName
DataCenter = $dataCenter
Connectivity = $False
ErrorMessage = $errorMessage.GetBaseException().message
}
$connectivityResult | ConvertTo-Json | Out-File -Encoding utf8 -LiteralPath ($reportPath + $logTime + ".json")
$connectivityResult | ConvertTo-Json | Out-File -Encoding utf8 -LiteralPath ($DBCheckPath + "DBCheck.html")
}
}
finally
{
$sqlConnection.Close()
}
}

Code not being seen if I include it from a file

I'm writing some Powershell scripts to manage a SQL Server. When I create my SMO object, I do a test to see if I can list my databases. If so, then I assume I'm connected and call a function (via an included file) that has an Invoke-Sqlcmd that causes my database to disconnect or something.
However, if I run the invoke command directly in the script, it works fine.
Looking at the provided code, my output is as follows:
I'm connected
$SqlServer is not contactable
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | Out-Null
$ErrorActionPreference = "Stop"
Import-Module 'sqlps' -DisableNameChecking #load all of SMO
$ScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -
Parent
try {
("$ScriptDirectory\_HRbackup.ps1")
("$ScriptDirectory\_HRprinter.ps1")
("$ScriptDirectory\_HRbody.ps1")
} catch {
Write-Host "Error while loading supporting PowerShell Scripts"
}
$ServerList = $env:COMPUTERNAME
$SqlServer = New-Object ('Microsoft.SqlServer.Management.Smo.Server')
$ServerList # add server list
try {
$databases = $SqlServer.Databases
if ($databases.Count -gt 0) {
Write-Host "I am connected"
Backup-Html
} else {
$login = Get-Credential -Message 'Please prov#ide your SQL
Credentials'
$SqlServer.ConnectionContext.LoginSecure = $false
$SqlServer.ConnectionContext.Login = $login.UserName
$SqlServer.ConnectionContext.set_SecurePassword($login.Password)
$SqlServer.ConnectionContext.connect()
}
} catch {
$WarningPreference = 'continue'
Write-Warning "$SqlServer is not contactable"
#$SqlServer.ConnectionContext.Disconnect()
} finally {
$SqlServer.ConnectionContext.Disconnect()
}
Here is the content of Backup-Html:
$Query = "select top 5 a.server_name, a.database_name,
backup_finish_date, a.backup_size,
CASE a.[type] -- Let's decode the three main types of
backup here
WHEN 'D' THEN 'Full'
WHEN 'I' THEN 'Differential'
WHEN 'L' THEN 'Transaction Log'
ELSE a.[type]
END as BackupType
-- Build a path to the backup
,'\\' +
-- lets extract the server name out of the recorded
server and instance name
CASE
WHEN patindex('%\%',a.server_name) = 0 THEN
a.server_name
ELSE
substring(a.server_name,1,patindex('%\%',a.server_name)-1)
END
-- then get the drive and path and file information
+ '\' + replace(b.physical_device_name,':','$') AS
'\\Server\Drive\backup_path\backup_file'
from msdb.dbo.backupset a join msdb.dbo.backupmediafamily
b
on a.media_set_id = b.media_set_id
where a.database_name Like 'Easy%'
order by a.backup_finish_date desc"
#Use SQLCmd to execute the query on the server
Invoke-Sqlcmd -ServerInstance $SQLServer -Query $Query

Script powershell import multiple CSV

I'm doing a script to import CSVs (commands) that update the stock in SQL Server. But I encounter this error when I run the following script:
Invoke-Sqlcmd : La conversion de la valeur varchar '2200100001' a dépassé une colonne int.
L'instruction a été arrêtée.
Au caractère C:\Users\admin\Desktop\updateDb.ps1:36 : 19
+ ... $impcsv = Invoke-Sqlcmd -Database $db_name -Query $query -ServerIns ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation : (:) [Invoke-Sqlcmd], SqlPowerShellSqlExecutionException
+ FullyQualifiedErrorId : SqlError,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand
Here is my powershell script:
$sql_instance_name = 'SERVER\SAGE100'
$db_name = 'SERVER_DB'
$table = "dbo.F_ARTSTOCK"
$csv_folder = 'F:\EUR'
$csv_completed_folder = 'F:\EUR\done'
$batchsize = 50000
$csv_files = Get-Childitem -Path $csv_folder -Filter '*.csv'
$connectionstring = "Data Source=$sql_instance_name;Integrated Security=true;Initial Catalog=$db_name;"
$bulkcopy = New-Object Data.SqlClient.SqlBulkCopy($connectionstring, [System.Data.SqlClient.SqlBulkCopyOptions]::TableLock)
$bulkcopy.DestinationTableName = $table
$bulkcopy.bulkcopyTimeout = 0
$bulkcopy.batchsize = $batchsize
foreach($file in $csv_files) {
$impcsv = $file.FullName
write-host "Processing file ..........$impcsv" -foregroundcolor green
$data = import-csv -Delimiter ";" $impcsv
$count = 1
foreach($i in $data) {
Write-Host $i.Reference
$reference = $i.Reference
$quantity = $i.Quantity
$query = "UPDATE dbo.F_ARTSTOCK (AR_Ref,AS_QteSto)
SET dbo.F_ARTSTOCK.AS_QteSto = dbo.F_ARTSTOCK.AS_QteSto - $quantity
WHERE dbo.F_ARTSTOCK.AR_Ref = $reference"
Write-Host $query
$impcsv = invoke-sqlcmd -Database $db_name -Query $query -ServerInstance $sql_instance_name
write-host "Processing row ..........$count" -foregroundcolor green
$count = $count + 1
}
}
Do you have any idea where the problem would come from?
Thank you for your help.
The error message is in french. Translated it reads: The conversion of the '2200100001' varchar value has exceeded an int column. The instruction has been stopped.
Basically what that means is you have a 32-bit int column on that table and it needs to be of bigint type to handle a larger value... Or go through the data that you're trying to submit and verify that it is accurate (aka: remove that row from the csv. Depending on how sensitive of data you are working on).

How do I find the Collection Membership Information with PowerShell

I have the following code, but I get an "Invalid Namespace" error constantly, I am pretty sure I am entering the correct information.
If you have another way of doing this, it's also accepted.
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
Rather than connecting to each computer and extracting the information (slow) get it from the straight from the database....
[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
}
Execution:-
PS C:\> ListSCCMCollections.ps1 -sccmsrv SCCMSERVER -hosts host1,host2,host3 -path "c:\temp\Outfile.csv"
or
PS C:\> Get-Content hostlist.txt | ListSCCMCollections.ps1 -sccmsrv SCCMSERVER -path c:\temp\Outfile.csv
Getting the requested info straight from 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'))
This script can be used with any SQL query on the SCCM database. All you need to do is update the SQL query in the script. i.e. the $memberQuery array (if you spread the query over a couple of lines like below, be sure to leave a space at the end of each line with exception to the last).
For example; If you'd like the script to show the clients collections with live advertisements assigned to them change the SQL query in the $memberQuery array to:-
$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'))"
and the $sObject variable to:-
$sObject = $enumColl | select Hostname, ResourceID, "Collection Name", CollectionID, IsDirect, AdvertisementID, AdvertisementName
Complete script to view client collections with live advisements (execution the same as before):-
[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
}
And if you connect to SCCM from station with only SCCM Console installed and every other SCCM cmdlets works, trying Get-WmiObject:
Get-WmiObject -Namespace "root\sms\site_$SiteCode" ...
you will have an error:
“Get-WmiObject : Invalid namespace …”
In this situation you should specify parameter ComputerName and point to server where SCCM is installed:
Get-WmiObject -ComputerName "SCCMserver" -Namespace "root\sms\site_$SiteCode" ...
Hope it helps, I waste few minutes by this.