Alright there seems to be several issues with the script and i can't seem to figure out any of them, also some feedback on the script would be greatly apperciated. This is still my first script so it probably needs lots of little tweaks so please tell me whatever suggestions comes to mind.
Issues: Mostly all issues revolve around the logging.
Log file is not being checked so the script keeps adding computers to the log file over and over.
The log file does not update the information that is generated such as os,mac,ip, etc.
Issues Being Displayed:
Property 'Result' cannot be found on this object. Make sure that it
exists. At W:\Powershell Scripting\Test Lab\TestFunction.ps1:86
char:17
+ IF ($Computer. <<<< Result -ne "Successful") {
+ CategoryInfo : InvalidOperation: (.:OperatorToken) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFoundStrict
The Script
Set-PSDebug -strict
Set-StrictMode -Version latest
$consoleObject = (Get-Host).UI.RawUI
# Adjustable Variables
$Computers_Path = ".\computers.txt"
$Log_Path = ".\Log.txt"
$Log_MaxTick = 5
$RunOnServers = 0
# Multi-Threading Variables
$Jobs_MaxAtOnce = 20
$SleepTimer = 500
# Script Specific Variables
$ScriptTitle = "Local Admin Check"
# Validate Adjustable Variables
$Computers = #(Import-CSV $Computers_Path -header "Name","MAC")
# Framework Specific Variables (Pre-Setting Variables)
$Run = 0; $Succssful = 0; $Jobs_Count = 0; $Log_Tick= 0; $WriteToLog = "No"
# Misc
$Total = $Computers.length
IF (!(Test-Path $Log_Path)) { Add-Content $Log_Path "Name,OS,Mac,IPAddress,Status,Attempts,Result,LastAttempt" }
$Log = #(Import-Csv $Log_Path)
$Successful = ($Log | Where-Object {$_.Result -eq "Successful"} | Select-String -inputobject {$_.Name} -pattern $Computers | Measure-Object).Count
# Load Functions
Function GetOS {
$RegCon = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $Computer.Name )
$RegKey = $RegCon.OpenSubKey("SOFTWARE\Microsoft\Windows NT\CurrentVersion\")
$RegValue = $RegKey.GetValue("ProductName")
$RegCon.Close()
$Computer.OS = $RegValue
}
Function SmartLogging {
If ($Args[0] -eq "AddComputer") {
Add-Content ($Computer.Name + "," + $Computer.OS + "," + $Computer.Mac + "," + $Computer.IPAddress + "," + $Computer.Status + "," + $Computer.Attempts + "," + $Computer.Result + "," + $Computer.LastAttempt) -path .\log.txt
} ELSEIF ( $Log_Tick -eq $Log_MaxTick -OR $Args -eq "Update" ) {
$Log_Tick = 0;
Get-Content $Log_Path | Foreach-Object {$_ -replace "$Computer.Name,.*", ($Computer.Name + "," + $Computer.OS + "," + $Computer.Mac + "," + $Computer.IPAddress + "," + $Computer.Status + "," + $Computer.Attempts + "," + $Computer.Result + "," + $Computer.LastAttempt)} | Set-Content $Log_Path
} ELSEIF ($Args[0] -eq "CheckComputer") {
IF (!($Log | Select-String -pattern $Computer.Name -SimpleMatch)) {
$Log += New-Object PSObject -Property #{ Name = $Computer.Name; OS = $NULL; Mac = $Computer.MAC; IPAddress = $NULL; Status = $NULL; Attempts = 0; Result = $NULL; LastAttempt = $NULL;}
$Computer = $Log | Where-Object {$_.Name -eq $Computer.Name}
SmartLogging AddComputer
} ELSE {
$Computer = $Log | Where-Object {$_.Name -eq $Computer.Name}
}
} ELSEIF (-not $Args[0]) {
"Log Ticked"
$Log_Tick++
}
}
Function GetIPAddress {
$IPAddress = [System.Net.Dns]::GetHostAddresses("TrinityTechCorp") | Where-Object {$_.IPAddressToString -like "*.*.*.*"};
$Computer.IPAddress = $IPAddress.IPAddressToString
}
Function WindowTitle {
[int]$Successful_Percent = $Successful / $Total * 100
$consoleObject.WindowTitle = “$ScriptTitle - $Successful Out Of $Total ($Successful_Percent%) Successful `| Run`: $Run”
}
# Start Script
while ( $Successful -le $Total ) {
$Run++
ForEach ($Computer in $Computers) {
WindowTitle
SmartLogging CheckComputer
IF ($Computer.Result -ne "Successful") {
IF (test-connection $Computer.Name -quiet ) {
$Computer.Status = "Awake"
IF (!$Computer.OS){GetOS}
IF (!$Computer.IPAddress){GetIPAddress}
## Start Script ##
$CheckComputer = [ADSI]("WinNT://" + $Computer.Name + ",computer")
$Group = $CheckComputer.psbase.children.find("Administrators")
$members= $Group.psbase.invoke("Members") | %{$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)}
ForEach($user in $members) {
$Result = $Computer.Name + "," + $user.ToString()
Add-Content $Result -path .\Result.csv
}
## End Script ##
SmartLogging Update
$Computer.Result = "Successful"
$Successful += 1
} ELSE {
$Computer.Status = "Unknown"
}
$Computer.Attempts = [int] $Computer.Attempts + 1
$Computer.LastAttempt = Get-Date -uFormat "%I:%M:%S%p %d%b%y"
}
SmartLogging
}
}
Write-Output "Script Completed"
This declaration of $Computers collection....
$Computers = #(Import-CSV $Computers_Path -header "Name","MAC")
...will not work with this condition:
IF ($Computer.Result -ne "Successful")
The exception message explicitly states this, and where:
Property 'Result' cannot be found on this object. Make sure that it exists. \TestFunction.ps1:86 char:17
To resolve this, I would recommend initializing the property of Result, most likely like so:
$Computers = #(Import-CSV $Computers_Path -header "Name","MAC","Result")
The problem this time is that you don't have Result member in $Computers collection member, only Name and MAC. Unless you add such a member later on your code, which I don't really want to read, as it already is about 100 rows and contains a lot of code that is not related to the actual problem statement.
$Computers = #(Import-CSV $Computers_Path -header "Name","MAC")
Have you tried debugging the script on Powershell ISE? It's built-in debugger for Powershell 2. Take a look at a Technet article about it.
Related
I am trying to modify a script that used to work when executed on each of the servers manually to generate the DFS replication then send an email, so it can be executed once from one location then remotely connect to each and every server.
Invoke-Command:
$ComputerName = Get-DfsrMember | Select-Object -ExpandProperty ComputerName -Unique | Sort-Object
$ComputerName | ForEach-Object {
Try {
$session = New-PSSession -ComputerName $_ -ErrorAction Stop
Invoke-Command -ErrorAction Stop -Session $session -ScriptBlock {
## Script body starts here....
Write-Host "Processing on server $($_) `n" -ForegroundColor Yellow
Param (
[String[]]$ReplicationGroupList = ("")
)
....
}
}
Catch [System.UnauthorizedAccessException] {
Write-Warning "You do not have the proper access to this system!"
Break
}
Catch [System.Runtime.InteropServices.COMException] {
Write-Warning "Communications Exception occurred!"
Break
}
}
This is the error I have received:
The term 'Param' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:7 char:9
+ Invoke-Command -ErrorAction Stop -Session $session -ScriptBlo ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Param:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
+ PSComputerName : PRDDC01-VM
The actual Powershell script that used to be working, but must be manually executed in each of the server RDP session:
Param (
[String[]]$ReplicationGroupList = ("")
)
$RGroups = Get-WmiObject -Namespace "root\MicrosoftDFS" -Query "SELECT * FROM DfsrReplicationGroupConfig"
#If replication groups specified, use only those.
if ($ReplicationGroupList) {
$SelectedRGroups = #()
foreach ($ReplicationGroup IN $ReplicationGroupList) {
$SelectedRGroups += $rgroups | Where-Object { $_.ReplicationGroupName -eq $ReplicationGroup }
}
if ($SelectedRGroups.count -eq 0) {
Write-Error "None of the group names specified were found, exiting"
exit
}
else {
$RGroups = $SelectedRGroups
}
}
$ComputerName = $ENV:ComputerName
$Succ = 0
$Warn = 0
$Err = 0
Start-Transcript -path "$([Environment]::GetFolderPath("Desktop"))\dfsr1.txt"
foreach ($Group in $RGroups) {
$RGFoldersWMIQ = "SELECT * FROM DfsrReplicatedFolderConfig WHERE ReplicationGroupGUID='" + $Group.ReplicationGroupGUID + "'"
$RGFolders = Get-WmiObject -Namespace "root\MicrosoftDFS" -Query $RGFoldersWMIQ
$RGConnectionsWMIQ = "SELECT * FROM DfsrConnectionConfig WHERE ReplicationGroupGUID='" + $Group.ReplicationGroupGUID + "'"
$RGConnections = Get-WmiObject -Namespace "root\MicrosoftDFS" -Query $RGConnectionsWMIQ
foreach ($Connection in $RGConnections) {
$ConnectionName = $Connection.PartnerName#.Trim()
if ($Connection.Enabled -eq $True) {
if (((New-Object System.Net.NetworkInformation.ping).send("$ConnectionName")).Status -eq "Success") {
foreach ($Folder in $RGFolders) {
$RGName = $Group.ReplicationGroupName
$RFName = $Folder.ReplicatedFolderName
if ($Connection.Inbound -eq $True) {
$SendingMember = $ConnectionName
$ReceivingMember = $ComputerName
$Direction = "inbound"
}
else {
$SendingMember = $ComputerName
$ReceivingMember = $ConnectionName
$Direction = "outbound"
}
$BLCommand = "dfsrdiag Backlog /RGName:'" + $RGName + "' /RFName:'" + $RFName + "' /SendingMember:" + $SendingMember + " /ReceivingMember:" + $ReceivingMember
$Backlog = Invoke-Expression -Command $BLCommand
$BackLogFilecount = 0
foreach ($item in $Backlog) {
if ($item -ilike "*Backlog File count*") {
$BacklogFileCount = [int]$Item.Split(":")[1].Trim()
}
}
if ($BacklogFileCount -eq 0) {
$Color = "white"
$Succ = $Succ + 1
}
elseif ($BacklogFilecount -lt 10) {
$Color = "yellow"
$Warn = $Warn + 1
}
else {
$Color = "red"
$Err = $Err + 1
}
Write-Output "$BacklogFileCount files in backlog $SendingMember->$ReceivingMember for $RGName"
} # Closing iterate through all folders
} # Closing If replies to ping
} # Closing If Connection enabled
} # Closing iteration through all connections
} # Closing iteration through all groups
Write-Output "$Succ successful, $Warn warnings and $Err errors from $($Succ+$Warn+$Err) replications."
Stop-Transcript
$file = "$([Environment]::GetFolderPath("Desktop"))\dfsr1.txt"
get-content $file |
Select-Object -Skip 18 |
set-content "$file-temp"
Move-Item "$file-temp" $file -Force
$emailrecipients = "boss#it.com";
$emailbody = Get-Content -Path "$([Environment]::GetFolderPath("Desktop"))\dfsr1.txt" -Raw
Send-MailMessage -to $emailrecipients -smtpserver smtp.domain.COM -from "$env:COMPUTERNAME#$env:userdnsdomain" -subject "DFSR Report for $(get-date -format dd/MM/yyyy) from $env:COMPUTERNAME" -body $emailbody;
Remove-Item "$([Environment]::GetFolderPath("Desktop"))\dfsr1.txt"
Theo is correct, the Param() code needs to be first thing in the script block. You can find more information about script blocks here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_script_blocks?view=powershell-7
I have the following powershell with the aim of collecting a reg value from a list of remote machines, Ive tried using a test-connection to speed up process where devices are not online but the test-connection fails for all....
Here is the script:
clear
$servers = Get-Content -Path C:\ukdeviceswin10.txt
$PatternSID = 'S-1-5-21-\d+-\d+\-\d+\-\d+$'
$ProfileList = ForEach ($server in $servers)
{ if(test-connection $server -quiet -count 1)
{
invoke-command -computername $server {gp 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\*' | Where-Object {$_.PSChildName -match $PatternSID} |
Select #{name="SID";expression={$_.PSChildName}}}}
foreach ($profile in $profilelist) {
$profile = $profile -replace ".$"
$profile = $profile.substring(6,46)
$profile = $profile -replace "[;]"
$profile = $profile -replace "[ ]"
$profiletest = $profile.substring(0,8)
if ($profiletest -eq "S-1-5-21"){
$Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::Users, "$server")
$profilekey = $profile + "\\SOFTWARE\\Microsoft\\Office\\Outlook\\Addins\\CofenseOutlookReporter.AddinModule"
$RegKey= $Reg.OpenSubKey("$profilekey")
if ($regKey -eq $null){} else {$LoadbehaviourVersion = $RegKey.GetValue("LoadBehaviour")
$results = $server + " " + $profile + " " + $LoadbehaviourVersion | out-file -filepath c:\dell\regresults.txt -Append
}
$RegKey=""
$LoadbehaviourVersion=""
}
}
}
in this script i am pulling info from my SQL servers. i create the psobject and then i attempt to += each object into the $results table so that i can get a complete final report.
for some reason if i run the script all the way through it gives me the error
Method invocation failed because [system.management.managementobject] does not contain a method named 'op_Addition'
But if i run the script line by line I do not get the error.
$Results = #()
$servers = get-content .\computers.txt
ForEach ($server in $servers) {
# Ping the machine to see if it's on the network
$results = Get-WMIObject -query "select StatusCode from
Win32_PingStatus where Address = '$server'"
$responds = $false
ForEach ($result in $results) {
# If the machine responds break out of the result loop and indicate success
if ($result.statuscode -eq 0) {
$responds = $true
break
}
}
If ($responds) {
# Gather info from the server because it responds
Write-Output "$server responds"
} else {
# Let the user know we couldn't connect to the server
Write-Output "$server does not respond"
}
# Check to see if a directory exists for this machine, if not create one
if (!(Test-Path -path .\$server)) {
New-Item .\$server\ -type directory
}
#get-WMI-Information
function getwmiinfo ($srv) {
# Get ComputerSystem info and write it to a CSV file
gwmi -query "select * from
Win32_ComputerSystem" -computername $srv | select Name,
Model, Manufacturer, Description, DNSHostName,
Domain, DomainRole, PartOfDomain, NumberOfProcessors,
SystemType, TotalPhysicalMemory, UserName,
Workgroup | export-csv -path .\$srv\BOX_ComputerSystem.csv -noType
# Get OperatingSystem info and write it to a CSV file
gwmi -query "select * from
Win32_OperatingSystem" -computername $srv | select Name,
Version, FreePhysicalMemory, OSLanguage, OSProductSuite,
OSType, ServicePackMajorVersion, ServicePackMinorVersion |
export-csv -path .\$server\BOX_OperatingSystem.csv -noType
# Get PhysicalMemory info and write it to a CSV file
gwmi -query "select * from
Win32_PhysicalMemory" -computername $srv | select Name,
Capacity, DeviceLocator, Tag |
export-csv -path .\$srv\BOX_PhysicalMemory.csv -noType
# Get LogicalDisk info and write it to a CSV file
gwmi -query "select * from Win32_LogicalDisk
where DriveType=3" -computername $srv | select Name, FreeSpace,
Size | export-csv -path .\$srv\BOX_LogicalDisk.csv -noType
}
# Get the server info
getwmiinfo $server
#Get-SQLInfo
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | Out-Null
# Create an ADO.Net connection to the instance
$cn = new-object system.data.SqlClient.SqlConnection(
"Data Source=$server;Integrated Security=SSPI;Initial Catalog=master");
# Create an SMO connection to the instance
$s = new-object ('Microsoft.SqlServer.Management.Smo.Server') $server
# Set the CSV output file name and pipe the instances Information collection to it
$outnm = ".\" + $server + "\" + $instnm + "GEN_Information.csv"
$s.Information | export-csv -path $outnm -noType
# Set ShowAdvancedOptions ON for the query
$s.Configuration.ShowAdvancedOptions.ConfigValue = 1
$s.Configuration.Alter()
# Create a DataSet for our configuration information
$ds = new-object "System.Data.DataSet" "dsConfigData"
# Build our query to get configuration, session and lock info, and execute it
$q = "exec sp_configure;
"
$q = $q + "exec sp_who;
"
$q = $q + "exec sp_lock;
"
$da = new-object "System.Data.SqlClient.SqlDataAdapter" ($q, $cn)
$da.Fill($ds)
# Build datatables for the config data, load them from the query results, and write them to CSV files
$dtConfig = new-object "System.Data.DataTable" "dtConfigData"
$dtWho = new-object "System.Data.DataTable" "dtWhoData"
$dtLock = new-object "System.Data.DataTable" "dtLockData"
$dtConfig = $ds.Tables[0]
$dtWho = $ds.Tables[1]
$dtLock = $ds.Tables[2]
$outnm = ".\" + $server + "\" + $instnm + "GEN_Configure.csv"
$dtConfig | select name, minimum, maximum, config_value, run_value | export-csv -path $outnm -noType
$outnm = ".\" + $server + "\" + $instnm + "GEN_Who.csv"
$dtWho | select spid, ecid, status, loginame, hostname, blk, dbname, cmd, request_id | export-csv -path $outnm -noType
$outnm = ".\" + $server + "\" + $instnm + "GEN_Lock.csv"
$dtLock | select spid, dbid, ObjId, IndId, Type,Resource, Mode, Status | export-csv -path $outnm -noType
# Set ShowAdvancedOptions OFF now that we're done with Config
$s.Configuration.ShowAdvancedOptions.ConfigValue = 0
$s.Configuration.Alter()
# Write the login name and default database for Logins to a CSV file
$outnm = ".\" + $server + "\" + $instnm + "GEN_Logins.csv"
$s.Logins | select Name, DefaultDatabase | export-csv -path $outnm -noType
# Write information about the databases to a CSV file
$outnm = ".\" + $server + "\" + $instnm + "GEN_Databases.csv"
$dbs = $s.Databases
$dbs | select Name, Collation, CompatibilityLevel, AutoShrink,
RecoveryModel, Size, SpaceAvailable | export-csv -path $outnm -noType
foreach ($db in $dbs) {
# Write the information about the physical files used by the database to CSV files for each database
$dbname = $db.Name
if ($db.IsSystemObject) {
$dbtype = "_SDB"
} else {
$dbtype = "_UDB"
}
# Write the user information to a CSV file
$users = $db.Users
$outnm = ".\" + $server + "\" + $instnm + $dbname + "_Users.csv"
$users | select $dbname, Name, Login, LoginType, UserType, CreateDate |
export-csv -path $outnm -noType
$fgs = $db.FileGroups
foreach ($fg in $fgs) {
$files = $fg.Files
$outnm = ".\" + $server + "\" + $instnm + $dbname + "_DataFiles.csv"
$files | select $db.Name, Name, FileName, Size,
UsedSpace | export-csv -path $outnm -noType
}
$logs = $db.LogFiles
$outnm = ".\" + $server + "\" + $instnm + $dbname + "_LogFiles.csv"
$logs | select $db.Name, Name, FileName, Size, UsedSpace |
export-csv -path $outnm -noType
}
# Create CSV files for each ErrorLog file
$outnm = ".\" + $server + "\" + $instnm + "_ERL_ErrorLog_.csv"
$s.ReadErrorLog() | export-csv -path $outnm -noType
$outnm = ".\" + $server + "\" + $instnm + "_ERL_ErrorLog_1.csv"
$s.ReadErrorLog(1) | export-csv -path $outnm -noType
$outnm = ".\" + $server + "\" + $instnm + "_ERL_ErrorLog_2.csv"
$s.ReadErrorLog(2) | export-csv -path $outnm -noType
$outnm = ".\" + $server + "\" + $instnm + "_ERL_ErrorLog_3.csv"
$s.ReadErrorLog(3) | export-csv -path $outnm -noType
$outnm = ".\" + $server + "\" + $instnm + "_ERL_ErrorLog_4.csv"
$s.ReadErrorLog(4) | export-csv -path $outnm -noType
$outnm = ".\" + $server + "\" + $instnm + "_ERL_ErrorLog_5.csv"
$s.ReadErrorLog(5) | export-csv -path $outnm -noType
$outnm = ".\" + $server + "\" + $instnm + "_ERL_ErrorLog_6.csv"
$s.ReadErrorLog(6) | export-csv -path $outnm -noType
$outnm = ".\" + $server + "\" + $instnm + "Gen_Information.csv"
$Gen_Information = Import-Csv $outnm
$outnm = ".\" + $server + "\" + $instnm + "Gen_Databases.csv"
$Gen_Databases = Import-Csv $outnm
$outnm = ".\" + $server + "\" + $instnm + "Box_ComputerSystem.csv"
$Box_ComputerSystem = Import-Csv $outnm
$outnm = ".\" + $server + "\" + $instnm + "Box_OperatingSystem.csv"
$Box_OperatingSystem = Import-Csv $outnm
$Gen_Info = $Gen_Information[0]
$Gen_DBs = ForEach($object in $Gen_Databases){$object.Name}
$Box_OS = $Box_OperatingSystem[0]
$Box_CS = $Box_ComputerSystem[0]
$Box_OSOS = $box_os.Name.Split("|")
#region Correct SQL Version Name
#correct Version Name
if($Gen_Info.VersionString -like "8.*.*.*")
{
$Gen_InfoVers = "SQL Server 2000"
}
elseif($Gen_Info.VersionString -like "12.*.*.*")
{
$Gen_InfoVers = "SQL Server 2014"
}
elseif($Gen_Info.VersionString -like "10.*.*.*" -and $Gen_info.VersionString -notlike "10.5*.*.*")
{
$Gen_InfoVers = "SQL Server 2008"
}
elseif($Gen_Info.VersionString -like "9.*.*.*")
{
$Gen_InfoVers = "SQL Server 2005"
}
elseif($Gen_Info.VersionString -like "10.5*.*.*")
{
$Gen_InfoVers = "SQL Server 2008r2"
}
elseif($Gen_Info.VersionString -like "11.*.*.*")
{
$Gen_InfoVers = "SQL Server 2012"
}
elseif($Gen_Info.VersionString -like "13.*.*.*")
{
$Gen_InfoVers = "SQL Server 2016"
}
else{$Gen_InfoVers = "Unknown Version"}
#endregion
$object = New-Object psobject -Property #{
Server = $Box_CS.Name
OS = $box_osos[0]
Edition = $Gen_Info.EngineEdition
SQLVersion = $Gen_InfoVers.ToString()
TotalDBs = $Gen_DBs.count
DatabaseName1 = $Gen_DBs[0]
DatabaseName2 = $Gen_DBs[1]
DatabaseName3 = $Gen_DBs[2]
DatabaseName4 = $Gen_DBs[3]
DatabaseName5 = $Gen_DBs[4]
DatabaseName6 = $Gen_DBs[5]
DatabaseName7 = $Gen_DBs[6]
DatabaseName8 = $Gen_DBs[7]
DatabaseName9 = $Gen_DBs[8]
DatabaseName10 = $Gen_DBs[9]
DatabaseName11 = $Gen_DBs[10]
DatabaseName12 = $Gen_DBs[11]
DatabaseName13 = $Gen_DBs[12]
DatabaseName14 = $Gen_DBs[13]
DatabaseName15 = $Gen_DBs[14]
DatabaseName16 = $Gen_DBs[15]
DatabaseName17 = $Gen_DBs[16]
DatabaseName18 = $Gen_DBs[17]
DatabaseName19 = $Gen_DBs[18]
DatabaseName20 = $Gen_DBs[19]
DatabaseName21 = $Gen_DBs[20]
DatabaseName22 = $Gen_DBs[21]
DatabaseName23 = $Gen_DBs[22]
DatabaseName24 = $Gen_DBs[23]
DatabaseName25 = $Gen_DBs[24]
DatabaseName26 = $Gen_DBs[25]
}
$object = $object | select Server,OS,SQLVersion,Edition,TotalDBs,DatabaseName1,DatabaseName2,DatabaseName3,DatabaseName4,DatabaseName5,DatabaseName6,DatabaseName7,DatabaseName8,DatabaseName9,DatabaseName10,DatabaseName11,DatabaseName12,DatabaseName13,DatabaseName14,DatabaseName15,
DatabaseName16,DatabaseName17,DatabaseName18,DatabaseName19,DatabaseName20,DatabaseName21,DatabaseName22,DatabaseName23,DatabaseName24,DatabaseName25,DatabaseName26
$object | Export-Csv ".\$server\FinalReport.csv" -NoTypeInformation -Force
$Results += $object
}
$Results | Export-Csv ".\Final\FinalReport.csv" -NoTypeInformation -Force
#alroc has a valid point, that's a lot of code. You can try typing $Result as an [array].
change
$Results += $object
to
[array]$Results += $object
Your error happens here
$Results += $object
You are using the same variable name for holding different data. The first time you are gathering the results from a WMI query.
$results = Get-WMIObject -query "select StatusCode from Win32_PingStatus where Address = '$server'"
Then you add it again when you get the error. Arrays do support addition but $results is not an array when the error is generated.
You have some other issues but mainly change the variable name to address this problem.
Ok, am having some issues with my script, they probably are pretty apparent but here is the script. Would greatly appreciate a review of the script with some feedback as why they are broken.
## Script Startup
$Computers = Get-Content .\computers.txt
$Total = $Computers.length
$consoleObject = (Get-Host).UI.RawUI
## Set Variables
$Run = 0
$Successful = 0
# Checks to see if there is a log file already created. If so check number of successful computer ran against, if not, create the log file.
IF ( test-path .\~temp.txt ) {
$Log = Get-Content .\~temp.txt
ForEach ($LogLine in $Log) {
$LogCheck = $LogLine.ToString().Split(",")[2]
IF ( "$LogCheck" -eq "Successful" ) {
$Successful += 1
}
}
} ELSE {
add-content .\~temp.txt "Computer Name,Attempts,Last Attempt,Time,Date"
}
while ( "$Completed" -le "$total" ) {
$Run += 1
$Time = Get-Date
$consoleObject.WindowTitle = “Admin Check - $Successful Out Of $Total Successful `| Run`: $Run”
ForEach ($Computer in $Computers) {
IF ( Select-String .\~temp.txt -pattern "$Computer" -quiet ) {
$LogUpdate = Select-String .\~Temp.txt -pattern $Computer
$Attempts = $LogUpdate.ToString().Split(",")[1]
$Result = $LogUpdate.ToString().Split(",")[3]
} ELSE {
add-content .\~temp.txt "$Computer,0,Not Checked,Not Run Yet,Not Run Yet"
$Attempts = ""
$Result = ""
}
IF ( "$Result" -eq "Successful") {
write-output "$Computer Already Completed"
} ELSE {
IF ( test-connection $Computer -quiet ) {
# Command Here
$Successful += 1
$IsOn = "True"
} ELSE {
$IsOn = "False"
}
$Attempts += 1
}
( Get-Content .\~temp.txt ) | Foreach-Object {$_ -replace "$Computer,.*", ($Computer + "," + $Attempts + "," + $IsOn + "," + $Result + "," + $Time.ToShortTimeString() + "," + $Time.ToShortDateString())} | Set-Content .\~temp.txt
}
}
~temp.txt
Computer Name,Attempts,Last Attempt Result,Time,Date
52qkkgw-94210jv,11111111111111,False,,8:47 PM,10/27/2012
HELLBOMBS-PC,11111111111111111111111111111111111111111111111111111111111,True,,8:47 PM,10/27/2012
52qkkgw-94210dv,11111111111111111111111111111111111111111111111111111111,False,,8:46 PM,10/27/2012
Current Issue:
- Doesn't actually stop when successful equals total.
- doesn't check result vs successful so keeps redoing all comps forever.
- The Attempts tab just keeps adding 1 to the last time or something, so it makes some weird continuous "1111" thing.
Probably more just havn't noticed them yet.
Here's working code:
clear
## Script Startup
$Computers = Get-Content \computers.txt
cd c:\pst
$Total = $Computers.length
$consoleObject = (Get-Host).UI.RawUI
## Set Variables
$Run = 1
$Successful = 0
# Checks to see if there is a log file already created. If so check number of successful computer ran against, if not, create the log file.
IF ( test-path .\~temp.txt ) {
$Log = Get-Content .\~temp.txt
ForEach ($LogLine in $Log) {
$LogCheck = $LogLine.ToString().Split(",")[2]
IF ( "$LogCheck" -eq "Successful" ) {
$Successful += 1
}
}
} ELSE {
add-content .\~temp.txt "Computer Name,Attempts,Last Attempt,Time,Date"
}
while ( $Run -ne $total ) {
$Run += 1
$Time = Get-Date
$consoleObject.WindowTitle = “Admin Check - $Successful Out Of $Total Successful `| Run`: $Run”
ForEach ($Computer in $Computers) {
IF ( Select-String .\~temp.txt -pattern "$Computer" -quiet ) {
$LogUpdate = Select-String .\~Temp.txt -pattern $Computer
$Attempts = $LogUpdate.ToString().Split(",")[1]
$Result = $LogUpdate.ToString().Split(",")[3]
} ELSE {
add-content .\~temp.txt "$Computer,0,Not Checked,Not Run Yet,Not Run Yet"
$Attempts = ""
$Result = ""
}
IF ( "$Result" -eq "Successful") {
write-output "$Computer Already Completed"
} ELSE {
IF ( test-connection $Computer -quiet ) {
# Command Here
$Successful += 1
$IsOn = "True"
} ELSE {
$IsOn = "False"
}
$Attempts += 1
}
( Get-Content .\~temp.txt ) | Foreach-Object {$_ -replace "$Computer,.*", ($Computer + "," + $Attempts + "," + $IsOn + "," + $Result + "," + $Time.ToShortTimeString() + "," + $Time.ToShortDateString())} | Set-Content .\~temp.txt
}
}
I have a powershell script that parses a lotus notes INI file and replaces text inside the file. But only the replaced text is showing up in the output file.
# Example of PowerShell -replace parameter
## Get-DistinguishedName -- look up a DN from a user's (login) name
function Get-DistinguishedName {
Param($UserName)
$ads = New-Object System.DirectoryServices.DirectorySearcher([ADSI]'')
$ads.filter = "(&(objectClass=Person)(samAccountName=$UserName))"
$s = $ads.FindOne()
return $s.GetDirectoryEntry().DistinguishedName
}
clear-Host
set-executionpolicy remotesigned
$original_file = '.\notes.ini'
$destination_file = '.\notes2.ini'
$OS = Get-WmiObject -Class win32_OperatingSystem -namespace "root\CIMV2" -ComputerName .
$username = [Environment]::UserName
$userprofile = $env:userprofile
$fullname = Get-DistinguishedName($username) | %{$data = $_.split(","); $data[0].Substring(3)}
write-Host "Creating $userprofile"
if (($OS.Version -eq "5.1.2600") -or ($OS.Version -eq "5.2.3790")) {
$lookupTable = #{
'^SU_FILE_CLEANUP=' = 'SU_FILE_CLEANUP=' + $userprofile + '\Local Settongs\Application Data\smkits'
'%username%' = $username
'%fullname%' = $fullname
'%userprofile%' = $userprofile
'^Directory=' = 'Directory=' + $userprofile + '\Local Settongs\Application Data\Lotus\Notes\Data'}
} else {
$lookupTable = #{
'SU_FILE_CLEANUP=' = 'SU_FILE_CLEANUP=' + $userprofile + '\AppData\Roaming\smkits'
'%username%' = $username
'%fullname%' = $fullname
'%userprofile%' = $userprofile
'Directory=' = 'Directory=' + $userprofile + '\AppData\Local\Lotus\Notes\Data'}
}
Get-Content -Path $original_file | ForEach-Object {
$line = $_
$lookupTable.GetEnumerator() | ForEach-Object {
if ($line -match $_.Key)
{
$line -replace $_.Key, $_.Value
#break
}
}
write-Host $line
} | Set-Content -Path $destination_file
What am I missing
On this line, you are writing he output of the replace operator onto the pipeline, this will then get picked up by Set-Content
$line -replace $_.Key, $_.Value
whereas on this line, you are writing the output to the host (i.e. the powershell console) it will not end up on the pipeline and will not get picked up up Set-Content:
write-Host $line
To fix this, just replace write-host with write-output:
Write-Output $line