How can I log everything that is written in powershell window? - powershell

I am needing to create a logfile for every action that is performed by this script.
I have attempted to use redirection(>>) however, cannot get the output to actually write to the file.
while($true){
$FromMC = Get-ChildItem -Path "\\x\From MC" -Filter *.mpg
Write-Host "Checking '\\x\From MC' for files" -ForegroundColor Cyan
Write-Host $FromMC.count"Files Found" -ForegroundColor Cyan
Write-Host ""
ForEach($file in $FromMC){
try{
Move-Item -Filter 7ST* -Path $file.Fullname -Destination "\\x\programs\7TH STREET THEATER" -Verbose -Force -ErrorAction Stop
}
catch{...}
Write-Host "Pausing for"$ts.Minutes"minutes..." -ForegroundColor Cyan
Write-Host "Ctrl+C to Stop"
Write-Host ""
Start-Sleep -Seconds $ts.TotalSeconds
}
I expect the output to be exactly as "-verbose" outputs into the shell. Types of output: Write-Host, Verbose, Write-Warning
I feel the solution is extremely simple, and I am just overlooking it.

To log everything that would normally be written to the console, like -verbose you can use Start-Transcript and when you are finished Stop-Transcript.
Example:
Start-Transcript -Path "C:\logs.txt"
#run code you want to capture
Stop-Transcript

Related

Powershell loops for syslog management

If I run the script below it will perform all the tasks that I need it to. I need the task to run every 15 seconds in a loop. When I add a loop of any type, the loop gets stuck on only a portion of the script an no longer functions as expected. I'm looking to loop the entire script top to bottom. The current script does not have any loops at this time. Any help would be greatly appreciated.
# Syslog Management. Automate has a max size of 977KB before it dumps everything into a file called Syslogold.txt
# If Syslogold.txt already exists it will be overwriten and logs will be gone.
# Script below will move syslogold.txt into syslog folder where it will be renamed to Syslog-(CurrentDate).TxT
# When ever a new Syslogold.txt is generated by Automate, this script will append the output to a daily file in a monthly folder.
# On the first day of every month, the previous month will be zipped and archived.
#
$LastMonth = (Get-Date).AddMonths(-1).ToString('MMM-yyyy')
$CurrentSyslogFolder = "C:\Windows\LTsvc\Syslogs\Syslogs-$(Get-Date -Format "MMM-yyyy")"
$OldDirectory = "C:\Windows\LTsvc\Syslogs\Syslogs-$LastMonth"
$CurrentLog = "Syslog-$(Get-Date -Format "dd-MMM-yyyy").txt"
$OldLog = "C:\Windows\LTSvc\syslogold.txt"
$SyslogArchive = "C:\Windows\LTSvc\Syslogs\Archive\Syslog-$LastMonth.zip"
do{
$TestPath01 = Test-Path -Path $CurrentSyslogFolder
$TestPath02 = Test-Path -Path $CurrentSyslogFolder\$CurrentLog
$TestPath03 = Test-Path -Path $OldLog
$TestPath04 = Test-Path -Path $OldDirectory
if($TestPath01)
{
write-host "Syslog directory current."
}
else
{
write-host "Current syslog directory is for last month. Creating new folder."
New-Item -ItemType Directory -Force -Path $CurrentSyslogFolder
}
if(($TestPath02) -and ($TestPath03))
{
write-host "Automate syslog archive found"
write-host "Daily syslog Found."
write-host "Appending Automate archive with daily syslog"
Add-Content -Path $CurrentSyslogFolder\$CurrentLog -Value ""
Get-Content -Path $OldLog | Add-Content -Path $CurrentSyslogFolder\$CurrentLog
Remove-Item -Path $OldLog
start-sleep -Seconds 15
}
else
{
write-host "Automate syslogs active."
write-host "Waiting for Automate to archive syslogs."
if ($TestPath03)
{
Write-Host "Automate has completed archiving Syslogs."
Write-Host "Moving archive to daily syslog."
Write-host "Daily syslog missing. Creating daily syslog now"
Move-Item $OldLog -Destination $CurrentSyslogFolder\$CurrentLog
}
}
if($TestPath04)
{
write-host "Last months directory found."
Write-Host "Compressing last months directory"
Compress-Archive -Path "$OldDirectory" -DestinationPath "$SyslogArchive"
Write-host "Moving compressed directory to archive"
Write-host "Cleaning up files"
Remove-Item -Path "$SyslogDirectory\Syslogs-$LastMonth" -Recurse
Write-host "Cleanup completed"
start-sleep -Seconds 15
}
else
{
Write-host "Will try again in 15 seconds"
start-sleep -Seconds 15
}
}until($infinity)
To be honest the best way would be Scheduled Task ScheduledTask
But you can also use do or while
do{ YOURSCRIPT start-sleep -Seconds 15 }until($infinity)

Powershell not able to clear IE Browsing Cookies, Caches, etc

I am trying to clear browser data from default location C:\Users\\AppData\Local\Microsoft\Windows\INetCache. I am trying to clear Cookies, Cache or any type files located in that path but I am not sure what am I missing here
screenshot
Write-Host -ForegroundColor yellow "#######################################################"
""
Write-Host -ForegroundColor Green "Powershell commands to delete cache & cookies in Firefox, Chrome & IE browsers"
Write-Host -ForegroundColor Green "By Cesar Silva"
Write-Host -ForegroundColor Green "VERSION: 3"
""
Write-Host -ForegroundColor yellow "#######################################################"
""
Write-Host -ForegroundColor Green "CHANGE_LOG:
v2.4: - Resolved *.default issue, issue was with the file path name not with *.default, but issue resolved
v2.3: - Added Cache2 to Mozilla directories but found that *.default is not working
v2.2: - Added Cyan colour to verbose output
v2.1: - Added the location 'C:\Windows\Temp\*' and 'C:\`$recycle.bin\'
v2: - Changed the retrieval of user list to dir the c:\users folder and export to csv
v1: - Compiled script"
""
Write-Host -ForegroundColor yellow "#######################################################"
""
#########################
"-------------------"
Write-Host -ForegroundColor Green "SECTION 1: Getting the list of users"
"-------------------"
# Write Information to the screen
Write-Host -ForegroundColor yellow "Exporting the list of users to c:\users\%username%\users.csv"
# List the users in c:\users and export to the local profile for calling later
dir C:\Users | select Name | Export-Csv -Path C:\users\$env:USERNAME\users.csv -NoTypeInformation
$list=Test-Path C:\users\$env:USERNAME\users.csv
""
#########################
"-------------------"
Write-Host -ForegroundColor Green "SECTION 2: Beginning Script..."
"-------------------"
if ($list) {
"-------------------"
# Clear Internet Explorer
Write-Host -ForegroundColor Green "SECTION 5: Clearing Internet Explorer Caches"
"-------------------"
Write-Host -ForegroundColor yellow "Clearing Google caches"
Write-Host -ForegroundColor cyan
Import-CSV -Path C:\users\$env:USERNAME\users.csv | foreach {
Remove-Item -path "C:\Users\$($_.Name)\AppData\Local\Microsoft\Windows\INetCache\*.*" -Recurse -Force -EA SilentlyContinue -Verbose
Remove-Item -path "C:\Users\$($_.Name)\AppData\Local\Microsoft\Windows\WER\*" -Recurse -Force -EA SilentlyContinue -Verbose
Remove-Item -path "C:\Users\$($_.Name)\AppData\Local\Temp\*" -Recurse -Force -EA SilentlyContinue -Verbose
Remove-Item -path "C:\Windows\Temp\*" -Recurse -Force -EA SilentlyContinue -Verbose
Remove-Item -path "C:\`$recycle.bin\" -Recurse -Force -EA SilentlyContinue -Verbose
}
Write-Host -ForegroundColor yellow "Done..."
""
Write-Host -ForegroundColor Green "All Tasks Done!"
} else {
Write-Host -ForegroundColor Yellow "Session Cancelled"
Exit
}
Well if any errors are occurring, you are suppressing them with the -EA SilentlyContinue flag. I would remove that from your Remove-Item calls and see if any sneaky errors are hiding there.
I'm not sure if you intended this, but in your first Remove-Item call under INetCache:
Remove-Item -path "C:\Users\$($_.Name)\AppData\Local\Microsoft\Windows\INetCache\*.*"
You are removing only files with a . in the filename, basically only files with extensions. If you want to remove everything from that directory regardless of whether it has a file extension, just use * instead of *.* as you do for your other paths.

why doesnt tee-object work with NoNewline?

i have the following function in my script
function Write-Host($object)
{
if($global:LogFile -eq $null)
{
$global:LogFile = $logFile
}
$object | tee $global:LogFile -Append
}
referencing this post: https://stackoverflow.com/a/25847258/8397835
I am trying specifically this part here:
$job = Start-Job -ScriptBlock { Start-Sleep -Seconds 10 }
while (($job.State -eq "Running") -and ($job.State -ne "NotStarted"))
{
Write-Host ([char]9632) -NoNewLine
Start-Sleep -Seconds 1
}
apparently, with tee, nonewline appears to be ignored...and without tee, i am getting the characters to display on one line as i am seeking
with tee:
without tee
I think i know whats happening. since write-host is being converted to tee, any switches are ignored, be it color or in this case, nonewline. How can i make nonewline work with tee?
After our chat I understand what you're trying to do. You want to write yourself a custom progress bar that both writes to a log file as well as to the console without line breaks in either. For that you can write a function that will accomplish it, but I do recommend picking a new name that doesn't conflict with an existing cmdlet. I'll use Write-MyProgress.
Function Write-MyProgress{
[cmdletbinding()]
Param(
[parameter(valuefrompipeline=$true)]$message,
[switch]$NoNewLine
)
if($global:LogFile -eq $null)
{
$global:LogFile = $logFile
}
Add-Content -Value $message -Path $LogFile -NoNewline:$NoNewLine
Write-Host $Message -NoNewLine:$NoNewLine
}
You could then call it explicitly:
Write-MyProgress ([char]9632) -NoNewLine
or pipe things to it:
[char]9632 | Write-MyProgress -NoNewLine
Or, if you don't want to use a function, you could just do it all with native cmdlets like in this example:
1..10 | ForEach-Object -Process {
[char]9632 | Add-Content $LogFile -NoNewLine -PassThru | Write-Host -NoNewLine
start-sleep -Sec 1
} -End {Add-Content -Value '' -Path $LogFile}
(Note that I add '' to the log file at the end, so the log file gets a new line after the progress bar is done)

Stop process thats using a file remotely

I have a script in which Some of the files get deleted...
VERBOSE: Performing the operation "Remove Directory" on target
\name1\subitem
VERBOSE: Performing the operation "Remove Directory" on target
\name1\subitem1
VERBOSE: Performing the operation "Remove Directory" on target
\name1\subitem2
but others throw this error following the other verbose messages:
Cannot remove item d:\temp\name1.db\metadata.sqlitedb: The process
cannot access the file 'metadata.sqlitedb' because it is being used by
another process.
Directory d:\temp\name1.db cannot be removed because it is not empty.
How can i automatically kill the process used (whichever it is) and attempt to remove the item again as part of my script above?
i tried handle suggestion from this thread PowerShell script to check an application that's locking a file?, but i think our servers dont allow external tools as i either dont get any output or getting access denied...so im looking for some other option that doesnt require external tool
Essentially looking for something like this as part of my script:
$Directory = "d:\temp"
Invoke-Command -Computer $Server -ScriptBlock {
param ($dir, $name)
#Write-Output "dir='$dir', name='$name'"
$f = Get-ChildItem -Path $dir | Where {$_.Name -Match $name} | Select -ExpandProperty FullName
if ($f) {
$f | Foreach {
try
{
Remove-Item $_ -confirm:$false -recurse -Verbose #-WhatIf
}
catch
{
if ($_.Exception.Message -like '*it is being used by another process*')
{ write-host "that process is " $pid + $pname
try{
KILL PROCESS
Remove-Item $_ -confirm:$false -recurse -Verbose #-WhatIf
}
catch
{
$error[0]
}
}
else
{
Write-Host "$($error[0])`r`n" -foregroundcolor magenta -backgroundcolor black
}
}
}
}
else {
Write-Verbose "No file found"
}
} -ArgumentList $Directory, $DB -verbose

how to merge multiple scripts and use functions to show output

A couple of you (Shay especially!) helped me yesterday and I have managed to come up with multiple scripts and am now merging them into one.
The problem is that I have put them all into "Functions" and one function relies on the successful check on a hotfix - if the hotfix is not installed then the script has to stop right there and then - that is the first check the script does. How do I get the next function to call the successful output of the hotfix function?
Also I have no idea how to call the functions - ie at the bottom I put the name of the functions one line after each other but ended up looping over and over!
hope someone can assist.
Write-Host "=================================="
Write-Host "Pre-Staging Script for DFSR Server"
Write-Host "=================================="
Function Service
{
Write-Host "=================================="
Write-Host "Checking Service Installation"
Write-Host "=================================="
write-host "This will check if Hotfix KB979808 is installed." -ForegroundColor Black -BackgroundColor Cyan
write-host "This is required for Windows Server 2008 R2 Robocopying" -ForegroundColor Black -BackgroundColor Cyan
Write-Host ""
$hotfix1 = Get-HotFix -id KB979808 -ErrorAction SilentlyContinue
If($hotfix1)
{
Write-Host "Hotfix is installed you may proceed" -foregroundcolor "green"
Write-Host ""
}
else
{
Write-Host "Hotfix is NOT installed - Please ensure you install this hotfix BEFORE" -ForegroundColor "red"
Write-host "Copying any data" -foregroundcolor "red"
Write-Host ""
}
}
Function Robocopy ($hotfix1)
{
Write-Host "============="
Write-Host "Robocopy Data"
Write-Host "============="
$Source = Read-Host "Please enter path of SOURCE"
$Destination = Read-Host "Please enter path of TARGET"
$Output = Read-Host "Please enter where to place output file eg c:\temp\COPY.log"
robocopy $Source $Target /b /e /copyall /r:1 /xd dfsrprivate /log:$Output /tee
}
Function Comparision
{
Write-Host "==============================================="
Write-Host "Checking Directory Count and Folder comparision" -ErrorAction SilentlyContinue -BackgroundColor Cyan -ForegroundColor Black
Write-Host "==============================================="
Write-Host ""
$Source = Read-Host "Please enter Source directory to check"
$Target = Read-Host "Please enter Target directory to check"
Write-Host ""
If($source -and (Test-Path -Path $source -PathType Container))
{
"There are $(#(Get-ChildItem $Source).Count) items in the '$Source' directory"
}
Else
{
Write-Host "Please enter a directory"
}
If($source -and (Test-Path -Path $Target -PathType Container))
{
"There are $(#(Get-ChildItem $Target).Count) items in the '$Target' directory"
}
Else
{
Write-Host "Please enter a directory"
}
Write-Host ""
$child1 = Get-ChildItem -Path $Source -Recurse -Force
$child2 = Get-ChildItem -Path $Target -Recurse -Force
Compare-Object $child1 -DifferenceObject $child2 -Property Name
Write-Host ""
Write-Host "NOTE:" -BackgroundColor Cyan -ForegroundColor Black
Write-Host "Any symbols with '=>' mean that the file Does NOT exist in SOURCE but is in the Target" -BackgroundColor Cyan -ForegroundColor Black
Write-Host "Any symbols with '<=' mean that the file Does NOT exist in TARGET but is in the Source" -BackgroundColor Cyan -ForegroundColor Black
}
To use the hotfix found in the function Service, you should return the hotfix to a variable. The function would look like this:
Function Service
{
Write-Host "=================================="
Write-Host "Checking Service Installation"
Write-Host "=================================="
write-host "This will check if Hotfix KB979808 is installed." -ForegroundColor Black -BackgroundColor Cyan
write-host "This is required for Windows Server 2008 R2 Robocopying" -ForegroundColor Black -BackgroundColor Cyan
Write-Host ""
# This will return any output.
Get-HotFix -id KB979808 -ErrorAction SilentlyContinue
}
Then the function calls would be:
$hotfix = Service
if($hotfix) {
Robocopy
}
else {
# This will exit the script.
return
}
Function Robocopy doesn't need $hotfix1 as a parameter since it's not used anywhere in the function.
The Robocopy function is probably looping because the call to robocopy.exe is the same as your Robocopy function; try adding ".exe" to the robocopy.exe call. It is important to name functions to accurately reflect their purpose. Service could be Get-HotFixKB979808 and Robocopy could be Start-MyRobocopy
Having said all that, since your functions do very specific things, they really don't need to be their own functions. You could change them to be more reusable by having them accept parameters.