Recent Discussions
Unleashing Parallelism in PowerShell
This blog on my site got a lot of possitive feedback. Hopefully it can help others as well hence I share it here. If you want to check more check my blog on: https://bartpasmans.tech/ or check my LinkedIn: https://www.linkedin.com/in/bart-pasmans-6533094b/ Unleashing Parallelism in PowerShell If you’ve been around PowerShell for a while, you know it’s great at looping through stuff. Need to process a list of files? Easy. Query a set of servers? Piece of cake. But sometimes… you hit a wall. The problem? Sequential execution. By default, your loops work in a single-file line, like shoppers at a small-town bakery. That’s fine for five people. Not so fine for five thousand. That’s where ForEach-Object -Parallel enters the chat. 🚀 This feature, introduced in PowerShell 7, lets you process multiple items at the same time, tapping into all those CPU cores just sitting there looking bored. Today, we’re going to walk through how it works, why it’s a game-changer, and where you should (and shouldn’t) use it. We’ll keep it hands-on, so keep PowerShell open! you’ll see the 🎬 icon whenever it’s time to get your hands dirty. Today’s Toolbelt Here’s the deal: ForEach-Object -Parallel is like the express checkout lane at the grocery store. Instead of every task waiting for the one ahead to finish, they all get their own lane. We’ll explore: Basic parallel loops – Using ForEach-Object -Parallel in the simplest form Passing variables – How to get data into your parallel script block Controlling thread counts – Because unlimited parallelism can get… messy Real-world scenarios – Places where it shines (and where it doesn’t) Why Parallel? Imagine you have 50 servers to check for a certain log file. Running them one after another takes… forever. With parallel processing, you can hit multiple servers at once, finishing in a fraction of the time. 📒 Under the hood: PowerShell spins up runspaces, lightweight, isolated environment, to execute each chunk of work simultaneously. It’s not “true” OS-level multithreading, but it’s incredibly efficient for I/O-bound tasks like network calls, file reads, or API requests. 1..5 | ForEach-Object -Parallel { Start-Sleep -Seconds 1 "Task $_ completed on thread $([System.Threading.Thread]::CurrentThread.ManagedThreadId)" } What’s happening: 1..5 gives us five items. Each item is processed in a parallel runspace. They all sleep for one second…. 🥁🥁🥁 but because they run in parallel, the whole thing finishes in just over a second, not five! My previous blog: https://bartpasmans.tech/start-scripting-like-a-pro-6-speeding-up-your-code/ I showed you how to make your own threads and consume them. Check it out! 😊 This blog sticks with PowerShell cmdlets natively. Passing Data Into Parallel Blocks One catch with ForEach-Object -Parallel: it runs in its own scope. Your outer variables aren’t magically available inside. 🎬 Here’s how to pass variables in: $prefix = "Server" 1..3 | ForEach-Object -Parallel { "$using:prefix-$($_)" } 📒 The magic word: $using: tells PowerShell to bring in a variable from outside the parallel block. Controlling the Chaos Yes, parallelism is powerful, but if you let 200 jobs spin up at once, you might as well be starting a tiny CPU apocalypse 💣. 🎬 Throttle it with 1..10 | ForEach-Object -Parallel { Start-Sleep -Seconds 2 "Processed $_" } -ThrottleLimit 3 Here, only three parallel tasks run at a time. As soon as one finishes, the next starts. Real-World Example: Network Ping 🎬 Checking multiple hosts in parallel: $servers = "server1","server2","server3","server4","server5" $servers | ForEach-Object -Parallel { $result = Test-Connection -ComputerName $_ -Count 1 -Quiet "$_ is " + ($(if ($result) { "online" } else { "offline" })) } -ThrottleLimit 2 The pings happen two at a time. Overall time drops drastically compared to running sequentially. When Not to Use It 📒 Parallelism is not a free lunch. If your task is super short and light (like adding numbers), spinning up runspaces is actually slower. For CPU-heavy operations, you might saturate your system quickly. Avoid it when order matters—parallel execution doesn’t guarantee output order unless you take extra steps. Summary Wrapping It Up! PowerShell Meets Parallelism 🎉 Today we saw how ForEach-Object -Parallel lets you take PowerShell’s already-great iteration abilities and put them into warp speed. We covered: The basics of parallel loops Passing variables with $using: Throttling to keep your system happy Real-world use cases like pinging servers The takeaway? When you’re faced with a big list of time-consuming tasks, don’t just wait your turn in the single checkout lane. Open more lanes with ForEach-Object -Parallel! Just remember that more isn’t always better. Got your own clever use for parallel loops? Share it, I love seeing how people bend PowerShell to their will. Until next time! Keep automating, keep experimenting, and keep pushing your scripts to the next level. 🚀☕🍰8Views0likes0CommentsProblem restoring deleted user with mggraph
Hello, I have done a few 365 migration and almost everytime there are some user data that has been missed in the migration. Earlier I solved this by restoring the 365 user in the source tenant to another domain using this msol script in powershell: Restore-MsolUser -UserPrincipalName email address removed for privacy reasons -Verbose Restore-MsolUser -UserPrincipalName email address removed for privacy reasons -Verbose -AutoReconcileProxyConflicts Restore-MsolUser -UserPrincipalName email address removed for privacy reasons -Verbose -AutoReconcileProxyConflicts -NewUserPrincipalName email address removed for privacy reasons I know it is not perfect but it worked well and saved a bunch of times. I have now done another migration now and got the same issue so I need to restore the users so we can access the data again and move it. BUT! I realized today that msol service is no more, so I am kinda stuck with figuring this out in mggraph. I have tried for a few hours now and I am not sure if this even possible with mggraph. Whenever I try to build a script using Restore-MgDirectoryDeletedUser/Item which google, copilote etc tells me to use I only get this error: The term 'Restore-MgDirectoryDeletedUser/item' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. Or I get that it "works" but that the proxy/domain conflicts: Errors detected while trying to restore the user restoreUserErrors: ErrorValue:<pii><pii>E*****.E*******</pii>@domain.com</pii> ObjectType: ConflictingObjectId:, ErrorType:UserPrincipalName, ErrorId:InvalidDomainErrorValue:<pii>smtp:<pii>ee</pii>@domain.com</pii> ObjectType: ConflictingObjectId:, ErrorType:ProxyAddress, ErrorId:InvalidDomain Status: 400 (BadRequest) ErrorCode: Request_BadRequest Date: 2025-09-08T13:49:36 Since I do not have the first domain in the source tenant anymore I need to restore the user to a different domain. Does anyone have any idea on how I can recreate the msol version to mggraph? I feel like I have tried everything to my knowledge now so hopefully anyone here can give me help or tips. Thanks! /Adam87Views0likes4CommentsError setting profile for interface Primary LAN Interface
Hi all I have a problem with this script. It says "Error setting profile for interface Primary LAN Interface: The network connection profile is corrupted". I need to set the Network card Protected EAP Properties to "Smartcard or other certificate" and set the Trusted Root Certification Autorities to use our Root certificate. Is there any other way to automate this or can you help me finding the problem in this script? Thanks for your help! Powershell Script: # ================================ # 802.1X PEAP (EAP-TLS) for Wired # Interface: "Primary LAN Interface" # Root CA can be selected by Thumbprint or Subject Match # Run as Administrator # ================================ $InterfaceName = "Primary LAN Interface" # Target NIC display name $ProfileName = "Network" # Wired profile name to manage $TempFolder = "D:\iltis\tools\Temp\LanProfile" # Root CA selection (choose ONE approach) $RootCAThumbprint = "96f2bf58b39db8b704a4dda8c5df456c725fce24" # e.g. "AB12CD34EF56..."; leave blank to use subject search $RootCASubjectLike = "Root" # Used only if $RootCAThumbprint is blank # ---------- Helpers ---------- function Ensure-Folder($path) { if (-not (Test-Path $path)) { New-Item -ItemType Directory -Path $path | Out-Null } } function Get-RootCAThumbprint { param( [string]$Thumbprint, [string]$SubjectLike ) if ($Thumbprint -and $Thumbprint.Trim() -ne "") { return ($Thumbprint -replace "\s","").ToUpper() } $match = Get-ChildItem Cert:\LocalMachine\Root | Where-Object { $_.Subject -like "*$SubjectLike*" } | Select-Object -First 1 if (-not $match) { throw "Root CA with subject like '$SubjectLike' not found in LocalMachine\Root." } return ($match.Thumbprint -replace "\s","").ToUpper() } function Start-WiredAutoConfig { $svc = Get-Service -Name dot3svc -ErrorAction SilentlyContinue if (-not $svc) { throw "Wired AutoConfig (dot3svc) service not found." } if ($svc.StartType -ne 'Automatic') { Set-Service dot3svc -StartupType Automatic } if ($svc.Status -ne 'Running') { Start-Service dot3svc } } function Get-NicOrThrow { param([string]$Name) $nic = Get-NetAdapter -Name $Name -ErrorAction SilentlyContinue if (-not $nic) { throw "Network adapter '$Name' not found. Use Get-NetAdapter to confirm the exact name." } if ($nic.Status -ne 'Up') { Write-Warning "Adapter '$Name' is not Up (status: $($nic.Status)). Continuing anyway." } return $nic } # Minimal valid LAN profile XML with EAPHostConfig placeholder (we’ll inject the Root CA thumbprint). function New-LanProfileXml { param([string]$ProfName) @" <?xml version="1.0"?> <LANProfile xmlns="http://www.microsoft.com/networking/LAN/profile/v1"> <name>$ProfName</name> <MSM> <security> <OneX xmlns="http://www.microsoft.com/networking/OneX/v1"> <authMode>userOrComputer</authMode> <EAPConfig> <EapHostConfig xmlns="http://www.microsoft.com/provisioning/EapHostConfig"> <EapMethod> <Type xmlns="http://www.microsoft.com/provisioning/EapCommon">25</Type> <AuthorId xmlns="http://www.microsoft.com/provisioning/EapCommon">0</AuthorId> </EapMethod> <Config xmlns="http://www.microsoft.com/provisioning/EapHostConfig"> <Eap xmlns="http://www.microsoft.com/provisioning/BaseEapConnectionPropertiesV1"> <Type>13</Type> <EapType xmlns="http://www.microsoft.com/provisioning/EapTlsConnectionPropertiesV1"> <CredentialsSource> <CertificateStore> <SimpleCertSelection>true</SimpleCertSelection> </CertificateStore> </CredentialsSource> <ServerValidation> <DisableUserPromptForServerValidation>true</DisableUserPromptForServerValidation> <ServerNames></ServerNames> <TrustedRootCA>__ROOT_CA_THUMBPRINT__</TrustedRootCA> </ServerValidation> <DifferentUsername>false</DifferentUsername> </EapType> </Eap> </Config> </EapHostConfig> </EAPConfig> </OneX> </security> </MSM> </LANProfile> "@ } # ---------- Main ---------- try { Write-Host "Preparing environment..." -ForegroundColor Cyan Ensure-Folder $TempFolder Start-WiredAutoConfig $null = Get-NicOrThrow -Name $InterfaceName $thumb = Get-RootCAThumbprint -Thumbprint $RootCAThumbprint -SubjectLike $RootCASubjectLike Write-Host "Using Root CA Thumbprint: $thumb" -ForegroundColor Green # Try to export existing profile for this interface+name; if missing, build a fresh one. $exported = $false Write-Host "Exporting existing wired profile (if present)..." -ForegroundColor Cyan $null = netsh lan export profile folder="$TempFolder" interface="$InterfaceName" name="$ProfileName" 2>$null $ProfilePath = Join-Path $TempFolder "$ProfileName.xml" if (Test-Path $ProfilePath) { $exported = $true } if (-not $exported) { Write-Host "No existing profile named '$ProfileName' found. Creating a new one..." -ForegroundColor Yellow $xmlText = New-LanProfileXml -ProfName $ProfileName $xmlText = $xmlText -replace "__ROOT_CA_THUMBPRINT__", $thumb $xmlText | Set-Content -Path $ProfilePath -Encoding UTF8 } else { # Load existing, replace EAP host config with our desired PEAP->EAP-TLS block [xml]$xml = Get-Content $ProfilePath # Find any EapHostConfig node and replace its InnerXml with our config (PEAP 25 -> inner EAP-TLS 13) $ns = New-Object System.Xml.XmlNamespaceManager($xml.NameTable) $ns.AddNamespace("lp", "http://www.microsoft.com/networking/LAN/profile/v1") $ns.AddNamespace("ox", "http://www.microsoft.com/networking/OneX/v1") $eapConfigNode = $xml.SelectSingleNode("//lp:LANProfile/lp:MSM/lp:security/ox:OneX/ox:EAPConfig", $ns) if (-not $eapConfigNode) { throw "EAPConfig node not found in exported profile. Cannot proceed safely." } $newEap = New-LanProfileXml -ProfName $ProfileName # extract just the EAPHostConfig from the template [xml]$tmp = $newEap $tmpNs = New-Object System.Xml.XmlNamespaceManager($tmp.NameTable) $tmpNs.AddNamespace("lp", "http://www.microsoft.com/networking/LAN/profile/v1") $tmpNs.AddNamespace("ox", "http://www.microsoft.com/networking/OneX/v1") $eapHostConfig = $tmp.SelectSingleNode("//lp:LANProfile/lp:MSM/lp:security/ox:OneX/ox:EAPConfig/*", $tmpNs) # Replace placeholder with real thumbprint $eapHostConfigOuterXml = $eapHostConfig.OuterXml.Replace("__ROOT_CA_THUMBPRINT__", $thumb) # Replace EAPConfig contents $eapConfigNode.InnerXml = $eapHostConfigOuterXml # Save back $xml.Save($ProfilePath) } Write-Host "Importing wired 802.1X profile to '$InterfaceName'..." -ForegroundColor Cyan # Adds the profile and associates it with the specified interface netsh lan add profile filename="$ProfilePath" interface="$InterfaceName" # Optional: force 802.1X reauth/reconnect try { netsh lan reconnect interface="$InterfaceName" | Out-Null } catch {} Write-Host "" Write-Host "✅ Done." -ForegroundColor Green Write-Host "The adapter '$InterfaceName' is configured for PEAP with inner 'Smart Card or other certificate' (EAP-TLS) and trusts the specified Root CA." -ForegroundColor Green Write-Host "Profile name: $ProfileName" Write-Host "" Write-Host "Tip: If your NAC expects machine auth, make sure a valid machine certificate is present in LocalMachine\My." -ForegroundColor DarkGray } catch { Write-Error $_.Exception.Message exit 1 }71Views0likes2CommentsError When Promoting User to Channel Owner via PowerShell – Teams
Hello everyone, I'm trying to assign a colleague as an owner of the Teams channels where I am already an owner. I wrote a sequence of PowerShell commands, following the required steps: first adding them to the team as a member, then promoting them to owner, and finally adding them to the channels using the same steps. There’s no issue adding them to the Teams as a member and then as an owner. Adding them to the channels as a member also works fine. However, I’m unable to assign them as an owner of the channels. I keep getting the same error message, and I haven’t found any documentation or similar error online. From the Teams interface, I can perform the operation without any issue. However, since I need to do this for several hundred channels, I’m using PowerShell to automate the process. I’m attaching a screenshot showing the attempt to add them to a single channel, to clearly demonstrate that the issue lies with assigning ownership. Do you have any idea what might be causing this? Thanks, and have a great day.79Views0likes2CommentsAttempting Powershell Remoting but experiencing errors
Hi, all. I'm attempting to use PowerShell Remoting and came across this article, which also addresses the double hop issue, but I don't even get to that part. https://4sysops.com/archives/solve-the-powershell-multi-hop-problem-without-using-credssp/ Powershell Remoting is enabled on both Server VMs and I tested the connection between the two. According to the command "Test-NetConnection ServerName -Port 5985", the connection between the two Servers is good. Also tried increasing the "MaxEnvelopeSizekb" to 8192 Following the instructions, I run this command: (removed the actual computer name and domain/usn) but receiving these errors: Invoke-Command -ComputerName RemoteServerName -ScriptBlock { Register-PSSessionConfiguration -Name GP4WinScript -RunAsCredential domain\username-Force } WARNING: When RunAs is enabled in a Windows PowerShell session configuration, the Windows security model cannot enforce a security boundary between different user sessions that are created by using this endpoint. Verify that the Windows PowerShell runspace configuration is restricted to only the necessary set of cmdlets and capabilities. WARNING: You are running in a remote session and have selected the Force option which means the WinRM service may restart.If the WinRM service restarts then this remote session will be terminated and you will need to create a new session to continue [RemoteServerName] Processing data from remote server RemoveServerName failed with the following error message: The I/O operation has been aborted because of either a thread exit or an application request. For more information, see the about_Remote_Troubleshooting Help topic. + CategoryInfo : OpenError: (RemoveServerName:String) [], PSRemotingTransportException + FullyQualifiedErrorId : WinRMOperationAborted,PSSessionStateBroken Pleas help! Thank you.100Views0likes4CommentsBug: Invoke-MgGraphRequest not respecting ErrorAction.
Hi folks, This is a brief callout that Invoke-MgGraphRequest is not currently respecting the ErrorAction parameter. Rather, it's hardwired to throwing an exception as if ErrorAction:Stop had been provided. If you're like me and typically use ErrorAction:Stop in a try/catch block then you won't be impacted, but if use another value like Continue (the default) or SilentlyContinue, you may find this breaks your automation. Example Hopefully this is addressed in a future version of the Microsoft.Graph.Authentication module. Cheers, Lain29Views0likes0CommentsProblem with Copy-Item
I'm trying to copy all files from a webdav folder to a local folder. It worked one time, after that, just a file with the the expected folder name (back) was created. What could be the issue? # Define Drive $netzLaufwerk = "Z:" # Connect net use $netzLaufwerk $webdavUrl /user:$username $passwort # Copy files Copy-Item -Path "$netzLaufwerk\*" -Destination "C:\Users\innov\Desktop\Backup\back" -Recurse # Disconnect net use $netzLaufwerk /delete47Views0likes1CommentHow to: Finding large directories/recovering lost space.
Hi folks, Every once in a blue moon I need to figure out where a disk's free space has disappeared to. There's boatloads of free tools that do this via a GUI but I felt like a basic PowerShell solution I can use in other contexts. Here's the simple module I wrote as well as some basic examples on how it can be leveraged in a standalone context. Props to anyone who spots the Easter egg. Module: XTree.psm1 function Get-DirectorySize { [cmdletbinding()] param( [parameter(Mandatory=$true)][ValidateNotNull()][string] $Path ) Write-Verbose -Message "Parsing $Path"; $Summary = [PSCustomObject] @{ Path = $Path.ToLowerInvariant(); Count = 0; Size = 0; } [System.IO.Directory]::EnumerateFiles($Path) | ForEach-Object { [System.IO.FileInfo]::new($_) | ForEach-Object { $Summary.Count++; $Summary.Size += $_.Length; } } $Summary; } function Get-DirectoryTreeSize { [cmdletbinding()] param( [parameter(Mandatory=$true)][ValidateNotNull()][string] $Path ) # Reference: https://learn.microsoft.com/en-us/dotnet/api/system.io.fileattributes?view=netframework-4.8.1 New-Variable -Name "ReparsePoint" -Value ([System.IO.FileAttributes]::ReparsePoint.value__) -Option Constant; #region Create a new output object with default values. $Summary = [PSCustomObject] @{ Path = $Path.ToLowerInvariant(); Count = 0; Size = 0; TotalCount = 0; TotalSize = 0; } #endregion #region Make any recursive calls first. [System.IO.Directory]::EnumerateDirectories($Path) | ForEach-Object { # We do not want to process reparse points. if (0 -eq (([System.IO.DirectoryInfo]::new($_).Attributes.value__ -band $ReparsePoint))) { Get-DirectoryTreeSize -Path $_ | ForEach-Object { $Summary.TotalCount += $_.Count; $Summary.TotalSize += $_.Size; $_; } } } #endregion #region Now, process and output the current directory. $Stats = Get-DirectorySize -Path $Path; $Summary.Count = $Stats.Count; $Summary.Size = $Stats.Size; $Summary.TotalCount += $Stats.Count; $Summary.TotalSize += $Stats.Size; $Summary; #endregion } Export-ModuleMember -Function @( "Get-DirectorySize" , "Get-DirectoryTreeSize" ); Example 1: Selecting the top five consumers by TotalSize This sort method is most useful for getting a high-level overview of a large directory structure. Get-DirectoryTreeSize -Path "D:\Data\Temp\Edge\windows" | Sort-Object -Property TotalSize -Descending | Select-Object -First 5 | Format-Table -AutoSize -Property TotalSize, TotalCount, Path; Example 2: Selecting the top five consumers by Size This sort method is more useful where you're looking for large individual directories. Get-DirectoryTreeSize -Path "D:\Data\Temp\Edge\windows" | Sort-Object -Property Size -Descending | Select-Object -First 5 | Format-Table -AutoSize -Property Size, Count, Path; Example output from both examples Additional information We do not want to process reparse points because: If the reference points to within the structure then we end up counting the same files twice, which is misleading; If the reference points outside the structure then it shouldn't be counted as contributing within the structure. I've used the native .NET class [System.IO.Directory] in lieu of the PowerShell-native Get-ChildItem as it's more efficient in a few scenarios - both in execution and coding effort. Get-ChildItem also errors out on certain reparse points in Windows PowerShell, which you can test for yourself using: Get-ChildItem -Directory -Force -Path "$env:USERPROFILE\Application Data\"; Cheers, Lain61Views1like0CommentsLocal Admin Script not working for certain OU's all of a sudden
I run the local admin scripts against our domain every month for a total of 13 location OUs. It has worked just fine for over 2 years until a couple of months ago when 3 OUs are not responding to the script so it puts all assets in the error report. I have checked and we have not made any sort of network or group policy changes. I am reviewing the PowerShell logs in Event Viewer but I am not finding a root cause. Any thoughts. Here is the code that works for most OUs <# .SYNOPSIS . .DESCRIPTION This script will find local administrators of client computers in your domain and will same them as CSV file in current directory. .PARAMETER Path This will be the DN of the OU or searchscope. Simply copy the DN of OU in which you want to query for local admins. If not defined, the whole domain will be considered as search scope. .PARAMETER ComputerName This parametr defines the computer account in which the funtion will run agains. If not specified, all computers will be considered as search scope and consequently this function will get local admins of all computers. You can define multiple computers by utilizing comma (,). .EXAMPLE C:\PS> Get-LocalAdminToCsv This command will get local admins of all computers in the domain. C:\PS> Get-LocalAdminToCsv -ComputerName PC1,PC2,PC3 This command will get local admins of PC1,PC2 and PC3. C:\PS> Get-LocalAdminToCsv -Path "OU=Computers,DC=Contoso,DC=com" .NOTES Author: Mahdi Tehrani Date : February 18, 2017 #> Import-Module activedirectory Clear-Host function Get-LocalAdminToCsv { Param( $Path = (Get-ADDomain).DistinguishedName, $ComputerName = (Get-ADComputer -Filter * -Server (Get-ADDomain).DNsroot -SearchBase $Path -Properties Enabled | Where-Object {$_.Enabled -eq "True"}) ) begin{ [array]$Table = $null $Counter = 0 } process { $Date = Get-Date -Format MM_dd_yyyy_HH_mm_ss $FolderName = "LocalAdminsReport("+ $Date + ")" New-Item -Path ".\$FolderName" -ItemType Directory -Force | Out-Null foreach($Computer in $ComputerName) { try { $PC = Get-ADComputer $Computer $Name = $PC.Name $CountPC = @($ComputerName).count } catch { Write-Host "Cannot retrieve computer $Computer" -ForegroundColor Yellow -BackgroundColor Red Add-Content -Path ".\$FolderName\ErrorLog.txt" "$Name" continue } finally { $Counter ++ } Write-Progress -Activity "Connecting PC $Counter/$CountPC " -Status "Querying ($Name)" -PercentComplete (($Counter/$CountPC) * 100) try { $row = $null $members =[ADSI]"WinNT://$Name/Administradores" $members = @($members.psbase.Invoke("Members")) $members | foreach { $User = $_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null) $row += $User $row += " ; " } write-host "Computer ($Name) has been queried and exported." -ForegroundColor Green -BackgroundColor black $obj = New-Object -TypeName PSObject -Property @{ "Name" = $Name "LocalAdmins" = $Row } $Table += $obj } catch { Write-Host "Error accessing ($Name)" -ForegroundColor Yellow -BackgroundColor Red Add-Content -Path ".\$FolderName\ErrorLog.txt" "$Name" } } try { $Table | Sort Name | Select Name,LocalAdmins | Export-Csv -path ".\$FolderName\Report.csv" -Append -NoTypeInformation } catch { Write-Warning $_ } } end{} This happens under a local admin account as well as a domain admin account.57Views0likes2CommentsGet-MessageTraceV2 not recognized
I'm updating a script that automatically pulls message traces in Exchange Online. From my understanding, the Get-MessageTrace cmdlet will no longer work at the end of the month, and it needs to be upgraded to Get-MessageTraceV2. Below is the script. # Connect to Exchange Online Connect-ExchangeOnline -ShowBanner:$False # Define the start and end dates for the mail trace $startDate = (Get-Date).AddDays(-7).ToString("MM/dd/yyyy") $endDate = (Get-Date).ToString("MM/dd/yyyy") # Get the mail trace $params = @{ StartDate = $start DateEndDate = $endDate SenderAddress = "email address removed for privacy reasons" Status = "Failed" } Get-MessageTraceV2 @params Each time I run it, I get an error that the Get-MessageTracev2 is not recognized. I've confirmed I have ExchangeOnlineManagement module 3.8 installed (Microsoft documentation says the cmdlet was introduced in 3.7). When I run "Get-Command Get-MessageTraceV2" I get the same message saying the cmdlet is not recognized. When I try "Get-Command *V2" it lists several cmdlets from Microsoft.Graph but nothing from ExchangeOnlineManagement. I've tried the following all with the same results. Uninstalling and reinstalling the ExchangeOnlineManagement module. Installing with the -AllowClobber switch. Installed PowerShell 7 and installed the 3.9 prerelease. On a freshly reset computer, installed ExchangeOnlineManagement module. On the fresh computer, I uninstalled and then installed prerelease. I'm able to use other ExchangeOnlineManagement cmdlets like Get-Mailbox without issues. I am using a GCC tenant if that matters (I hope not). What am I missing (besides the cmdlet haha)?160Views0likes2CommentsGet-MgBookingsBusiness/Graph API Pagination Limits = 1000
Has anyone had success pulling all Bookings Businesses of their tenant over 1000? I cannot for the life of me figure out how to get past 1000 results because there are. # Make sure you're connected # Connect-MgGraph -Scopes "Bookings.Read.All" $uri = "https://graph.microsoft.com/v1.0/solutions/bookingBusinesses" $allBusinesses = @() Write-Host "🔄 Starting paged retrieval..." do { # Send GET request $response = Invoke-MgGraphRequest -Method GET -Uri $uri # Extract raw JSON $json = $response | ConvertTo-Json -Depth 10 $parsed = $json | ConvertFrom-Json # Add current page of businesses $allBusinesses += $parsed.value Write-Host " Retrieved $($parsed.value.Count) businesses..." # Next page URL if available $uri = $parsed.'@odata.nextLink' } while ($null -ne $uri) Write-Host "✅ Total retrieved: $($allBusinesses.Count)" # Export to CSV properly $desktopPath = [Environment]::GetFolderPath("Desktop") $exportPath = Join-Path $desktopPath "all_bookings_full.csv" # Choose specific fields to export (optional - improves readability) $allBusinesses | Select-Object id, displayName, email, phone, address | Export-Csv -Path $exportPath -NoTypeInformation -Encoding UTF8 Write-Host "✅ Exported clean data to: $exportPath"52Views0likes2CommentsCan't add device member in Static Security Entra Group with powershell
Hi, With Graph, I want to add some device members in a static security Entra group using it to deploy some certificates with Intune. I do it with following command: New-MgGroupMember -GroupId $groupId -DirectoryObjectId $device.AzureAdDeviceId but I receive this error: New-MgGroupMember : Resource 'df75dfe1-8b5a-4cc6-8f99-17746bb8c07e' does not exist or one of its queried reference-property objects are not present. In C:\Users\E21996\OneDrive - Fondazione Enasarco\Lavoro\!HelpDesk\!Intune\Scripts\Set-Device-Department-Attribute.ps1:57 car:9 + New-MgGroupMember -GroupId $groupId -DirectoryObjectId $devic ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: ({ GroupId = 9fa...ferenceCreate }:<>f__AnonymousType1`2) [New-MgGroupMember_CreateExpanded], Exception + FullyQualifiedErrorId : Request_ResourceNotFound,Microsoft.Graph.PowerShell.Cmdlets.NewMgGroupMember_CreateExpanded I've checked the GroupID and Azure Device ID and are correct. If I try to add a user it works fine, with device I have this error. In the group I can add device member manually from Intune without problems. There is a known issue when add device members to groups in Graph? Can anyone help me to resolve this issue, please?50Views0likes1CommentGet DGs for a specific person from EXO
Having trouble with my script working right. Tried several scenarios. Looking for a GUI version. Attached are the two PS1's. I can connect to EXO but the GUI script won't produce anything ot just locks up Connect EXO: Connect-ExchangeOnLine This is straight forward and works but I cannot get it to work with the script below in an all in one script ------------------- <# Get-UserDGs-GUI.ps1 Author: You + ChatGPT Purpose: GUI to retrieve a user's Distribution Groups (member/owner) from Exchange Online. #> #region Preconditions if ($Host.Runspace.ApartmentState -ne 'STA') { Write-Warning "Re-running in STA mode..." Start-Process powershell.exe "-NoLogo -NoProfile -ExecutionPolicy Bypass -STA -File `"$PSCommandPath`"" -Verb RunAs exit } Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing [System.Windows.Forms.Application]::EnableVisualStyles() #endregion #region Helper Functions function Ensure-ExchangeModule { if (-not (Get-Module ExchangeOnlineManagement -ListAvailable)) { Write-Host "Installing ExchangeOnlineManagement..." Install-Module ExchangeOnlineManagement -Scope CurrentUser -Force -ErrorAction Stop } Import-Module ExchangeOnlineManagement -ErrorAction Stop } function Test-EXOConnection { try { # Fast no-op cmdlet to see if session works; adjust if needed Get-OrganizationConfig -ErrorAction Stop | Out-Null return $true } catch { return $false } } function Connect-EXO { param( [string]$AdminUpn ) if (Test-EXOConnection) { return $true } $connectParams = @{} if ($AdminUpn) { $connectParams.UserPrincipalName = $AdminUpn } try { Connect-ExchangeOnline @connectParams -ShowProgress $false -ErrorAction Stop | Out-Null return $true } catch { [System.Windows.Forms.MessageBox]::Show("Connection failed:`r`n$($_.Exception.Message)","Error", [System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Error) | Out-Null return $false } } function Disconnect-EXO-Safe { try { Disconnect-ExchangeOnline -Confirm:$false -ErrorAction SilentlyContinue | Out-Null } catch {} } function Get-UserDGData { param( [string]$TargetUpn, [bool]$IncludeOwner, [bool]$IncludeDynamic ) $resultTable = New-Object System.Data.DataTable "Groups" "DisplayName","PrimarySmtpAddress","ManagedBy","RecipientTypeDetails","MembershipType","IsDynamic" | ForEach-Object { [void]$resultTable.Columns.Add($_) } try { # DistinguishedName for membership filter $dn = (Get-User $TargetUpn -ErrorAction Stop).DistinguishedName # Member DGs $memberDgs = Get-DistributionGroup -ResultSize Unlimited -Filter "Members -eq '$dn'" -ErrorAction SilentlyContinue foreach ($dg in $memberDgs) { $managedBy = ($dg.ManagedBy | ForEach-Object { $_.Name }) -join '; ' $row = $resultTable.NewRow() $row.DisplayName = $dg.DisplayName $row.PrimarySmtpAddress = $dg.PrimarySmtpAddress $row.ManagedBy = $managedBy $row.RecipientTypeDetails = $dg.RecipientTypeDetails $row.MembershipType = "Member" $row.IsDynamic = if ($dg.RecipientTypeDetails -match 'Dynamic') {'Yes'} else {'No'} $resultTable.Rows.Add($row) } # Owner DGs if ($IncludeOwner) { $ownerDgs = Get-DistributionGroup -ResultSize Unlimited | Where-Object { ($_.ManagedBy -contains $dn) } foreach ($dg in $ownerDgs) { $managedBy = ($dg.ManagedBy | ForEach-Object { $_.Name }) -join '; ' $row = $resultTable.NewRow() $row.DisplayName = $dg.DisplayName $row.PrimarySmtpAddress = $dg.PrimarySmtpAddress $row.ManagedBy = $managedBy $row.RecipientTypeDetails = $dg.RecipientTypeDetails $row.MembershipType = "Owner" $row.IsDynamic = if ($dg.RecipientTypeDetails -match 'Dynamic') {'Yes'} else {'No'} $resultTable.Rows.Add($row) } } # Dynamic DG hit test (optional) if ($IncludeDynamic) { $dynamicHits = foreach ($ddg in Get-DynamicDistributionGroup -ResultSize Unlimited) { $filter = $ddg.RecipientFilter $ou = $ddg.RecipientContainer $match = Get-Recipient -ResultSize Unlimited -RecipientPreviewFilter $filter -OrganizationalUnit $ou | Where-Object { $_.PrimarySmtpAddress -ieq $TargetUpn } if ($match) { $ddg } } foreach ($dg in $dynamicHits) { # Avoid duplicates if already in table if (-not $resultTable.Select("PrimarySmtpAddress = '$($dg.PrimarySmtpAddress)' AND MembershipType='Member'").Count) { $row = $resultTable.NewRow() $row.DisplayName = $dg.DisplayName $row.PrimarySmtpAddress = $dg.PrimarySmtpAddress $row.ManagedBy = ($dg.ManagedBy | ForEach-Object { $_.Name }) -join '; ' $row.RecipientTypeDetails = $dg.RecipientTypeDetails $row.MembershipType = "Member (Dynamic Match)" $row.IsDynamic = "Yes" $resultTable.Rows.Add($row) } } } return $resultTable } catch { throw $_ } } #endregion #region GUI Build # Colors $colorBg = [System.Drawing.Color]::FromArgb(35,45,60) $colorPanel = [System.Drawing.Color]::FromArgb(50,60,80) $colorAccent = [System.Drawing.Color]::FromArgb(106,176,222) $colorText = [System.Drawing.Color]::White $fontMain = New-Object System.Drawing.Font("Segoe UI",10) $fontSmall = New-Object System.Drawing.Font("Segoe UI",7) $form = New-Object System.Windows.Forms.Form $form.Text = "Exchange Online - Distribution Groups Lookup" $form.StartPosition = "CenterScreen" $form.Size = New-Object System.Drawing.Size(1000,650) $form.BackColor = $colorBg $form.Font = $fontMain # Top panel $panelTop = New-Object System.Windows.Forms.Panel $panelTop.Dock = 'Top' $panelTop.Height = 120 $panelTop.BackColor = $colorPanel $form.Controls.Add($panelTop) # Labels / Inputs $lblAdminUpn = New-Object System.Windows.Forms.Label $lblAdminUpn.Text = "Admin UPN (for Connect):" $lblAdminUpn.ForeColor = $colorText $lblAdminUpn.Location = "20,15" $lblAdminUpn.AutoSize = $true $panelTop.Controls.Add($lblAdminUpn) $txtAdminUpn = New-Object System.Windows.Forms.TextBox $txtAdminUpn.Location = "220,12" $txtAdminUpn.Width = 250 $panelTop.Controls.Add($txtAdminUpn) $btnConnect = New-Object System.Windows.Forms.Button $btnConnect.Text = "Connect" $btnConnect.Location = "490,10" $btnConnect.Width = 100 $btnConnect.BackColor = $colorAccent $btnConnect.FlatStyle = 'Flat' $btnConnect.ForeColor = [System.Drawing.Color]::Black $panelTop.Controls.Add($btnConnect) $lblTargetUpn = New-Object System.Windows.Forms.Label $lblTargetUpn.Text = "Target User UPN:" $lblTargetUpn.ForeColor = $colorText $lblTargetUpn.Location = "20,50" $lblTargetUpn.AutoSize = $true $panelTop.Controls.Add($lblTargetUpn) $txtTargetUpn = New-Object System.Windows.Forms.TextBox $txtTargetUpn.Location = "220,47" $txtTargetUpn.Width = 250 $panelTop.Controls.Add($txtTargetUpn) $chkOwner = New-Object System.Windows.Forms.CheckBox $chkOwner.Text = "Include groups where user is OWNER" $chkOwner.ForeColor = $colorText $chkOwner.Location = "490,48" $chkOwner.Width = 260 $panelTop.Controls.Add($chkOwner) $chkDynamic = New-Object System.Windows.Forms.CheckBox $chkDynamic.Text = "Check Dynamic DG membership (slow)" $chkDynamic.ForeColor = $colorText $chkDynamic.Location = "490,70" $chkDynamic.Width = 260 $panelTop.Controls.Add($chkDynamic) $btnGet = New-Object System.Windows.Forms.Button $btnGet.Text = "Get Groups" $btnGet.Location = "770,44" $btnGet.Width = 160 $btnGet.Height = 40 $btnGet.BackColor = $colorAccent $btnGet.FlatStyle = 'Flat' $btnGet.ForeColor = [System.Drawing.Color]::Black $panelTop.Controls.Add($btnGet) # Grid $grid = New-Object System.Windows.Forms.DataGridView $grid.Dock = 'Fill' $grid.ReadOnly = $true $grid.AutoSizeColumnsMode = 'Fill' $grid.BackgroundColor = $colorBg $grid.ForeColor = [System.Drawing.Color]::Black $grid.EnableHeadersVisualStyles = $false $grid.ColumnHeadersDefaultCellStyle.BackColor = $colorAccent $grid.ColumnHeadersDefaultCellStyle.ForeColor = [System.Drawing.Color]::Black $grid.RowHeadersVisible = $false $form.Controls.Add($grid) # Bottom bar $panelBottom = New-Object System.Windows.Forms.Panel $panelBottom.Dock = 'Bottom' $panelBottom.Height = 70 $panelBottom.BackColor = $colorPanel $form.Controls.Add($panelBottom) $btnExport = New-Object System.Windows.Forms.Button $btnExport.Text = "Export CSV" $btnExport.Location = "20,15" $btnExport.Width = 110 $btnExport.BackColor = $colorAccent $btnExport.FlatStyle = 'Flat' $btnExport.ForeColor = [System.Drawing.Color]::Black $panelBottom.Controls.Add($btnExport) $btnCopy = New-Object System.Windows.Forms.Button $btnCopy.Text = "Copy to Clipboard" $btnCopy.Location = "140,15" $btnCopy.Width = 140 $btnCopy.BackColor = $colorAccent $btnCopy.FlatStyle = 'Flat' $btnCopy.ForeColor = [System.Drawing.Color]::Black $panelBottom.Controls.Add($btnCopy) $btnClear = New-Object System.Windows.Forms.Button $btnClear.Text = "Clear" $btnClear.Location = "290,15" $btnClear.Width = 90 $btnClear.BackColor = $colorAccent $btnClear.FlatStyle = 'Flat' $btnClear.ForeColor = [System.Drawing.Color]::Black $panelBottom.Controls.Add($btnClear) $btnDisconnect = New-Object System.Windows.Forms.Button $btnDisconnect.Text = "Disconnect" $btnDisconnect.Location = "390,15" $btnDisconnect.Width = 110 $btnDisconnect.BackColor = $colorAccent $btnDisconnect.FlatStyle = 'Flat' $btnDisconnect.ForeColor = [System.Drawing.Color]::Black $panelBottom.Controls.Add($btnDisconnect) $chkAutoDisc = New-Object System.Windows.Forms.CheckBox $chkAutoDisc.Text = "Auto-disconnect on close" $chkAutoDisc.ForeColor = $colorText $chkAutoDisc.Location = "520,20" $chkAutoDisc.Width = 180 $panelBottom.Controls.Add($chkAutoDisc) $statusLabel = New-Object System.Windows.Forms.Label $statusLabel.Text = "Ready." $statusLabel.ForeColor = $colorText $statusLabel.AutoSize = $true $statusLabel.Location = "720,22" $panelBottom.Controls.Add($statusLabel) # Footer $lblFooter = New-Object System.Windows.Forms.Label $lblFooter.Text = "Interactive Form Created By: Mark Snyder - All Rights Reserved!" $lblFooter.ForeColor = $colorText $lblFooter.Font = $fontSmall $lblFooter.AutoSize = $true $lblFooter.Location = New-Object System.Drawing.Point(20, $panelBottom.Top - 20) $form.Controls.Add($lblFooter) #endregion #region UI Logic $currentTable = $null function Set-Status { param([string]$msg) $statusLabel.Text = $msg [System.Windows.Forms.Application]::DoEvents() } $btnConnect.Add_Click({ Set-Status "Connecting..." Ensure-ExchangeModule if (Connect-EXO -AdminUpn $txtAdminUpn.Text) { Set-Status "Connected." } else { Set-Status "Not connected." } }) $btnGet.Add_Click({ if (-not $txtTargetUpn.Text.Trim()) { [System.Windows.Forms.MessageBox]::Show("Please enter the Target User UPN.","Missing Info", [System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Warning) | Out-Null return } Set-Status "Working..." $btnGet.Enabled = $false $btnGet.Text = "Working..." [System.Windows.Forms.Application]::DoEvents() Ensure-ExchangeModule if (-not (Test-EXOConnection)) { if (-not (Connect-EXO -AdminUpn $txtAdminUpn.Text)) { Set-Status "Connection failed." $btnGet.Enabled = $true $btnGet.Text = "Get Groups" return } } try { $table = Get-UserDGData -TargetUpn $txtTargetUpn.Text.Trim() -IncludeOwner $chkOwner.Checked -IncludeDynamic $chkDynamic.Checked $currentTable = $table $grid.DataSource = $currentTable Set-Status ("Retrieved {0} group(s)." -f $currentTable.Rows.Count) } catch { [System.Windows.Forms.MessageBox]::Show("Error retrieving data:`r`n$($_.Exception.Message)","Error", [System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Error) | Out-Null Set-Status "Error." } finally { $btnGet.Enabled = $true $btnGet.Text = "Get Groups" } }) $btnExport.Add_Click({ if (-not $currentTable -or $currentTable.Rows.Count -eq 0) { [System.Windows.Forms.MessageBox]::Show("Nothing to export.","Info",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Information) | Out-Null return } $sfd = New-Object System.Windows.Forms.SaveFileDialog $sfd.Filter = "CSV (*.csv)|*.csv" $sfd.FileName = "UserDGs.csv" if ($sfd.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { try { $currentTable | Export-Csv -NoTypeInformation -Path $sfd.FileName -Encoding UTF8 Set-Status "Saved to $($sfd.FileName)" } catch { [System.Windows.Forms.MessageBox]::Show("Export failed: $($_.Exception.Message)","Error", [System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Error) | Out-Null } } }) $btnCopy.Add_Click({ if (-not $currentTable -or $currentTable.Rows.Count -eq 0) { [System.Windows.Forms.MessageBox]::Show("Nothing to copy.","Info",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Information) | Out-Null return } $string = $currentTable | ConvertTo-Csv -NoTypeInformation | Out-String [System.Windows.Forms.Clipboard]::SetText($string) # Small toast-ish popup $popup = New-Object System.Windows.Forms.Form $popup.FormBorderStyle = 'None' $popup.StartPosition = 'Manual' $popup.BackColor = $colorAccent $popup.Size = New-Object System.Drawing.Size(200,60) $popup.TopMost = $true $popup.ShowInTaskbar = $false $popup.Location = New-Object System.Drawing.Point(($form.Location.X + $form.Width - 220), ($form.Location.Y + 40)) $lbl = New-Object System.Windows.Forms.Label $lbl.Text = "Copied to clipboard!" $lbl.AutoSize = $false $lbl.TextAlign = 'MiddleCenter' $lbl.Dock = 'Fill' $lbl.Font = New-Object System.Drawing.Font("Segoe UI",10,[System.Drawing.FontStyle]::Bold) $popup.Controls.Add($lbl) $popup.Show() $timer = New-Object System.Windows.Forms.Timer $timer.Interval = 1200 $timer.Add_Tick({ $timer.Stop(); $popup.Close(); $popup.Dispose() }) $timer.Start() }) $btnClear.Add_Click({ $grid.DataSource = $null $currentTable = $null Set-Status "Cleared." }) $btnDisconnect.Add_Click({ Disconnect-EXO-Safe Set-Status "Disconnected." }) $form.Add_FormClosing({ if ($chkAutoDisc.Checked) { Disconnect-EXO-Safe } else { $res = [System.Windows.Forms.MessageBox]::Show("Disconnect from Exchange Online now?","Disconnect?", [System.Windows.Forms.MessageBoxButtons]::YesNoCancel,[System.Windows.Forms.MessageBoxIcon]::Question) if ($res -eq [System.Windows.Forms.DialogResult]::Cancel) { $_.Cancel = $true } elseif ($res -eq [System.Windows.Forms.DialogResult]::Yes) { Disconnect-EXO-Safe } } }) #endregion [void]$form.ShowDialog()37Views0likes0CommentsInstall-Package - failed to be installed: End of Central Directory record could not be found.
Hi all, Since last week I've had multiple errors in my pipelines when trying to install NuGet packages: Install-Package -Name Microsoft.PowerBi.Api -Source MyNuGet -ProviderName NuGet -Scope CurrentUser -RequiredVersion 3.18.1 -SkipDependencies This seems to be affecting multiple packages: Install-Package : Package Newtonsoft.Json failed to be installed because: End of Central Directory record could not be found. Install-Package : Package Microsoft.Rest.ClientRuntime failed to be installed because: End of Central Directory record could not be found. Install-Package : Package Microsoft.PowerBI.Api failed to be installed because: End of Central Directory record could not be found. When downloading the package I don't see any errors using nuget verify. I get these errors in microsoft hosted agents in ADO pipelines, on my laptop, or any VM I use. Doesn't seem to be related to PS or OS version or any proxies/firewalls. Any ideas? Thank you344Views1like0CommentsPowerShell Not Creating Smartsheet Row as Expected
BACKGROUND: I created a PowerShell script that reads a Word document, extracts fields, and then creates a row on a Smartsheet with the data from that Word document...but the row created was blank, even though it showed success in PowerShell (ID's replaced with asterisks). What could I be missing? Best, Chris Hallo | email address removed for privacy reasons FROM POWERSHELL: Results: Post row to Smartsheet? (Y/N): Y Posting row to Smartsheet... ✅ Row added. Response: message : SUCCESS resultCode : 0 version : 13580 result : @{id=*; sheetId=*; rowNumber=1; expanded=True; locked=False; lockedForUser=False; createdAt=2025-07-16T19:07:35Z; modifiedAt=2025-07-16T19:07:35Z; cells=System.Object[]}23Views0likes0CommentsIssue with loop not completing as expected
I am trying to write a script that parses a text file that has been generated earlier in the script and will go line by line using the text to configure cisco switches. The issue I am running into is the script will not configure every interface as expected. It always seems to stop at interface g1/0/30 and jumping to the next device and the same thing. Here is the loop portion of my script. When I check the $counterinit before it runs this part, it reads 55 but for some reason only completes about 30. At the end of the script the $counterinit is 0. I have also posted a copy of the text file. I am very new to PS scripting and trying my best. foreach ($port in $final) { if ($counterinit -le 1){ break } if ($port -match $FM) { $process.StandardInput.WriteLine($port) $process.StandardInput.WriteLine("device-tracking attach-policy ACCESS_IPDT") $process.StandardInput.WriteLine("exit") $process.StandardInput.Flush() $counterinit-- } elseif($port -match "!") { $process.StandardInput.WriteLine("!") $process.StandardInput.Flush() $counterinit-- } }41Views0likes1CommentUpdate-AppxPackage....where is it????
hi, i am trying to update my Microsoft Store Apps using powershell. Several different sources like this: https://powershellcommands.com/update-windows-store-apps-powershell show simple code like this: Get-AppxPackage | ForEach-Object { Update-AppxPackage -Package $_.PackageFullName } the problem is that although get-appxpackage works fine, update-appxpackage throws an error....there seems to be no update-appxpackage commandlet installed on any system i have and moreover, i cannot find any documentation for this command anywhere.. am i crazy? where is this a real command, or are all these sites written by AI and just hallucinating?? thanks in advance296Views0likes3CommentsI need to remove an email from multiple exchange online mailboxes
PowerShell & Exchange Online. We had an online crime tips email sent to a distribution group in or organization. It has sensitive information related to an investigative case we're working on. We are a Law Enforcement Agency. I can connect to exchange with PowerShell but haven't been able to remove the message. Anyone have the proper syntax or guidance to share? Thank you!102Views0likes3CommentsArray and array member methods
The following PowerShell code: class MyClass { } class MyClass1 : MyClass { [void] OutMsg([string] $Str) { Write-Host -Object "MyClass1: $Str" } } class MyClass2 : MyClass { [void] OutMsg([string] $Str) { Write-Host -Object "MyClass2: $Str" } } [MyClass[]] $ClassArray = @([MyClass1]::new(), [MyClass2]::new()) $ClassArray.OutMsg('TestString') outputs: MyClass1: TestString MyClass2: TestString A Get-Member -InputObject $ClassArray shows me that the array object itself has no OutMsg method. Why can I successfully call $ClassArray.OutMsg('TestString') though (looks like this calls the OutMsg method of each array member in turn)?99Views0likes3Commentsresolve-dnsname returns odd data
hi, appreciate your time. I am working with resolve-dnsname and I am seeing some odd results. for example: resolve-dnsname -server 10.0.20.5 -name "60.16.40.194.in-addr.arpa" -NoHostsFile -type ptr Name Type TTL Section NameHost ---- ---- --- ------- -------- 60.16.40.194.in-addr.arpa. PTR 1200 Question LNB050825-LT3 so here is what's weird about this.... when I look at my dns server with dns manager and look at the reverse zone, I do not have a record for this IP address: Also, when I look at the resolve-dnsname data, I see there is something called "Section", and it is set to "Question". Also notice that the "NameHost" is short and not a FQDN. The "Section" is interesting because on requests the return the right data, Section is set to "Answer". Equally weird is that if I pick a different IP that I also know does not exist, I get this: PS C:\Trash> resolve-dnsname -server 10.0.20.5 -name "60.1.40.194.in-addr.arpa" -NoHostsFile -type ptr Resolve-DnsName: 60.1.40.194.in-addr.arpa : DNS name does not exist. this is what I would expect if the record does not exist....so what is happening in the first example? Thanks in advance for anyone's time on this.126Views0likes2Comments