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 }71Views0likes2CommentsAttempting 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.100Views0likes4CommentsCopy text always as text from Onenote
Hi there, I have the following problem: I often copy paste things from here to there which is never is any problem. Except I am copying from Onenote. Because then in most of the cases it just spits out an image of the text I copied instead of the text itself. ctrl+ shift + v often works, but not always and also it is quite annoying to remember everytime to hit shift as well, when pasting from Onenote. The only real solution I found so far was an auto hotkey script. But as I am working with this on my business PC I'd like to have a non thirdparty solution. So I thought there might be a solution to this using powershell, where it checks, if I copy text from Onenote and if so, remove formatting automatically, so I can paste it as text right away with ctrl+v Anyone came across this issue and might have a working solution already as I am not familiar with powershell unfortunately? Best regards!Solved61Views0likes1CommentError 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.79Views0likes2CommentsCopy-Item -Recurse bug
We are copying files using the Copy-Item cmdlet from a local disk to a remote disk. The source folder contains around 900 files in numerous subdirectories. Copy-Item -Path "build\image\*" -Destination $output_path -Recurse -Verbose Get-Command Copy-Item | Select-Object Name, Version Name Version ---- ------- Copy-Item 3.1.0.0177Views1like3CommentsBug: 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, Lain29Views0likes0CommentsFetch Email of Login User In System Context
Dear Team, We are working on retrieving email address of the user joined to Entra ID from Entra-joined Windows devices, specifically while running in a system context.The whoami /upn command successfully returns the joined user’s email address in a user context, but it does not work in a system context, particularly when using an elevated terminal via the psexec utility.We also tested the dsregcmd /status command; however, in a system context, the User Identity tab in the SSO State section only appears when there is an error in AzureAdPrt. Under normal, healthy operating conditions, this command does not provide the user identity or the full domain username. We would greatly appreciate guidance on how to retrieve the Entra ID joined user’s email address in a system context, especially from those with prior experience in this area. Thank you for your support.Solved137Views0likes3CommentsProblem 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, Lain61Views1like0CommentsFC Target discovery
I was looking for a way to discover FC targets for each initiator. Searching on the web I found this code # Get all initiator ports (HBA ports) $initiatorPorts = Get-InitiatorPort # Loop through each initiator port and list its targets foreach ($port in $initiatorPorts) { Write-Host "Initiator Port: $($port.NodeAddress) - $($port.PortAddress)" $targets = Get-InitiatorTarget -InitiatorPortAddress $port.PortAddress foreach ($target in $targets) { Write-Host " Target: $($target.NodeAddress) - $($target.PortAddress)" } } But is not working because the Get-initiatortarget is not recognized as valid command. Is there a way I can do it thanks99Views0likes2CommentsHelp to add some functions to PowerShell Vpn Script
Good day sorry if sounds silly I am new learning everything. I for the life of me cannot find on the documentation for VpnClient find how to add Enable software compression under PPP settings and Negotiate multi-link for single-link connections. Also how do I add like dns address with the script for like under Advanced TCP/ICP Settings? Also with Register this connections addressess in DNS and Use the connections DNS suffic in DNS registration. And also with WINS with the ip address under it. If anyone could spare some time to help me understand this would be helpful. I fear I am overthinking it way to much. I was never explained prior how any of this works.95Views0likes2CommentsCan'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?50Views0likes1CommentLocal 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)?161Views0likes2Comments.Net mail message, PowerShell and Microsoft Purview Infrmation Protection
I have a PowerShell script that using the .net mail message to send emails. We want to restrict some of those emails to a certain sensitivity (we call it classification) and restrict it to only internal users (which this label does when sending via Outlook). I have looked at a number of ways to do this but haven't come up with anything that works. Here are the issues: The smtp server is NOT in Office 365. The PowerShell window is opened as an admin account so using an Outlook interface might not work. Currently, I have it set to send remotly (A session is created with the server that is whitelisted and it actually sends the message). Any information would be of great assistance.110Views0likes2CommentsGet-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"52Views0likes2Comments