powershell
2225 TopicsApp-only authentication for unattended scripts in MicrosoftPlaces
Like other modules such as ExchangeOnline (https://learn.microsoft.com/en-us/powershell/exchange/app-only-auth-powershell-v2?view=exchange-ps) , the Microsoft Places module should include the option do an App-only authentication.Solved39Views0likes2CommentsFinding Forwards based upon to address
I have a distribution list that is designed to send an email to every mailbox associated with my company's domain. This distribution list only contains company generated mailboxes. When I send an email to this list, I get automatic replies from 2 email addresses that are not associated with my company. The emails state that those employees have new email addresses and to update my address book. The address that I get the reply from does not disclose the employee's name. All I know is that it's from a business position like school principal or school resource officer. Yes, I can lookup the name of the current office holder, but the account is generically tied to the position rather than a specific employee. The most likely cause of this is that 2 of the email accounts in my company have forwarding turned on. How do I search my company directory to find the 2 mailboxes that are forwarding to external email addresses so I can turn off that forwarding? I've read that this can be achieved with a powershell command but have not seen anything in the way of a working script. Nor do I have the slightest knowledge to write my own script.34Views0likes1CommentGet-Secret fails when PowerShell script runs as a scheduled task.
I have a PowerShell backup script that connects to SMB shares, copies files from one share to the other share, and disconnects. Passwords used to connect to the shares are stored in a SecretStore. The user account that the script runs under is an unpriviledged Backup Operator that has access to the SMB shares. THe SecretStore was created under the same user context. I can run the script manually in the console, and it executes correctly. When I run the same script as a scheduled task, running under the same user account, the script stops when the Get-Secret cmdlet is called. Here is some pertinent information: PS C:\Users\incodebackup\Documents\Scripts\TUNet_Backup> $PSVersionTable Name Value ---- ----- PSVersion 5.1.14393.3471 PSEdition Desktop PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...} BuildVersion 10.0.14393.3471 CLRVersion 4.0.30319.42000 WSManStackVersion 3.0 PSRemotingProtocolVersion 2.3 SerializationVersion 1.1.0.1 PS C:\Users\incodebackup\Documents\Scripts\TUNet_Backup> Get-Module -ListAvailable Directory: C:\Program Files\WindowsPowerShell\Modules ModuleType Version Name ExportedCommands ---------- ------- ---- ---------------- Script 1.0.1 Microsoft.PowerShell.Operation.V... {Get-OperationValidation, Invoke-OperationValidation} Binary 1.1.2 Microsoft.PowerShell.SecretManag... {Register-SecretVault, Unregister-SecretVault, Get-SecretVault, Set-SecretVaultDefault...} Binary 1.0.6 Microsoft.PowerShell.SecretStore {Unlock-SecretStore, Set-SecretStorePassword, Get-SecretStoreConfiguration, Set-SecretStoreConfiguration...} PS C:\Users\incodebackup\Documents\Scripts\TUNet_Backup> Get-SCheduledTask | Format-List -Property * State : Ready Actions : {MSFT_TaskExecAction} Author : WIN-M95PVJLVDAB\incodebackup Date : 2026-01-27T15:28:35.7952875 Description : This task copies files out of the TUNET/datafile directory once a say to ARCHIBALD. Documentation : Principal : MSFT_TaskPrincipal2 SecurityDescriptor : Settings : MSFT_TaskSettings3 Source : TaskName : Daily TUNet Backup Copy TaskPath : \ Triggers : {MSFT_TaskDailyTrigger} URI : \Daily TUNet Backup Copy Version : PSComputerName : CimClass : Root/Microsoft/Windows/TaskScheduler:MSFT_ScheduledTask CimInstanceProperties : {Actions, Author, Date, Description...} CimSystemProperties : Microsoft.Management.Infrastructure.CimSystemProperties I execute Start-Transcript early in the script execution, and because of the crash(?), it is short enough to included in its entirety: ********************** Windows PowerShell transcript start Start time: 20260127190002 Username: WIN-M95PVJLVDAB\incodebackup RunAs User: WIN-M95PVJLVDAB\incodebackup Machine: WIN-M95PVJLVDAB (Microsoft Windows NT 10.0.14393.0) Host Application: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -NonInteractive -File C:\Users\Incodebackup\Documents\Scripts\TUNet_Backup\Copy-TUNetBackup.ps1 -daily -test Process ID: 2084 PSVersion: 5.1.14393.3471 PSEdition: Desktop PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.14393.3471 BuildVersion: 10.0.14393.3471 CLRVersion: 4.0.30319.42000 WSManStackVersion: 3.0 PSRemotingProtocolVersion: 2.3 SerializationVersion: 1.1.0.1 ********************** Transcript started, output file is C:\Users\Incodebackup\Documents\Scripts\TUNet_Backup\daily_2026-01-27_190002.log 2026/01/27 19:00:02 INFO 940 TUNet backup script started. 2026/01/27 19:00:02 INFO 941 Copy-TUNetBackup.ps1 Version: 6.0F 2026/01/27 19:00:02 INFO 942 Parameter qhourly: False 2026/01/27 19:00:02 INFO 943 Parameter hourly: False 2026/01/27 19:00:02 INFO 944 Parameter daily: True 2026/01/27 19:00:02 INFO 945 Parameter purge: False 2026/01/27 19:00:02 INFO 946 Parameter archive: False 2026/01/27 19:00:02 INFO 947 Parameter test: True 2026/01/27 19:00:02 INFO 1035 Creating mutex object. 2026/01/27 19:00:02 INFO 1037 Creating semaphore object. 2026/01/27 19:00:02 INFO 1058 Mutex timeout set: 300000 2026/01/27 19:00:02 INFO 1072 Attempting to acquire mutex to enter semaphore... 2026/01/27 19:00:02 INFO 1074 ...got the mutex! 2026/01/27 19:00:02 INFO 1075 Attempting to enter the semaphore... 2026/01/27 19:00:02 INFO 1077 ... got the semaphore! 2026/01/27 19:00:02 INFO 719 Release-Mutex: Attempting to release mutex... 2026/01/27 19:00:02 INFO 721 Release-Mutex: ...done. 2026/01/27 19:00:02 INFO 1090 Using TEST values for source and destination paths. 2026/01/27 19:00:02 INFO 1109 TUnet Source: \\192.168.100.46\Netbackup\Netbackup\Tantalus\test_src\datafile 2026/01/27 19:00:02 INFO 1110 ARCHIE Dest: \\192.168.100.46\Netbackup\Netbackup\Tantalus\test_dest\datafile 2026/01/27 19:00:02 INFO 1114 Attempt to acquire mutex to mount network shares... 2026/01/27 19:00:02 INFO 1116 ...got the mutex! 2026/01/27 19:00:02 INFO 1117 Opening SecretStore vault...! 2026/01/27 19:00:02 INFO 1120 ... vault opened! 2026/01/27 19:00:02 INFO 1121 Checking connection to \\192.168.100.46\Netbackup\Netbackup\Tantalus ... 2026/01/27 19:00:02 INFO 1126 ...not connected to \\192.168.100.46\Netbackup\Netbackup\Tantalus . 2026/01/27 19:00:02 INFO 1127 Get FULTON\incodebackup password... ********************** Windows PowerShell transcript end End time: 20260127190002 ********************** Now I will show you the script around line 1127 where it goes out into the weeds: Write-Log -Level "INFO" -Message "$(__LINE__) Opening SecretStore vault...!" $pw = Import-CliXml -Path '.\TUNet-Backup-Vault.xml' -Verbose Unlock-SecretStore -Password $pw Write-Log -Level "INFO" -Message "$(__LINE__) ... vault opened!" # # Statements omitted # Write-Log -Level "INFO" -Message "$(__LINE__) Get $archie_un password..." try { $pw = Get-Secret -Name $archie_un -Verbose -Debug } catch { $err_msg = "Get-Secret exception. Name: $archie_un Exception: $($_.Exception.Message)" Write-Log -Level "FATAL" -Message "$(__LINE__) $err_msg" throw $err_msg } Write-Log -Level "INFO" -Message "$(__LINE__) ...done!" I was able to unlock the SecretStore, but Get-Secret fails. The very odd thing, besides not getting my password out the SecretStore, is that there is no exception posted by Powershell. I have no information at all about why my attempt did not work. If Get-Secret exited, then I would expect one of the two possible log messages printed in the transcript, but as you can see, the transcript ended. Note: the entire script body is encapsulated in a try{} block, which has an associated finally{} block, which contains other logging commands that execute when the finally{} block is entered, but in scheduled task instance, nothing. If anyone can tell me how to make Get-Secret work, that would be great, but I'll settle very gratefully for some way to get more information from this system to try to figure out why it is not, that would be most helpful. Additional information supplied on request.94Views0likes2CommentsCan't connect with GDAP using ExchangeOnlineManagement 3.7.0/3.8.0, but 3.6.0 works
Since upgrading to ExchangeOnlineManagement version 3.7.0, I've been unable to connect to any of my clients using GDAP. I thought I'd try upgrading to 3.8.0, but I still get the same error: PS C:\Users\username> connect-exchangeonline -userprincipalname email address removed for privacy reasons -DelegatedOrganization contoso.com ---------------------------------------------------------------------------------------- This V3 EXO PowerShell module contains new REST API backed Exchange Online cmdlets which doesn't require WinRM for Client-Server communication. You can now run these cmdlets after turning off WinRM Basic Auth in your client machine thus making it more secure. Unlike the EXO* prefixed cmdlets, the cmdlets in this module support full functional parity with the RPS (V1) cmdlets. V3 cmdlets in the downloaded module are resilient to transient failures, handling retries and throttling errors inherently. REST backed EOP and SCC cmdlets are also available in the V3 module. Similar to EXO, the cmdlets can be run without WinRM basic auth enabled. For more information check https://aka.ms/exov3-module Starting with EXO V3.7, use the LoadCmdletHelp parameter alongside Connect-ExchangeOnline to access the Get-Help cmdlet, as it will not be loaded by default ---------------------------------------------------------------------------------------- The role assigned to user email address removed for privacy reasons isn't supported in this scenario. Please check online documentation for assigning correct Directory Roles to User. At C:\Users\username\OneDrive - MSP\Documents\WindowsPowerShell\Modules\ExchangeOnlineManagement\3.7.2\netFramework\ ExchangeOnlineManagement.psm1:758 char:21 + throw $_.Exception; + ~~~~~~~~~~~~~~~~~~ + CategoryInfo : OperationStopped: (:) [], SystemException + FullyQualifiedErrorId : The role assigned to user email address removed for privacy reasons isn't supported in this scenario. Please check online documentation for assigning correct Directory Roles to User. You'd think there'd be something wrong with my GDAP permissions, but there doesn't appear to be. I can do anything via the Microsoft 365 Admin Center. Plus, most notably, if I manually load ExchangeOnlineManagement 3.6.0, everything works perfectly. I'm running Windows 11, and this behavior is reproducible on Windows PowerShell 5.1 as well as my preferred PowerShell 7.5.2. How can I troubleshoot this?443Views1like3CommentsI built a free, open-source M365 security assessment tool - looking for feedback
I work as an IT consultant, and a good chunk of my time is spent assessing Microsoft 365 environments for small and mid-sized businesses. Every engagement started the same way: connect to five different PowerShell modules, run dozens of commands across Entra ID, Exchange Online, Defender, SharePoint, and Teams, manually compare each setting against CIS benchmarks, then spend hours assembling everything into a report the client could actually read. The tools that automate this either cost thousands per year, require standing up Azure infrastructure just to run, or only cover one service area. I wanted something simpler: one command that connects, assesses, and produces a client-ready deliverable. So I built it. What M365 Assess does https://github.com/Daren9m/M365-Assess is a PowerShell-based security assessment tool that runs against a Microsoft 365 tenant and produces a comprehensive set of reports. Here is what you get from a single run: 57 automated security checks aligned to the CIS Microsoft 365 Foundations Benchmark v6.0.1, covering Entra ID, Exchange Online, Defender for Office 365, SharePoint Online, and Teams 12 compliance frameworks mapped simultaneously -- every finding is cross-referenced against NIST 800-53, NIST CSF 2.0, ISO 27001:2022, SOC 2, HIPAA, PCI DSS v4.0.1, CMMC 2.0, CISA SCuBA, and DISA STIG (plus CIS profiles for E3 L1/L2 and E5 L1/L2) 20+ CSV exports covering users, mailboxes, MFA status, admin roles, conditional access policies, mail flow rules, device compliance, and more A self-contained HTML report with an executive summary, severity badges, sortable tables, and a compliance overview dashboard -- no external dependencies, fully base64-encoded, just open it in any browser or email it directly The entire assessment is read-only. It never modifies tenant settings. Only Get-* cmdlets are used. A few things I'm proud of Real-time progress in the console. As the assessment runs, you see each check complete with live status indicators and timing. No staring at a blank terminal wondering if it hung. The HTML report is a single file. Logos, backgrounds, fonts -- everything is embedded. You can email the report as an attachment and it renders perfectly. It supports dark mode (auto-detects system preference), and all tables are sortable by clicking column headers. Compliance framework mapping. This was the feature that took the most work. The compliance overview shows coverage percentages across all 12 frameworks, with drill-down to individual controls. Each finding links back to its CIS control ID and maps to every applicable framework control. Pass/Fail detail tables. Each security check shows the CIS control reference, what was checked, what the expected value is, what the actual value is, and a clear Pass/Fail/Warning status. Findings include remediation descriptions to help prioritize fixes. Quick start If you want to try it out, it takes about 5 minutes to get running: # Install prerequisites (if you don't have them already) Install-Module Microsoft.Graph, ExchangeOnlineManagement -Scope CurrentUser Clone and run git clone https://github.com/Daren9m/M365-Assess.git cd M365-Assess .\Invoke-M365Assessment.ps1 The interactive wizard walks you through selecting assessment sections, entering your tenant ID, and choosing an authentication method (interactive browser login, certificate-based, or pre-existing connections). Results land in a timestamped folder with all CSVs and the HTML report. Requires PowerShell 7.x and runs on Windows (macOS and Linux are experimental -- I would love help testing those platforms). Cloud support M365 Assess works with: Commercial (global) tenants GCC, GCC High, and DoD environments If you work in government cloud, the tool handles the different endpoint URIs automatically. What is next This is actively maintained and I have a roadmap of improvements: More automated checks -- 140 CIS v6.0.1 controls are tracked in the registry, with 57 automated today. Expanding coverage is the top priority. Remediation commands -- PowerShell snippets and portal steps for each finding, so you can fix issues directly from the report. XLSX compliance matrix -- A spreadsheet export for audit teams who need to work in Excel. Standalone report regeneration -- Re-run the report from existing CSV data without re-assessing the tenant. I would love your feedback I have been building this for my own consulting work, but I think it could be useful to the broader community. If you try it, I would genuinely appreciate hearing: What checks should I prioritize next? Which security controls matter most in your environment? What compliance frameworks are most requested by your clients or auditors? How does the report land with non-technical stakeholders? Is the executive summary useful, or does it need work? macOS/Linux users -- does it run? What breaks? I have tested it on macOS, but not extensively. Bug reports, feature requests, and contributions are all welcome on GitHub. Repository: https://github.com/Daren9m/M365-Assess License: MIT (free for commercial and personal use) Runtime: PowerShell 7.x Thanks for reading. Happy to answer any questions in the comments.564Views1like1CommentTotal Size of Preservation Hold Libraries
Hello All, I am wondering if someone can help with a PowerShell script to retrieve the size of Preservation hold libraries in all the SharePoint Sites and OneDrive. I need to calculate the total space being used by items in Preservation Hold Libraries in our tenant. Thanks so much for the help in advance.15KViews0likes7CommentsAutomating SharePoint Site Status Reporting with PowerShell
Introduction Migrating Microsoft 365 workloads is a critical step during organizational transitions such as mergers or de‑mergers. SharePoint site collections often contain business‑critical data, and ensuring visibility into their readiness is essential for a smooth migration. To address this, I developed a PowerShell script that automatically generates a SharePoint Site Status Report, categorizing sites into Active, Read‑Only, and Offline. This report provides administrators and migration engineers with actionable insights to plan and execute migrations confidently. Why This Matters Visibility: Quickly assess site readiness across all web applications. Governance: Ensure compliance and proper access controls. Efficiency: Automate reporting to reduce manual effort. Risk Mitigation: Identify offline or read‑only sites before migration. How It Works The script leverages the SharePoint Management Shell and runs under the Farm Account with elevated permissions. It performs the following steps: Loads SharePoint cmdlets. Iterates through all web applications. Categorizes sites into Active, Read‑Only, and Offline. Compiles results into a structured CSV/Excel/HTML report. Sends the report via email to stakeholders. Key PowerShell Cmdlets Add-PSSnapin Microsoft.SharePoint.PowerShell Get-SPWebApplication Get-SPSite -WebApplication -Limit All $site.ReadOnly / $site.Status Export-Csv Send-MailMessage Parameters to Replace Before running the script, update these placeholders: SMTP Server → mail.company.com → replace with your mail server Sender Address ($from) → email address removed for privacy reasons → replace with reporting account Recipient Address ($to) → email address removed for privacy reasons → replace with stakeholder distribution list Email Subject ($subject) → "SharePoint Site Status Report" → customize for clarity Report File Path ($csvPath) → C:\Reports\SharePoint_SiteStatusReport.csv → replace with desired location Web Application URLs → ensure correct farm references Execution Context → must run under Farm Account Conclusion This automated reporting solution provides clarity, governance, and efficiency during SharePoint migrations. By categorizing sites and delivering structured reports, administrators can prioritize tasks, mitigate risks, and ensure a seamless transition to Microsoft 365. Code: #Adding Snapin for SharePoint #Add-PSSnapin Microsoft.SharePoint.Powershell -ErrorAction SilentlyContinue $TodayDate =Get-Date Write-Host $TodayDate $FileName = "C:\Results_Active_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } $FileName = "C:\Results_NoAccess_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } $FileName = "C:\Results_Readonly_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } $FileName = "C:\Results_Active_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } $FileName = "C:\Results_Readonly_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } $FileName = "C:\Results_NoAccess_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } $FileName = "C:\Results_Active_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } $FileName = "C:\Results_Readonly_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } $FileName = "C:\Results_NoAccess_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } $FileName = "C:\Results_Active_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } $FileName = "C:\Results_Readonly_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } $FileName = "C:\Results_NoAccess_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } ##My Connect # $FileName = "C:\Results_Active_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } # $FileName = "C:\Results_Readonly_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } # $FileName = "C:\Results_NoAccess_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } # # WebSites $FileName = "C:\Results_Active_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } # $FileName = "C:\Results_Readonly_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } # $FileName = "C:\Results_NoAccess_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } # ##Websites # $FileName = "C:\Results_Active_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } # $FileName = "C:\Results_Readonly_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } # $FileName = "C:\Results_NoAccess_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } # ## Websites # $FileName = "C:\Results_Active_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } # $FileName = "C:\Results_Readonly_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } # $FileName = "C:\Results_NoAccess_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } # ##FGC-SalesShareWebSites # $FileName = "C:\Results_Active_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } # $FileName = "C:\Results_Readonly_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } # $FileName = "C:\Results_NoAccess_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } ##WebSites # $FileName = "C:\Results_Active_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } # $FileName = "C:\Results_Readonly_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } # $FileName = "C:\Results_NoAccess_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } ##WebSites # $FileName = "C:\Results_Active_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } # $FileName = "C:\Results_Readonly_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } # $FileName = "C:\Results_NoAccess_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } ##WebSites # $FileName = "C:\Results_Active_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } # $FileName = "C:\Results_Readonly_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } # $FileName = "C:\Results_NoAccess_WebSites.txt" if (Test-Path $FileName) { Remove-Item $FileName } Add-PSSnapin Microsoft.SharePoint.Powershell [string[]]$WebapplicationList = "" Foreach($Webapp in $WebapplicationList) { Write-Host $Webapp $displaywebappname=Get-SPWebApplication $webapp $webappname=$displaywebappname.name Write-Host $webappname $Sites = Get-SPWebApplication $webapp | Get-SPSite -limit all | foreach { if ($_.ReadOnly -eq $false -and $_.ReadLocked -eq $false -and $_.WriteLocked -eq $false) { $Result =”Site is Active” $save2= "Results_Active_${webappname}.txt" #Write-Host $save2 $saveCSVactive="Results_Active_${webappname}.csv" $_.RootWeb.Title +”`t” + $_.URL + “`t” + $Result | Out-File $save2 -append #$_.RootWeb.Title +”`t” + $_.URL + “`t” + $Result | Out-File $saveCSVactive -Append } elseif ($_.ReadOnly -eq $true -and $_.ReadLocked -eq $false -and $_.WriteLocked -eq $true) { $Result = “Site is Read-Only” $save1= "Results_Readonly_${webappname}.txt" $_.RootWeb.Title +”`t” + $_.URL + “`t” + $Result | Out-File $save1 -Append } elseif ($_.ReadOnly -eq $null -and $_.ReadLocked -eq $null -and $_.WriteLocked -eq $null) { $Result=”Site status is No Access” $save3= "Results_NoAccess_${webappname}.txt" #$_.RootWeb.Title +”`t” + $_.URL + “`t” + $Result | Out-File $save3 -Append $_.URL +”`t” + $_.RootWeb.Title + “`t” + $Result | Out-File $save3 -Append } } } $TodayDate =Get-Date Write-Host $TodayDate sleep -Seconds 100 #Active Sites WebSites $ActiveSites_Websites= Get-Content -Path "C:\Results_Active_WebSites.txt" | Measure-Object Write-Host "Websites Active sites" $ActiveSites_Websites.count $Websites_ActiveSitescount = $ActiveSites_Websites.count #Read-only Sites WebSites $ReadonlySites_Websites=Get-Content -Path "C:\Results_Readonly_WebSites.txt" | Measure-Object Write-Host "Websites Read-only Sites" $ReadonlySites_Websites.count $Websites_Readonlysitescount=$ReadonlySites_Websites.count #No-Access Sites WebSites $NoaccessSies_Websites= Get-Content -Path "C:\Results_NoAccess_WebSites.txt" | Measure-Object Write-Host "Websites No-Access Sites" $NoaccessSies_Websites.count $Websites_NoAccessSitesCount=$NoaccessSies_Websites.count #Active Sites WebSites $ActiveSites_WebSites= Get-Content -Path "C:\Results_Active_WebSites.txt" | Measure-Object Write-Host "WebSites Active sites" $ActiveSites_WebSites.count $WebSites_ActiveSitescount = $ActiveSites_WebSites.count #Read-only Sites WebSites #$Readonlysite_WebSites =Get-Content -Path C:\Results_Readonly_Websites.txt | Measure-Object #If($Readonlysite_WebSites -eq $null) #{ #$WebSites_Readonlysitecount ="0" #} #else{ $Readonlysite_WebSites =Get-Content -Path "C:\Results_Readonly_WebSites.txt" | Measure-Object Write-Host "WebSites Readonly Sites" $Readonlysite_WebSites.count $WebSites_ReadonlySitesCount= $Readonlysite_WebSites.count # Write-Host $WebSites_ReadonlySitesCount #} #WebSites - No Access Sites #$NoAccessSites_WebSites= Get-Content -Path "C:\Results_NoAccess_Websites.txt" $NoAccessSites_WebSites= Get-Content -Path "C:\Results_NoAccess_WebSites.txt" | Measure-Object Write-Host "WebSites NoAccess Sites" $NoAccessSites_WebSites.count # #Write-Host "Site Count $($NoAccessSites_WebSites.Count)" $WebSites_NoAccessSitesCount= $NoAccessSites_WebSites.count ################################################################## # #Active Sites Websites $ActiveSites_WebSites= Get-Content -Path "C:\Results_Active_Websites.txt" | Measure-Object Write-Host "WebSites Active sites" $ActiveSites_WebSites.count $WebSites_ActiveSitescount = $ActiveSites_WebSites.count # # #Read-only Sites WebSites $ReadonlySites_WebSites=Get-Content -Path "C:\Results_Readonly_Websites.txt" | Measure-Object Write-Host "WebSites Read-only Sites" $ReadonlySites_WebSites.count $WebSites_Readonlysitescount=$ReadonlySites_WebSites.count # # #No-Access Sites WebSites $NoaccessSies_WebSites= Get-Content -Path "C:\Results_NoAccess_Websites.txt" | Measure-Object Write-Host "WebSites No-Access Sites" $NoaccessSies_WebSites.count $WebSites_NoAccessSitesCount=$NoaccessSies_WebSites.count # # #Active Sites Websites $ActiveSites_WebSites= Get-Content -Path "C:\Results_Active_Websites.txt" | Measure-Object Write-Host "WebSites Active sites" $ActiveSites_WebSites.count $WebSites_ActiveSitescount = $ActiveSites_WebSites.count # # #Read-only Sites WebSites $ReadonlySites_WebSites=Get-Content -Path "C:\Results_Readonly_Websites.txt" | Measure-Object Write-Host "WebSites Read-only Sites" $ReadonlySites_WebSites.count $WebSites_Readonlysitescount=$ReadonlySites_WebSites.count # # #No-Access Sites WebSites $NoaccessSies_WebSites= Get-Content -Path "C:\Prod\Results_NoAccess_Websites.txt" | Measure-Object Write-Host "WebSites No-Access Sites" $NoaccessSies_WebSites.count $WebSites_NoAccessSitesCount=$NoaccessSies_WebSites.count # # #WebSites # # #Active Sites WebSites ##$ActiveSites_WebSites= Get-Content -Path "C:\Results_Active_WebSites.txt" | Measure-Object ##Write-Host "WebSites Active sites" $ActiveSites_WebSites.count ##$WebSites_ActiveSitescount = $ActiveSites_WebSites.count # # #Read-only Sites WebSites ##$ReadonlySites_WebSites=Get-Content -Path "C:\Results_Readonly_WebSites.txt" | Measure-Object ##Write-Host "WebSites Read-only Sites" $ReadonlySites_WebSites.count ##$WebSites_Readonlysitescount=$ReadonlySites_WebSites.count # # #No-Access Sites WebSites ##$NoaccessSies_WebSites= Get-Content -Path "C:\Results_NoAccess_WebSites" | Measure-Object ##Write-Host "WebSites No-Access Sites" $NoaccessSies_WebSites.count ##$WebSites_NoAccessSitesCount=$NoaccessSies_WebSites.count # # #WebSites # # #Active Sites WebSites ##$ActiveSites_WebSites= Get-Content -Path "C:\Results_Active_WebSites.txt" | Measure-Object ##Write-Host "WebSites Active sites" $ActiveSites_WebSites.count ##$WebSites_ActiveSitescount = $ActiveSites_WebSites.count # # #Read-only Sites WebSites ##$ReadonlySites_WebSites=Get-Content -Path "C:\Results_Readonly_WebSites.txt" | Measure-Object ##Write-Host "WebSites Web Read-only Sites" $ReadonlySites_WebSites.count ##$WebSites_Readonlysitescount=$ReadonlySites_WebSites.count # # #No-Access Sites WebSites ##$NoaccessSies_WebSites= Get-Content -Path "C:\Results_NoAccess_WebSites.txt" | Measure-Object ##Write-Host "WebSites Web No-Access Sites" $NoaccessSies_WebSites.count ##$WebSites_NoAccessSitesCount=$NoaccessSies_WebSites.count # # #Websites # # #Active Sites Websites ##$ActiveSites_Websites= Get-Content -Path "C:\Results_Active_WebSites.txt" | Measure-Object ##Write-Host "Websites Active sites" $ActiveSites_Websites.count ##$Websites_ActiveSitescount = $ActiveSites_Websites.count # # #Read-only Sites Websites ##$ReadonlySites_Websites=Get-Content -Path "C:\Results_Readonly_WebSites.txt" | Measure-Object ##Write-Host "Websites Read-only Sites" $ReadonlySites_Websites.count ##$Websites_Readonlysitescount=$ReadonlySites_Websites.count # # #No-Access Sites Websites ##$NoaccessSies_Websites= Get-Content -Path "C:\Results_NoAccess_WebSites.txt" | Measure-Object ##Write-Host "Websites No-Access Sites" $NoaccessSies_Websites.count ##$Websites_NoAccessSitesCount=$NoaccessSies_Websites.count # # #Websites # # #Active Sites Websites ##$ActiveSites_Websites= Get-Content -Path "C:\Results_Active_WebSites.txt" | Measure-Object ##Write-Host "Websites Active sites" $ActiveSites_Websites.count ##$Websites_ActiveSitescount = $ActiveSites_Websites.count # # #Read-only Sites Websites ##$ReadonlySites_Websites=Get-Content -Path "C:\Results_Readonly_WebSites.txt" | Measure-Object ##Write-Host "Websites Read-only Sites" $ReadonlySites_Websites.count ##$Websites_Readonlysitescount= $ReadonlySites_Websites.count # # #No-Access Sites Websites ##$NoaccessSies_Websites= Get-Content -Path "C:\Results_NoAccess_WebSites.txt" | Measure-Object ##Write-Host "Websites No-Access Sites" $$NoaccessSies_Websites.count ##$Websites_NoAccessSitesCount=$NoaccessSies_Websites.count # # #Websites # # #Active Sites Websites ##$ActiveSites_Websites= Get-Content -Path "C:\Results_Active_WebSites.txt" | Measure-Object ##Write-Host "Websites Active sites" $ActiveSites_Websites.count ##$Websites_ActiveSitescount = $ActiveSites_Websites.count # # #Read-only Sites Websites ##$ReadonlySites_Websites=Get-Content -Path "C:\Results_Readonly_WebSites.txt" | Measure-Object ##Write-Host "Websites Read-only Sites" $ReadonlySites_Websites.count ##$Websites_Readonlysitescount=$ReadonlySites_Websites.count # # #No-Access Sites Websites ##$NoaccessSies_Websites= Get-Content -Path "C:\Results_NoAccess_WebSites.txt" | Measure-Object ##Write-Host "Websites No-Access Sites" $NoaccessSies_Websites.count ##$Websites_NoAccessSitesCount=$NoaccessSies_Websites.count # #WebSites # # #Active Sites Websites ##$ActiveSites_Websites= Get-Content -Path "C:\Results_Active_WebSites.txt" | Measure-Object ##Write-Host "Websites Active sites" $ActiveSites_Websites.count ##$Websites_ActiveSitescount = $ActiveSites_Websites.count # # #Read-only Sites Websites ##$ReadonlySites_Websites= Get-Content -Path "C:\Results_Readonly_WebSites.txt" | Measure-Object ##Write-Host "Websites Read-only Sites" $ReadonlySites_Websites.count ##$Websites_Readonlysitescount=$ReadonlySites_Websites.count # # #No-Access Sites Websites ##$NoaccessSies_Websites= Get-Content -Path "C:\Results_NoAccess_WebSites.txt" | Measure-Object ##Write-Host "Websites No-Access Sites" $NoaccessSies_Websites.count ##$Websites_NoAccessSitesCount=$NoaccessSies_Websites.count # #WebSites # # #Active Sites Websites ##$ActiveSites_Websites= Get-Content -Path "C:\Results_Active_WebSites.txt" | Measure-Object ##Write-Host "Websites Active sites" $ActiveSites_Websites.count ##$Websites_ActiveSitescount = $ActiveSites_Websites.count # # #Read-only Sites Websites ##$ReadonlySites_Websites= Get-Content -Path "C:\Results_Readonly_WebSites.txt" | Measure-Object ##Write-Host "Websites Read-only Sites" $ReadonlySites_Websites.count ##$Websites_Readonlysitescount=$ReadonlySites_Websites.count # # #No-Access Sites Websites ##$NoaccessSies_Websites= Get-Content -Path "C:\Results_NoAccess_WebSites.txt" | Measure-Object ##Write-Host "Websites No-Access Sites" $NoaccessSies_Websites.count ##$Websites_NoAccessSitesCount=$NoaccessSies_Websites.count # #WebSites # # #Active Sites Websites ##$ActiveSites_Websites= Get-Content -Path "C:\Results_Active_WebSites.txt" | Measure-Object ## Write-Host "Websites Active sites" $ActiveSites_Websites.count ##$Websites_ActiveSitescount = $ActiveSites_Websites.count # # #Read-only Sites Websites ## $ReadonlySites_Websites= Get-Content -Path "C:\Results_Readonly_WebSites.txt" | Measure-Object ##Write-Host "Websites Read-only Sites" $ReadonlySites_Websites.count ##$Websites_Readonlysitescount=$ReadonlySites_Websites.count # # #No-Access Sites Websites ##$NoaccessSies_Websites= Get-Content -Path "C:\Results_NoAccess_WebSites.txt" | Measure-Object ##Write-Host "Websites No-Access Sites" $NoaccessSies_Websites.count ##$Websites_NoAccessSitesCount=$NoaccessSies_Websites.count $TotalActiveSite = ($Websites_ActiveSitescount + $WebSites_ActiveSitescount + $WebSites_ActiveSitescount + $WebSites_ActiveSitescount + $WebSites_ActiveSitescount + $WebSites_ActiveSitescount + $Websites_ActiveSitescount + $CTLQwest_ActiveSitescount + $RecordsCenter_ActiveSitescount + $Websites_ActiveSitescount + $Websites_ActiveSitescount + $Websites_ActiveSitescount + $Websites_ActiveSitescount + $Websites_ActiveSitescount) $TotalReadonlySites = ($Websites_Readonlysitescount + $WebSites_ReadonlySitesCount + $WebSites_Readonlysitescount + $WebSites_Readonlysitescount + $WebSites_Readonlysitescount + $WebSites_Readonlysitescount + $Websites_Readonlysitescount + $Websites_Readonlysitescount + $Websites_Readonlysitescount + $Websites_Readonlysitescount + $Websites_Readonlysitescount + $Websites_Readonlysitescount) $TotalNoAccessSite = ($Websites_NoAccessSitesCount + $WebSites_NoAccessSitesCount + $WebSites_NoAccessSitesCount + $WebSites_NoAccessSitesCount + $WebSites_NoAccessSitesCount + $WebSites_NoAccessSitesCount + $Websites_NoAccessSitesCount + $Websites_NoAccessSitesCount + $Websites_NoAccessSitesCount + $Websites_NoAccessSitesCount + $Websites_NoAccessSitesCount + $Websites_NoAccessSitesCount) #Total Sites $TotalWebSites = ($WebSites_ActiveSitescount + $WebSites_Readonlysitescount + $WebSites_NoAccessSitesCount) $TotalWebSites = ($WebSites_ActiveSitescount + $WebSites_ReadonlySitesCount + $WebSites_NoAccessSitesCount) $TotalWebSites = ($WebSites_ActiveSitescount + $WebSites_Readonlysitescount + $WebSites_NoAccessSitesCount) $TotalWebSites = ($WebSites_ActiveSitescount + $WebSites_Readonlysitescount + $WebSites_NoAccessSitesCount) $TotalWebSites = ($WebSites_ActiveSitescount + $WebSites_Readonlysitescount + $WebSites_NoAccessSitesCount) $TotalWebSites = ($WebSites_ActiveSitescount + $WebSites_Readonlysitescount + $WebSites_NoAccessSitesCount) $TotalWebSites = ($Websites_ActiveSitescount + $Websites_Readonlysitescount + $Websites_NoAccessSitesCount) $TotalWebSites = ($Websites_ActiveSitescount + $Websites_Readonlysitescount + $Websites_NoAccessSitesCount) $TotalWebSites =($Websites_ActiveSitescount + $Websites_Readonlysitescount + $Websites_NoAccessSitesCount) $TotalWebSites = ($Websites_ActiveSitescount + $Websites_Readonlysitescount + $Websites_NoAccessSitesCount) $TotalWebSites = ($Websites_ActiveSitescount + $Websites_Readonlysitescount + $Websites_NoAccessSitesCount) $TotalWebSites = ($Websites_ActiveSitescount + $Websites_Readonlysitescount + $Websites_NoAccessSitesCount) #====== All Sites Count $TotalSites =($TotalWebSites + $TotalWebSites + $TotalWebSites + $TotalWebSites + $TotalWebSites + $TotalWebSites + $TotalWebSites + $TotalWebSites + $TotalWebSites + $TotalWebSites + $TotalWebSites + $TotalWebSites) #Sending Email #================ #[string[]]$recipients = "" $recipients11 = @("") #[string[]]$recipients = "" # "" $smtp = "smtp" #$to = $recipients11 $from = "" #$from = "" $subject = "SharePoint Sites Current Status" $body = " <b> <font color=Navy> Date -$todaydate </b> </font> <br>" #$attachment11="C:\Results_Active_Web.txt","C:\Results_Active_Web.txt" #$body = " <b><font color=red> SP-Apps Read-only Sites Count - $Readonlysitecount </b></font> <br>" #$body += " <b><font color=red> SP-Apps Active Sites Count - $ActiveSitescount </b></font> <br>" #$body += " <b><font color=red> SP-Apps No-Access Sites Count - $NoAccessSiteCount </b></font> <br>" #$body += "Click <a href=http://www.google.com>here</a> to open google <br>" #### Now send the email using \> Send-MailMessage #========= $report = "<html> <style> {font-family: Arial; font-size: 15pt;color: #F70707; } {color:#F70707;} TABLE{border: 1px solid black; border-collapse: collapse; font-size:15pt;} #TH{border: 1px solid black; background: #F4D03F; padding: 5px; color: #000000;} TR{color: #2E86C1;text-align: center;background: #13B5ED; padding: 5px; color: #0F0F0F;} TR{color: #2E86C1;text-align: center;background: #13B5ED; padding: 5px; color: #0F0F0F;} TH{border: 1px solid black; background: #F4D03F; padding: 5px; color: #F70707;} TD{border: 1px solid black; padding: 5px; } H2{color: #F70707;} H1{Color: #0C0B0A;} </style> <h1> SharePoint Sites Current Status</h1> <table> <tr> <td> <b> Web Application </b> </td> <td> <b> Active Sites </b> </td> <td> <b> Read-Only Sites </b> </td> <td> <b> No-Access (Locked) Sites </b></td> <td> <b> Total Sites </b> </td> <tr> <tr> <td> <b> Web Application </b> </td> <td> $Web_ActiveSitescount </td> <td> $Web_Readonlysitescount</td> <td> $Web_NoAccessSitesCount </td> <td> <b> $TotalWebSites </b> </td> </tr> <tr> <td> <b> Web Application </b> </td> <td> $Web_ActiveSitescount </td> <td> $Web_ReadonlySitesCount</td> <td> $Web_NoAccessSitesCount </td> <td> <b> $TotalWebSites </b> </td> </tr> <tr> <td> <b> Web Application </b> </td> <td> $Web_ActiveSitescount </td> <td> $Web_Readonlysitescount </td> <td> $Web_NoAccessSitesCount </td> <td> <b> $TotalWebSites </b> </td> </tr> <tr> <td> <b> Web Application </b> </td> <td> $Web_ActiveSitescount </td> <td> $Web_Readonlysitescount </td> <td> $Web_NoAccessSitesCount </td> <td> <b> $TotalWebSites </b> </td> </tr> </tr> </table> " $report1 = "<html> <style> {font-family: Arial; font-size: 12pt;color: #0F0F0F; } {color:#F70707;} TABLE{border: 1px solid black; border-collapse: collapse; font-size:15pt;} #TH{border: 1px solid black; background: #F4D03F; padding: 5px; color: #000000;} TR{color: #F70707;text-align: center;background: #13B5ED; padding: 5px; color: #0F0F0F;} TR{color: #F70707;text-align: center;background: #13B5ED; padding: 5px; color: #0F0F0F;} TH{border: 1px solid black; background: #F4D03F; padding: 5px; color: #F70707;} TD{border: 1px solid black; padding: 5px; } H2{color: #F70707;} H1{Color: #0C0B0A;} </style> <table> <tr> <td> <b>Total Active Sites Count </b> </td> <td> <b> Total Read-Only Sites Count </b> </td> <td> <b> Total NoAccess Sites Count </b> </td> <td> <b> Total Sites </b> </td> </tr> <tr> <td> <b> $TotalActiveSite </b> </td> <td> <b> $TotalReadonlySites </b> </td> <td> <b> $TotalNoAccessSite </b> </td> <td> <b> $TotalSites </b> </td> </tr> </table> " #========== $body += " <br> $report< </br>" $body += " <br> $report1 </br>" $attachment12="C:\Results_Active_Web.txt" toadd="" #$toadd= "" #$toadd="" #send-MailMessage -SmtpServer $smtp -To $to -From $from -Subject $subject -Body $body -BodyAsHtml -Attachments $attachment11 -Priority Low #Send-MailMessage -SmtpServer "smtp" -To $toadd -From "email address removed for privacy reasons" -Subject $subject -Body $body -BodyAsHtml #Send-MailMessage -SmtpServer "smtp" -To $toadd -From "email address removed for privacy reasons" -Subject $subject -Body $body -BodyAsHtml -Attachments $attachment12 -Priority Low Send-MailMessage -SmtpServer "smtp" -To $toadd -From "email address removed for privacy reasons" -Subject $subject -Body $body -BodyAsHtml -Priority Low #Send-MailMessage -SmtpServer "smtp" -To $toadd -From "email address removed for privacy reasons" -Subject $body -24Views0likes0CommentsHow to hide the Modify this view and Create View as per users available in groups
Hi All, I have classic view of SharePoint in list/libraries. I have group(for Managers). I just want want to show and hide the Create View/Modify View/Modify this view depends on users available in group. If user available in group(for Managers) then they can do anything like Create View/Modify View/Modify this view but if user is not a part of the group(for Managers) then they can not modify any Public views but the can create Personal view. Is there any way how I can achieve this functionality?38Views0likes0CommentsAutomating Microsoft 365 with PowerShell Second Edition
The Office 365 for IT Pros team are thrilled to announce the availability of Automating Microsoft 365 with PowerShell (2nd edition). This completely revised 350-page book delivers the most comprehensive coverage of how to use Microsoft Graph APIs and the Microsoft Graph PowerShell SDK with Microsoft 365 workloads (Entra ID, Exchange Online, SharePoint Online, Teams, Planner, and more). Existing subscribers can download the second edition now free of charge. https://office365itpros.com/2025/06/30/automating-microsoft-365-with-powershell2/815Views2likes10CommentsAdd-PublicFolderClientPermission: Object reference not set to an instance of an object.
Running into an issue with adding public folder permissions in Exchange Online. I've used this PowerShell script for a few years without any issues, but suddenly getting this error no matter what I try. I do have Owner permissions and there are Default and Anonymous permissions on the public folder, tried completely removing and reinstalling the ExchangeOnlineManagement module as well. Anyone else having this problem? $PF = Get-MailPublicFolder -Identity "\pf1" $User = Get-User -Anr "User1" $AccessRights = @( "ReadItems", "CreateItems", "EditOwnedItems", "EditAllItems", "FolderVisible" ) Add-PublicFolderClientPermission -Identity "\$($PF.Id)" -User $User.UserPrincipalName -AccessRights $AccessRights -Verbose VERBOSE: Returning precomputed version info: 3.9.2 VERBOSE: Requested HTTP/1.1 POST with 227-byte payload VERBOSE: Received HTTP/1.1 response of content type application/json of unknown size VERBOSE: Query 1 failed. Add-PublicFolderClientPermission: Object reference not set to an instance of an object. Thank you160Views0likes3Comments