Nun einmal etwas anderes als immer nur IT :). Ich muss einfach meinen Ärger über die Jungfraubahnen los werden:
Wir (3-köpfige Familie) mussten im August 2024 eine Busse von 2x 90 Fr. bezahlen, weil wir aus Versehen ohne gültigen Fahrausweis in den Jungfraubahnen (von Grindelwald nach Interlaken wohlgemerkt) unterwegs waren. Ich hatte beim Kauf des Tickets mittels SBB App nicht darauf geachtet, dass die App vom Ticket auf den 1.-Klass-Zuschlag wechselt, wenn man diesen anwählt. Das ursprünglich ausgewählte Ticket wird dann nicht dazu gebucht.
Dass man auf dieser Strecke ohne gültiges Ticket unterwegs ist, ist zweifach unlogisch:
es findet IMMER eine Kontrolle statt
wieso sollte ich NUR den 1.-Klass-Zuschlag, nicht aber ein gültiges Ticket kaufen?
Natürlich wurden wir kontrolliert, und mussten eben die Busse bezahlen. Die Zugbegleiterin hatte absolut keine Einsicht ab unserem Versehen.
Ich wollte im Zug aber keinen grossen Aufstand machen, denn ich ging davon aus, dass wir das offensichtliche versehen nachträglich lösen können.
Weit gefehlt.
Ich wandte mich an per Mail an direktion@jungfrau.ch. Leider wurde überhaupt nicht auf unser Problem eingegangen, obwohl mir bestätigt wurde, dass es sich offensichtlich um ein Versehen handelte.
Ich wandte mich dann auch an Stefan Würgler, seines Zeichens „Leiter Betrieb Eisenbahn“. Ich hoffte, dass er etwas Berufsstolz zeigen würde, und seinen Betrieb ins richtige Licht rücken möchte. Leider auch hier: absolut keine Einsicht, keine Kulanz, keine Kundenfreundlichkeit.
Im Anschluss dachte ich mir: „OK, mindestens das Tourismusbüro wird genug anständig sein, um meinem Problem beachtung zu schenken“. Weit gefehlt. Ich meldete mich bei „GRINDELWALD TOURISMUS“ (ja, die schreiben sich gross). Doch sogar hier: ich erhielt nur eine überhebliche, kundenUNfreundliche Antwort.
Eigentlich hatten wir als Familie Grindelwald eben erst (seit letztem Jahr) lieb gewonnen. Wir waren 2x auf der Pfingstegg, und wollten dies weiterführen. Immer mit Mittagessen, beide Male mit Nachtessen. Wir überlegten uns sogar, einmal da zu übernachten.
Die Moral von dieser Geschichte: Grindelwald scheint es nicht nötig zu haben, eine junge schweizer Familie für ihre Destination zu begeistern. Das ist tragisch.
Wir jedenfalls werden NIE mehr in diesem Gebiet verkehren. Und dies auch all unseren Bekannten so weiter erzählen.
Auf tripadvisor.ch habe ich eine entsprechende Bewertung hinterlegt.
Auch wenn all das diesen Institutionen in Grindelwald komplett egal sein wird :(.
Ich vermute, dass während dem Update die Datei mit der Endung „.apk-new“ erstellt wurde. In dieser ist auch eine Option enthalten, welche in meiner originalen nicht vorhanden ist:
webdir=“/usr/share/webapps/jellyfin-web“
Ich habe diese Zeile in der ursprünglichen Datei „jellyfin“ hinzugefügt, und konnte den Dienst danach erfolgreich starten.
Um das neue Teams auf einem Remote Desktop Session Host (RDSH) installieren zu können, muss man in die Trickkiste greifen. Denn Microsoft unterstützt kein Verteilen als Admin für alle Benutzer, wie dies auf Clients der Fall ist.
Wir brauchen das MSIX-Setupfile. Hier findet ihr den Link, hier die Direktlinks für 64bit und 32bit.
Wir nutzen für diesen Vorgang das „sideloading“. Dies muss zuerst in der Registry erlaubt werden:
Das neue Teams steht dann per sofort allen RDSH-Usern zur Verfügung.
ACHTUNG: Sicherheits-sensitive Admins fragen sich, ob die Freigabe zum sideloading nun wieder entfernt werden kann. Dies wäre mit folgendem Befehl möglich:
Ein User hatte viele (>30GB!) Daten in seiner Mailbox gelöscht, und konnte nun keine weiteren Elemente mehr löschen. Das Verhalten war typisch: im Outlook Client wird die Mail einfach nicht gelöscht. D.h. ich markiere ein Element, drücke Shift-Delete, bestätige die Warnung – … und nix passiert. Kein Fehler, kein Löschen.
In OWA konnten die Mails gelöscht werden, erschienen dann aber eine Sekunde später wieder im selben Ordner.
Wichtig, für folgende Befehle muss mit ExchangeOnline sowie Security & Compliance hergestellt werden:
Name : SubstrateHolds FolderAndSubfolderSize : 0 B (0 bytes) ItemsInFolderAndSubfolders : 0
Name : Versions FolderAndSubfolderSize : 0 B (0 bytes) ItemsInFolderAndSubfolders : 0
Im Ordner „Recoverable Items“ („gelöschte Elemente“) befanden sich die noch (definitiv) zu löschenden Elemente.
Im Ordner „Purges“ befinden sich die Elemente, welche zwar bereits definitiv gelöscht wurden, aber durch Exchange Online noch zurückbehalten werden (falls es sich der Benutzer – trotz dreimaligem löschen – noch anders überlegt).
Ich habe hier absichtlich meine gesamte „Reise“ dargestellt. Die Lösung gibt es ganz unten.
Zuerst habe ich die Anleitung von Microsoft befolgt:
Danach muss man übers GUI eine neue Suche erstellen, für den entsprechenden Ordner (bei mir war das /Purges folderid:0A4ABD8C1C5F934283D2D2ED83724B370000000001170000)
Das geht ganz fix. Nur wenige Sekunden. Der Nachteil: pro Befehl-Ausführung (sagt man dem so?) werden ganze 10 (zehn!!) Elemente gelöscht.
Ich habe knapp 38’000!!!
38’000!
Und unter „Recoverable Items“ sogar 80’000 Elemente!
Es kann doch nicht sein, dass ich hier ein extra Script schreiben muss, um eine Microsoft-Anleitung in einem Loop auszuführen (leider war das dann doch so, siehe unten).
Der Vollständigkeit halber, mit diesen Befehlen wird dies abgeschlossen:
kann dann wieder überprüft werden, ob’s geklappt hat.
Doch die Story geht weiter. Leider hat das nix gebracht. Ich habe dann die Retention-Policy geprüft:
Get-Mailbox $user | select *Retention*
Hier war die Default-Policy aktiv. Mittels folgendem Befehl kann die entfernt werden:
Set-Mailbox $user -RetentionPolicy $null
Leider passierte auch damit nichts. Ich habe mich entschlossen, wieder den Weg von Microsoft einzuschlagen, aber halt ein Script zu schreiben/finden, welches den Löschvorgang in einem Loop ausführt.
Hier gibt es ein ganzes Toolset, welches u.a. diese Funktion beinhaltet. Aber das war mir dann too much.
In diesem Spiceworks Thread habe ich dann meine Lösung gefunden: Das Script des Users jonesbones. Ich habe es leicht angepasst, um den Ordner noch als Variable zu setzen. Ausserdem habe ich den foreach-Teil angepasst, dass das Löschen schneller abläuft:
$ScriptStart = Get-Date
$SearchName = 'DeleteSearch1'
$Mailbox = 'user@domain.ch'
$Folder = '/Purges'
# oder: $Folder = '/Recoverable Items'
$FolderStatistics = Get-MailboxFolderStatistics -Identity $Mailbox
# Convert Inbox folder ID to ID that can be used in compliance search
# https://docs.microsoft.com/en-us/microsoft-365/compliance/use-content-search-for-targeted-collections
$InboxFolderId = ($FolderStatistics | Where-Object {$_.FolderPath -eq $Folder}).FolderId
$Encoding= [System.Text.Encoding]::GetEncoding("us-ascii")
$Nibbler= $Encoding.GetBytes("0123456789ABCDEF");
$FolderIdBytes = [Convert]::FromBase64String($InboxFolderId);
$IndexIdBytes = New-Object byte[] 48;
$IndexIdIdx=0
$FolderIdBytes | select -skip 23 -First 24 | %{$indexIdBytes[$indexIdIdx++]=$nibbler[$_ -shr 4];$indexIdBytes[$indexIdIdx++]=$nibbler[$_ -band 0xF]}
$FolderQuery = "folderid:$($encoding.GetString($indexIdBytes))"
$Items = ($FolderStatistics | Where-Object {$_.FolderId -eq $InboxFolderId}).ItemsInFolder
$Iterations = [math]::Ceiling($Items / 10)
Remove-ComplianceSearch $SearchName -Confirm:$false # wird benötigt, wenn Script zuvor abgebrochen wurde
New-ComplianceSearch -Name $SearchName -ExchangeLocation $Mailbox -ContentMatchQuery $FolderQuery | Out-Null
Start-ComplianceSearch -Identity $SearchName | Out-Null
Do {
Start-Sleep -Seconds 2 # Adding 2 sec wait in case of possible timeouts from MS end
$ComplianceSearch = (Get-ComplianceSearch -Identity $SearchName)
#Write-Host "-- CS $($ComplianceSearch.Status), $($ComplianceSearch.Items)"
} While ($ComplianceSearch.Status -ne 'Completed')
foreach ($Iteration in @(1..$Iterations)) {
Write-Progress -Activity "Purging $Folder" -Status "$($ComplianceSearch.Items) items left" -PercentComplete ($Iteration / $Iterations * 100)
Write-Host "[$Iteration / $Iterations]" #$($ComplianceSearch.Items) items left"
New-ComplianceSearchAction -SearchName $SearchName -Purge -PurgeType HardDelete -Confirm:$false | Out-Null
Do {
#Start-Sleep -Seconds 1
$PurgeAction = Get-ComplianceSearchAction -Identity "$SearchName`_Purge"
#Write-Host "-- PA $($PurgeAction.Status)"
} While ($PurgeAction.Status -ne 'Completed')
}
Remove-ComplianceSearch $SearchName -Confirm:$false
$ScriptEnd = Get-Date
$ExecutionTime = $ScriptEnd - $ScriptStart
Write-Host "$ExecutionTime"
Das Script läuft dann einfach ne (lange, seeehr lange) Weile, weil extrem ineffizient – danke Microsoft :|.
Wieso einfach, wenn’s kompliziert geht? Diese Frage stelle ich mir in letzter Zeit immer öfter, wenn’s um Microsoft, und insbesondere deren Cloud M365 geht.
Hier ein schönes Beispiel: ich will nur einen Haken einer App entfernen. Im GUI brauche ich dazu nur ein paar Klicks:
Um dasselben mittels Powershell zu lösen, benötige ich, sagen wir, ein paar Schritte mehr:
$User = "user@domain.ch"
## Get the services that have already been disabled for the user.
$userLicense = Get-MgUserLicenseDetail -UserId $User
$userDisabledPlans = $userLicense.ServicePlans | Where ProvisioningStatus -eq "Disabled" | Select -ExpandProperty ServicePlanId
## Get the new service plans that are going to be disabled
$e5Sku = Get-MgSubscribedSku -All | Where SkuPartNumber -eq 'TEAMS_ESSENTIALS_AAD'
$newDisabledPlans = $e5Sku.ServicePlans | Where ServicePlanName -in ("EXCHANGE_S_DESKLESS") | Select -ExpandProperty ServicePlanId
## Merge the new plans that are to be disabled with the user's current state of disabled plans
$disabledPlans = ($userDisabledPlans + $newDisabledPlans) | Select -Unique
$addLicenses = @(
@{
SkuId = $e5Sku.SkuId
DisabledPlans = $disabledPlans
}
)
## Update user's license
Set-MgUserLicense -UserId $User -AddLicenses $addLicenses -RemoveLicenses @()
Ich wollte einen Exchange-Server migrieren, und währenddessen die noch vorhandenen onPrem-Mailboxen der PublicFolder löschen. Die PublicFolder waren schon lange migriert, aber die Postfächer hat irgendjemand nicht gelöscht ;).
Get-Mailbox -PublicFolder | where {$_.IsRootPublicFolderMailbox -eq $False} | Remove-Mailbox -PublicFolder
Es konnten keine aktiven Postfächer für öffentliche Ordner gefunden werden. Entweder wurden keine Postfächer für öffentliche Ordner bereitgestellt, oder sie wurden im HoldForMigration-Modus bereitgestellt. Wenn Sie aktuell keine Migration ausführen, erstellen Sie ein Postfach für öffentliche Ordner. + CategoryInfo : NotSpecified: (:) [Remove-Mailbox], ObjectNotFoundException + FullyQualifiedErrorId : [Server=SRV,RequestId=a6c72a8d-c6cb-4c15-a5cc-068977ab21b4,TimeStamp=18.04.2024 19: 28:51] [FailureCategory=Cmdlet-ObjectNotFoundException] 159E9A7C,Microsoft.Exchange.Management.RecipientTasks.Remo veMailbox + PSComputerName : srv.domain.local
Wenn ich das Script ausführe, erhalte ich folgende Fehlermeldung:
Ausnahme beim Aufrufen von "SetAccessRule" mit 1 Argument(en): "Manche oder alle Identitätsverweise konnten nicht
übersetzt werden."
In C:\Program Files\Microsoft\AzureMfa\Config\AzureMfaNpsExtnConfigSetup.ps1:92 Zeichen:2
$acl.SetAccessRule($buildAcl) #Add Access Rule
~~~~~~~~~
CategoryInfo : NotSpecified: (:) [], MethodInvocationException
FullyQualifiedErrorId : IdentityNotMappedException
Nach der Analyse des Scripts, hat Microsoft hier mal wieder bei den Sprachen gepatzt. Die original Zeile:
Dies musste ich auf folgendes anpassen:
Der Benutzer „NETWORK SERVICE“ hat die SID „S-1-5-20“. Damit konnte ich den korrekten Namen auf dem deutschen System idenfizieren.