none
Script zur Remoteabfrage der Macadressen RRS feed

  • Frage

  • Da ich ein Anfänger im Bereich der Powershell bin, bitte ich um Hilfe bei der Lösung meines Problems.

    Ziel der ganzen Sache ist eine Automation mithilfe von Powershell und geplanten Task, so dass Clientcomputer im Unternehmen zu einer bestimmten Zeit gestartet und dann auch wieder heruntergefahren werden. Für den Virenscan wurden ansonsten alle Computer angelassen, jedoch ist dies unpraktisch und wenn vergessen wird den PC nicht Auszuschalten dann wurde auch nicht gescannt.

    Plan: Ein Script liest aus dem AD die Computer einer bestimmten Gruppe aus und führt für jeden den GetMac Befehl aus. Der Computername ist dabei der Name der Textdatei, mit Inhalt der Macadresse. Für jeden Computer einzeln gespeichert.

    Nun hab ich aber das Problem, dass es in der normalen Powershell funkioniert die Mac per

    getmac /S "Servername" /U domäne\admin /P passwort

    abzurufen.

    Im Script auf dem AD-Domänencontroller jedoch nicht.

    import-module activedirectory 
    $i = 0;
    
    $maccomputer = Get-ADGroupMember DomänenComputer | select-object Name
    
    foreach ($adgroupmember in $maccomputer)
    {
    
    $inhaltmac = Get-Content \\XXXX\XXXX\IT\Intern\maclist\"$adgroupmember".txt
    #$pcname = gc env:computername
    $mac = getmac /S "$adgroupmember" /U XXX\XXXX /P XXXXX | %{
        $i +=1;
        if($_ -match "([^ ]+)"){ 
            if($i -gt 3){
                 $matches[1] | ? {$_ -ne "nicht"}
            }
        }
    }
    if ($inhaltmac -ne $mac)
    {
    $mac | out-file \\XXXXX\XXXXX\IT\Intern\maclist\"$adgroupmember".txt -Force
    }
    }
    

    Donnerstag, 10. April 2014 11:18

Antworten

  • RPC Server nicht Verfügbar..... 

    Diese Meldung heisst nur, dass der Rechner nicht erreichbar ist....

    da ist es natürlich immer ein richtiger Spass den Fehler zu finden. :-(

    1. Wenn du den folgenden Befehl ausführst bekommst du die gewünschte Liste mit Rechnernamen?

    Get-ADGroupMember DomänenComputer | select-object Name

    2. Wenn ein Rechner nicht eingeschaltet ist dann bekommst du natürlich die Meldung RPC Server!!!

    Hier sollte der Rechner Vorher Angepingt werden, dazu benutzt man in PowerShell das Komando Test-Connection.

    # Nur 1 Ping senden und dann $True = Online oder $False = Offline
    If(Test-Connection -ComputerName Localhost -Count 1 -Quiet) {
        # Rechner ist Online und Pigbar
    
        # mach was mit dem Rechner hier......
    
    }


    3. Nutze beim Select-Object den Parameter -ExpandProperty


    PowerShell erzeugt und verarbeitet Objekte!

    Mach dich mit Objekten in PowerShell vertraut!
    Was meinst du warum so viele Befehle in der PowerShell mit xxx-Object enden?

    Compare-Object
    ForEach-Object
    Group-Object
    Measure-Object
    New-Object
    Select-Object
    Sort-Object
    Tee-Object
    Where-Object

    Objekte sind Behälter die einen Bestimmten Typ haben.
    Objekte enthalten Daten und Methoden.

    Wenn man Select-Object so einsetzt wie du, dann nimmt Select-Object den GroupMember der Gruppe als Objekt und schneidet aus dem Objekt den Namen heraus.
    Aus diesem Namen wird ein neues Objekt erzeugt.

    Select-Objekt kann man sich ungefähr so vorstellen.....

    Get-ADGroupMember ist ein Lieferant, der ganz viele Schweine Anliefert. Select-Objekt ist der Metzger der die Schweine in Ihre Bestandteile zerlegen kann.
    Nach dem du Select-Objekt benutzt hast, ist dann kein Objekt mit dem Typ Schwein mehr in der Pipeline, sondern nur noch Objekte mit dem Typ Schnitzel, Eisbein oder Schinken (je nachdem was man auswählt).

    Dein Einkaufskorb mit dem du aus der Metzgerei heraus gehst, ist dein neues Objekt, das du von Select-Object bekommst!!!!

    In deinem Objekt-Einkaufkorb, kannst aus der Metzgerei kannst du VERSCHIEDENE Sachen einpacken, dadurch das man Select-Object eine Einkaufsliste mitgibt.

    AUCH WENN DU NUR EIN BESTIMMTES ATTRIBUT HABEN WILLST, DU BEKOMMST EIN PS-OBJEKT ZURÜCK !!!

    Siehe Beispiel mit Get-ChildItem:

    # dieser Befehl zeigt alle Daten an, die ein Objekt vom Typ Folder bietet
    # es wird ein neues Objekt mit dem Typ PSObject erstellt das nur noch die Daten enthält!
    # Methoden die das Objekt besaß, werden weggeschmissen!!!!!!
    Get-ChildItem | Where-Object { $_.PSIsContainer-eq'true'} | Select-Object *
    
    # dieser Befehl filetiert nur gewünschte Daten aus dem Objekt mit dem Typ Folder heraus
    # es wird ein neues Objekt mit dem Typ PSObject erstellt das die Daten enthält
    # Daten ala carte...
    Get-ChildItem | Where-Object { $_.PSIsContainer-eq'true'} | Select-Object FullName,CreationTime,Mode
    
    # dieser Befehl filetiert nur das gewünschte Property aus dem Objekt mit dem Typ Folder heraus
    # es wird ein neues Objekt mit dem Typ PSObject erstellt das die Daten enthält
    # Daten ala carte...
    Get-ChildItem | Where-Object { $_.PSIsContainer-eq'true'} | Select-Object Name
    
    # mit dem Parameter -ExpandProperty bekommt man nicht ein neues Objekt zurück,
    # sondern man bekommt den Daten Inhalt des Properties !!!
    Get-ChildItem | Where-Object { $_.PSIsContainer-eq'true'} | Select-Object -ExpandProperty Name


    Dein Befehl müsste also so aussehen wie die letzte Zeile.

    Es lohnt sich die Dokumentation zu Select-Objekt und zu jedem anderen PowerShell Cmdlet zu lesen!

    Get-Help Select-Object

    oder:

    http://www.colorconsole.de/PS_Windows/de/Select-Object.htm

    Man kann auch Daten von einem Objekt abrufen, in dem man den Punkt als Pfadangabe zu den Daten in dem Objekt benutzt.

    $Object.Name

    Oder

    $Object.MacAddress

    Diese Technik nutze ich hier im folgenden (ungetestet!!):

    Import-Module ActiveDirectory 
    
    # Pfad zum Logfile
    $LogFilePath = '\\XXXXX\XXXXX\IT\Intern\maclist\Get_MAC_Logfile.txt'
    
    # Ordner wo die MAC-Text-Dateien liegen sollen
    $MacFolder = '\\XXXXX\XXXXX\IT\Intern\maclist'
    
    
     # Datum zu begin ins Logfile Schreiben
     "Logfile Daten vom: $(Get-Date)" | Out-File -FilePath $LogFilePath -Append -Force
    
    
    # für jeden Computer in der Gruppe DomänenComputer einen Code ausführen
    Get-ADGroupMember DomänenComputer | Select-Object Name {
        
        # in der Automatisch generierten Varaiable mit dem Namen $_ steckt das Aktuelle Objekt 
        $AdgroupMemberName = $_.Name
    
        # Nur 1 Ping senden und dann $True = Online oder $False = Offline
        If(Test-Connection -ComputerName $Name -Count 1 -Quiet) {
            # Rechner ist Online und Pingbar
    
            # Versuche MAC Adresse(n) auszulesen
            Try {
                $Macs = Get-WmiObject -Query "Select MACAddress FROM Win32_NetworkAdapterConfiguration Where IpEnabled='True'" -ErrorAction Stop | Select-Object -ExpandProperty MACAddress
            } Catch {
                # Fehler abfangen wenn einer auftritt beim auslesen der MAC
                
                
                # Logfile Schreiben
                "Error beim auslesen der MAC: $($_.Tostring())" | Out-File -FilePath $LogFilePath -Append -Force 
            }
                    
            ForEach($Mac In $Macs) {
                $mac | Out-File (Join-Path $MacFolder "$AdgroupMemberName.txt" ) -Force
            }
    
            # Meldung am Bildschirm ausgeben
            Write-Host "Folgender Computer wurde Erreicht: $Name" -ForegroundColor Green
             
            # Logfile Schreiben
            "Folgender Computer wurde Erreicht: $Name" | Out-File -FilePath $LogFilePath -Append -Force
    
        } Else {
            # Computer nicht erreircht
            # Warnung am Bildschirm ausgeben
            Write-Warning "Folgender Computer konnte nicht gepingt werden: $Name"
            
            # Logfile Schreiben
            "Folgender Computer konnte nicht gepingt werden: $Name" | Out-File -FilePath $LogFilePath -Append -Force
        }
    
    }

    In PowerShell gibt es 2 Verschiedene ForEach Konstrukte!!

    siehe: http://www.admin-source.de/BlogDeu/905/powershell-foreach-und-foreach-object


    PowerShell Artikel, Buchtipps und kostenlose PowerShell Tutorials + E-Books
    auf der deutschsprachigen PowerShell Community

    Mein 21 Teiliger PowerShell Video Grundlehrgang
    Deutsche PowerShell Videos auf Youtube
    Folge mir auf:
    Twitter | Facebook | Google+


    Freitag, 11. April 2014 14:06

Alle Antworten

  • Hallo Christian!

    Getmac ist ein DOS Befehl der nur ein haufen von Text auswirft.
    Das herauspopeln von Daten aus Text durh das Parsen, ist schwer und fehleranfällig.
    Deshalb erzeugt und verarbeitet PowerShell Objekte.

    Versuch es mal mit folgender Zeile. Diese erzeugt einen Strukturierten CSV Text den PowerShell besser versteht.

     $mac = getmac /S $_ /FO CSV /U XXX\XXXX /P XXXXX | ConvertFrom-Csv | Select-Object -ExpandProperty Phy* | ForEach-Object {
       #...Code...       
     }

    Wenn das nicht geht, empfehle ich dir mit WMI und der Klasse "Win32_NetworkAdapterConfiguration" zu Arbeiten.

    Diese Klasse bietet dir sehr viele Daten von den Netzwerkkarten:

    get-wmiobject -class "Win32_NetworkAdapterConfiguration" |Where{$_.IpEnabled -Match "True"} | select *

    Unter anderem auch die MAC:

    get-wmiobject -class "Win32_NetworkAdapterConfiguration" |Where{$_.IpEnabled -Match "True"} | select MACAddress

    # oder besser:

    Get-WmiObject -Query "Select MACAddress FROM Win32_NetworkAdapterConfiguration Where IpEnabled='True'" | Select-Object -ExpandProperty MACAddress



    PowerShell Artikel, Buchtipps und kostenlose PowerShell Tutorials + E-Books
    auf der deutschsprachigen PowerShell Community

    Mein 21 Teiliger PowerShell Video Grundlehrgang
    Deutsche PowerShell Videos auf Youtube
    Folge mir auf:
    Twitter | Facebook | Google+

    Donnerstag, 10. April 2014 15:42
  • vielen Dank, das ist wirklich um längen leichter zu verstehen.

    Nun habe ich jedoch ein Problem, etwas weiter oben im Kontext. Er zeigt mir an, dass der RPC-Server nicht verfügbar ist. Was meiner meinung nach darauf zurückzuführen ist, das die Variable "adcomputer" nicht nur den namen eines computers sondern auch noch das name = "name" enthält. weiterhin ist es es so, dass der Get-WmiObject-Befehl mit einem festen wert als Computer, also:

    Get-WmiObject -computer holzmichelspc -Query "Select MACAddress FROM Win32_NetworkAdapterConfiguration Where IpEnabled='True'" | Select-Object -ExpandProperty MACAddres

    funkioniert. Jedoch wiederrum im Script nicht. Firewall und IPv6 wurden als Fehlerquellen schon ausgeschlossen.

    $adcomputers = Get-ADGroupMember DomänenComputer | select-object Name

    nicht wundern, dass es nun andere Variablen sind, es wurde alles neu strukturiert.

    Freitag, 11. April 2014 12:20
  • RPC Server nicht Verfügbar..... 

    Diese Meldung heisst nur, dass der Rechner nicht erreichbar ist....

    da ist es natürlich immer ein richtiger Spass den Fehler zu finden. :-(

    1. Wenn du den folgenden Befehl ausführst bekommst du die gewünschte Liste mit Rechnernamen?

    Get-ADGroupMember DomänenComputer | select-object Name

    2. Wenn ein Rechner nicht eingeschaltet ist dann bekommst du natürlich die Meldung RPC Server!!!

    Hier sollte der Rechner Vorher Angepingt werden, dazu benutzt man in PowerShell das Komando Test-Connection.

    # Nur 1 Ping senden und dann $True = Online oder $False = Offline
    If(Test-Connection -ComputerName Localhost -Count 1 -Quiet) {
        # Rechner ist Online und Pigbar
    
        # mach was mit dem Rechner hier......
    
    }


    3. Nutze beim Select-Object den Parameter -ExpandProperty


    PowerShell erzeugt und verarbeitet Objekte!

    Mach dich mit Objekten in PowerShell vertraut!
    Was meinst du warum so viele Befehle in der PowerShell mit xxx-Object enden?

    Compare-Object
    ForEach-Object
    Group-Object
    Measure-Object
    New-Object
    Select-Object
    Sort-Object
    Tee-Object
    Where-Object

    Objekte sind Behälter die einen Bestimmten Typ haben.
    Objekte enthalten Daten und Methoden.

    Wenn man Select-Object so einsetzt wie du, dann nimmt Select-Object den GroupMember der Gruppe als Objekt und schneidet aus dem Objekt den Namen heraus.
    Aus diesem Namen wird ein neues Objekt erzeugt.

    Select-Objekt kann man sich ungefähr so vorstellen.....

    Get-ADGroupMember ist ein Lieferant, der ganz viele Schweine Anliefert. Select-Objekt ist der Metzger der die Schweine in Ihre Bestandteile zerlegen kann.
    Nach dem du Select-Objekt benutzt hast, ist dann kein Objekt mit dem Typ Schwein mehr in der Pipeline, sondern nur noch Objekte mit dem Typ Schnitzel, Eisbein oder Schinken (je nachdem was man auswählt).

    Dein Einkaufskorb mit dem du aus der Metzgerei heraus gehst, ist dein neues Objekt, das du von Select-Object bekommst!!!!

    In deinem Objekt-Einkaufkorb, kannst aus der Metzgerei kannst du VERSCHIEDENE Sachen einpacken, dadurch das man Select-Object eine Einkaufsliste mitgibt.

    AUCH WENN DU NUR EIN BESTIMMTES ATTRIBUT HABEN WILLST, DU BEKOMMST EIN PS-OBJEKT ZURÜCK !!!

    Siehe Beispiel mit Get-ChildItem:

    # dieser Befehl zeigt alle Daten an, die ein Objekt vom Typ Folder bietet
    # es wird ein neues Objekt mit dem Typ PSObject erstellt das nur noch die Daten enthält!
    # Methoden die das Objekt besaß, werden weggeschmissen!!!!!!
    Get-ChildItem | Where-Object { $_.PSIsContainer-eq'true'} | Select-Object *
    
    # dieser Befehl filetiert nur gewünschte Daten aus dem Objekt mit dem Typ Folder heraus
    # es wird ein neues Objekt mit dem Typ PSObject erstellt das die Daten enthält
    # Daten ala carte...
    Get-ChildItem | Where-Object { $_.PSIsContainer-eq'true'} | Select-Object FullName,CreationTime,Mode
    
    # dieser Befehl filetiert nur das gewünschte Property aus dem Objekt mit dem Typ Folder heraus
    # es wird ein neues Objekt mit dem Typ PSObject erstellt das die Daten enthält
    # Daten ala carte...
    Get-ChildItem | Where-Object { $_.PSIsContainer-eq'true'} | Select-Object Name
    
    # mit dem Parameter -ExpandProperty bekommt man nicht ein neues Objekt zurück,
    # sondern man bekommt den Daten Inhalt des Properties !!!
    Get-ChildItem | Where-Object { $_.PSIsContainer-eq'true'} | Select-Object -ExpandProperty Name


    Dein Befehl müsste also so aussehen wie die letzte Zeile.

    Es lohnt sich die Dokumentation zu Select-Objekt und zu jedem anderen PowerShell Cmdlet zu lesen!

    Get-Help Select-Object

    oder:

    http://www.colorconsole.de/PS_Windows/de/Select-Object.htm

    Man kann auch Daten von einem Objekt abrufen, in dem man den Punkt als Pfadangabe zu den Daten in dem Objekt benutzt.

    $Object.Name

    Oder

    $Object.MacAddress

    Diese Technik nutze ich hier im folgenden (ungetestet!!):

    Import-Module ActiveDirectory 
    
    # Pfad zum Logfile
    $LogFilePath = '\\XXXXX\XXXXX\IT\Intern\maclist\Get_MAC_Logfile.txt'
    
    # Ordner wo die MAC-Text-Dateien liegen sollen
    $MacFolder = '\\XXXXX\XXXXX\IT\Intern\maclist'
    
    
     # Datum zu begin ins Logfile Schreiben
     "Logfile Daten vom: $(Get-Date)" | Out-File -FilePath $LogFilePath -Append -Force
    
    
    # für jeden Computer in der Gruppe DomänenComputer einen Code ausführen
    Get-ADGroupMember DomänenComputer | Select-Object Name {
        
        # in der Automatisch generierten Varaiable mit dem Namen $_ steckt das Aktuelle Objekt 
        $AdgroupMemberName = $_.Name
    
        # Nur 1 Ping senden und dann $True = Online oder $False = Offline
        If(Test-Connection -ComputerName $Name -Count 1 -Quiet) {
            # Rechner ist Online und Pingbar
    
            # Versuche MAC Adresse(n) auszulesen
            Try {
                $Macs = Get-WmiObject -Query "Select MACAddress FROM Win32_NetworkAdapterConfiguration Where IpEnabled='True'" -ErrorAction Stop | Select-Object -ExpandProperty MACAddress
            } Catch {
                # Fehler abfangen wenn einer auftritt beim auslesen der MAC
                
                
                # Logfile Schreiben
                "Error beim auslesen der MAC: $($_.Tostring())" | Out-File -FilePath $LogFilePath -Append -Force 
            }
                    
            ForEach($Mac In $Macs) {
                $mac | Out-File (Join-Path $MacFolder "$AdgroupMemberName.txt" ) -Force
            }
    
            # Meldung am Bildschirm ausgeben
            Write-Host "Folgender Computer wurde Erreicht: $Name" -ForegroundColor Green
             
            # Logfile Schreiben
            "Folgender Computer wurde Erreicht: $Name" | Out-File -FilePath $LogFilePath -Append -Force
    
        } Else {
            # Computer nicht erreircht
            # Warnung am Bildschirm ausgeben
            Write-Warning "Folgender Computer konnte nicht gepingt werden: $Name"
            
            # Logfile Schreiben
            "Folgender Computer konnte nicht gepingt werden: $Name" | Out-File -FilePath $LogFilePath -Append -Force
        }
    
    }

    In PowerShell gibt es 2 Verschiedene ForEach Konstrukte!!

    siehe: http://www.admin-source.de/BlogDeu/905/powershell-foreach-und-foreach-object


    PowerShell Artikel, Buchtipps und kostenlose PowerShell Tutorials + E-Books
    auf der deutschsprachigen PowerShell Community

    Mein 21 Teiliger PowerShell Video Grundlehrgang
    Deutsche PowerShell Videos auf Youtube
    Folge mir auf:
    Twitter | Facebook | Google+


    Freitag, 11. April 2014 14:06