{"id":1755,"date":"2014-03-26T00:01:00","date_gmt":"2014-03-26T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2014\/03\/26\/use-powershell-to-manage-office-365-users\/"},"modified":"2014-03-26T00:01:00","modified_gmt":"2014-03-26T00:01:00","slug":"use-powershell-to-manage-office-365-users","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/use-powershell-to-manage-office-365-users\/","title":{"rendered":"Use PowerShell to Manage Office 365 Users"},"content":{"rendered":"<p><b>Summary<\/b>: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to manage Office&nbsp;365 users.<\/p>\n<p>Microsoft Scripting Guy, Ed Wilson, is here. The weather here in Charlotte has been nearly perfect recently. I love spring. It offers hope, and it seems to be a time of renewed commitments. A quick trip to the garden center, and the Scripting Wife and I return with bundles of flowers and other stuff to plant. It is the very essence of hope. We hope they will thrive. We hope to enjoy their blooms in the future. We hope they will not overtake the rest of our garden. Ah, lots of hope.<\/p>\n<p><b>&nbsp; &nbsp; &nbsp;Note&nbsp;<\/b> This is the third in a series of Hey, Scripting Guy! Blog posts where I talk about using Windows PowerShell <br \/>&nbsp; &nbsp; &nbsp;with Office&nbsp;365.<\/p>\n<ul>\n<li>In <a href=\"https:\/\/devblogs.microsoft.com\/scripting\/getting-started-with-office-365-and-powershell\/\" target=\"_blank\">Getting Started with Office&nbsp;365 and PowerShell<\/a>, I talked about setting up a demo environment and installing the prerequisite software to enable Windows PowerShell management of the demo environment. I also walked through the installation of the management module.<\/li>\n<li>In <a href=\"https:\/\/devblogs.microsoft.com\/scripting\/use-powershell-to-explore-office-365-installation\/\" target=\"_blank\">Use PowerShell to Explore Office&nbsp;365 Installation<\/a>, I talked about using Windows PowerShell to explore the settings and the capabilities of my Office&nbsp;365 tenant installation.<\/li>\n<li>In today&rsquo;s post, I talk about finding unlicensed users, removing users, and modifying users.<\/li>\n<\/ul>\n<p>In some respects, as IT pros, we invest in Office&nbsp;365 technology in much the same way as I invest in flowers. We hope that in the future we will receive the promised benefit. We hope that Office&nbsp;365 will be more stable, easier to manage, easier to maintain, and therefore provide a promised benefit to the bottom line. One of the keys to unlocking that promise is knowing how to use Windows PowerShell.<\/p>\n<p>The first thing I need to do is to connect to Office&nbsp;365. To do this, I am using the stored credential that I talked about in yesterday&rsquo;s blog post, and then I use a cmdlet to make my connection to Office&nbsp;365. The two commands are shown here:<\/p>\n<p style=\"margin-left:30px\">$cred = Import-Clixml C:\\fso\\cred.xml<\/p>\n<p style=\"margin-left:30px\">Connect-MsolService -Credential $cred<\/p>\n<p>When I am connected, I like to user the <b>Get-Command<\/b> cmdlet to display available Windows PowerShell commands. This is shown in the image that follows:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-3-26-14-01.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-3-26-14-01.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>Because this is Windows PowerShell, I can use standard Windows PowerShell techniques to discover commands that I need to use. Then when I have found the cmdlet, I can use <b>Get-Help<\/b> to find examples of use. Here are some ideas keep in mind:<\/p>\n<ul>\n<li>Use <b>Get-Command<\/b> to find cmdlets. The main module to use is the MSOnline module.<\/li>\n<li>Use Tab expansion to expand the names of cmdlets, and also the names of modules. Hit the Tab key, and it will cycle through available options.<\/li>\n<li>To find Help, use the <b>Get-Help<\/b> cmdlet. If you are using Windows PowerShell&nbsp;4.0 or Windows PowerShell&nbsp;3.0, you need to first open the Windows PowerShell console with admin rights, and then use the <b>Update-Help<\/b> cmdlet to update all the Help for modules.<\/li>\n<li>Use the <b>Get-Member<\/b> cmdlet to find object properties to use when filtering.<\/li>\n<li>Use the <b>Where-Object<\/b> cmdlet to reduce or to filter returned information.<\/li>\n<li>Use the <b>Group-Object<\/b> cmdlet to group returned objects by properties.<\/li>\n<li>Use the <b>Out-GridView<\/b> to produce a usable control that permits filtering and sorting.<\/li>\n<li>Use the <b>Show-Command<\/b> cmdlet to produce a floatable control that permits you to easily fill in options.<\/li>\n<li>Use the <b>Measure-Object<\/b> cmdlet for counting.<\/li>\n<\/ul>\n<h2>Display and work with users<\/h2>\n<p>To display basic user information about the Office&nbsp;365 users, use the <b>Get-MsolUser<\/b> cmdlet. To count the number of users, use the <b>Measure-Object<\/b> (<b>measure<\/b> is an alias) cmdlet. The use of these two cmdlets is shown in the image that follows:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-3-26-14-02.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-3-26-14-02.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>It is pretty obvious from the previous image that I have&nbsp;32 total users, but some are licensed and some are not. Therefore, I want to know how many of each type user exists. I can use the <b>Group-Object<\/b> cmdlet to figure this out. The best way to use <b>Group-Object<\/b> is to first sort the data and then group the data. The command is:<\/p>\n<p style=\"margin-left:30px\">Get-MsolUser | Sort islicensed | group islicensed<\/p>\n<p>This command displays the needed information, but the output is a bit clunky. This is because of the grouping information that says it is a bunch of user objects. I already knew that. Therefore, to clean up the list, I want to remove the element grouping information. To do that, I add the <b>&ndash;noelement<\/b> switch to the command. The output from the two commands is shown here:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-3-26-14-03.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-3-26-14-03.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>I want to get a good list of users that are not licensed. I can do this by piping my list of users to <b>Where-Object<\/b> and filtering on the <b>islicensed<\/b> property. I come up with the following command:<\/p>\n<p style=\"margin-left:30px\">Get-MsolUser | where {-not $_.islicensed}<\/p>\n<p>But then I start thinking&hellip;<\/p>\n<p>Dude, this is a lot of work. And not only that&mdash;it is inefficient. This is because it needs to get the list of users, and then filter them. So I use the <b>Get-Command<\/b> cmdlet, and I find that there is a switch parameter that I can use. The command is shown here:<\/p>\n<p style=\"margin-left:30px\">Get-Command Get-MsolUser | select -expand Definition<\/p>\n<p>The output from the command is shown here:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-3-26-14-04.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-3-26-14-04.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>I re-run the command using the <b>LicenseReconciliationNeededOnly<\/b> switch parameter, and I see the output is exactly the same.<\/p>\n<p style=\"margin-left:30px\"><b>Note&nbsp;<\/b> The switch parameter is really long, so please do not fool with trying to type it. Use Tab expansion until it appears. This will ensure that it is spelled correctly, and save at least&nbsp;30 seconds of typing.<\/p>\n<p>The output from the two commands is shown here:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-3-26-14-05.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-3-26-14-05.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<h2>Remove unlicensed users<\/h2>\n<p>I know that I said Windows PowerShell is Windows PowerShell is Windows PowerShell. But not always&hellip;<\/p>\n<p>Unfortunately, this is not always exactly true. For example, I would have expected the <b>Remove-MsolUser<\/b> cmdlet to implement <b>ShouldProcess<\/b>, so that I could use the <b>&ndash;whatif<\/b> parameter to see what a cmdlet would do. But unfortunately, it does not.<\/p>\n<p>What the cmdlet does do, is default to using <b>&ndash;confirm<\/b>, but there is no <b>&ndash;confirm<\/b> parameter available either. So when I try to run the following command, it prompts for each of the user objects:<\/p>\n<p style=\"margin-left:30px\">Get-MsolUser -LicenseReconciliationNeededOnly | Remove-MsolUser<\/p>\n<p>This is no good for automation. So I try a couple of things, and I eventually find that the cmdlet actually uses the <b>&ndash;Force<\/b> parameter to suppress confirmation messages.<\/p>\n<p>So, here is the command I ended up using:<\/p>\n<p style=\"margin-left:30px\">Get-MsolUser -LicenseReconciliationNeededOnly | Remove-MsolUser &ndash;Force<\/p>\n<p>Now I check to see if the command actually worked:<\/p>\n<p style=\"margin-left:30px\">PS C:\\&gt; Get-MsolUser -LicenseReconciliationNeededOnly<\/p>\n<p style=\"margin-left:30px\">PS C:\\&gt;<\/p>\n<p>Yep, they are gone.<\/p>\n<p>Luckily, Office&nbsp;365 has a Recycle Bin, and it is easy to recover the deleted users via the admin tool. This is shown here:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-3-26-14-06.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-3-26-14-06.png\" alt=\"Image of menu\" title=\"Image of menu\" \/><\/a><\/p>\n<p>There is also a <b>Restore-MsolUser<\/b> cmdlet, but unfortunately, there is no obvious way to find all the users in the Recycle Bin. Therefore, I would need to know each UPN to restore the users. In this case, for me, using the GUI is easier. If I had kept a log of the user objects that I deleted, I could have more easily reactivated the users.<\/p>\n<p>That is all there is to using Office&nbsp;365 cmdlets. Office&nbsp;365 Week will continue tomorrow when I will talk about more cool stuff.<\/p>\n<p>I invite you to follow me on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\">Facebook<\/a>. If you have any questions, send email to me at <a href=\"mailto:scripter@microsoft.com\" target=\"_blank\">scripter@microsoft.com<\/a>, or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.<\/p>\n<p><b>Ed Wilson, Microsoft Scripting Guy<\/b><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to manage Office&nbsp;365 users. Microsoft Scripting Guy, Ed Wilson, is here. The weather here in Charlotte has been nearly perfect recently. I love spring. It offers hope, and it seems to be a time of renewed commitments. A quick trip to the garden center, [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[49,291,3,45],"class_list":["post-1755","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-office","tag-office-365","tag-scripting-guy","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to manage Office&nbsp;365 users. Microsoft Scripting Guy, Ed Wilson, is here. The weather here in Charlotte has been nearly perfect recently. I love spring. It offers hope, and it seems to be a time of renewed commitments. A quick trip to the garden center, [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/1755","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=1755"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/1755\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=1755"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=1755"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=1755"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}