Benutzer mit den meisten Antworten
Powershell - Continiue on"Error" or "Access denied" bei - System.IO.Directory Klasse GetFiles Methode

Frage
-
Hi,
ich habe da ein Problem mit Powershell.
Ich suche einen Weg eine Datei im Benutzerprofil C:\Users\Username auf über 1000 Windows 7 Computern zu finden.
Get-ChildItem ist viel zu langsam. Bin bei meinen recherchen hierrauf gestoßen:
[System.IO.Directory]::GetFiles
Leider bekomme ich immer den untestehenden Fehler.
Beim Versuch den Fehler mit try{} catch{} zu umgehen bekomme ich gar keine Ausgabe mehr zu sehen.
Wie bringe ich meinem Script bei das es einfach weitermachen soll, auch wenn es Fehler erzeugt?
Ich suche ein: -ErrorAction SilentlyContinue
Befehl:
[System.IO.Directory]::GetFiles("\\Computername\c$\Users\Username" , "MobaXterm.ini" , "ALLDIRECTORIES")
Ausgabe:
Exception calling "GetFiles" with "3" argument(s): "Access to the path '\\Computername\c$\Users\Username\AppData\Local\Application Data' is denied."
At line:1 char:1
+ [System.IO.Directory]::GetFiles("\\vm-barakise-7\c$\Users\barakise" , ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : UnauthorizedAccessException
Antworten
-
Moin,
ich muss meinen Vorrednern aufs Vehementeste in dem Punkt zustimmen, dass eine Remote-Pull-Abfrage nicht optimal ist. Mein Favorit wäre in dem Fall die Software-Verteilung (SCCM kann übrigens von Hause aus Dateien inventarisieren, vermutlich können die Konkurrenzprodukte das auch).
Wenn es aber remote sein soll, wäre ich für so etwas wie
$comps = (Get-ADComputer -Filter <Filter Deiner Wahl>).DNSHostName $sessions = New-CIMSession -ComputerName $comps $sess = New-CIMSession -ComputerName localhost Get-CIMInstance CIM_DataFile -Filter "(Drive='C:') AND (Path LIKE '\\Users\\%) AND (FileName='MobaXTerm') AND (Extension='ini')" -CIMSession $sessions | ft Name, PSComputerName
Da wird die Suche immerhin lokal durch den CIM-Provider ausgeführt.
Evgenij Smirnov
I work @ msg services ag, Berlin -> http://www.msg-services.de
I blog (in German) @ http://it-pro-berlin.de
my stuff in PSGallery --> https://www.powershellgallery.com/profiles/it-pro-berlin.de/
Exchange User Group, Berlin -> https://exusg.de
Windows Server User Group, Berlin -> http://www.winsvr-berlin.de
Mark Minasi Technical Forum, reloaded -> http://newforum.minasi.com
In theory, there is no difference between theory and practice. In practice, there is.
- Bearbeitet Evgenij Smirnov Dienstag, 31. Juli 2018 21:10 Dutzende Typos, ich muss ins Bett...
- Als Antwort vorgeschlagen Denniver ReiningMVP, Moderator Donnerstag, 9. August 2018 09:55
- Als Antwort markiert Denniver ReiningMVP, Moderator Donnerstag, 9. August 2018 09:56
-
Try/Catch kann man auch für die Get-Childitem-Variante anwenden und wirkt quasi wie die ErrorAction.
Allerdings, und da ist das Missverständniss, wird eben für das ausgeführte cmdlet insgesamt ein Error ausgeworfen.
Ein Fortsetzen innerhalb der tiefsten Ebene, auf der der Fehler gerade passiert, ist technisch nicht vorgesehen.Zum Verständnis:
Ein Fehler wird an die erste Ebene über den Callstack gemeldet, die eine Try/Catch-Fehlerbehandlung durchführt. Und das ist nun mal leider dein Skript.Um also den Fehler zu umgehen und immer weiter zu machen, musst du das ganze selber rekursiv über eine Schleifen-Funktion je Verzeichnisebene ereldigen. Eine automatische Rekursion hilft dir da nicht.
Wenn du mehrere PC's parallel abfragen willst, hilft dir u.U. das Threading weiter:
http://www.get-blog.com/?p=189
https://blogs.technet.microsoft.com/santhse/invokeall/Der Nachteil ist aber immer noch, dass alle Daten erst mal lokal von den Rechnern geholt werden müssen.
Man kann aber die Remoterechner dies selber tun lassen:
https://www.windowspro.de/wolfgang-sommergut/powershell-remote-ausfuehren-winrm-ueber-gpos-aktivierenSomit machst du 2 Dinge:
a) Je computer ein Thread
b) Je Thread ein Remote-AufrufDamit hast du dann ParallelComputing über zig Rechner gelöst.
- Bearbeitet Der Suchende Dienstag, 31. Juli 2018 15:48
- Als Antwort vorgeschlagen Denniver ReiningMVP, Moderator Donnerstag, 9. August 2018 09:54
- Als Antwort markiert Denniver ReiningMVP, Moderator Donnerstag, 9. August 2018 09:56
Alle Antworten
-
Ist es wirklich eine gute Idee, auf diese Weise 1000 PCs direkt zu durchsuchen? .... ich bin skeptisch. Nach meiner Erfahrung hat man in Infrastrukturen solcher Größe ein AD und irgendeine Art Softwareverteilung, die für solche Aufgaben deutlich besser geeignet wären. Notfalls dann eben mittels GPOs.
Wenn Du direkt .Net-Klassen benutzt, kannst Du Dir ein -ErrorAction sparen. Der Parameter funktioniert nur mit Powershell-cmdlets. Und ohne Deinen Code zu sehen, können wir auch schwer beurteilen, warum Dein Try-Catch nicht wie gewünscht funktioniert.
Unabhängig davon nochmal: Bitte überdenk Deinen Ansatz nochmal. Es gibt vermutlich deutlich bessere (robustere) Ansätze, so eine Aufgabe zu lösen.
Best regards,
(79,108,97,102|%{[char]$_})-join''
-
Hi,
erst mal danke für die Antwort.
Kurze Erklärung zum Code:
Computername Name: K3-FischerM-WS
AD User Name: FischerM
UserProfilPfad: C:\Users\FischerM\
Deswegen die Codezeile
$Username = ($computer.Split("-"))[1]
um den Usernamen vom Computernamen zu trennen.
Der Username wird gebraucht um auf das jeweilige Windows User Profil Verzeichniss zuzugreifen um eine bestimmte Datei MobaXterm.ini zu finden.
Die Datei befindet sich an verschiedenen und immer unterschiedlichen Stellen im Userprofil.
Ein weiteres Problem ist das auf ca. 50% der Computer das User Profil auf der D: Partition in D:\Data\Username gespeichert ist, und nicht wie üblich auf C:\User\Username
Wie schon gesagt ist das cmdlet Get-ChildItem viel zu langsam. Und dauert mit unter viele Tage bis das Script durchgelaufen ist.
Hier mein Code mit .NET Klassen
foreach ($computer in Get-Content D:\VirtualMachines.txt) { $Username = ($computer.Split("-"))[1] Write-Host "Currently searching in $computer at Path $username" $PathC = "\\$computer\c$\Users\$username" $PathD = "\\$computer\d$\Data\$username" $filenameC = try {[System.IO.Directory]::GetFiles($PathC, "MobaXterm.ini", "ALLDIRECTORIES")} catch {continue} $filenameD = try {[System.IO.Directory]::GetFiles($PathD, "MobaXterm.ini", "ALLDIRECTORIES")} catch {continue} $filenameC $filenameD }
Hier mein Code mit Get-ChildItem
foreach ($computer in Get-Content D:\VirtualMachines.txt) { $Username = ($computer.Split("-"))[1] Write-Host "Currently searching in $computer at Path $username" Get-ChildItem -Recurse -Force \\$computer\c$\Users\$username -ErrorAction SilentlyContinue | Where-Object { ($_.PSIsContainer -eq $false) -and ( $_.Name -eq "MobaXterm.ini") } | Select-Object Name,Directory | Export-Csv D:\MobaXTermAtUserProfileC.csv -nti -append Get-ChildItem -Recurse -Force \\$computer\d$\data\$username -ErrorAction SilentlyContinue | Where-Object { ($_.PSIsContainer -eq $false) -and ( $_.Name -eq "MobaXterm.ini") } | Select-Object Name,Directory | Export-Csv D:\MobaXTermAtUserProfileD.csv -nti -append }
Habt ihr andere Lösungsansätze?
Ich brauche eine schnelle Lösung mit der ich Dateien mit einem bestimmten Namen auf allen Remote-Computern finden kann.
Danke für eure Hilfe ;-)
- Bearbeitet RoyalFlash Dienstag, 31. Juli 2018 15:10
-
Deswegen die Codezeile
$Username = ($computer.Split("-"))[1]
um den Usernamen vom Computernamen zu trennen.
omg :-))
Der Username wird gebraucht um auf das jeweilige Windows User Profil Verzeichniss zuzugreifen um eine bestimmte Datei MobaXterm.ini zu finden.
Warum? Steck die Suche in ein Logonskript, das unterhalb von %userprofile% bei der Anmeldung des Benutzers sucht. Das zeigt dann auch immer auf das richtige Verzeichnis. Und das Ergebnis speicherst auf einem Netzwerkshare...
Viel einfacher, schneller und robuster als die Remote-Lösung von Dir.
Oder mach's als Computerstartskript, das alle lokalen Profilverzeichnisse durchsucht (Registry -> ProfileList, da steht der Pfad aller vorhandenen Profile drin...).
-
Try/Catch kann man auch für die Get-Childitem-Variante anwenden und wirkt quasi wie die ErrorAction.
Allerdings, und da ist das Missverständniss, wird eben für das ausgeführte cmdlet insgesamt ein Error ausgeworfen.
Ein Fortsetzen innerhalb der tiefsten Ebene, auf der der Fehler gerade passiert, ist technisch nicht vorgesehen.Zum Verständnis:
Ein Fehler wird an die erste Ebene über den Callstack gemeldet, die eine Try/Catch-Fehlerbehandlung durchführt. Und das ist nun mal leider dein Skript.Um also den Fehler zu umgehen und immer weiter zu machen, musst du das ganze selber rekursiv über eine Schleifen-Funktion je Verzeichnisebene ereldigen. Eine automatische Rekursion hilft dir da nicht.
Wenn du mehrere PC's parallel abfragen willst, hilft dir u.U. das Threading weiter:
http://www.get-blog.com/?p=189
https://blogs.technet.microsoft.com/santhse/invokeall/Der Nachteil ist aber immer noch, dass alle Daten erst mal lokal von den Rechnern geholt werden müssen.
Man kann aber die Remoterechner dies selber tun lassen:
https://www.windowspro.de/wolfgang-sommergut/powershell-remote-ausfuehren-winrm-ueber-gpos-aktivierenSomit machst du 2 Dinge:
a) Je computer ein Thread
b) Je Thread ein Remote-AufrufDamit hast du dann ParallelComputing über zig Rechner gelöst.
- Bearbeitet Der Suchende Dienstag, 31. Juli 2018 15:48
- Als Antwort vorgeschlagen Denniver ReiningMVP, Moderator Donnerstag, 9. August 2018 09:54
- Als Antwort markiert Denniver ReiningMVP, Moderator Donnerstag, 9. August 2018 09:56
-
Moin,
ich muss meinen Vorrednern aufs Vehementeste in dem Punkt zustimmen, dass eine Remote-Pull-Abfrage nicht optimal ist. Mein Favorit wäre in dem Fall die Software-Verteilung (SCCM kann übrigens von Hause aus Dateien inventarisieren, vermutlich können die Konkurrenzprodukte das auch).
Wenn es aber remote sein soll, wäre ich für so etwas wie
$comps = (Get-ADComputer -Filter <Filter Deiner Wahl>).DNSHostName $sessions = New-CIMSession -ComputerName $comps $sess = New-CIMSession -ComputerName localhost Get-CIMInstance CIM_DataFile -Filter "(Drive='C:') AND (Path LIKE '\\Users\\%) AND (FileName='MobaXTerm') AND (Extension='ini')" -CIMSession $sessions | ft Name, PSComputerName
Da wird die Suche immerhin lokal durch den CIM-Provider ausgeführt.
Evgenij Smirnov
I work @ msg services ag, Berlin -> http://www.msg-services.de
I blog (in German) @ http://it-pro-berlin.de
my stuff in PSGallery --> https://www.powershellgallery.com/profiles/it-pro-berlin.de/
Exchange User Group, Berlin -> https://exusg.de
Windows Server User Group, Berlin -> http://www.winsvr-berlin.de
Mark Minasi Technical Forum, reloaded -> http://newforum.minasi.com
In theory, there is no difference between theory and practice. In practice, there is.
- Bearbeitet Evgenij Smirnov Dienstag, 31. Juli 2018 21:10 Dutzende Typos, ich muss ins Bett...
- Als Antwort vorgeschlagen Denniver ReiningMVP, Moderator Donnerstag, 9. August 2018 09:55
- Als Antwort markiert Denniver ReiningMVP, Moderator Donnerstag, 9. August 2018 09:56
-
Deswegen die Codezeile
$Username = ($computer.Split("-"))[1]
um den Usernamen vom Computernamen zu trennen.
omg :-))
Der Username wird gebraucht um auf das jeweilige Windows User Profil Verzeichniss zuzugreifen um eine bestimmte Datei MobaXterm.ini zu finden.
Warum? Steck die Suche in ein Logonskript, das unterhalb von %userprofile% bei der Anmeldung des Benutzers sucht. Das zeigt dann auch immer auf das richtige Verzeichnis. Und das Ergebnis speicherst auf einem Netzwerkshare...
Viel einfacher, schneller und robuster als die Remote-Lösung von Dir.
Oder mach's als Computerstartskript, das alle lokalen Profilverzeichnisse durchsucht (Registry -> ProfileList, da steht der Pfad aller vorhandenen Profile drin...).
Guten Morgen,
an das Logonskript hab ich auch schon gedacht. Leider sind das maschinen die rund um die Uhr laufen und sich User nicht einfach an und abmelden. Reboots erfolgen nur bei Windows Updates alle paar Wochen....
Ich brauche aber eine schnelle Lösung.
-
Moin,
ich muss meinen Vorrednern aufs Vehementeste in dem Punkt zustimmen, dass eine Remote-Pull-Abfrage nicht optimal ist. Mein Favorit wäre in dem Fall die Software-Verteilung (SCCM kann übrigens von Hause aus Dateien inventarisieren, vermutlich können die Konkurrenzprodukte das auch).
Wenn es aber remote sein soll, wäre ich für so etwas wie
$comps = (Get-ADComputer -Filter <Filter Deiner Wahl>).DNSHostName $sessions = New-CIMSession -ComputerName $comps $sess = New-CIMSession -ComputerName localhost Get-CIMInstance CIM_DataFile -Filter "(Drive='C:') AND (Path LIKE '\\Users\\%) AND (FileName='MobaXTerm') AND (Extension='ini')" -CIMSession $sessions | ft Name, PSComputerName
Da wird die Suche immerhin lokal durch den CIM-Provider ausgeführt.
Evgenij Smirnov
I work @ msg services ag, Berlin -> http://www.msg-services.de
I blog (in German) @ http://it-pro-berlin.de
my stuff in PSGallery --> https://www.powershellgallery.com/profiles/it-pro-berlin.de/
Exchange User Group, Berlin -> https://exusg.de
Windows Server User Group, Berlin -> http://www.winsvr-berlin.de
Mark Minasi Technical Forum, reloaded -> http://newforum.minasi.com
In theory, there is no difference between theory and practice. In practice, there is.
-
Danke, ich werde es ausprobieren...
...aber bitte nicht gleich gegen alle ;-)Evgenij Smirnov
I work @ msg services ag, Berlin -> http://www.msg-services.de
I blog (in German) @ http://it-pro-berlin.de
my stuff in PSGallery --> https://www.powershellgallery.com/profiles/it-pro-berlin.de/
Exchange User Group, Berlin -> https://exusg.de
Windows Server User Group, Berlin -> http://www.winsvr-berlin.de
Mark Minasi Technical Forum, reloaded -> http://newforum.minasi.com
In theory, there is no difference between theory and practice. In practice, there is.
-
...aber bitte nicht gleich gegen alle ;-)
Kohschn iz ze mazer ov ze porselin kräht
Schisser! ;-) :-D
Evgenij Smirnov
I work @ msg services ag, Berlin -> http://www.msg-services.de
I blog (in German) @ http://it-pro-berlin.de
my stuff in PSGallery --> https://www.powershellgallery.com/profiles/it-pro-berlin.de/
Exchange User Group, Berlin -> https://exusg.de
Windows Server User Group, Berlin -> http://www.winsvr-berlin.de
Mark Minasi Technical Forum, reloaded -> http://newforum.minasi.com
In theory, there is no difference between theory and practice. In practice, there is.