2016-07-27 15 views
2

Ich erhebe Dateien von einer Festplatte, in der einige der Dateien nicht lesbar sind. Ich bin nicht in der Lage, das Hardware-Level-Timeout/ERC zu ändern, und es ist extrem schwierig, zu arbeiten, wenn ich mehrere hunderttausend Dateien habe, von denen Zehntausende möglicherweise nicht lesbar sind.Copy-Item mit Timeout

Die Datenprobleme waren das Ergebnis eines Controllerfehlers. Da ich ein passendes Laufwerk gekauft habe (ganz unten), konnte ich auf das Laufwerk zugreifen und große Teile ohne Probleme kopieren. Es sind jedoch nicht lesbare Dateien auf dem Laufwerk vorhanden, die beim Zugriff dazu führen, dass der SATA-Bus hängen bleibt. Ich habe verschiedene fortsetzbare Dateikopie-Anwendungen wie robocopy, RichCopy und ein Dutzend andere verwendet, aber sie alle haben das gleiche Problem. Sie haben eine RETRY-Zählung, die darauf basiert, dass tatsächlich ein Fehler vom Laufwerk gemeldet wird. Das Problem ist, dass das Laufwerk extrem lange braucht, um den Fehler zu melden, und das bedeutet, dass eine einzelne Datei bis zu einer Stunde dauern kann, bis sie offiziell ausfällt. Ich weiß, wie schnell jede Datei sein sollte, also möchte ich ein Powershell-CMDLET oder ähnliches erstellen, das mir erlaubt, einen Quell- und Zieldateinamen einzugeben und es versuchen zu lassen, die Datei zu kopieren. Wenn die Datei nach 5 Sekunden nicht kopiert wurde (oder falls dies der Fall ist - dies kann ein dummer Prozess sein), möchte ich, dass sie beendet wird. Ich schreibe ein Skript, das jeden Kopiervorgang einzeln abfeuert und auf den Prozess wartet, bevor es fertig ist, aber ich bin bisher nicht in der Lage, ein gutes Zeitlimit für den Prozess zu finden.

Alle Vorschläge, die Sie haben könnten, würden sehr geschätzt werden!

Edit: Ich würde mit dem Laichen ein Copy-Item in einem neuen Thread glücklich sein, mit einem neuen PID, dann heruntergezählt, dann ist das PID zu töten. Ich bin nur ein Neuling bei PowerShell und habe so viele widersprüchliche Methoden gesehen, wie man Zeitgebern auferlegt, dass ich auf dem Weg der Best Practices verloren bin.

Bearbeiten 2: Bitte beachten Sie, dass Anwendungen wie robocopy völlig hängen bleiben, wenn die schlechten Regionen der Festplatte auftreten. Dies sind keine einfachen Hänge, aber Bus hängt, dass Fenster versuchen, zu bewahren, um keine Daten zu verlieren. In diesen Fällen kann der Task-Manager den Prozess nicht beenden, sondern Process Explorer IS. Ich bin nicht sicher, was der Unterschied in der Methodik ist, aber unabhängig davon scheint es relevant.

+0

[robocopy] (https://technet.microsoft.com/en-us/library /cc733145(v=ws.11).aspx)/w: 10/r: 1 – lloyd

+0

@lloyd Das wird nach Timeout + 10 Sekunden einmal wiederholt. –

+0

Lloyd, In diesem Fall empfängt Robocopy keine Nachricht von dem Laufwerk, dass der Vorgang fehlgeschlagen ist, sodass die Anzahl der Wiederholungen keine Rolle spielt. Das Laufwerk wird sitzen und glücklich vorgeben, dass es die Daten noch viele, viele Stunden (pro Datei) abruft, so dass es nie vernünftigerweise zum Wiederholungszähler kommt. –

Antwort

6

Ich würde sagen, die kanonische Art, Dinge in PowerShell zu tun, sind background jobs.

$timeout = 300 # seconds 

$job = Start-Job -ScriptBlock { Copy-Item ... } 
Wait-Job -Job $job -Timeout $timeout 
Stop-Job -Job $job 
Receive-Job -Job $job 
Remove-Job -Job $job 

ersetzen Copy-Item in der Skript mit dem, was Sie ausführen möchten befehlen. Beachten Sie jedoch, dass alle Variablen, die Sie im Skriptblock verwenden möchten, entweder im Skriptblock definiert sein müssen, über den Parameter -ArgumentList übergeben werden müssen oder dem Bereichsqualifikator using: vorangestellt werden müssen.

Eine Alternative zu Wait-Job wäre eine Schleife, die wartet, bis der Auftrag abgeschlossen ist oder der Timeout erreicht wird:

$timeout = (Get-Date).AddMinutes(5) 
do { 
    Start-Sleep -Milliseconds 100 
} while ($job.State -eq 'Running' -and (Get-Date) -lt $timeout) 
+0

Vielen Dank für den Zeiger! Da ich bei den Problemen mit SATA MIGHT ein Problem sein könnte, wenn es hängt, wird der Prozess am Ende nicht beendet und kann nur durch Trennen des Laufwerks freigegeben werden. Ich habe es mit einer Kopie von einem bekannten Arbeitslaufwerk getestet und es hat genau wie erwartet funktioniert. Mein nächster Schritt wird sein, einen Powerdown-Befehl an einen Mikrocontroller zwischen Dateien zu senden, wenn der Prozess nicht beendet wird. Dieser Code kümmert sich angemessen um das Timing und ich bin sehr dankbar! Vielen Dank! edit: und danke für die Editierhilfe! –