Licensed software can be a pain, especially with manual user assignment and then deployment.
Fortunately for MS Project and MS Visio it can be automated so users can automatically receive Visio and Project upon being given a license and if you revoke the license, it can automatically uninstall.
Better still, the group creation can be scripted (and who doesn’t love a script!)
In this post I’ll run through both creating the groups via script and also deploying the apps themselves (manually, or fully scripted)
Fully Scripted Deployment
This script will create your Entra ID groups (as described below) and using the Microsoft Graph Powershell samples from Microsoft will create your Microsoft Project and Visio Applications, upload the intunewin file (again described below) and deploy to Intune with the Entra ID groups assigned.
The script is long so I’m not going to run through it line by line, but you can grab a copy here
Manual Option (app deployment)
Let’s start with the script which can be found here
As with my Autopilot script, this uses the Graph module which we need to look for and install first:
#Install MS Graph if not available
if (Get-Module -ListAvailable -Name Microsoft.Graph) {
Write-Host "Microsoft Graph Already Installed"
}
else {
try {
Install-Module -Name Microsoft.Graph -Scope CurrentUser -Repository PSGallery -Force
}
catch [Exception] {
$_.message
exit
}
}
As you can see, it’s using the Current User scope to avoid any issues if you don’t have admin rights
Now we need to import the module
import-module -Name microsoft.graph
And connect to Graph
Select-MgProfile -Name Beta
Connect-MgGraph -Scopes Group.ReadWrite.All, GroupMember.ReadWrite.All, openid, profile, email, offline_access
Now we create the groups, these use the service plan IDs from Azure:
Project: fafd7243-e5c1-4a3a-9e40-495efcb1d3c3
Visio: 663a804f-1c30-4ff0-9915-9db84f0d1cea
So, to create a group of licensed Visio users we need to look for that plan and make sure it’s enabled:
New-MGGroup -DisplayName "Visio-Install" -Description "Dynamic group for Licensed Visio Users" -MailEnabled:$False -MailNickName "visiousers" -SecurityEnabled -GroupTypes "DynamicMembership" -MembershipRule "(user.assignedPlans -any (assignedPlan.servicePlanId -eq ""663a804f-1c30-4ff0-9915-9db84f0d1cea"" -and assignedPlan.capabilityStatus -eq ""Enabled""))" -MembershipRuleProcessingState "On"
For the uninstall group, we’re just looking for anyone who doesn’t have the plan:
New-MGGroup -DisplayName "Visio-Uninstall" -Description "Dynamic group for users without Visio license" -MailEnabled:$False -MailNickName "visiouninstall" -SecurityEnabled -GroupTypes "DynamicMembership" -MembershipRule "(user.assignedPlans -all (assignedPlan.servicePlanId -ne ""663a804f-1c30-4ff0-9915-9db84f0d1cea"" -and assignedPlan.capabilityStatus -ne ""Enabled""))" -MembershipRuleProcessingState "On"
Same for Project with both install and uninstall, just with the new service plan ID:
New-MGGroup -DisplayName "Project-Install" -Description "Dynamic group for Licensed Project Users" -MailEnabled:$False -MailNickName "projectinstall" -SecurityEnabled -GroupTypes "DynamicMembership" -MembershipRule "(user.assignedPlans -any (assignedPlan.servicePlanId -eq ""fafd7243-e5c1-4a3a-9e40-495efcb1d3c3"" -and assignedPlan.capabilityStatus -eq ""Enabled""))" -MembershipRuleProcessingState "On"
$projectuninstall = New-MGGroup -DisplayName "Project-Uninstall" -Description "Dynamic group for users without Project license" -MailEnabled:$False -MailNickName "projectuninstall" -SecurityEnabled -GroupTypes "DynamicMembership" -MembershipRule "(user.assignedPlans -all (assignedPlan.servicePlanId -ne ""fafd7243-e5c1-4a3a-9e40-495efcb1d3c3"" -and assignedPlan.capabilityStatus -ne ""Enabled""))" -MembershipRuleProcessingState "On"
Now onto the app deployment
Both of these need Office closed or the install will fail so I’m going to use the excellent PSADT along with ServiceUI.exe from MDT
The script for the apps are here: Visio | Project
I’ve also included the install and uninstall string, detection method, an icon and a packaged Win32 file
Both are installing the current branch latest version using the XML in the Files folder, feel free to amend for your requirements:
Project:
<Configuration ID="3c5aba9e-67dc-48d2-b1a2-c09cb4f05916">
<Add OfficeClientEdition="64" Channel="Current" ForceUpgrade="TRUE" MigrateArch="TRUE">
<Product ID="ProjectProRetail">
<Language ID="MatchOS" />
</Product>
</Add>
<Property Name="SharedComputerLicensing" Value="0" />
<Property Name="PinIconsToTaskbar" Value="FALSE" />
<Property Name="SCLCacheOverride" Value="0" />
<Property Name="AUTOACTIVATE" Value="0" />
<Property Name="FORCEAPPSHUTDOWN" Value="TRUE" />
<Property Name="DeviceBasedLicensing" Value="0" />
<Updates Enabled="FALSE" />
<RemoveMSI />
<Display Level="None" AcceptEULA="FALSE" />
<Logging Level="Off" />
</Configuration>
Visio:
<Configuration ID="c1230666-d756-491b-b093-2d4d64413b17">
<Add OfficeClientEdition="64" Channel="Current" ForceUpgrade="TRUE">
<Product ID="VisioProRetail">
<Language ID="MatchOS" />
<ExcludeApp ID="Groove" />
<ExcludeApp ID="OneDrive" />
</Product>
</Add>
<Property Name="SharedComputerLicensing" Value="0" />
<Property Name="PinIconsToTaskbar" Value="FALSE" />
<Property Name="SCLCacheOverride" Value="0" />
<Property Name="AUTOACTIVATE" Value="0" />
<Property Name="DeviceBasedLicensing" Value="0" />
<Updates Enabled="TRUE" />
<RemoveMSI />
<Display Level="None" AcceptEULA="FALSE" />
<Logging Level="Off" />
</Configuration>
The uninstallers are also pretty straight forward:
Project:
<Configuration>
<Remove All="FALSE">
<Product ID="ProjectProRetail">
<Language ID="en-us" />
</Product>
</Remove>
<Updates Enabled="TRUE" Channel="Monthly" />
<Display Level="None" AcceptEULA="TRUE" />
<Property Name="AUTOACTIVATE" Value="1" />
<Logging Level="Standard" Path="%temp%" />
</Configuration>
Visio:
<Configuration>
<Remove All="FALSE">
<Product ID="VisioProRetail">
<Language ID="en-us" />
</Product>
</Remove>
<Updates Enabled="TRUE" Channel="Monthly" />
<Display Level="None" AcceptEULA="TRUE" />
<Property Name="AUTOACTIVATE" Value="1" />
<Logging Level="Standard" Path="%temp%" />
</Configuration>
The actual installation is handled by the Deploy-Application.ps1 files in the root
First set some variables (Project)
##*===============================================
##* VARIABLE DECLARATION
##*===============================================
## Variables: Application
[string]$appVendor = 'Microsoft'
[string]$appName = 'Project'
[string]$appVersion = 'Latest'
[string]$appArch = 'x64'
[string]$appLang = 'EN'
[string]$appRevision = '01'
[string]$appScriptVersion = '1.0.0'
[string]$appScriptDate = '01/11/2021'
[string]$appScriptAuthor = 'Andrew Taylor'
##*===============================================
## Variables: Install Titles (Only set here to override defaults set by the toolkit)
[string]$installName = 'Project'
[string]$installTitle = 'Installing MS Project'
Visio
## Variables: Application
[string]$appVendor = 'Microsoft'
[string]$appName = 'Visio'
[string]$appVersion = 'Latest'
[string]$appArch = 'x86'
[string]$appLang = 'EN'
[string]$appRevision = '01'
[string]$appScriptVersion = '1.0.0'
[string]$appScriptDate = '01/11/2021'
[string]$appScriptAuthor = 'Andrew Taylor'
##*===============================================
## Variables: Install Titles (Only set here to override defaults set by the toolkit)
[string]$installName = 'Visio'
[string]$installTitle = 'Installing MS Visio'
Now we make sure the apps are closed
Show-InstallationWelcome -CloseApps 'excel,groove,onenote,outlook,mspub,powerpnt,winword,iexplore,teams,visio,winproj' -CheckDiskSpace -PersistPrompt
Then install
Execute-Process -Path "$dirFiles\setup.exe" -Parameters "/CONFIGURE InstallO365withVisio.xml"
Tell them it’s done
If (-not $useDefaultMsi) { Show-InstallationPrompt -Message 'Installation has been completed. You will find Visio in the All Programs section.' -ButtonRightText 'OK' -Icon Information -NoWait }
Or uninstall
Execute-Process -Path "$dirFiles\setup.exe" -Parameters "/CONFIGURE RemoveVisio.xml"
Now we need to deploy to Intune (I’ll just use Project to demonstrate, it’s the same process for Visio)
Grab the intunewin file (or create your own) and add details about the app
Add the install and uninstall commands (included in the source files). Here we are using ServiceUI.exe to allow desktop interaction with popup messages to close apps.
It’s a 64-bit version so make sure to limit the device type, you can pick any Windows version here, I generally just select the last supported version to try and tempt the dinosaurs into upgrading
For detection you are looking for the executable which is either winproj.exe (Project) or visio.exe (Visio)
It shouldn’t have any dependencies so you can skip this section and unless you already have a version to replace, skip Supersedence as well
Now we deploy to our newly created dynamic groups. I normally do a silent uninstall because the users don’t need to know
Now you have a fully automated deployment of Project and Visio, enjoy!
Great article – are you deploying MDT and PSADT to devices using Intune first?
Hi, no need to deploy separately, PSADT and service UI are packaged into the intunewin file
Thanks for the reply, that makes sense. One other thing I noticed, the ps1 tells user to close Office applications but not for the new Outlook and Teams.
Would that be as simple as just adding the application name into that script and re-packaging into a new intunewin file?
They are appx packages so won’t need to be closed for the core apps to update
Hey Andrew,
Brilliant tutorial and it works very well, Could you please help me with one thing, I am not sure if it is included or not, but I would like to do a silent install so that the App Deployment Toolkit does not come up on screen when a user installs Visio from the company portal.
Your help would be much appreciated.
Hi,
PSADT supports this parameter:
-DeployMode ‘Silent’
If you add that after the deployapplication.exe it should suppress them
Is there a solution for VLSC licenses? I think I’ve played with it in the past and trying to install Visio standalone after m365 doesn’t work that great
I think the config xml can handle VLSC but I’ve never tried it myself
Forgive me i’m not familiar with Visio and project licensing, why do you leave AUTOACTIVATE to 0 for the installs but 1 for the uninstalls?
I just grabbed those straight from the Office config tool, either setting will probably work
Hi Andrew, amazing article. Thank you!
How would the install/uninstall work given the group is user based and the deployments and machine based?
Hi,
It would follow the user, the install will happen at the machine level, but it will install/uninstall based on the current user
While it’s an atypical deployment option, does this mean that on a machine used by multiple users if one user has project it will install, but if another user does not have project it will uninstall when they log in, leading to the first user re-installing it when they log back in?
Yes, that’s correct. For a multi-user machine, you can either just install it at the device and those without a license just can’t use it, or if the machines are the same model etc. you could use device based filtering to exclude the installation