I'm trying to divide output into two files with following script:
try {
gci C:\Windows\System32 -r -Force | % {
if (!$_.PsIsContainer) {
$_.FullName;
$file = $_.FullName
}
} > paths.txt
} catch [System.UnauthorizedAccessException] {
$file > errors.txt
}
I'm aware that you can't catch non-terminating scripts with catch [System.UnauthorizedAccessException], but I don't want to use -ErrorAction Stop with catch [System.Management.Automation.ActionPreferenceStopException] either (like here), because I won't get all file paths.
This worked for me
$epath2 = $null
Get-ChildItem -Path C:\Windows\System32 -Recurse -Force -Directory -ErrorVariable epath2 |
foreach {
if ($?) {
Out-File -InputObject $_.FullName -FilePath c:\test\paths.txt -Append
}
}
if ($epath2) {
$epath2 |
foreach {
($_.Exception -split "'")[1] | Out-File -FilePath c:\test\errors.txt -Append
}
}
catch the errors in the -ErrorAction variable and send to errors.txt as a second pass. There may be other errors than access denied but you'll know which folders were showing problems
Related
I am working on a Windows Server File Security project, and need the explicit ACL permissions for our " O:" and all of the subfolders. I am wanting to export it to an CSV for easy formatting. I am looking for a Powershell script that can list the folder name and the Security Group or User that has access to that folder.
$rootpath = "O:\ADSMO"
$outfile = "ExplicitACLs.txt"
New-Variable acl
$Report = #"
Explicit permissions on folders under parent $rootpath.
"#
$Report | out-file -Encoding ASCII -FilePath $outfile
Get-ChildItem -Recurse $rootpath -Exclude "*.*" | Where-Object {$_.PSisContainer } | ForEach-Object {
$acl = Get-Acl -Path $_.FullName
$access = $acl.access
if ( $access | Where-Object { $_.IsInherited -eq $False }) {
Add-Content -Path $outfile $_
$access | Where-Object { $_.IsInherited -eq $False } | ForEach-Object {
$i = $_.IdentityReference
$t = "`t"
$r = $_.FileSystemRights
$c = "$i"+"$t"+"$t"+"$t"+"$r"
Add-Content -Path $outfile $c
}
Add-Content -Path $outfile ""
}
Clear-Variable acl
Clear-Variable access
}
Add-Content -Path $outfile ""
Seems like you're trying to build a CSV manually, which is definitely not recommended. You can use Export-Csv to export your report to CSV. From what I'm seeing, your code could be simplified to this:
Get-ChildItem O:\ADSMO -Directory -Recurse | ForEach-Object {
foreach($access in (Get-Acl $_.FullName).Access) {
# if `IsInherited = $true` go to next iteration
if($access.IsInherited) { continue }
[pscustomobject]#{
FolderName = $_.Name
FolderPath = $_.FullName
IdentityReference = $access.IdentityReference
FileSystemRights = $access.FileSystemRights
}
}
} | Export-Csv 'C:\path\to\acls.csv' -NoTypeInformation
I'm trying to use this function to monitor BSOD remotely I know I have to add a parameter of computername just not sure where
Function Get-BSODInfo{
try {
Invoke-WebRequest -Uri "https://www.nirsoft.net/utils/bluescreenview.zip" -OutFile "$($ENV:Temp)\bluescreeview.zip"
Expand-Archive "$($ENV:Temp)\bluescreeview.zip" -DestinationPath "$($ENV:Temp)" -Force
Start-Process -FilePath "$($ENV:Temp)\Bluescreenview.exe" -ArgumentList "/scomma `"$($ENV:Temp)\Export.csv`"" -Wait
}
catch {
Write-Host "BSODView Command has Failed: $($_.Exception.Message)"
exit 1
}
$BSODs = get-content "$($ENV:Temp)\Export.csv" | ConvertFrom-Csv -Delimiter ',' -Header Dumpfile, Timestamp, Reason, Errorcode, Parameter1, Parameter2, Parameter3, Parameter4, CausedByDriver | foreach-object { $_.Timestamp = [datetime]::Parse($_.timestamp, [System.Globalization.CultureInfo]::CurrentCulture); $_ }
Remove-item "$($ENV:Temp)\Export.csv" -Force
$BSODFilter = $BSODs | where-object { $_.Timestamp -gt ((get-date).addhours(-24)) }
if (!$BSODFilter) {
write-host "Healthy - No BSODs found in the last 24 hours"
}
else {
write-host "Unhealthy - BSOD found. Check Diagnostics"
$BSODFilter
exit 1
}
}
I am new to powershell scripting and have been tasked to create some alerts based on errors in certain logfiles. These are just logs from a bespoke application.
My current Code is
`$OutputFile3 = (Get-Location).Path + ".\Results.txt"
$Sourcefolder= "C:\Users\dewana\Documents\Test\"
$Targetfolder= "C:\Users\dewana\Documents\Test\Test3"
Get-ChildItem -Path $Sourcefolder -Recurse|
Where-Object {
$_.LastWriteTime -gt [datetime]::Now.AddMinutes(-5)
}| Copy-Item -Destination $Targetfolder
$Testing5 = Get-Content -Tail -1 -Path "C:\Users\dewana\Documents\Test\Test3\*.txt" | Where-Object
{ $_.Contains("errors") }
Remove-Item $OutputFile3
New-Item $OutputFile3 -ItemType file
try
{
$stream = [System.IO.StreamWriter] $OutputFile3
$stream.WriteLine('clientID 1111')
$stream.WriteLine('SEV 1')
$stream.WriteLine('Issue with this process')
}
finally
{
$stream.close()
}`
What i am struggling with is trying is
$Testing5 = Get-Content -Tail -1 -Path "C:\Users\dewana\Documents\Test\Test3\*.txt" | Where-Object { $_.Contains("errors") }
I am trying to store the latest string which contains the word error in the log file. i would want to use the stored string to the create an if statement to say if $Testing5 have a new value of error assigned the create a custom text file.
I can't seem to find out why the get-content is not working with the where-object
The only issue I can see is your Where-Object code block is on the next line.
Get-Content -Tail -1 -Path $tempfile | Where-Object
{ $_.Contains("errors") }
If you separate at the pipe it's fine.
Get-Content -Tail -1 -Path $tempfile |
Where-Object { $_.Contains("errors") }
I have a CSV file of file paths. For each path, I want to test if the file exists. If it does, copy to a new location. If it does not, write that path to a "missing files" file.
This is what I have so far...
Import-Csv .\files.csv | ForEach {
If (Test-Path -Path $_.File) {
Write-Output "$($_.File) exists"
} Else {
Write-Output "$($_.File) does NOT exist"
$_.File | Out-File .\missingFiles.txt -Append
}
}
Import-Csv .\files.csv | ForEach {
If (Test-Path -Path $_.File) {
Write-Output "$($_.File) exists"
Copy-Item -Path $_.File -Destination "\\Wherever\You\Want"
} Else {
Write-Output "$($_.File) does NOT exist"
$_.File | Out-File .\missingFiles.txt -Append
}
}
You should not trust the filesystem this way. A file can disappear or change permissions between your Test-Path and your Copy-Item. A safer way to do this (and you may decide you don't need this kind of safety)...
Import-Csv -Path .\files.csv | %{
try {
Copy-Item -Path $_ -Destination <path>
Write-Verbose -Message "Found: $_"
} catch {
$_ | Out-File -Append -Path .\missing.txt
Write-Verbose -Message "Not Found: $_"
}
}
I am trying to write a powershell script that does the following:
Check to see if a folder on a remote machine(text list of computers) exists, if so delete it.
Copy a folder from a remote share to the same machine and if there is an error output to an error log file, if not, output to a success log file.
I have searched but have been unable to find a solution to my seemingly simple problem, please see my code below:
$computers=Get-Content C:\pcs.txt
$source="\\RemoteShare\RemoteFolder"
$dest="C$\Program Files\Destination"
foreach ($computer in $computers) {
If (Test-Path \\$computer\$dest){
Remove-Item \\$computer\$dest -Force -Recurse
}
Copy-Item $source \\$computer\$dest -recurse -force -erroraction silentlycontinue
If (!$error)
{Write-Output $computer | out-file -append -filepath "C:\logs\success.log"}
Else
{Write-Output $computer | out-file -append -filepath "C:\logs\failed.log"}
}
Currently, when the script runs, everything is getting put in the failed.log file, regardless of if it fails or not.
How can I properly handle errors in powershell, while running through a for loop?
Here's an example.
$array = #(3,0,1,2)
foreach ($item in $array)
{
try
{
1/$item | Out-Null
$computer | Add-Content -Path "C:\logs\success.log"
}
catch
{
"Error: $_" | Add-Content -Path "C:\logs\failed.log"
}
}
Don't use $error, it always contains an array of recent error objects, even if the last command was successful. To check the results of the last command, use the $?, it will be false if the last command failed.
See about_Automatic_Variables for more details on these variables.