I am writing a script to gather data about domain computers and I ma trying to output this to a csv file. However its not coming out the way I want it to.
Here is my code:
Set-ExecutionPolicy Unrestricted -force
Import-Module ActiveDirectory
$CSVPath = $ScriptFolderPath + "\" + $ScriptName + ".csv"
$Import = Get-Content "c:\T2\AD Computers Scripts\ComputersTest.csv"
foreach ($Member in $Import)
{
$ComputerName = Get-ADComputer $Member -Properties Name, CanonicalName | Select Name, CanonicalName
$ConnectionStatus = Test-Connection $Member -Quiet
IF ($ConnectionStatus -eq $TRUE)
{
$IPAddress = Test-Connection $Member -Count 1 | Select -ExpandProperty IPV4Address
}
ELSE
{
$IPAddress = "Not able to contact server"
}
$CSVPath
$Report1 = $ComputerName | ForEach -Process {$_ | Add-Member -Name IPAddress -Value $IPAddress -MemberType NoteProperty -PassThru}
$Report1 | Add-Member -Name Subnet -Value $CSVPath -MemberType NoteProperty -PassThru
$Report1
"`n`n`n"
The out put looks like this:
Name CanonicalName IPAddress Subnet
---- ------------- --------- ------
CEN-RVS abc.local/Servers/Corpora... 10.19.95.2 C:\t2\AD Computers Scripts
CEN-RVS abc.local/Servers/Corpora... 10.19.95.2 C:\t2\AD Computers Scripts
All I need is a single line. It should look like this:
Name CanonicalName IPAddress Subnet
---- ------------- --------- ------
CEN-RVS abc.local/Servers/Corpora... 10.19.95.2 C:\t2\AD Computers Scripts
The -PassThru parameter to Add-Member means "output the modified object".
Thus, these two statements are (apart from the side-effect of adding a NoteProperty to $Report1) redundant:
$Report1 | Add-Member -Name Subnet -Value $CSVPath -MemberType NoteProperty -PassThru
$Report1
Either remove the $Report1 statement at the end or remove -PassThru switch from the Add-Member statement
Related
I'm trying to create a Powershell script that shows the folder permissions and the members of the permission groups. I have a function called "Get-Members" that returns (as a comma separated string) the members of the group that has sent to the function as an argument.
Now I'd like to know how i can use the returning string with the Add-Member's value parameter. How can i use the function with that? I tried
Add-Member -MemberType NoteProperty -Name "Members" -Value Get-Members($_.IdentityReference) -PassThru
but it doesn't seem to be working.
Here's the whole thing:
($root | get-acl).Access | Add-Member -MemberType NoteProperty -Name "Members" -Value Get-Members($_.IdentityReference) -PassThru | Add-Member -MemberType NoteProperty -Name "Folder" -Value $($root.fullname).ToString() -PassThru | select -Property Path, IdentityReference, FileSystemRights
And here's the function:
Function Get-Members {
param( [string]$group )
$xyz=$group
if ($group -match '\\')
{
$xyz=$group -creplace '^[^\\]*\\', ''
}
$Group = [ADSI]"LDAP://cn=$xyz,ou=SecurityGroups,ou=Accounting,ou=Services,dc=CONTOSO,dc=ny,dc=local"
$Members = $Group.Member | ForEach-Object {[ADSI]"LDAP://$_"}
$combined = $Members | select -ExpandProperty name
$result= $combined -join ","
return $result
}
How can I get this to work?
Your brackets are wrong. Try this:
Add-Member -MemberType NoteProperty -Name "Members" -Value (Get-Members $_.IdentityReference) -PassThru
Which would make the Get-Members part execute first and return its values to the -Value property due to the brackets.
As an aside, i'd recommend you choose a different name over Get-Members because its too close to the very well known Get-Member cmdlet.
This question already has answers here:
Can Powershell Run Commands in Parallel?
(10 answers)
Closed 6 years ago.
I have 100,000 list of servers from the text file (serverlist.txt)
When I run in one shot it will burst my memory and cpu and the time took longer (about 3 days)to complete the scanning for DNSlookup.
I tried to split the file that contain 20k list of servers below and can be completed to scan up to 10mins for each file.
serverlist1.txt
serverlist2.txt
serverlist3.txt
serverlist4.txt
serverlist5.txt
$objContainer = #()
$values = #()
$domains = Get-Content -path "serverlist1.txt"
$named = 0
$timestamp= get-date
$domains | ForEach-Object {
$domain = $_
nslookup $domain 2>&1 | ForEach-Object {
if ($_ -match '^Name:\s*(.*)$') {
$values += $matches[1]
$named = 1;
} elseif (($_ -match '^.*?(\d*\.\d*\.\d*\.\d*)$') -and ($named -eq 1)) {
$values += $matches[1]
} elseif ($_ -match '^Aliases:\s*(.*)$') {
$values += $matches[1]
}
}
$obj = New-Object -TypeName PSObject
#$obj | Add-Member -MemberType NoteProperty -name 'Domain' -value $domain
$obj | Add-Member -MemberType NoteProperty -name 'Name' -value $values[0]
$obj | Add-Member -MemberType NoteProperty -name 'IP Address' -value $values[1]
$obj | Add-Member -MemberType NoteProperty -name 'Alias' -value $values[2]
$obj | Add-Member -MemberType NoteProperty -name 'Timestamp' -value $timestamp
$objContainer += $obj
$values = #()
$named = 0
}
Write-Output $objContainer
$objContainer | Export-csv "dnslog_$((Get-Date).ToString('MM-dd-yyyy_hh-mm-ss')).csv" -NoTypeInformation
My question is, how to execute at once and looping the input from the text file after generate the dnslog(datetime).csv
e.g:
run the powershell script .\filename.ps1
input from serverlist1.txt
output dnslog(datetime).csv
input from serverlist2.txt
output dnslog(datetime).csv
input from serverlist3.txt
output dnslog(datetime).csv
input from serverlist4.txt
output dnslog(datetime).csv
input from serverlist5.txt
output dnslog(datetime).csv
Finish!
If i have more then 5 list of text file, it will continue to loop from the input file until completed.
Adding to Chris's answer I would also add a ReadCount flag to the Get-Content like so:
Get-Content -path "serverlist1.txt" -ReadCount 1 | % {
This will save having to read the entire file into memory.
You should consider running this a parallel batching job. Have you already tried doing so?
You can deal with the RAM busting problem by removing all those commits to memory (variable assignments and array rewriting with +=).
$timestamp = get-date
Get-Content -path "serverlist1.txt" | ForEach-Object {
$domain = $_
# You can clear this here.
$values = #()
$named = 0
# There are potentially better options than nslookup.
# Needs a bit of care to understand what's an alias here though.
# [System.Net.Dns]::GetHostEntry($domain)
# And if you don't like that, quite a few of us have written equivalent tools in PowerShell.
nslookup $domain 2>&1 | ForEach-Object {
if ($_ -match '^Name:\s*(.*)$') {
$values += $matches[1]
$named = 1;
} elseif (($_ -match '^.*?(\d*\.\d*\.\d*\.\d*)$') -and ($named -eq 1)) {
$values += $matches[1]
} elseif ($_ -match '^Aliases:\s*(.*)$') {
$values += $matches[1]
}
}
# Leave the output object in the output pipeline
# If you're running PowerShell 3 or better:
[PSCustomObject]#{
Domain = $domain
Name = $values[0]
'IP Address' = $values[1]
Alias = $values[2]
TimeStamp = $timestamp
}
# PowerShell 2 is less flexible. This or Select-Object.
#$obj = New-Object -TypeName PSObject
##$obj | Add-Member -MemberType NoteProperty -name 'Domain' -value $domain
#$obj | Add-Member -MemberType NoteProperty -name 'Name' -value $values[0]
#$obj | Add-Member -MemberType NoteProperty -name 'IP Address' -value $values[1]
#$obj | Add-Member -MemberType NoteProperty -name 'Alias' -value $values[2]
#$obj | Add-Member -MemberType NoteProperty -name 'Timestamp' -value $timestamp
# To leave this in the output pipeline, uncomment this
# $obj
# No version of PowerShell needs you to do this. It's a good way to ramp up memory usage
# for large data sets.
# $objContainer += $obj
} | Export-Csv "dnslog_$(Get-Date -Format 'MM-dd-yyyy_hh-mm-ss').csv" -NoTypeInformation
When exporting data to a CSV file, the first column always are without quotes and I do not understand why. I can move and change so that the secound value becomes the first and the same thing happends there since it's the first column.
foreach ($item in $item_array)
{
$global:f_server_s = "SERVER123"
$global:f_share = "$item"
$global:f_path = "\\$global:f_server_s\$global:f_share"
$obj_fileshare_list = New-Object -TypeName PSObject
$obj_fileshare_list | Add-Member -Type NoteProperty -Name Name -Value "$global:f_share"
$obj_fileshare_list | Add-Member -Type NoteProperty -Name Server -Value "$global:f_server"
$obj_fileshare_list | Add-Member -Type NoteProperty -Name Path -Value "$global:f_path"
$Fileshare_list += $obj_fileshare_list
}
CSV output:
Name,"Server","Path"
item1,"SERVER123","\\SERVER123\item1"
item2,"SERVER123","\\SERVER123\item2"
Save file:
$Fileshare_list | Export-Csv ".\file.csv" -NoTypeInformation -Encoding unicode
In this case, why is Name and all the items without double quotes?
I'm running into this over and over in my script. I have this line of code:
$Errors = Get-DeploymentErrors $uniqueID
When this runs, $Errors is assigned the result of Get-DeploymentErrors and the value of $uniqueID. I just want $Errors to be assigned the result of Get-DeploymentErrors.
Here is the Get-DeploymentErrors function:
Function Get-DeploymentErrors($uniqueID)
{
$Errors = #()
$conn = New-Object -TypeName System.Data.SqlClient.SqlConnection
$conn.ConnectionString = 'removed connection string'
$cmd = New-Object -TypeName System.Data.SqlClient.SqlCommand
$cmd.Connection = $conn
$cmd.CommandText = "removed sql statement"
$cmd.Parameters.AddWithValue("#uniqueID", $uniqueID)
$conn.Open()
$reader = $cmd.ExecuteReader()
if($reader.HasRows)
{
While ($reader.Read())
{
$error = New-Object -TypeName PSObject
$error | Add-Member -MemberType NoteProperty -Name StepID -Value $reader["StepID"]
$error | Add-Member -MemberType NoteProperty -Name DeploymentID -Value $reader["DeploymentID"]
$error | Add-Member -MemberType NoteProperty -Name MessageID -Value $reader["MessageID"]
$error | Add-Member -MemberType NoteProperty -Name Severity -Value $reader["Severity"]
$error | Add-Member -MemberType NoteProperty -Name Message -Value $reader["Message"]
$error | Add-Member -MemberType NoteProperty -Name StepName -Value $reader["StepName"]
$error | Add-Member -MemberType NoteProperty -Name CurrentStep -Value $reader["CurrentStep"]
$error | Add-Member -MemberType NoteProperty -Name TotalSteps -Value $reader["TotalSteps"]
$error | Add-Member -MemberType NoteProperty -Name CurrentTime -Value $reader["CurrentTime"]
$Errors += $error
}
}
return $Errors
}
$cmd.Parameters.AddWithValue() echoes the added parameter, and PowerShell functions return the entire non-captured output on the success output stream, not just the argument of the return keyword.
Quoting from about_Return (emphasis mine):
SHORT DESCRIPTION
Exits the current scope, which can be a function, script, or script block.
LONG DESCRIPTION
The Return keyword exits a function, script, or script block. It can be used to exit a scope at a specific point, to return a value, or to indicate that the end of the scope has been reached.
Users who are familiar with languages like C or C# might want to use the Return keyword to make the logic of leaving a scope explicit.
In Windows PowerShell, the results of each statement are returned as output, even without a statement that contains the Return keyword. Languages like C or C# return only the value or values that are specified by the Return keyword.
Use any of the following methods to suppress the undesired output:
[void]$cmd.Parameters.AddWithValue("#uniqueID", $uniqueID)
$cmd.Parameters.AddWithValue("#uniqueID", $uniqueID) | Out-Null
$cmd.Parameters.AddWithValue("#uniqueID", $uniqueID) > $null
$param = $cmd.Parameters.AddWithValue("#uniqueID", $uniqueID)
I have powershell version 2.0.0.1082 on my server. I want to import data from a text file to SQL server, and add two new fields (character and current datetime) to the input to SQL 2008 database. I have been using bulk import or SSIS to do it but I want to use powershell for the ease of maintaining the process. The file has column name at top and each field is seperated by "|".
Code so far:
clear
import-csv "Disk.txt" -Delimiter "|" |
foreach { add-member -in $_ -membertype noteproperty DateRecorded $((Get-Date).ToString("yyyy-MM-dd"))
add-member -in $_ -membertype noteproperty SystemName 'System Name'
add-member -in $_ -membertype noteproperty Drive 'Drive Letter'
add-member -in $_ -membertype noteproperty TotalSizeGB 'Total Size'
add-member -in $_ -membertype noteproperty UsedGB Used
add-member -in $_ -membertype noteproperty FreeGB Free
add-member -in $_ -membertype noteproperty PercentFree '% Free'}|
select DateRecorded,SystemName,Drive,TotalSizeGB,UsedGB,FreeGB,PercentFree |Format-Table
Any ideas please?
Thanks!
Manjot
You'll either need to add the -PassThru switch to the Add-Member cmdlet to forward the objects on in the pipeline or put $_ all by itself at the end of the ForEach block.
Here is an example using -PassThru:
Import-Csv "Disk.txt" -Delimiter "|" | ForEach {
Add-Member -InputObject $_ -MemberType NoteProperty -name "DateRecorded" -value $((Get-Date).ToString("yyyy-MM-dd"))
Add-Member -InputObject $_ -MemberType NoteProperty -name "SystemName" -value 'System Name' -PassThru
} | Select DateRecorded,SystemName,Drive,TotalSizeGB,UsedGB,FreeGB,PercentFree | Format-Table
Another example without -PassThru:
Import-Csv "Disk.txt" -Delimiter "|" | ForEach {
Add-Member -InputObject $_ -MemberType NoteProperty -name "DateRecorded" -value $((Get-Date).ToString("yyyy-MM-dd"))
Add-Member -InputObject $_ -MemberType NoteProperty -name "SystemName" -value 'System Name'
$_
} | Select DateRecorded,SystemName,Drive,TotalSizeGB,UsedGB,FreeGB,PercentFree | Format-Table
Once you've prepared your CSV data for input into the database you can use the Invoke-SqlCmd cmdlet that comes with SQL Server 2008 to perform Inserts. There is a wealth of information on MSDN here to show you how.