removing items

This topic contains 20 replies, has 5 voices, and was last updated by  Sayed Hussein Mahdi 10 months ago.

  • Author
    Posts
  • #63812

    Sayed Hussein Mahdi
    Participant

    Hey,

    I need little help, I configured the security event log to automatically backup and clear itself when it's full, so .evtx files starting with word Archive are being created in the log folder.
    I created a script which I want it to be run on weekly basis to extract a particular events related to deletion of files, save them in xml file and then delete those .evtx files.
    however when I run the script it gives error that the .evtx files can't be deleted because they are being used by another process, is there anyway around this? you can find below my script:

    $loc = Get-ChildItem "D:\Logs\archive*"

    Get-WinEvent -FilterHashtable @{ path = $loc ; ID = 4659} |

    Select-Object -Property TimeCreated,

    @{ n = "AccountName" ; e = {($_.Message.split("`n"))[4].Substring(16) } } ,

    @{ n = "ObjectName" ; e = {($_.Message.split("`n"))[11].Substring(14) } } |

    ? {$_.ObjectName -notlike "*~$*" -and $_.ObjectName -notlike "*.tmp*"} |

    Export-Clixml -Path "D:\Logs\$(((Get-Date).AddDays(-1).ToShortDateString()).Replace("/","-")).xml"

    Remove-Item -Path $loc

  • #64020

    Sayed Hussein Mahdi
    Participant

    Really No body?

    • #64030

      Olaf Soyk
      Participant

      Are all of your .evtx files used by another process or just some or one? Did you try to figure out what process is blocking them?

  • #64032

    Sayed Hussein Mahdi
    Participant

    I tried, and I think it is the same the powershell session that that the script is using to extract info from them, I tried to use start-sleep with up 10 seconds thinking that it might help but it didn't, however after the script has been executed I can delete them normally via any mean

    thanks

  • #64033

    Olaf Soyk
    Participant

    ... and I think it is ...

    The best way to know is not to guess. There are tools to determine what process is blocking a file – use it! 😉

  • #64045

    Dan Potter
    Participant

    Declare the $loc again before the remove-item. Best guess, $loc has them committed to memory.

  • #64060

    The PowerShell Bear
    Participant

    I decided to test this, and found something interesting;

    I went into my event viewer and saved a handful of recent events (just random events, nothing special), then performed the same steps you were doing, pointing at the saved test.evtx file that I created and picking an ID that happened to appear a few times in the sample I grabbed. What was interesting is that after executing the command (Get-WinEvent), I could not delete the test.evtx file I'd created using Explorer (it claimed that DHCP Client was locking it, which I think is really odd, and somewhat doubtful). Waiting for a period of time did not change this, but after executing another command (a simple Get-ChildItem worked), the file was unlocked and I could delete it.

    I was able to repeat this several times, so Get-WinEvent appears to be locking the file until you do something else with the shell.

    Since a Start-Sleep didn't fix this for you (I just tested, and it worked for me), I'm going to guess that when running from a script, it's not going to drop the lock until the scope changes.

    I have an idea and will post back after I've tested to see if it works.

  • #64063

    The PowerShell Bear
    Participant

    Okay, this is a bit hacky, but by throwing the Get-WinEvent command into an Invoke-Command scriptblock, you will exit the context scope that is locking the file.

    Long story short, this test code worked on my test file:

    invoke-command -scriptblock { 
    	$loc = ls 'C:\temp\test - Copy.evtx'
    	get-winevent -FilterHashtable @{path = $loc; id = 63} 
    }
    
    rm $loc
    

    So, give this a try and see if it fixes your problem:

    Invoke-Command -ScriptBlock {
    	$loc = Get-ChildItem "D:\Logs\archive*"
    
    	Get-WinEvent -FilterHashtable @{ path = $loc ; ID = 4659} |
    		Select-Object -Property TimeCreated,
    			@{ n = "AccountName" ; e = {($_.Message.split("`n"))[4].Substring(16) } } ,
    			@{ n = "ObjectName" ; e = {($_.Message.split("`n"))[11].Substring(14) } } |
    		where {$_.ObjectName -notlike "*~$*" -and $_.ObjectName -notlike "*.tmp*"} |
    	Export-Clixml -Path "D:\Logs\$(((Get-Date).AddDays(-1).ToShortDateString()).Replace("/","-")).xml"
    }
    
    Remove-Item -Path $loc
    
  • #64068

    Sayed Hussein Mahdi
    Participant

    unfortunately "The Powershell bear" that hasn't work either, I got the error:
    Remove-Item : Cannot bind argument to parameter 'Path' because it is null.

    but you kinda opened my eyes in the scope issue, so I'll play a bit with invoke-command and see what I can get

    • #64123

      The PowerShell Bear
      Participant

      Since I only tried it out with a single evtx file, you may need to use a foreach loop. Maybe this:

      Invoke-Command -ScriptBlock {
          $loc = Get-ChildItem "D:\Logs\archive*"
          $output = @()
      
          foreach ($file in $loc) {
              $output += Get-WinEvent -FilterHashtable @{ path = $file ; ID = 4659} |
                  Select-Object -Property TimeCreated,
                      @{ n = "AccountName" ; e = {($_.Message.split("`n"))[4].Substring(16) } } ,
                      @{ n = "ObjectName" ; e = {($_.Message.split("`n"))[11].Substring(14) } } |
                  where {$_.ObjectName -notlike "*~$*" -and $_.ObjectName -notlike "*.tmp*"}
          }
          
          $output | Export-Clixml -Path "D:\Logs\$(((Get-Date).AddDays(-1).ToShortDateString()).Replace("/","-")).xml"
      }
      
      Remove-Item -Path $loc
      
  • #64071

    Sayed Hussein Mahdi
    Participant

    oh yeah "Dan Potter" I don't want to declare $loc again, the whole purpose of the variable anyway is that I don't want the script when starts off checks against for instance 3 .evtx logs but before the it complete its execution the event log clears it self and saves new evtx file (I know the chances are really slim here but nonetheless) so the remove-item cmdlets remove 4 logs instead of 3
    I want the script to deletes only what it has extracted information from

  • #64072

    Sayed Hussein Mahdi
    Participant

    hi "Olaf Soyk" I checked using "find handle or Dll" of "Process Explorer" right after executing the cmdlet in the powershell, and it showed that svchost.exe was locking them, not really sure how much helpful this is

    • #64081

      Olaf Soyk
      Participant

      Unfortunately that's much less helpfull than I hoped. 🙁 But lets try to improve the Bears code a little:

      $loc = Get-ChildItem "D:\Logs\archive*"
      Invoke-Command -ScriptBlock {
      	Get-WinEvent -FilterHashtable @{ path = $args[0] ; ID = 4659} |
      		Select-Object -Property TimeCreated,
      			@{ n = "AccountName" ; e = {($_.Message.split("`n"))[4].Substring(16) } } ,
      			@{ n = "ObjectName" ; e = {($_.Message.split("`n"))[11].Substring(14) } } |
      		where {$_.ObjectName -notlike "*~$*" -and $_.ObjectName -notlike "*.tmp*"} |
      	Export-Clixml -Path "D:\Logs\$(((Get-Date).AddDays(-1).ToShortDateString()).Replace("/","-")).xml"
      } -ArgumentList $loc
      Remove-Item -Path $loc

      Does this do the trick?

    • #64090

      Sayed Hussein Mahdi
      Participant

      No it doesn't do the trick,

      I should say that after all the testing I've done, I noticed that it sometimes manages to delete one or two logs but not all of them

    • #64096

      Ron
      Participant

      If it works occasionally, perhaps it just needs a delay to release the file. I found this to check for locked files.

      Put in a check for the file being locked, with maybe a limit of 10 loops with 1 second delays. Then remove the file once unlocked. You should probably log the lock checks to see how long it typically takes to release. Might not need full 1 second delays, might only need a few tenths.

    • #64125

      The PowerShell Bear
      Participant

      In my testing, it never released the lock until the script moved on to something else. I could sit and wait a full minute and it would remain, but as soon as I executed something else, it unlocked.

      I don't think timing has anything to do with it, and I don't think a retry loop will help. I think it's going to need the read to be pushed into a new, temporary scope that will close the lock when the scope is disposed.

    • #64131

      Olaf Soyk
      Participant

      If that's really the problem we could try something like this:

      $loc = Get-ChildItem "D:\Logs\archive*"
      Invoke-Command -ScriptBlock {
      	Get-WinEvent -FilterHashtable @{ path = $args[0] ; ID = 4659} |
      		Select-Object -Property TimeCreated,
      			@{ n = "AccountName" ; e = {($_.Message.split("`n"))[4].Substring(16) } } ,
      			@{ n = "ObjectName" ; e = {($_.Message.split("`n"))[11].Substring(14) } } |
      		where {$_.ObjectName -notlike "*~$*" -and $_.ObjectName -notlike "*.tmp*"} |
      	Export-Clixml -Path "D:\Logs\$(((Get-Date).AddDays(-1).ToShortDateString()).Replace("/","-")).xml"
      } -ArgumentList $loc
      $foo = Get-ChildItem -File -Path $ENV:TMP -ErrorAction SilentlyContinue
      Remove-Variable -Name foo
      Remove-Item -Path $loc -Force

      I keep my fingers crossed. 😉

  • #64159

    Sayed Hussein Mahdi
    Participant

    Unfortunately Olaf that didn't work also 🙁

    • #64167

      The PowerShell Bear
      Participant

      Did you try my second suggestion above?

      Here it is again in case you didn't see it:

      Invoke-Command -ScriptBlock {
          $loc = Get-ChildItem "D:\Logs\archive*"
          $output = @()
      
          foreach ($file in $loc) {
              $output += Get-WinEvent -FilterHashtable @{ path = $file ; ID = 4659} |
                  Select-Object -Property TimeCreated,
                      @{ n = "AccountName" ; e = {($_.Message.split("`n"))[4].Substring(16) } } ,
                      @{ n = "ObjectName" ; e = {($_.Message.split("`n"))[11].Substring(14) } } |
                  where {$_.ObjectName -notlike "*~$*" -and $_.ObjectName -notlike "*.tmp*"}
          }
          
          $output | Export-Clixml -Path "D:\Logs\$(((Get-Date).AddDays(-1).ToShortDateString()).Replace("/","-")).xml"
      }
      
      Remove-Item -Path $loc
      
    • #64216

      Sayed Hussein Mahdi
      Participant

      hi bear

      Yeah I kinda missed it, but I've just tried it today and I got this error:

      Remove-Item : Cannot bind argument to parameter 'Path' because it is null.

      however, I've been trying all these hacky things, and I ended up with a solution that is working fine:
      I created 2 powershell scripts and a batch file, the first script (first.ps1) has:

      $loc = Get-ChildItem "D:\Logs\archive*"

      Get-WinEvent -FilterHashtable @{ path = $loc ; ID = 4659} |

      Select-Object -Property TimeCreated,

      @{ n = "AccountName" ; e = {($_.Message.split("`n"))[4].Substring(16) } } ,

      @{ n = "ObjectName" ; e = {($_.Message.split("`n"))[11].Substring(14) } } |

      where {$_.ObjectName -notlike "*~$*" -and $_.ObjectName -notlike "*.tmp*"} |

      Export-Clixml -Path "D:\Logs\$(((Get-Date).AddDays(-1).ToShortDateString()).Replace("/","-")).xml"

      $loc | Export-Clixml -Path "D:\Logs\loc.xml"

      the second Script (second.ps1) has:

      Remove-Item -Path (Import-Clixml -Path "D:\Logs\loc.xml")

      And the batch file (final.bat) has:

      powershell.exe -file "D:\Logs\Scripts\first.ps1"
      powershell.exe -file "D:\Logs\Scripts\second.ps1"

      Now before using the batch file I created a third script which included both 1 & 2 scripts but I ended up with the same negative result.

      so currently that is my stupid solution for the problem, 😉 any comments?

      thanks

  • #64230

    Sayed Hussein Mahdi
    Participant

    I should say, that I was planning to add extra "if statement" right at the beginning of the script to go check for a certain backup job and if it has succeeded only then it execute the script. not really sure now who Am I going to do that.

You must be logged in to reply to this topic.