Powershell Scripting Issues (Newbie) - powershell

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
}
}

Related

having trouble with powershell using Out-File to append results to existing file

so I m having this issue with getting my results to write out to an Out-file.
The problem I m having is, if new file item does exist, the error message I m getting is saying the path is null.
Please review the script and let me know your thoughts
thanks
$sScriptVersion = "1.0"
$dir = $PSScriptRoot
$svrlist += $dir + '\' + 'serverlist.txt'
$folder = 'search'
$computername = Get-Content $svrlist
$drv_array = #()
$new_drv_array =#()
$SearchStr = "error"
$log_pth = 'ProgramData\something\something\something\logs'
$file_logs = #()
$log_pth = #()
$log_nme = #()
$srchpath = #()
foreach($server in $computername)
{
$disks = Get-WmiObject -ComputerName $server -Class Win32_LogicalDisk -Filter "DriveType = 3";
foreach($disk in $disks)
{
$drv_array += $disk.DeviceID;
}
$driv =Foreach-Object {$drv_array -replace ":", "$"}
foreach($drv in $driv)
{
$new_drv_array += '\\'+ $server + '\'+ $drv +'\'+ $log_pth
}
}
Foreach($tst_pth in $new_drv_array )
{
$dvr_testpath = test-path $tst_pth
$srchpath += $tst_pth + '\'+ "*.*"
if ($dvr_testpath -eq $false)
{
write-host "This path does not exist " $tst_pth
}
else
{
write-host "This path does exist" $tst_pth
$Sel = Select-String -pattern $SearchStr -Context 2, 3 -path $srchpath
$out_file = New-item -ErrorAction ignore -itemtype File (join-path $dir1 $log_nme)
This is the part I'm having the issues with
$tst = Test-Path $out_file
if($tst -eq $false)
{
write-host "writing out parsed log file"
if($Sel -ne $null)
{
$Sel| Out-File $out_file
}
}
else
{
write-host " parsed log file does exist"
if($Sel -ne $null)
{
$Sel| Out-File -Append $out_file
}
}
}
}

Write Informations into existing csv

My existing csv looks like this:
"Name","Surename","Workstation"
"Doe","John","PC1"
"Fonzarelli","Arthur","PC4"
"Tribbiani","Joey","PC77"
Now, I want to check whether the host is online or not and write a new column named "Status" with the result into my csv.
$file = Import-Csv "C:\Scripts\WS-Status.csv"
Foreach ($ws in $file) {
If (Test-Connection $ws.Workstation -Count 1 -Quiet) {
Write-Host $ws.Workstation "is online"
}
Else {Write-Host $ws.Workstation "is offline"}
}
It works fine in the console, but how the heck can I export the result into my csv?
You could use the Add-Member cmdlet to add a member (status) to your current entity:
$file = Import-Csv "C:\Scripts\WS-Status.csv"
Foreach ($ws in $file)
{
if (Test-Connection $ws.Workstation -Count 1 -Quiet)
{
Add-Member -InputObject $ws -NotePropertyName "Status" -NotePropertyValue "online"
}
else
{
Add-Member -InputObject $ws -NotePropertyName "Status" -NotePropertyValue "offline"
}
}
$file | Export-Csv "C:\Scripts\WS-Status.csv" -NoTypeInformation
You could create a PSCustomObject within yourForEach loop:
$file = Import-Csv "C:\Scripts\WS-Status.csv"
Foreach ($ws in $file) {
if(Test-Connection $ws.Workstation -Count 1 -Quiet){
Write-Host $ws.Workstation "is online"
$status = "Online"
}else{
Write-Host $ws.Workstation "is offline"
$status = "Offline"
}
[array]$result += [PSCustomObject] #{
Name = $ws.Name
Surename = $ws.Surename
Workstation = $ws.Workstation
Status = $status
}
}
$result | Export-Csv thing.csv -NoTypeInformation
You have to use Out-File cmdlet which enables you to send pipelined output directly to a text file.
$file = Import-Csv "C:\Scripts\WS-Status.csv"
Foreach ($ws in $file) {
If (Test-Connection $ws.Workstation -Count 1 -Quiet) {
$ws.Workstation + " is online" | Out-File -Append OutPutFile.csv
}
Else {
$ws.Workstation + ' is offline' | Out-File -Append OutPutFile.csv
}
}

My script runs in powershell ISE but not powershell console?

function Get-LoggedOnUsers ($server) {
if($server -eq $null){
$server = "localhost"
}
$users = #()
# Query using quser, 2>$null to hide "No users exists...", then skip to the next server
$quser = quser /server:$server 2>$null
if(!($quser)){
Continue
}
#Remove column headers
$quser = $quser[1..$($quser.Count)]
foreach($user in $quser){
$usersObj = [PSCustomObject]#{Server=$null;Username=$null;SessionName=$null;SessionId=$Null;SessionState=$null;LogonTime=$null;IdleTime=$null}
$quserData = $user -split "\s+"
#We have to splice the array if the session is disconnected (as the SESSIONNAME column quserData[2] is empty)
if(($user | select-string "Disc") -ne $null){
#User is disconnected
$quserData = ($quserData[0..1],"null",$quserData[2..($quserData.Length -1)]) -split "\s+"
}
# Server
$usersObj.Server = $server
# Username
$usersObj.Username = $quserData[1]
# SessionName
$usersObj.SessionName = $quserData[2]
# SessionID
$usersObj.SessionID = $quserData[3]
# SessionState
$usersObj.SessionState = $quserData[4]
# IdleTime
$quserData[5] = $quserData[5] -replace "\+",":" -replace "\.","0:0" -replace "Disc","0:0"
if($quserData[5] -like "*:*"){
$usersObj.IdleTime = [timespan]"$($quserData[5])"
}elseif($quserData[5] -eq "." -or $quserData[5] -eq "none"){
$usersObj.idleTime = [timespan]"0:0"
}else{
$usersObj.IdleTime = [timespan]"0:$($quserData[5])"
}
# LogonTime
$usersObj.LogonTime = (Get-Date "$($quserData[6]) $($quserData[7]) $($quserData[8] )")
$users += $usersObj
}
return $users
}
function LogOutUser {
$test = Get-LoggedOnUsers
$count = 0
$nameArray = #()
$sessionArray = #()
$logonTimeArray = #()
foreach($line in $test){
$field1 = $line.Username
$field2 = $line.SessionID
$field3 = $line.LogonTime
$nameArray += $field1
$sessionArray += $field2
$logonTimeArray += $field3
$count+=1
}
$session1 = [INT]$sessionArray[0]
$session2 = [INT]$sessionArray[1]
Write-Host $nameArray
Write-Host $sessionArray
Write-Host $logonTimeArray
Write-Host $count
Write-Host $session1
Write-Host $session2
if(($count -gt 1) -and ($session2 -gt $session1 )){
logoff $session1
}
}
Get-LoggedOnUsers
LogOutUser
this code works in the ISE but it does not work when running from the console, what is happening? It does exactly what i want it to do through the ISE but when I try running as a scheduled task it doesn't work also it doesnt work when trying to run with console. i have tried powershell.exe -noexit -file c:\logofftest1.ps1 but still no success

Powershell Compare Two Strings

cls
$logFile = "C:\test\output1.txt"
Function LogWrite
{
Param ([string]$logstring)
Add-content $Logfile -value $logstring
}
LogWrite "DocumentID|Correct|Wrong|UDI|Number of Errors|Line Number"
LogWrite "------------------------------------------"
$file = "C:\test\test\Birth records evt logging.txt"
$pattern = "^(.*)`t(.*)`t(.*)`t(.*)`t(.*)`t(.*)`t(.*)`t(COB Reviewed)$"
$pattern2 = "^(.*)`t(.*)`t(.*)`t(.*)`t(.*)`t(.*)`t(.*)`t(DocSecID)$"
$pattern3 = "^(.*)`t(.*)`t(.*)`t(.*)`t(.*)`t(.*)`t(.*)`t(.*)$"
$errorCountTotal = 0
$linecount = 0
$line2Count = 0
Get-Content $file|
ForEach-Object{
$errorCountLine = 0
$linecount++
$transposition = $false
if($_ -match $pattern){
}elseif($_ -match $pattern2){
}elseif($_ -match $pattern3){
$line2Count++
if($matches[6].Length -eq $matches[7].length){
$wrong = $matches[6]
$correct = $matches[7]
$documentID = $matches[3]
$UDI = $matches[8]
$a = [char[]]$Matches[6]
$b = [char[]]$matches[7]
# for($i = 0; $i -lt $a.Length; $i++){
# for($x = 1; $x -lt $a.Length; $x++){
# if($a[$i] -eq $b[$i+$x] -and $a[$i+$x] -eq $b[$i]){
# if($a[$i] -eq $a[$i+$x]){
# write-host "same letter"
# }else{
# $errorCountLine += 2
# }
# }
# }
#}
#Compare-Object $a $b |Format-List |Out-File "C:\test\test3.txt"
$errorCountLine += (#(Compare-Object $a $b -SyncWindow 0).count /2)
$errorCountTotal +=$errorCountLine
Write-Host $matches[6] " - " $matches[7] " - " $errorCountLine " - " $linecount
Write-Host $errorCountTotal
LogWrite "$documentID|$wrong|$correct|$UDI|$errorCountLine|$linecount"
}else{
$a = [char[]]$Matches[6]
$b = [char[]]$matches[7]
for($i = 0; $i -lt $a.Length; $i++){
for($x = 1; $x -lt $a.Length; $x++){
if($a[$i] -eq $b[$i+$x] -and $a[$i+$x] -eq $b[$i]){
if($a[$i] -eq $a[$i+$x]){
# write-host "same letter"
}else{
$errorCountLine += 2
}
}
}
}
$diffL = [math]::Abs($Matches[7].Length - $Matches[6].Length)
$errorCountLine = (((#(Compare-Object $a $b).count-$diffL) /2) + $diffL)
$test = #(Compare-Object $a $b).count
$errorCountTotal += $errorCountLine
Write-Host $matches[6] " - " $matches[7] " - " $errorCountLine " - " $linecount
$wrong = $matches[6]
$correct = $matches[7]
$documentID = $matches[3]
$UDI = $matches[8]
LogWrite "$documentID|$wrong|$correct|$UDI|$errorCountLine|$linecount"
Write-Host $errorCountTotal
}
}
}
Write-Host $line2Count #number of lines that the program looks at. passes through pattern3.
LogWrite `n
LogWrite "The total number of errors is $errorCountTotal"
I need to compare the contents of two Strings with this program. Above is what i have so far. The only problem is it tells me whether or not the two strings match or not(0 or -1) character by character in the string. Midred and Mildred would come up as 5 errors when in fact it needs to be only 1 error. i cannot just compare the strings as a whole either because there could be multiple errors in a string. any ideas would be great.
Try using Compare-Object on the character arrays:
$a = [char[]]'Mildred'
$b = [char[]]'Midred'
Compare-Object $a $b
InputObject SideIndicator
----------- -------------
l <=
#(Compare-Object $a $b).count
1
Why not just compare the two strings, e.g.
$matches[6] -ne $ matches [7]
?

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.