Powershell - how to log for each object - powershell

I'm slowly getting to grips with Powershell but I cant see how to capture the for-each loop in a log (its probably something straight forward). My current code creates the log but doesnt seem to write to it - any ideas where I am going wrong?
$CSVImp = Import-Csv -Path "C:\Support\Powershell-Rename\Data.csv"
$OutputLog = ".\output.log"
Write $CSVImp | Where-Object { $_.CompName -eq $env:computername } | ForEach-Object {Rename-Item $_.FileLocation -NewName $_.FileRename -ErrorAction SilentlyContinue } | Out-File $OutputLog -Append
Thanks

The scriptblock you pass to ForEach-Object can have as many statements as you like:
... |ForEach-Object {
Rename-Item $_.FileLocation -NewName $_.FileRename -ErrorAction SilentlyContinue
if($?){
"[+] Successfully renamed '$($_.FileLocation)' to '$($_.FileRename)'"
}
else {
"[!] Failed to rename '$($_.FileLocation)' to '$($_.FileRename)'"
}
} |Out-File $OutputLog -Append

I'd suggest something like this where you use a Try/Catch block to log your entries.
Updated re: Mathias' comment. Hope I got it right!
$CSVImp = Import-Csv -Path "C:\Support\Powershell-Rename\Data.csv"
$OutputLog = ".\output.log"
$CSVImp | Where-Object { $_.CompName -eq $env:computername } |
ForEach-Object {
Try {
$MsgTrailer = "Rename $($_.FileLocation) to $($_.FileRename)"
Rename-Item $_.FileLocation -NewName $_.FileRename -ErrorAction Stop
"Success: $MsgTrailer" |
Out-File $OutputLog -Append
}
Catch {
"Failed: $MsgTrailer" | Out-File $OutputLog -Append
}
Note: Untested code!

Related

How to check duplicate multiple file using powershell?

I want to check duplicate file.If the condition of the file like this, it means duplicate. The same name but different extension.
AAA18WWQ6BT602.PRO
AAA18WWQ6BT602.XML
I can figure out this case with my script. But I have problem if I have this more than 1 .XML file like this
AAA18WWQ6BT602.PRO
AAA18WWQ6BT602.XML
AAA18WWQ6BT601.XML
AAA18WWQ6BT604.XML
This case, it will not detect that file AAA18WWQ6BT602.PRO and AAA18WWQ6BT602.XML duplicated.
Anyone can help me please.
Thanks
$duplicate = #()
#(Get-ChildItem "$Flag_Path\*.xml") | ForEach-Object { $duplicate += $_.basename }
if(Test-Path -Path "$Flag_Path\*$duplicate*" -Exclude *.xml)
{
Get-ChildItem -Path "$Flag_Path\*$duplicate*" -Include *.xml | Out-File $Flag_Path\Flag_Duplicate
Write-Host "Flag duplicated, continue for Error_Monitoring"
pause
Error_Monitoring
}
else{
Write-Host "Flag does not duplicate, continue the process"
}
The -Include parameter only works if the path on Get-ChildItem ends in \* OR if the -Recurse switch is used.
The following should do what you want:
$flagFolder = 'D:\*'
$dupeReport = 'D:\Flag_Duplicate.txt'
$duplicates = Get-ChildItem -Path $flagFolder -File -Include '*.xml', '*.pro' |
Group-Object -Property BaseName | Where-Object { $_.Count -gt 1 }
if ($duplicates) {
# output the duplicate XML to Flag_Duplicate.txt
$duplicates.Group | Where-Object {$_.Extension -eq '.xml' } | ForEach-Object {
$_.FullName | Out-File -FilePath $dupeReport -Append
}
# do the rest of your code
Write-Host "Flag duplicated, continue for Error_Monitoring"
Error_Monitoring
}
else {
Write-Host "Flag does not duplicate, continue the process"
}
Your script does not iterate correctly. You need to have an iteration to check. The Test-Path logic looks mixed up to me. I tried to keep as much of your code as possible.
This script checks for a any xml basename filename against any suffix duplicate (not only pro):
$Flag_Path = "C:\dir_to_be_checked"
$xmlFilesArray = #()
$allFilesExceptXml = #() # all files excluding xml files
# Get all the xml files
Get-ChildItem -Path $Flag_Path -Include "*.xml" | ForEach-Object { $xmlFilesArray += $_.basename }
# Get all files from the directory the xml files
Get-ChildItem -Path $Flag_Path -Exclude "*.xml" | ForEach-Object { $allFilesExceptXml += $_.basename }
# Iterate over list of files names without suffix
ForEach ($xmlFile in $xmlFilesArray) {
ForEach ($fileToCheck in $allFilesExceptXml) {
If ($xmlFile -eq $fileToCheck) {
# logging the duplicate file (specifying utf8 or the output would be UTF-16)
Write-Output "$Flag_Path\$xmlFile.xml" | Out-File -Append -Encoding utf8 $Flag_Path\Flag_Duplicate
Write-Host "Flag duplicated, continue with duplicate search"
# pause
Write-Host "Press any key to continue ..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
Error_Monitoring
} Else {
Write-Host "Flag is not duplicated. Continue with the search."
}
}
}

Powershell Remove-Item get Loggingfile

i have probably searched the whole web, but I'm not able to help myself. Otherwise I'm just incapable.
All I want is to delete folders after 30 days and display the results in a simple .log file.
dir "C:\Users\sam\Desktop\Files_todelete\*" -ErrorAction SilentlyContinue | Where { ((Get-Date) - $_.LastWriteTime).days -gt 30 } | Remove-Item -Recurse
This works for me, but I tried nearly everything to log the results.
Hopefully you can help me to fix this issue.
You need to include logging part to your script. You can make foreach loop for every item that needs to be removed and write down activity to log file. Here is an example:
$LogFile = 'C:\log.txt'
dir "C:\Users\sam\Desktop\Files_todelete\*" -ErrorAction SilentlyContinue |
Where { ((Get-Date) - $_.LastWriteTime).days -gt 30 } |
ForEach-Object {
Remove-Item $_.FullName -Recurse
Out-File -InputObject $('Removed {0}' -f $_.FullName) -FilePath $LogFile -Append
}
So in this case it worked for me, but I want to use the Script for network drives. If I edit the path everything seems to be fine. But the problem here is the permission. Therefore I found a solution with Get-ChildItem -Directory.
My question here is can pipe this in front of the Remove-Item command?
Like:
$LogFile = '\netshare\folder\log.txt'
dir "\netshare\Files_todelete*" -ErrorAction SilentlyContinue |
Where { ((Get-Date) - $_.LastWriteTime).days -gt 30 } |
ForEach-Object {
Get-ChildItem -Directory | Remove-Item $_.FullName -Recurse
Out-File -InputObject $('Removed {0}' -f $_.FullName) -FilePath $LogFile -Append
}
Logically the Get-ChildItem needs to be in front of the loop?! But I'm not that firm to edit the beginning of the loop correctly.

Out-File only printing half of my results

I currently have a CSV file that has 2,440 lines of data. The data looks something like:
server1:NT:Y:N:N:00:N
server2:NT:Y:N:n:33:N
This is what I have so far:
$newCsvPath = Get-Content .\sever.csv |
Where-Object { $_ -notmatch '^#|^$|^"#' }
[int]$windows = 0
[int]$totalsever = 0
$Results = #()
$date = Get-Date -Format g
Clear-Content .\results.csv -Force
foreach ($thing in $newCsvPath) {
$totalsever++
$split = $thing -split ":"
if ($split[1] -contains "NT") {
$windows++
$thing | Out-File results.csv -Append -Force
} else {
continue
}
}
Clear-Content .\real.csv -Force
$servers = Get-Content results.csv
foreach ($server in $servers) {
$server.Split(':')[0] | Out-File real.csv -Append -Force
}
My issue is that when the script gets to the $server.Split(':')[0] | Out-File real.csv -Append -Force part, for some reason it only outputs 1,264 lines instead of all 2,440 to "real.csv". However, when I remove | Out-File real.csv -Append -Force, $server stores ALL 2,400 names of servers.
Does anyone have any idea of why this is happening?

Powershell check whether a file exists

On Windows 7 x64, Powershell 3.0:
I have a directory where I download files to, this is done with a .csv file.
A sample of the files is:
008KS04.zip
008KS05.zip
008KS06.zip
008KS07.zip
008KS08.zip
008KS09.zip
I have a Csv, op wich this is a sample:
Documentnummer,Versie,Status,Geocode,IDS datum,Documentgroep (Omsch),Documenttype (Wrd),Tekeningnummer
550164,I,AB,008,26.03.2016,Themalagen OI,KS,008KS09.zip
550163,D,AB,008,19.07.2013,Themalagen OI,KS,008KS08.zip
550162,D,AB,008,19.07.2013,Themalagen OI,KS,008KS07.zip
550161,C,AB,008,19.07.2013,Themalagen OI,KS,008KS06.zip
550160,D,AB,008,19.07.2013,Themalagen OI,KS,008KS05.zip
550159,E,AB,008,15.08.2014,Themalagen OI,KS,008KS04.zip
So, lets say the files are in c:\test\
and the csv in C:\drawings.csv
I want the files that are missing in a csv, lets say C:\missing.csv
At first I tried with one drawing in a variable:
$drawnr = '008KS09.zip'
$destcsv = "C:\missing.csv"
Set-Location C:\test
If(Test-Path -Path ${drawnr}) {
Write-Output "${drawnr}'.zip' exists"
} Else {
Write-Output "${drawnr}'.zip' doesnt exist"
${drawnr} | Export-Csv $destcsv -Append -NoTypeInformation
}
The output when having an existing and a non existsing drawing in the variable
This works perfect, see image but using the CSV as input, I can't get it to work.
This is what I have so far:
$sourcecsv = 'C:\drawings.csv'
$destcsv = 'C:\missing.csv'
Set-Location 'C:\test\'
Import-Csv $sourcecsv | Select-object -Property Tekeningnummer | ForEach {
Write-Output "${_} is the current object" #For Testing purpuse
If (Test-Path -Path ${_}) {
Write-Output "${_} does exist"
} Else {
Write-Output "${_} doesnt exist"
${_} | Export-Csv $destcsv -Append -NoTypeInformation
}
}
This tells me that none of the files exist, while all do exist.
See the picture to see the output of PowerShell and the content written to the missing.csv
The picture of the output where all files are reported as non existend
I'm not sure I get your intent, but it looks like this might work.
$sourcecsv = 'C:\drawings.csv'
$destcsv = 'C:\missing.csv'
Set-Location 'C:\test\'
Import-Csv $sourcecsv | ForEach {
Write-Output "${_} is the current object" #For Testing purpuse
$TK = $_.Tekeningnummer
If (Test-Path -Path $TK) {
Write-Output "$TK does exist"
} Else {
Write-Output "$TK doesnt exist"
$_ | Export-Csv $destcsv -Append -NoTypeInformation
}
}
not sure if ${_} is a new syntax I'm not aware of but I can't get it to work on my PS4 host so I'm changing that to the normal $_ in my answer. beyond that you just need to do an ExpandProperty as #DaveSexton suggests.
Import-Csv $sourcecsv | Select-object -ExpandProperty Tekeningnummer | ForEach {
Write-Output "$($_) is the current object" #For Testing purpuse
If (Test-Path -Path $($_) {
Write-Output "$($_) does exist"
} Else {
Write-Output "$($_) doesnt exist"
$_ | Export-Csv $destcsv -Append -NoTypeInformation
}
}
just do it ;)
$sourcecsv = 'C:\drawings.csv'
$destcsv = 'C:\missing.csv'
$dirtest='C:\test\'
Import-Csv $sourcecsv | where {-not (Test-Path "$dirtest$($_.Tekeningnummer)") } | export-csv $destcsv -NoTypeInformation

How to log output to file

powershell newb here. I am having some difficulty trying log my output to a file. I have tried two tactics, both of which do not work for me. The first is using the Start/Stop-Transcript cmdlet. This works great in testing on my local machine, but doesn't seem to work at all in a script that I deploy to workstations.
$path1 = Test-Path ($env:ProgramFiles + "\Sophos\Sophos Anti-Virus\SavService.exe")
$path2 = Test-Path (${env:ProgramFiles(x86)} + "\Sophos\Sophos Anti-Virus\SavService.exe")
$shareloc = '\\SERVER1\NETLOGON\SophosPackages\SophosInstall_wFW_Silent.exe'
$logpath = '\\SERVER1\NETLOGON\si_sophos_log.txt'
if (($path1 -eq $true) -or ($path2 -eq $true)) {} ELSE {
& $shareloc
Start-Transcript -Append -Path $logpath | Out-Null
Write-Output ""
Get-Date
Write-Output "Sophos has been installed on `"$env:COMPUTERNAME`""
Write-Output ""
Stop-Transcript
}
The way I would prefer to do it, is using: | Out-File -Append -FilePath $logpath
I think this would be the preferred method because it would catch any error that might occur in the log, as apposed to Start-Transcript. When I try to use this method however, I get an error at the pipeline "An empty pipeline element is not allowed."
$path1 = Test-Path ($env:ProgramFiles + "\Sophos\Sophos Anti-Virus\SavService.exe")
$path2 = Test-Path (${env:ProgramFiles(x86)} + "\Sophos\Sophos Anti-Virus\SavService.exe")
$shareloc = '\\SERVER1\NETLOGON\SophosPackages\SophosInstall_wFW_Silent.exe'
$logpath = '\\SERVER1\NETLOGON\si_sophos_log.txt'
if (($path1 -eq $true) -or ($path2 -eq $true)) {} ELSE {
& $shareloc
Write-Output ""
Get-Date
Write-Output "Sophos has been installed on `"$env:COMPUTERNAME`""
Write-Output ""
} | Out-File -Append -FilePath $logpath
Thank you in advance for any assistance!
If you write the following :
if ($true) {Write-Output "titi"} else {Write-Output "toto"} | Out-File -Append c:\temp\titi
You will get the same error, because the if condition is not evaluated when you pipe.
You can try to force ti evaluate it
$(if ($true) {Write-Output "titi"} else {Write-Output "toto"}) | Out-File -Append c:\temp\titi
When the if condition evaluates as true, the empty scriptblock gets piped to Out-File which causes your error. i.e. the following throws the error you specified:
if($true) { } else { Write-Output "Something" } | Out-File -Append -FilePath C:\temp\myfile.txt