Jump to content

MurdocX

Moderators
  • Gesamte Inhalte

    2.745
  • Registriert seit

  • Letzter Besuch

Beiträge erstellt von MurdocX

  1. Hallo, ich habe anhand von mittlerweile 2 verschiedenen Scripts versucht, die LastLogon-Zeit auszulesen. Bei jedem Script bekomme ich andere Ergebnisse und keins der beiden stimmt mit dem Ergebnis im AD überein. Wo liegt der Fehler (es handelt sich um 1-2 Jahre Differenz. Die Replizierung ist auf 15 Minuten gestellt.

     

    PS: bin noch nicht so ganz in der Materie.

     

    Kleiner Tipp: Arbeite an deiner Code-Lesbarkeit!

    • Nicht für alles leere Zeilen einfügen
    • Zusammenhängende Aufgaben gruppieren

    Ich habe mal versucht herauszulesen was du benötigst... Und dich in allen Bereichen zu verbessern, würde mich und Dich eine Ewigkeit kosten. So habe ich eine kleinere Variante gewählt und ein Skript verfasst. Alle kann ich nicht mit fertigen Skripts versorgen. Nimm dies als Vorlage und vergleiche es mit deinem Skript, um daraus zu lernen was bei deinem Skript falsch oder nicht optimal gelaufen / programmiert ist. 

     

     

    <#
        Autor: Jan Weis
        Homepage: www.it-explorations.de
    #>
    
    #
    # Custom Variable
    #
    
    [Int]$intInaktiveDays = 100 # Keine Anmeldung seit ... Tagen ab heute
    
    #
    # Script Variables
    #
    
    $objDateToday = Get-Date
    $objDateCriticalDate = $objDateToday.AddDays(-$intInaktiveDays)
    $strCriticalDate = $objDateCriticalDate.ToShortDateString().ToString()
    
    #
    # Script
    #
    
    Write-Host ':: Auslesen & Filtern der AD-Benutzer' -ForegroundColor Yellow
    $objADUserList = Get-ADUser -Filter '*' -Properties LastLogonTimestamp,Company | Where-Object { ([DateTime]::FromFileTime($_.LastLogonTimestamp)) -le $objDateCriticalDate -and $_.LastLogonTimestamp -notlike '' }
    
    Write-Host ':: Ausgabe...' -ForegroundColor Yellow
    $objADUserList | Format-Table @{Label='Firma';Expression={$_.Company}},Enabled, @{Label='Kritisches Anmeldedatum'; Expression={$strCriticalDate}}, @{Label='Letzte Anmeldung';Expression={[DateTime]::FromFileTime($_.LastLogonTimestamp)}},Name,SamaccountName 
    
    Write-Host ':: Export zu CSV' -ForegroundColor Yellow
    $objADUserList | Select-Object Company,Enabled,lastlogonTimestamp,Name,SamAccountName | Export-Csv -Delimiter ';' -Path 'C:\Users\XXX\Desktop\Benutzer.csv'
    
    • Like 1
  2. Die Bedingung im if sieht auch nicht so aus, als wenn dort true oder false rauskommen würde.

     

    Vollkommen korrekt. Diese Änderung ist mir Schnelle gar nicht aufgefallen!  :schreck:  In meinen Varianten kam ein "If" auch nicht drin vor. 

     

    Neue Variante....

    $objJavaProgramList = Get-WmiObject -Class Win32_Product | Where-Object {$_.Name -like 'Java*' -and $_.Version -ne '8.0.1010.13'}
    
    ForEach ($objJavaProgramItem in $objJavaProgramList)
    {
        Write-host ":: Entferne $($_.Name), Versionsstand: $($_.Version)"
        $objJavaProgramItem.Uninstall()
        Start-Process -FilePath '\\fileserver\install\Java8u101\jre-8u101-windows-i586.exe' -ArgumentList '/s' -Verb RunAs
    }
    
  3. "Start-Process" ist auch eine Anweisung die direkt ausgeführt wird. Falls das Cmdlet eine Ausgabe (Ergebnis) hat, dann wird diese in die Variable $java_setup abgelegt.

     

    Start-Process - TechNet

    https://technet.microsoft.com/de-de/library/hh849848.aspx

     

    Lass die Variable einfach weg und schreibe das "Start-Process" unter deine Uninstall-Routine

     

    Um der UAC noch genüge zu tun, musst du noch den Parameter "-Verb RunAs" in "Start-Process" mit einbauen. Sonst wird deine Anwendung als Benutzer und nicht als Administrator ausgeführt.

     

    PS: Für zwischen Ausgaben kannst du "Write-Host" benutzen. Bsp:

    Write-Host "Installiere nun..."

  4. Nachdem ich mich weiter schlau gelesen habe, möchte ich noch einen Punkt in die Runde schmeißen... "Workflow"

     

    Wissenswertes

    https://powershell.org/powershell-workflow-when-should-you-use-it/

    https://blogs.technet.microsoft.com/heyscriptingguy/2012/11/22/the-basics-of-windows-powershell-workflow-when-to-use-it-and-why/

     

    Damit kannst du "ForEach"-Schleifen mit dem Argument "parallel" laufen lassen. Das sieht dann in etwa so aus:

    workflow A {
    
      foreach -parallel ($item in $collection)
      {
    
      }
    
    }
    

    Aufgaben werden Parallel ausgeführt und sparen Dir noch mehr Zeit. Vielleicht bekommst du nun deine Auswertungen nun viel schneller. 

  5. Hallo nochmal,

     

    ich dachte, die if else-Bedingungen bekomme ich allein hin, aber leider wird das Setup immer ausgeführt, egal ob eine ältere oder die neueste Java-version drauf installiert ist. Mein bisheriges Script:

    $java_setup = (\\fileserver\install\Java8u101\jre-8u101-windows-i586.exe /s)
    if
    ($objJavaProgramList = Get-WmiObject -Class Win32_Product | Where-Object {$_.Name -like 'Java*' -and $_.Version -ne '8.0.1010.13'})
    {
    ForEach ($objJavaProgramItem in $objJavaProgramList)
        {
        $objJavaProgramItem.Uninstall()
        }
            {    
            $java_setup
            }
    }
    else
    {
    exit
    }
    
    

    Was habe ich nicht verstanden bzw. was mache ich falsch, danke vorab?

     

     

    Ich habe die unnötigen Leerzeilen mal entfernt und strukturiert. Das ist wichtig, damit man den Code im Nachgang auch wieder lesen kann. Das Debugging wird wesentlich erleichtert. Am Besten gleich angewöhnen. Das Ergebnis sieht das so aus: 

    $java_setup = (\\fileserver\install\Java8u101\jre-8u101-windows-i586.exe /s)
    
    
    if ($objJavaProgramList = Get-WmiObject -Class Win32_Product | Where-Object {$_.Name -like 'Java*' -and $_.Version -ne '8.0.1010.13'})
    {
      ForEach ($objJavaProgramItem in $objJavaProgramList)
      {
        $objJavaProgramItem.Uninstall()
      }
      {    
        $java_setup
      }
    }
    else
    {
      exit
    }
    

    Du hast einen Block der keine Funktion besitzt....  { $java_Setup }... Nachdem ForEach mit "}" beendet wurde, macht der Rest keinen Sinn ;-) Setze es einfach unter "....Uninstall()"

     

    In der Powershell solltest du die Programme über "Start-Process" starten, damit die übergebenen Argumente "/s" nicht falsch oder gar nicht interpretiert werden. (Bsp. Start-Process -FilePath -ArgumentList )

  6. Powershell ist eine OO-Programmiersprache mit sehr viel Power, das hast du richtig erkannt. Allerdings ist die Logik dahinter nicht anderst, als bei anderen Sprachen. Kannst du eine, kannst du "quasi" alle. 

     

    Es wäre allgemein sicher von Nützen, wenn du dich mal mit einer Programmiersprache deiner Wahl auseinandersetzt.

     

    Hier hilft auch viel lesen von anderen Skripten und versuchen diese zu verstehen. Am Besten mal in der ISE debuggen und die Variablen nach den einzelnen Vorgängen auslesen. 

  7. Hallo MurdocX,

     

    vielen Dank. Alle Codeschnipsel zu einem Script zusammengefügt scheinen genau das zu machen, was ich möchte. Der Operator -lt war mir gänzlich unbekannt, nun weiß ich, was er bewirkt.

     

    Danke, das freut mich zu hören. Dann ist das damit ja die Lösung ;-)

     

    Worin liegt der Vorteil, den Job an msiexec zu übergeben?

     

    Du könntest noch das ein oder andere Protokollieren. ( Bsp. msiexec.exe /? ) Wenn die Uninstall()-Funktion von dem WMI-Objekt sauber funktioniert, dann würde ich diese auch so einsetzen.

     

    Um auch den Rest der Forum-Benutzer glücklich zu machen, können wir das Ganze noch auf einen "Einzeiler" zusammenkürzen ;-)

    Get-WmiObject -Class Win32_Product | Where-Object { $_.Name -like 'Java*' -and $_.Version -lt '8.0.1010.13' } | ForEach-object { Write-host ":: Entferne $($_.Name), Versionsstand: $($_.Version)"; $_.Uninstall() }
    

     

  8. Hallo,

     

    ich würde die Versionen anhand des Versionseintrag unterscheiden und das ganze nicht so kompliziert machen. 

     

    Hier wird erst mal alles gesammelt was vorhanden ist.  Danach Filtern wir nach allem mit dem Namen "Java" und einer älteren Version als die angegebene.

    $objJavaProgramList = Get-WmiObject -Class Win32_Product | Where-Object {$_.Name -like 'Java*' -and $_.Version -lt '8.0.1010.13'} 
    

    Nun können wir im nächsten Schritt alle gesammelten alten Versionen entfernen. Dies kannst du mit einem ForEach durchführen.

    ForEach ($objJavaProgramItem in $objJavaProgramList)
    {
      $objJavaProgramItem.Uninstall()
    }
    

    Anstatt ".Uninstall()" zu verwenden, kannst du deine msiexec.exe Routine durchführen. Das "x" würde ich auch nicht an das Ende setzten, da das eventuell als Protokollierungsoption gewertet werden könnte.

     

    So würde ich das ungefähr umsetzen  ;)

    Start-Process -FilePath "msiexec.exe" -ArgumentList "/x $($objJavaProgramItem.IdentifyingNumber) /qn /norestart"
    

    Nun genug der Musterlösung....  :o

  9.  

    Hi,

    ich habe ein Script, welches mir alle Dynamischen Verteilerlisten aus Exchnage auslißt und deren Benutzer. Leider habe ich es nicht hinbekommen den Verteilerlistennamen darüber auszugeben, so dass ich nur eine elend lange Liste von namen bekomme.

    Ich müsste im ForEach{} wohl irgendwie ein Echo unterbringen, weiss alerdings nicht wie.

    Kann mir da jemand helfen?

     

    DANKE

    $Dyn = Get-DynamicDistributionGroup
    $Dyn | ForEach-Object{Get-Recipient -RecipientPreviewFilter $_.RecipientFilter -OrganizationalUnit $_.RecipientContainer | select Alias, Name}

     

    Probiere es mal mit "$_.Name", da "$Dyn" auch mit mehreren DynGruppen gefüllt sein könnte, dann klappt $Dyn.name nicht mehr ;-)

    Dyn = Get-DynamicDistributionGroup
    $Dyn | ForEach-Object{
      Write-Host "DynamicDistributionGroup: $($_.Name)"
      Get-Recipient -RecipientPreviewFilter $_.RecipientFilter -OrganizationalUnit $_.RecipientContainer | Select-Object Alias, Name
    }
    
  10. Was mir einfällt, verliere ich in dem Fall eine XML-Struktur. Und sie brauche ich um auf Properties von Events (z.B. TargetUserName) zu zugreifen.

     

    Ich würde die Daten in den Speicher laden und erst dann verarbeiten. Vielleicht bringt Dir das noch einen Geschwindigkeitsvorteil. Schon mal über diese Variante probiert?

    $objWinEvent = Get-WinEvent -LogName System | Where-Object {$_.Id -eq 4625 -or $_.Id -eq 4768 -or $_.Id -eq 4771 -or $_.Id -eq 4776 }
    

    Edit: Korrektur

  11.  

    - Konsequentes Whitelisting mit  AppLocker etc.

    - Nutzung von EMET

    - Whitelisting für die Windows-Firewall

    - Deinstallieren von nichtgebrauchten Packages, Deaktivieren von Diensten etc.

     

    Applocker

    Setzen wir bei uns mit den Default-Regeln ein. Bis auf eine Ausnahme gibt es keine Probleme. Kein einziges Ticket welches auf dem Applocker hinausgelaufen wäre. "VisualStudio...." funktioniert damit nicht, da die Anwendungen im TEMP-Verzeichnis erstellt werden. Eine Ausnahme für TEMP ist nicht drin. 

     

    EMET

    Keine Probleme bisher! Es geht leicht auf die Performance, jedoch bei dem Benefit vernachlässigbar. EMET wird bei mir im Image mit verteilt.

     

    Windows Firewall

    Bei uns wird die lokalen Einstellungen, sowie die Gruppenrichtlinien übernommen. Leider ist das bei einem Anwendungsjungel schwer einheitlich zu konfigurieren. 

     

    Deinstallieren von nichtgebrauchten Packages

    Halte ich für essentiell. Dank Powershell sind so Remote-Abfragen recht problemlos und einfach.

     

    EDIT:

    Überlegenswert wäre noch die Wechselmedien zu sperren und per Whitelist freizugeben. https://msdn.microsoft.com/en-us/library/bb530324.aspx

×
×
  • Neu erstellen...