One of the biggest pain points of many companies is the documentation of their infrastructure. With the fast changing products/features it’s more important to have an accurate documentation. The Automatic Microsoft 365 Documentation is the successor of the Automatic Intune Documentation which provides many advantages. It’s no longer a simple script and you can interact with the collected data.

General use
Install-Module MSAL.PS
Install-Module PSWriteWord
Install-Module M365Documentation
# Connect to your tenant
Connect-M365Doc
# Collect information for component Intune as an example
$doc = Get-M365Doc -Components Intune -ExcludeSections "MobileAppDetailed"
# Output the documentation to a Word file
$doc | Write-M365DocWord -FullDocumentationPath "c:\temp\$($doc.CreationDate.ToString("yyyyMMddHHmm"))-WPNinjas-Doc.docx"
Another example: detect deviations
From the community I got back many feedbacks for new features to allow them to fulfill their requirements. Some of them were also pretty useful for me and therefore I would like to highlight one of them directly in this blog.
From time to time you would like to see if something has changed in your environment. The Azure/Microsoft 365 Audit logs provide not always all information to fully understand the changes. Here the documentation module can help with the option to backup the whole configuration to a json file. These json files can be compared with a webservice like http://www.jsondiff.com/.
You can collect all information like normal, but then use the Write-M365DocJson Cmdlet to save the configuration in a comparable format:
# Connect to your tenant
Connect-M365Doc
# Collect information for component Intune as an example
$doc = Get-M365Doc -Components Intune -ExcludeSections "MobileAppDetailed"
# Output the documentation to a Word file
$doc | Write-M365DocJson -FullDocumentationPath "c:\temp\$($doc.CreationDate.ToString("yyyyMMddHHmm"))-WPNinjas-Doc.json"
The result looks pretty good:
Support translation process
Tto simplify the translation process I added a UI which is able to show and submit your contribution to the project. A step by step guide is available on the project page.
- Microsoft Purview Information protect predefined permission groups demystified - February 28, 2023
- Extending Microsoft Sentinel with important device data - January 30, 2023
- SOC Monitor wall – Develop your Video Wall Application (Part 2) - August 22, 2022
30 Comments
Donovan Sobrero · May 26, 2021 at 17:33
NetNew: after install the 3 required modules msal.ps, pswriteword, m365documenation modules without issue in PS7.1.3 I’m not able to issue the command “connect-m365doc”
Get-MsalToken: C:\Users\sobre\Documents\PowerShell\Modules\MSAL.PS\4.21.0.1\Get-MsalToken.ps1:304
Line |
304 | … ionResult = Get-MsalToken -Interactive -PublicClientApplication $Publ …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Only loopback redirect uri is supported, but
| msal37f82fa9-674e-4cae-9286-4b21eb9a6389://auth/ was found. Configure
| http://localhost or http://localhost:port both during app registration and when
| you create the PublicClientApplication object. See
| https://aka.ms/msal-net-os-browser for details
Thomas Kurth · June 13, 2021 at 08:25
Have you used your own App Registration or my Public Client?
I have now added http://localhost in my Public client. So you can test it again.
Leon Scott · May 30, 2021 at 09:18
You forgot to mention to enable the application inside your tenant if you have apps set as after approval only.
Thomas Kurth · June 13, 2021 at 08:21
Yes this is correct. In this case you can also create your own app registration in your tenant. Then you are under full control.
Brendan · June 2, 2021 at 05:36
error when running following command after approving permissions
PS C:\WINDOWS\system32> $doc = Get-M365Doc -Components Intune -ExcludeSections “MobileAppDetailed”
Used application does not have sufficiant permission to access: https://graph.microsoft.com/v1.0/organization
At C:\Program Files\WindowsPowerShell\Modules\M365Documentation\3.0.3\Internal\Helper\Invoke-DocGraph.ps1:51 char:13
+ throw “Used application does not have sufficiant permissi …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (Used applicatio….0/organization:String) [], RuntimeException
+ FullyQualifiedErrorId : Used application does not have sufficiant permission to access: https://graph.microsoft.
com/v1.0/organization
Thomas Kurth · June 13, 2021 at 08:28
Have you used an own app registration? If yes which scopes have you added?
Donovan · June 23, 2021 at 16:56
i’m having the same problem as brendan can you provide the steps to resolve this issue.
Thomas Kurth · July 21, 2021 at 22:04
Do you still have this issue? Because I fixed this on the 2021/06/13. If yes, can you delete the Enterprise Application created in your Azure AD. During the next connect this will be created again and hopefully pick up the adjustments.
Jimmy Phelan · June 24, 2021 at 12:38
Thomas, I have been trying to use this as a follow on from the Intune Documentation module, but i keep having the same issue as Brendan, and I have it on multiple tenants. My method was to install the module, run it as a Global Admin, and let it register itself as an App, with the appropriate permissions it requested. Is there any chance that the https://graph.microsoft.com/beta/identity/identityProviders permission is missing?
I have the exact same error as Brendan, i have not used my own app registration, i saw no documentation around that.
One other item, you have not listed what “Components” are potential options. I drilled into the directory of the module and found that your two componets are AzureAD and Intune, but you havent that list of components in the documentation anywhere that i could see
Thank you for this script, it is one of the most complete and excellent i have used, and if i can get this Graph permission sorted, i will be delighted to use it on Conditional Access and AzureAD Documentation too
Jimmy Phelan · June 24, 2021 at 12:53
This failure is in my AAD Sign-Ins
Sign-in error code
65001
The user or administrator has not consented to use the application with ID ‘{identifier}'{namePhrase}. Send an interactive authorization request for this user and resource.
Jimmy Phelan · June 24, 2021 at 13:51
I was able to work around this by moving the Get-AADIdentityProvider.ps1 script out of the folder “C:\Program Files\WindowsPowerShell\Modules\M365Documentation\3.0.3\Internal\Collector\AzureAD”
When i installed the module I used the “-scope AllUsers” to place it into that location. I can see that your method uses a Get-ChildItem in Get-M365Doc.ps1 to decide what to get. By moving it i have been able to stop it executing the “identityprovider” portion, and i have successfully retrieved the documentation for AzureAD.
Thomas Kurth · July 21, 2021 at 22:05
This is now fixed. I added the correct scope to the app registration.
Michael · July 6, 2021 at 19:27
Thomas, lovely work on this. Question have you worked with or seen with Microsoft365DSC https://microsoft365dsc.com/ ? Wondered if you did what your thoughts were?
Also, is there any documentation around the backed setting names in Azure/Off365 to the setting names that show in the portal all in one document? I know you now have that tool to modify transcription file (Thank you so much for that btw), but was looking for a doc that had everything on it. like a matching 1 to 1 chart.
Thomas Kurth · July 21, 2021 at 21:59
Hello Michael,
Thanks for the input. I was not aware of this tool. The problem I see is that this tool is using the PowerShell modules and not the Graph API directly. But if you want, you can find all translations which I have in the module as json file on Github.
Nik Charlebois · January 11, 2022 at 20:11
It actually uses the Microsoft Graph PowerShell SDK under the cover.
Camille Bovy · July 21, 2021 at 14:25
Hi Thomas, First of all great script for documenting, really like it! But I noticed when using the documentation script for AzureAd in Conditional access policies I get duplicates in the Exclude groups. Looking at your script Get-AADConditionalAccess.ps1 I see that on line 78 a empty array is created for Excludeapps and next it fills array Excludegroups. shouldn’t you start at line 78 with a $excludegroups = @()
$ExcludeApps = @()
foreach($group in $CAPolicy.conditions.users.excludeGroups){
$ExcludeGroups += (Invoke-DocGraph -Path “/groups/$($group)”).displayName
Thomas Kurth · July 21, 2021 at 21:51
Thanks for this input. Will be fixed in next version.
Imran Awan · October 12, 2021 at 16:47
Hello Sir, Ran the command below and the modules have been installed
Install-Module MSAL.PS
Install-Module PSWriteWord
Install-Module M365Documentation
Then trying to connect to …. Connect-M365Doc … I get this error
Connect-M365Doc : The ‘Connect-M365Doc’ command was found in the module ‘M365Documentation’, but the module could not be loaded. For more information, run ‘Import-Module M365Documentation’.
I have tried to Import-Module M365Documentation as well… Is there anything i am missing
Thomas Kurth · October 26, 2021 at 08:36
Hello Imran
Was no error generated during the Install-Module command? Normally it should just work. Or are you using AppLocker and our code sign certificate is blocked?
Kyle J · November 3, 2021 at 20:47
I’m getting an error when running : $doc = Get-M365Doc -Components Intune -ExcludeSections “MobileAppDetailed”
PS C:\Scripts> $doc = Get-M365Doc -Components Intune -ExcludeSections “MobileAppDetailed”
Get-GroupInfo : Cannot bind argument to parameter ‘Groups’ because it is an empty array.
At C:\Program Files\WindowsPowerShell\Modules\M365Documentation\3.1.2\Internal\Collector\Intune\Get-MobileApp.ps1:53 char:50
+ $DocSec2.Objects = Get-GroupInfo -Groups $AppGroups
+ ~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Get-GroupInfo], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyArrayNotAllowed,Get-GroupInfo
Thomas Kurth · December 3, 2021 at 07:47
Thanks for the feedback. I have just created an issue onngithub to track it: https://github.com/ThomasKur/M365Documentation/issues/15
Patrick Wilkens · December 17, 2021 at 14:32
How do I change the template? Right now i made my own template/design and need to copy every table over into it. Can i do this a smarter way?
Patrick Wilkens · December 20, 2021 at 22:33
Is it possible to change the template somehow?
Thomas Kurth · January 28, 2022 at 22:13
You can just specify an existing Word File as Target. Then this will be used.
Arnaud Bigot · February 16, 2022 at 11:38
Hello Thomas,
thank you for your script.
for information, I still have to add -scope AllUsers to make it work.
Donovan · May 19, 2022 at 00:42
PS C:\temp> Connect-M365Doc
PS C:\temp> $doc | Write-M365DocWord -FullDocumentationPath “c:\temp\$($doc.CreationDate.ToString(“yyyyMMddHHmm”))-WPNinjas-Doc.docx”
You cannot call a method on a null-valued expression.
At line:1 char:60
+ … ionPath “c:\temp\$($doc.CreationDate.ToString(“yyyyMMddHHmm”))-WPNinj …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Write-M365DocWord : Cannot bind argument to parameter ‘Data’ because it is null.
At line:1 char:8
+ $doc | Write-M365DocWord -FullDocumentationPath “c:\temp\$($doc.Creat …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Write-M365DocWord], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Write-M365DocWord
Jan · October 23, 2022 at 18:47
Is it possible to write the docx to an Azure storage share?
Thomas Kurth · October 24, 2022 at 18:12
It is not possible by my module. But just generate the document to a temp location and then upload via the AZ module for example: https://learn.microsoft.com/en-us/azure/storage/blobs/storage-quickstart-blobs-powershell
Ken Bergeron · December 5, 2022 at 20:02
Hi Thomas, thank you for this invaluable tool. I am unable to export to csv. Error is –
Write-M365DocCsv : Cannot validate argument on parameter ‘ExportFolder’. Folder does not exist.
Ken Bergeron · December 5, 2022 at 21:11
Please disregard. I was able to find under the advanced usage section.