lord.joao
Goto Top

Get-Content : Der Pfad "C." kann nicht gefunden werden, da er nicht vorhanden ist

Guten Tag zusammen,

für ein Programm welches in Powershell parallele Verarbeitung von IP-Verfügbarkeiten überorüfen soll habe ich nach wochenlangem erfolglosen scripttesting, folgenden Code aus Github entdeckt.
Nun existiert beim Aufrufen eines Pfades der Pfad scheinbar nicht.
Hat dazu jemand eine Idee was ich falsch mach?


Script:
#Prompting the user to enter a text file path where a list of computers are located
$computerFile = Read-Host "Enter the path to a text file where the list of comptuers is located. i.e. c:\temp\computer.txt"  

#Grabbing a list of computer names from a text file
$computerName = Get-Content $computerFile

#Setting up a max thread count
$threadCount = 2

#ForEach loop that will loop through a list of computers 
ForEach ($computer in $computerName) {

#This script block stores a list of commands that you want to perform. This is not just limited to a simple ping that I am demonstrating. 
$scriptBlock = {

        #parameter that you are receiving from outside the scriptblock will be stored here 
        param ($computerToPing)
        #Error handling Try/Catch Statement 
        Try {
        #Testing the connection to a computer or website quitely so it only stores a True or False statement
        $testComputerPing = Test-Connection -ComputerName $computerToPing -Count 1 -Quiet

        #condition if statment that will perform a action if the condition is true 
        if ($testComputerPing -eq 'True') {  
            Write-Host "$computerToPing ping status is true" -ForegroundColor Green -BackgroundColor Black  
        
        }
        #if the condition isnt true it will let you know that it failed
        else {Write-Host "$computerToPing ping timed out" -ForegroundColor Red -BackgroundColor Black}  
        } 
        #by some happenstance that there is a unknown error in this simple script, it will be caught here and gracefully fail
        Catch { Write-Host "$computerToPing failed with error $_.ExceptionMessage" }  
}

       #Starting a background job to run the commands in the scriptblock that you identified earlier and we are out-null this command to free up space in the console
       Start-Job -ScriptBlock $scriptBlock -ArgumentList $computer | Out-Null

       #while loop that will throttle the background jobs to not exceed the amount that you specified in $threadCount
       while($(Get-Job -State 'Running').Count -ge $threadCount)  
       {
            Get-Job | Wait-Job | Out-Null
       }
       #Auto removes jobs that are marked complete
       Get-Job -State Completed | % {
            Receive-Job $_ -AutoRemoveJob -Wait
       }
}
#While loop that will wait until the remaining jobs are finished
While ($(Get-Job -State Running).Count -gt 0) {
   Get-Job | Wait-Job -Any | Out-Null
}
#once all the jobs are complete then all remaining jobs will be removed. 
Get-Job -State Completed | % {
   Receive-Job $_ -AutoRemoveJob -Wait
}computerToPing

Error:
Get-Content : Der Pfad "C:\Users\admin\devices" kann nicht gefunden werden, da er nicht vorhanden ist.  
In Zeile:5 Zeichen:17
+ $computerName = Get-Content $computerFile
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\Users\admin\devices:String) [Get-Content], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand
 
ForEach-Object : Der Parameter "RemainingScripts" kann nicht gebunden werden. Der Wert "computerToPing" vom Typ "System.String" kann nicht in den Typ   
"System.Management.Automation.ScriptBlock" konvertiert werden.  
In Zeile:55 Zeichen:2
+ }computerToPing
+  ~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [ForEach-Object], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.ForEachObjectCommand


Fakt: Den Pfad gibt es, hab sogar mit change directory und oder Komplettpfad oder nur der Dateiangabe gearbeitet.

Content-Key: 667218

Url: https://administrator.de/contentid/667218

Printed on: April 19, 2024 at 06:04 o'clock

Member: Doskias
Doskias Jun 01, 2021 updated at 08:11:15 (UTC)
Goto Top
Naja... So wie ich das lese... Im Skript steht:

#Prompting the user to enter a text file path where a list of computers are located
$computerFile = Read-Host "Enter the path to a text file where the list of comptuers is located. i.e. c:\temp\computer.txt"

#Grabbing a list of computer names from a text file
$computerName = Get-Content $computerFile

Deine Fehlermeldung sagt, dass der Pfad nicht gefunden werden konnte. ich kann jetzt nur raten, was du beim Read-Host Befehl in Zeile 2 eingegeben hast, aber für mich sieht es so aus, als hättest du einen Pfad eingegeben. Erwartet wird jedoch wie in der Beschreibung steht der Pfad zu einer Text-Datei.

Im übrigen kannst du auch Einfach den read-host-Befehl durch den Pfad zu deiner TXT-Datei ersetzen.
Member: colinardo
colinardo Jun 01, 2021 updated at 20:28:44 (UTC)
Goto Top
Servus @Lord.Joao, willkommen auf Administrator.de!
Zitat von @Lord.Joao:
für ein Programm welches in Powershell parallele Verarbeitung von IP-Verfügbarkeiten überorüfen soll habe ich nach wochenlangem erfolglosen scripttesting, folgenden Code aus Github entdeckt.
Powershell-Jobs sind ehrlich gesagt super lahm weil deren Erstellung sehr lange dauert, außerdem ist Test-Connection diesbezüglich auch nicht so effizient, mach es besser gleich mittels Runspace-Pool, MultiThreading und Ping, das rennt dann erst richtig!

Hier meine Funktion dafür
<#
    Ping mass huge amount of hosts in parallel multithreading
#>

function Parallel-Ping {
    [CmdletBinding()]
    param(
        [parameter(mandatory=$true)][ValidateNotNullOrEmpty()][string[]]$hosts,
        [parameter(mandatory=$false)][ValidateNotNullOrEmpty()][int]$timeout = 2000,
        [parameter(mandatory=$false)][ValidateNotNullOrEmpty()][ValidateRange(1,255)][int]$ttl = 128,
        [parameter(mandatory=$false)][ValidateNotNullOrEmpty()][bool]$DontFragment = $false,
        [parameter(mandatory=$false)][ValidateNotNullOrEmpty()][byte[]]$data = ([byte[]]0),
        [parameter(mandatory=$false)][ValidateNotNullOrEmpty()][int]$MaxConcurrent = [System.Environment]::ProcessorCount,
        [parameter(mandatory=$false)][switch]$showprogress
    )
    begin{
        $rspool = [runspacefactory]::CreateRunspacePool(1,$MaxConcurrent)
        $rspool.ApartmentState = 'STA'  
        $rspool.Open()
        $jobs = New-Object System.Collections.ArrayList
    }
    process{
        foreach ($hostname in $hosts){
            $ps = [Powershell]::Create()
            $ps.RunspacePool = $rspool
            [void]$ps.AddScript({
                param($hostname,$timeout,$ttl,$DontFragment,$data)
                $result = [ordered]@{Host=$hostname;Address=$null;Status=[System.Net.NetworkInformation.IPStatus]::Unknown;RoundtripTime = -1;TTL=$ttl;DontFragment=$DontFragment;ResponseBuffer='';Time=(get-date)}  
                $ping = New-Object System.Net.NetworkInformation.Ping
                try{
                    $reply = $ping.Send($hostname,$timeout,$data,(New-Object System.Net.NetworkInformation.PingOptions($ttl,$DontFragment)))
                    $result.RoundtripTime = $reply.RoundtripTime
                    $result.Status = $reply.Status
                    $result.Address = $reply.Address
                    $result.ResponseBuffer = $reply.Buffer
                }catch [System.Net.NetworkInformation.PingException] {
                    $result.Status = [System.Net.NetworkInformation.IPStatus]::DestinationHostUnreachable
                }finally{
                    $ping.Dispose()
                }
                [pscustomobject]$result
            }).AddParameters(@($hostname,$timeout,$ttl,$DontFragment,$data))
            $job = $ps.BeginInvoke()
            [void]$jobs.Add(([pscustomobject]@{Handle = $job; Powershell = $ps}))
        }
    }
    end{
        write-verbose "Waiting for all jobs to complete."  
        while(($jobs | ?{!$_.Handle.IsCompleted})){
            if ($showprogress.IsPresent){
                $completed = ($jobs | ?{$_.Handle.IsCompleted}).Count
                Write-Progress -Activity $PSCmdlet.MyInvocation.InvocationName -Status "Pinging a total of $($hosts.Count) hosts." -PercentComplete (($completed / $hosts.Count) * 100) -CurrentOperation "Completed $completed from $($hosts.Count)."  
            }
        }
        # get results of jobs
        $results = $jobs | %{
            $_.Powershell.EndInvoke($_.handle)
            $_.Powershell.Dispose()
        }
        # cleanup
        $rspool.Close();$rspool.Dispose()
        $results
    }
}

Parallel-Ping -hosts (1..254 | %{"192.168.1.$_"}) -timeout 500 -MaxConcurrent 10 -showprogress | ogv  
Für den Parameter Hosts kannst du eine beliebiges Array nutzen, im Beispiel generiere ich hier alle Hosts eines 24er Subnets.
Stattdessen kannst du auch Hosts aus einer Datei laden
 Parallel-Ping -hosts (gc 'D:\hosts.txt') -timeout 500 -MaxConcurrent 10 -showprogress | ogv  
Damit scannst du wenn du willst ein ganzes Subnetz in Bruchteilen einer Sekunde wenn entsprechende Parameter genutzt werden.

Nun existiert beim Aufrufen eines Pfades der Pfad scheinbar nicht.
Hat dazu jemand eine Idee was ich falsch mach?
Doskias hat es schon erwähnt, du gibst statt einer erwarteten Textdatei nur einen Ordner-Pfad an und Get-Content kann nunmal keine Pfade "auslesen" sondern nur Dateiinhalte face-smile

Grüße Uwe
Member: Lord.Joao
Lord.Joao Jun 01, 2021 at 18:11:01 (UTC)
Goto Top
Hallo @colinardo und danke. face-smile

danke für die Antwort.
Beim Ausführen deines Skripts gab es unter den 256 Hosts keine ereichbare Adresse. Ist das so gewollt?
Einige Adressen die unter meinem Netz laufen sollten eigentlich erreichbar sein.

Grüße Joao
Member: colinardo
Solution colinardo Jun 01, 2021, updated at Jun 02, 2021 at 09:10:00 (UTC)
Goto Top
Beim Ausführen deines Skripts gab es unter den 256 Hosts keine ereichbare Adresse. Ist das so gewollt?
Du musst das Subnetz natürlich an deines anpassen. Wenn die Hosts länger als 500ms brauchen um zu antworten musst du zusätzlich den Timeout Parameter an deine Situation anpassen. Je nach vorhandener CPU-Kernanzahl den MaxConcurrent Parameter modifizieren.
Zusätzlich gilt natürlich zu beachten das nicht jeder Host auf ICMP Pakete auch antworten muss (z.B. wegen Firewalls)! Windows Büchsen tun das per Default auch nur, wenn man sie aus dem selben Subnetz aus an pingt, außer man hat die Firewall entsprechend angepasst.

screenshot
Member: Lord.Joao
Lord.Joao Jun 02, 2021 at 16:43:56 (UTC)
Goto Top
Vielen Danke, damit kann ich verfahren.

Grüße