Solved – Office 365 Room Calendar Not Auto Processing or Accepting Meeting Requests

After having created a Resource Room in the Office365 Admin console (with an Enterprise E1 license,) you may find that meetings which are created in Outlook and which are sent, are not automatically processing and sending verification confirmations back to the person that created the event. Nor will new events populate the event in the new room’s Outlook calendar. In this case, there are a few things we can check to ensure the room behaves as intended.

  1. First, after creating the room, ensure that you, as an admin, are set as an owner of the room. Under O365 > Admin Center > Rooms and Resources > place a checkmark next to the room in question. Ensure that Allow repeating meetings and Automatic Processing is On. Then, click on Edit Exchange Settings:

2. In this example, we don’t use booking delegates. In the Exchange Settings for the new resource room, make sure Booking requests are accepted automatically. 

3. Edit the booking options, contact information, email address, and mailtip settings to your preferences and then click on Mailbox Delegation. Here, add yourself under Full Access so that we can go on to our next step.

4. Next, log into your own OWA admin Outlook online inbox. In Outlook, click your profile photo in the upper right corner and click “Open another mailbox.” Type the address of the room and open the webmail for the room.

5. Here you may see some emails of previous attempts to book events like the following with the error “Your calendar couldn’t be checked to see whether this event conflicts with other events.“:

6. This error lets us know that automatic processing is not working even though we have it set to “On” in our first step. Had the processing worked correctly, we wouldn’t even see this event email in the mailbox of the room in question. 

7. In the upper right corner, click the Gear icon, then under Your app settings, click Calendar.

8. In the calendar resource scheduling settings, ensure that under the scheduling options, “Automatically process event invitations and cancellations” is checked, and then click Save. 

9. In theory, these settings should be enough to get the calendar to auto process and verify, however, your results may vary. Test by creating a meeting event in outlook with the new room. When you send the meeting, you should receive a verification email in your inbox in less than a minute. If you don’t receive the verification, check the inbox of the calendar again. You’ll probably find more emails with the “Your calendar couldn’t be checked…” errors.

10. Time to open PowerShell and connect to your O365 Exchange with the following commands:

$LiveCred = Get-Credential

$Session = New-PSSession -ConfigurationName Microsoft.Exchange-ConnectionUri https://ps.outlook.com/powershell/ -Credential $LiveCred -Authentication Basic -AllowRedirection

Import-PSSession $Session

11. Run the following command to get the calendar processing conditions:

Get-CalendarProcessing -Identity "[email protected]" | Format-List

12. It’s helpful to first get a list of all calendar processing objects of a room that already works correctly to refer to when editing your new room’s permissions. If you don’t already have a room that you can reference, below is a list of my room that is not behaving normally:

13. Notice that ProcessExternalMeetingMessages is set to False. Let’s change this to True with the following command:

Set-CalendarProcessing [email protected] -ProcessExternalMeetingMessages $True

14. After making this and a few other changes displayed in the following screenshot, go ahead and try creating another test meeting and see if the autoprocessing behaves as it should. If you’re still having trouble, try referring to the screenshot below as an example, and use the “Set-CalendarProcessing” command to edit the values.

15. Once you successfully receive verifications and the calendar populates with events as it should, you may want to set the calendar to display the owner of the event and details of the event (rather than the event is listed in the calendar as only “Busy”.) To do so, follow the instructions I wrote in my article here

If this article helped you, please click on an ad to help pay for hosting and site upgrades. 🙂

How to set an Office365 user Password to never expire with PowerShell

Occasionally we’ll be required to set a user account on Office365 to never expire. It’s not advisable to perform this action, as a compromised account who’s passwords never expires can be a liability. However, in some cases a utility account such as a scanner/copier or kiosk account may require a password that does not change. The following tutorial will show you how to set an Office365 password to never expire using PowerShell.

First, we’ll want to ensure that the account password is not already set to expire and we want to confirm it’s status. Using PowerShell we can get information about an Office365 user account password expiration status.

1. Connect to Microsoft Online Services with PowerShell by running the following commands:

Import-Module MSOnline
Connect-MsolService

2. Next, replace <UserID> with the user account (email address) of the user’s properties we want to get with the following command:

Get-MsolUser -UserPrincipalName <user ID> | Select PasswordNeverExpires

Our result should look like the following:

3. Because we get the message returned that the property PasswordNeverExpires = False, we want set it to $True and set the account password to never expire with the following command:

Set-MsolUser -UserPrincipalName <[email protected]> -PasswordNeverExpires $true

Again, change the <[email protected]> identifier to the email address of the account you want to change. Our result will not produce an output:

4. To verify the account password will no longer expire, we’ll run our first command again to see the result:

Get-MsolUser -UserPrincipalName <user ID> | Select PasswordNeverExpires

Our result should look similar to the following:

Because our PasswordNeverExpires property is now set to True, our task is complete. Disconnect from Office365 and close powershell by entering the command: exit.

If this article helped you, please click on an ad to help pay for hosting and new content. 

How to find the Windows Experience Index in Windows 10 with Powershell

Use PowerShell to get the Windows Experience Index in Windows 10

Windows 7 has the Windows Experience Index which is used often by hardware techs to get a good idea about the kind of hardware installed in a PC. It also allows you to quickly find  where improvements can be made to get the machine to run faster. The following screenshot is an example of the Windows 7 Windows Experience Index:

You can get an idea about how fast the components of your Windows 10 computer are by running the Windows System Assessment Tool, but the readout is a little hard to understand. Skip this part (winsat formal) to get the Windows Experience Index in Windows 10 or Windows 7 with PowerShell below.

First open an elevated command prompt and run the command:

winsat formal

Below is a screenshot of the command running and it’s output. Running this tool will slow down your PC for a few minutes as it runs the tests:

Results:

The Windows Experience Index WMI modules are still available in Windows 10, however, the scores are not readily apparent in the Windows 10 system settings.
To get your Windows 10 Windows Experience Index subscores with PowerShell, first open up the Windows PowerShell ISE. Next, go to the following link: https://pastebin.com/i5M81xsV, -credit goes to reddit user:
*(as of 12/20/18 this code was no longer available on pastebin, so I’ve copied below)
$SysInfo = Get-CimInstance -Query "SELECT WinSPRLevel,CPUScore,MemoryScore,DiskScore,GraphicsScore,D3DScore From Win32_WinSAT"

    $SysParams = @{
                    Perf_WinExp_All = $SysInfo.WinSPRLevel
                    Perf_WinExp_CPU = $SysInfo.CPUScore
                    Perf_WinExp_RAM = $SysInfo.MemoryScore
                    Perf_WinExp_DSK = $SysInfo.DiskScore
                    Perf_WinExp_VID = $SysInfo.GraphicsScore
                    Perf_WinExp_D3D = $SysInfo.D3DScore
                    Perf_WinExp_AVG = "{0:N2}" -f ((($SysInfo) |
                    ForEach-Object {$_.CimInstanceProperties.Value})[0..4] |
                    Measure-Object -Average).Average
                   }
                   
    New-Object -TypeName PSobject -Property $SysParams
Copy the code into the Windows 10 PowerShell ISE and then run the script, or create a .ps1 file, and you can get the Windows Experience Index with PowerShell in either Windows 10 or Windows 7:

 

Here’s my results

Perf_WinExp_D3D : 9.9
Perf_WinExp_DSK : 7.55
Perf_WinExp_CPU : 9.1
Perf_WinExp_AVG : 8.91
Perf_WinExp_RAM : 9.1
Perf_WinExp_VID : 8.9
Perf_WinExp_All : 7.55
Here are the scores from my friend’s laptop (thanks Stan):
Perf_WinExp_D3D : 9.9
Perf_WinExp_DSK : 8.15
Perf_WinExp_CPU : 8.2
Perf_WinExp_AVG : 8.09
Perf_WinExp_RAM : 8.2
Perf_WinExp_VID : 6
Perf_WinExp_All : 6

So you can see that in my results, my WEI score would be 7.5 – where the lowest subscore determines my overall result. Looking at the scores, I can improve my score and upgrade my computer by increasing the DSK (disk) performance. To do this I would probably have to upgrade my motherboard to one that supports an NVME hard drive.

My friend’s laptop’s lowest score is VID (video) which means his laptop GPU is keeping the score low. There are a few options for upgrading a laptop GPU, such as an external GPU, but this isn’t surprising as most laptops GPUs can’t compete with a full-sized computer and GPU.

Use Powershell to Get a List of Users with Out of Office enabled in Outlook Office365

How to get a list of users who have enabled Out of Office in Outlook with Office365 PowerShell

For administrators of Office 365, you may need to occasionally get a list of users who have set up or enabled their Out of Office in Outlook. In my case, we needed to see which parking spots were available on campus in a pinch, and who was not coming in the next day. To do this with PowerShell we’ll need to first connect to our Office 365 Exchange Tennant.

  1. In PowerShell ISE, enter the following code into the code view, save the function as Connect-O365.ps1, and then hit the green Play button.
  2. function Connect-O365{
     $o365cred = Get-Credential [email protected]
     $session365 = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://ps.outlook.com/powershell/" -Credential $o365cred -Authentication Basic -AllowRedirection 
     Import-Module (Import-PSSession $session365 -AllowClobber) -Global
    }
  3. Next, execute the new function with the following command:
  4. Connect-O365
  5. Replace the username and password with your Office365 admin credentials (not your on-premise domain credentials.) This will log you into your Exchange Admin with PowerShell where we can run our Out of Office commands.
  6. With authentication out of the way, now all we need to do is run the following command to get a list of mailbox identities who have AutoReply configured (and not disabled), and sort by Identity, Start Time, End Time, and Auto Reply State:
  7. Get-Mailbox -ResultSize Unlimited | Get-MailboxAutoReplyConfiguration | Where-Object { $_.AutoReplyState -ne "Disabled" } | Select Identity,StartTime,EndTime,AutoReplyState
  8. This will run for a while, and could take several minutes, but should produce a list similar to the following:

If this article helped you, please click on an ad to help pay for hosting and site upgrades. 🙂

Office365 Outlook Room Calendar not showing details – displays busy only – fix when Set-MailboxFolderPermission does not resolve

Solved: Office365 O365 Resources Rooms and & Equipment cannot view details or subject in shared calendar, can only see “Busy” and Set-MailboxFolderPermission did not fix or resolve.

So a room calendar would not display who reserved the room, and users requested that the calendars for room reservations display who reserved the room and the details. By default the event only displays “Busy”. Most posts I found online for this issue have the same resolution: use Set-MailboxFolderPermission to display details, comments, subject, and organizer. I did this and tried this using the identity in quotes as well as the full email address of the room, however the Set-MailboxFolderPermission setting did not work and the calendar would still only show “Busy”.

I was able to resolve the problem by looking at the rights of the users.

I found that the Calendar Access Rights for the User: “Default” only had {AvailabilityOnly}

To check permissions and fix this issue, first open PowerShell and connect to your O365 Exchange with the following commands:

$LiveCred = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange-ConnectionUri https://ps.outlook.com/powershell/ -Credential $LiveCred -Authentication Basic -AllowRedirection
Import-PSSession $Session

Once connected, first check that the default user has the correct AccessRights and permissions to work with the calendar. As you can see below here, the Default user has {AvailabilityOnly} permissions when issuing the following command:

Get-MailboxFolderPermission [email protected]:\Calendar
PS C:\admin> Get-MailboxFolderPermission [email protected]:\Calendar

FolderName           User                 AccessRights
----------           ----                 ------------
Calendar             Default              {AvailabilityOnly}
Calendar             Anonymous            {None}

I changed the AccessRights from {AvailabilityOnly} to {PublishingAuthor} with the following command:

Set-MailboxFolderPermission -Identity "[email protected]:\Calendar" -User default -AccessRights PublishingAuthor

And then ensured the identity has the correct CalendarProcessing switches with this command:

Set-CalendarProcessing -Identity "[email protected]" -AddOrganizerToSubject $true -DeleteComments $false -DeleteSubject $false

Now the event’s details and subject can be viewed by everyone. This change takes place pretty quickly, within a minute – the “Busy” events should change to display the details when you close/open Outlook and/or switch between the calendars in Outlook online. Hope this saves someone else a call to MS Support.

In the event the new room’s Calendar is not auto processing or accepting meeting requests, check out my article here:

Solved – Office 365 Room Calendar Not Auto Processing or Accepting Meeting Requests

If this article helped you, please click on an ad to help pay for hosting and site upgrades. 🙂

New Active Directory User and Office365 New User Powershell Procedure

As a systems administrator, quite often you’ll need to create new user accounts in Active Directory and MSOnline Office 365. It’s good to streamline your new user creation procedure as much as possible to make the process faster and more accurate. Thanks to PowerShell, we can turn a whole bunch of point and clicks into just a few PowerShell commands. In this example procedure we will first create an Active Directory AD user account with powershell and a .csv file and then add that user into multiple groups with a different powershell script and a .txt file that has a list of the groups. We will also use another powershell script to get the canonical name of the groups so that our script can find the LDAP location of the group in Active Directory. Secondly, because we do not run our own exchange server we will use powershell to connect to Office365, and create a new user there, license the user, and then add the user to some distribution groups. Prerequisites are powershell, and import AD components and MSOnline components.

  1. Go to https://gallery.technet.microsoft.com/scriptcenter/PowerShell-Create-Active-7e6a3978 and download the create_ad_users.zip and extract to c:\newusers\
  2. Edit create_ad_users.ps1 lines 92 and 98 to accommodate longer last names. In the original script it only allows for first initial and then a truncated last name of 4 characters. In my case, we have some users with long last names, so I set those values to 20:
  3. If($replace.length -lt 20)
    {
      $lastname = $replace
    }
    Else
    {
      $lastname = $replace.substring(0,20)
    }
    
  4. Copy info from your HR department about the new user into the .csv file c:\newusers\import_create_ad_users.csv
  5. Run PS C:\newusers> .\create_ad_users.ps1
  6. Next check the new username in ADUC for such things as account name, address, phone number etc. to ensure the entries are accurate.
  7. With our new user account created, most likely we will want to make that user a member of several security groups. To do that with PowerShell, we need to make sure that we have the correct LDAP names for our groups and place them into a file named groups.txt. In order to do so, we need to run another powershell script named find-dn.ps1 . The code is as follows:
    # Function Find Distinguished Name
    function find-dn { param([string]$adfindtype, [string]$cName)
        # Create A New ADSI Call
        $root = [ADSI]''
        # Create a New DirectorySearcher Object
        $searcher = new-object System.DirectoryServices.DirectorySearcher($root)
        # Set the filter to search for a specific CNAME
        $searcher.filter = "(&(objectClass=$adfindtype) (CN=$cName))"
        # Set results in $adfind variable
        $adfind = $searcher.findall()
        
        # If Search has Multiple Answers 
        if ($adfind.count -gt 1) {
            $count = 0 
            foreach($i in $adfind)
            {
                # Write Answers On Screen
                write-host $count ": " $i.path
                $count += 1
            }
            # Prompt User For Selection
            $selection = Read-Host "Please select item: "
            # Return the Selection
            return $adfind[$selection].path
        }
        # Return The Answer
        return $adfind[0].path
    }

    This code should be inserted into a new PowerShell ISE tab and then saved as find-dn.ps1 . Running the code will produce a new PowerShell function (but will not write any output to the screen.) Find the group names in ADUC that you want the CN name for, and then use the following command(s) to return the CN name:

    find-dn "group" "FinanceGroup"

    The script will return something similar to the following:

    LDAP://CN=FinanceGroup,CN=Users,DC=intranet,DC=contoso,DC=com

    Remove the part “LDAP://” and copy the remaining string into the c:\newusers\groups.txt file, which after finding the rest of your group CN names, should look something similar to the following:

    CN=FinanceGroup,CN=Users,DC=intranet,DC=contoso,DC=com
    CN=HRGroup,CN=Users,DC=intranet,DC=contoso,DC=com
    CN=OperationsGroup,CN=Users,DC=intranet,DC=contoso,DC=com
    CN=ITGroup,CN=Users,DC=intranet,DC=contoso,DC=com
    CN=AccountingGroup,CN=Users,DC=intranet,DC=contoso,DC=com
    CN=ComplianceGroup,CN=Users,DC=intranet,DC=contoso,DC=com
    CN=MarketingGroup,CN=Users,DC=intranet,DC=contoso,DC=com
  8. Now that we have our CN security group names, we can add the user(s) into the groups with the following script. For this step we can utilize the script found here: https://community.spiceworks.com/topic/459481-adding-users-to-multiple-security-groups-in-ad – which was contributed by Martin9700 . Copy the following script into a new PowerShell ISE tab and name the file Add-MultipleGroups.ps1 :
    #requires -Version 3.0
    Param (
        [Parameter(Mandatory,ValueFromPipeline)]
        [String[]]$Groups,
        [Parameter(Mandatory)]
        [String[]]$Users,
        [switch]$Passthru
    )
    
    Begin {
        Try { Import-Module ActiveDirectory -ErrorAction Stop }
        Catch { Write-Error "Unable to load Active Directory module, is RSAT installed?"; Exit }
        $Result = @()
    }
    
    Process {
        ForEach ($Group in $Groups)
        {   Try {
                Add-ADGroupMember $Group -Members $Users -ErrorAction Stop
                $Result += [PSCustomObject]@{
                    Group = $Group
                    AddMembers = $Users -join ", "
                }
            }
            Catch {
                Write-Error "Error adding members to $Group because $($Error[0])"
                $Result += [PSCustomObject]@{
                    Group = $Group
                    AddMembers = $Error[0]
                }
            }
        }
    }
    
    End {
        If ($Passthru)
        {   $Result
        }
    }
  9. Run the following command to add user to the appropriate security groups:
PS C:\newusers> .\Add-MultipleGroups.ps1 -Groups "CN=ITGroup,CN=Users,DC=intranet,DC=contoso,DC=com","CN=OperationsGroup,CN=Users,DC=intranet,DC=contoso,DC=com" -users user1, user2

With the above script you can use the file to run a number of different options as well such as:

You can just put the group names in -Groups:

.\Add-MultipleGroups.ps1 -Groups "testgroup1","testgroup2" -users user1,user2,user3,user4

You can use a text file (either in Groups or via pipeline):

.\Add-MultipleGroups.ps1 -Groups (Get-content c:\groups.txt) -users user1,user2,user3,user4

Get-content c:\groups.txt | .\Add-MultipleGroups.ps1 -Groups -users user1,user2,user3,user4

You can also use Get-Content for users, but you can pipe it:

Get-content c:\groups.txt | .\Add-MultipleGroups.ps1 -Groups -users (Get-content c:\users.txt)

You can confirm in ADUC that the users are now members of the security groups in our groups.txt file.

Add users to Office 365 and Distribution Groups with PowerShell

Great! Now that we have our user accounts created on the AD side of things, we will move on to adding our user(s) into Office365:

With PowerShell up and running will will issue the following commands:

From https://www.petri.com/use-powershell-create-assign-licenses-office-365-users

Import-Module MSOnline

Connect-MsolService

Now we will create the user with the following command:

New-MsolUser -UserPrincipalName [email protected] -DisplayName ‘User 1’ -FirstName User -LastName 1

This command will return something like the following (sorry about the formatting:)

PS C:\Users\jcoltrin> New-MsolUser -UserPrincipalName [email protected] -DisplayName ‘User 1’ -FirstName User -LastName 1



Password                                   UserPrincipalName                          DisplayName                                isLicensed

--------                                   -----------------                          -----------                                ----------

Suso4007                                   [email protected]                       User 1                                False

Now we need to add a license to the user account. We need to do two things before we can assign the licenses. First is we need to to determine the different sku’s we have available to license, and second, we need to set the usage location. To accomplish the first part, we can issue the command:

Get-MsolAccountSku

Second, by using the instructions here: https://social.technet.microsoft.com/Forums/ie/en-US/bfde2a73-579c-409b-a7cd-77110048c7b7/license-enabling-script?forum=onlineservicesadministrationcenter

We can set the MS Online user’s principal location:

Set-MsolUser -UserPrincipalName [email protected] -UsageLocation US


Set-MsolUserLicense -UserPrincipalName [email protected] -AddLicenses Contoso:STANDARDPACK

Now that the user is licensed, we will add the account to a few Exchange Distribution Groups. We will need to import a new PSSession from outlook.com before we can run the Exchange commands. Import the session by first creating a function called “Connect-O365” by running the following (just like we created the function find-dn above):

function Connect-O365{
 $o365cred = Get-Credential [email protected]
 $session365 = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://ps.outlook.com/powershell/" -Credential $o365cred -Authentication Basic -AllowRedirection 
 Import-Module (Import-PSSession $session365 -AllowClobber) -Global
}

Save and name this function: Connect-O365.ps1 and run it. We now have a function that we can run:

.\Connect-O365.ps1
Connect-O365

(enter creds)

Now we can add the distribution group members with the group identity and member name in quotes:

Add-DistributionGroupMember -Identity "Finance" -Member "[email protected]"

Add-DistributionGroupMember -Identity "AllEmployees" -Member "[email protected]"

A number of these scripts and commands can be combined into .ps1 files to optimize the workflow even further. With the information here you should have a good place to start. Let me know in the comments how you added your own features to the procedure.

If this article helped you, please click on an ad to help pay for hosting and site upgrades. 🙂

Get a list of computers, 32/64 bit architecture, Service Pack level, and IP address in active directory with PowerShell

To get an inventory .csv file list of all computers in AD, run the following command in powershell:

Make sure you import Active Directory modules into PowerShell prior to running the command.

Get-ADComputer -Filter * -Property * | Select-Object Name,OperatingSystem,OperatingSystemServicePack,OperatingSystemVersion,ipv4* | Export-Csv -Path "c:\admin\ComputersList.csv"

If you first receive the following error:

“The term ‘Get-ADComputer’ 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.”

This error indicates that the Active Directory module has not been imported into PowerShell. First do this by running the command:

import-module activedirectory

This script should produce and export a .csv file list that looks like the following:

Name OperatingSystem OperatingSystemServicePack OperatingSystemVersion IPv4Address
DC01 Windows Server 2008 R2 Standard Service Pack 1 6.1 (7601) 10.1.3.4
JasonCWKS Windows 7 Professional Service Pack 1 6.1 (7601) 10.1.2.129
JColtrinWin7 Windows 7 Professional Service Pack 1 6.1 (7601) 10.1.2.85

If you want to take this further, and get the csname (computer name), caption (Operating system title), OS Architecture (32/64 bit), and ServicePackMajorVersion (service pack level) from a list of IP’s that the previous command produced you can do the following:

  1. Copy the IP addresses of all the machines to a new file called win7pcs.txt and place it in C:\admin\
  2. Open Powershell ISE  and enter the following script:
$a = Get-Content "C:\admin\win7pcs.txt" 
foreach ($i in $a) 
{Get-WmiObject Win32_OperatingSystem -ComputerName $i | Format-Table csname,caption,OSArchitecture,ServicePackMajorVersion -AutoSize
}

This should produce the following output for each IP address:

csname caption OSArchitecture ServicePackMajorVersion
—— ——- ————– ———————–
JasonCWKS Microsoft Windows 7 Professional 64-bit 1

csname caption OSArchitecture ServicePackMajorVersion
—— ——- ————– ———————–
JcoltrinWin7 Microsoft Windows 7 Professional 32-bit 1

If this article helped you, please click on an ad to help pay for hosting and site upgrades. 🙂