Microsoft Store Intune Integration – Graph Commands

With the new Store Integration now speedily being added to tenants and my previous post on adding Company Portal proving so popular, I thought I’d have a look at what else is sitting in Graph

This post from Sander Rozemuller gave me an excellent starting point and the script dropped nicely into a function:

The full script can be found here on GitHub

Function Add-MSStoreApp(){
        
    <#
    .SYNOPSIS
    This function adds Microsoft Store Apps using Winget
    .DESCRIPTION
    The function connects to the Graph API Interface and creates a Microsoft Store App using the new experience
    .EXAMPLE
    Add-MSStoreApp -name "WhatsApp"
    .NOTES
    NAME: Add-MSStoreApp
    #>
    
    [cmdletbinding()]
    
    param
    (
        $name
    )
$appName = $name
$storeSearchUrl = "https://storeedgefd.dsx.mp.microsoft.com/v9.0/manifestSearch"
$body = @{
    Query = @{
        KeyWord   = $appName
        MatchType = "Substring"
    }
} | ConvertTo-Json
$appSearch = Invoke-RestMethod -Uri $storeSearchUrl -Method POST -ContentType 'application/json' -body $body
$exactApp = $appSearch.Data | Where-Object { $_.PackageName -eq $appName }

$appUrl = "https://storeedgefd.dsx.mp.microsoft.com/v9.0/packageManifests/{0}" -f $exactApp.PackageIdentifier
$app = Invoke-RestMethod -Uri $appUrl -Method GET 
$appId = $app.Data.PackageIdentifier
$appInfo = $app.Data.Versions[-1].DefaultLocale
$appInstaller = $app.Data.Versions[-1].Installers


    $appdescription = ($appInfo.Shortdescription).ToString()
    $appdescription2 = $appdescription.replace("`n"," ").replace("`r"," ").replace("\n"," ").replace("\\n"," ")
    $appdeveloper = $appInfo.Publisher
    $appdisplayName = $appInfo.packageName
    $appinformationUrl = $appInfo.PublisherSupportUrl
    $apprunAsAccount = ($appInstaller.scope | select-object -First 1)
    $appisFeatured = $false
    $apppackageIdentifier = $appId
    $appprivacyInformationUrl = $appInfo.PrivacyUrl
    $apppublisher = $appInfo.publisher


$deployUrl = "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps"
$json = @"
{
	"@odata.type": "#microsoft.graph.winGetApp",
	"categories": [],
	"description": "$appdescription2",
	"developer": "$appdeveloper",
	"displayName": "$appdisplayName",
	"informationUrl": "$appinformationUrl",
	"installExperience": {
		"runAsAccount": "$apprunAsAccount"
	},
	"isFeatured": false,
	"notes": "",
	"owner": "",
	"packageIdentifier": "$apppackageIdentifier",
	"privacyInformationUrl": "$appprivacyInformationUrl",
	"publisher": "$apppublisher",
	"repositoryType": "microsoftStore",
	"roleScopeTagIds": []
}
"@

$appDeploy = Invoke-mggraphrequest -uri $deployUrl -Method POST -Body $json -ContentType "application/JSON"



return $appDeploy
}

I also separated out the assignment and switched it to Group ID rather than everyone (NOTE: the group needs to be a user group):

Function Add-StoreAppAssignment(){

    <#
    .SYNOPSIS
    This function is used to add a store app assignment using the Graph API REST interface
    .DESCRIPTION
    The function connects to the Graph API Interface and adds a store app assignment
    .EXAMPLE
    Add-StoreAppAssignment -StoreAppID $StoreAppIdId -TargetGroupId $TargetGroupId
    Adds a Store app assignment in Intune
    .NOTES
    NAME: Add-SStoreAppAssignment
    #>
    
    [cmdletbinding()]
    
    param
    (
        $StoreAppID,
        $TargetGroupId
    )
    
    $graphApiVersion = "Beta"
    $Resource = "deviceManagement/deviceAppManagement/mobileApps/$storeAppID/assign"
        
        try {
    
            if(!$StoreAppID){
    
            write-host "No Compliance Policy Id specified, specify a valid Compliance Policy Id" -f Red
            break
    
            }
    
            if(!$TargetGroupId){
    
            write-host "No Target Group Id specified, specify a valid Target Group Id" -f Red
            break
    
            }
    
    $JSON = @"
    {
        "mobileAppAssignments":  [
                                     {
                                         "settings":  {
                                                          "installTimeSettings":  null,
                                                          "notifications":  "showAll",
                                                          "restartSettings":  null,
                                                          "@odata.type":  "#microsoft.graph.winGetAppAssignmentSettings"
                                                      },
                                         "intent":  "Required",
                                         "target":  {
                                            "groupId": "$TargetGroupId"
                                                    },
                                         "@odata.type":  "#microsoft.graph.mobileAppAssignment"
                                     }
                                 ]
    }
"@
    
        $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)"
        Invoke-MgGraphRequest -Uri $uri -Method Post -Body $JSON -ContentType "application/json"
    
    
        }
        
        catch {
    
        $ex = $_.Exception
        $errorResponse = $ex.Response.GetResponseStream()
        $reader = New-Object System.IO.StreamReader($errorResponse)
        $reader.BaseStream.Position = 0
        $reader.DiscardBufferedData()
        $responseBody = $reader.ReadToEnd();
        Write-Host "Response content:`n$responseBody" -f Red
        Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)"
        write-host
        
    
        }
    
    }

Then a function to display all Store Apps:

    Function Get-MSStoreApps(){
        
        <#
        .SYNOPSIS
        This function is used to get MS Store Apps from the Graph API REST interface
        .DESCRIPTION
        The function connects to the Graph API Interface and gets any MS Store Apps
        .EXAMPLE
        Get-MSStoreApps
        Returns any MS Store Apps configured in Intune

        Get-MSStoreApps -id $id
        Returns specific app
        .NOTES
        NAME: Get-MSStoreApps
        #>
        
        [cmdletbinding()]
        
        param
        (
            $id
        )
        
        $graphApiVersion = "beta"
        $DCP_resource = "deviceAppManagement/MobileApps"
        
            try {
        
                if($Name){
        $uri = "https://graph.microsoft.com/$graphApiVersion/$($DCP_resource)/$id"
        ((Invoke-MgGraphRequest -Uri $uri -Method Get -OutputType PSObject).value)

                }
        
                else {
        
                $uri = "https://graph.microsoft.com/$graphApiVersion/$($DCP_resource)?`$filter=(isof('microsoft.graph.winGetApp'))"
        (Invoke-MgGraphRequest -Uri $uri -Method Get -OutputType PSObject).value
        
                }
        
            }
        
            catch {
        
            $ex = $_.Exception
            $errorResponse = $ex.Response.GetResponseStream()
            $reader = New-Object System.IO.StreamReader($errorResponse)
            $reader.BaseStream.Position = 0
            $reader.DiscardBufferedData()
            $responseBody = $reader.ReadToEnd();
            Write-Host "Response content:`n$responseBody" -f Red
            Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)"
            write-host
            
        
            }
        
        }

Putting these together you could:

Assign all Store apps:

##Assign Store Apps
$sapps = Get-MSStoreApps

foreach ($sapp in $sapps) {
Add-StoreAppAssignment -Id $sapp.id -TargetGroupId "$intunegrp.id"GROUPIDHERE"
}

Or add multiple apps:

##List of apps to install
$storeapps = @("Company Portal", "Microsoft To Do: Lists, Tasks & Reminders", "Windows Terminal")

##Add each
foreach ($app in $storeapps) {
   Add-MSStoreApp -Name $app
}

The possibilities are endless!!

6 thoughts on “Microsoft Store Intune Integration – Graph Commands”

  1. It’s also failing for me. Trying to get Adobe Create Cloud deployed. I also had to remove the icon capture piece as that was failing completely.

    Invoke-mggraphrequest : POST https://graph.microsoft.com/beta/deviceAppManagement/mobileApps
    HTTP/1.1 400 Bad Request

    {“error”:{“code”:”BadRequest”,”message”:”Unable to read JSON request payload. Please ensure Content-Type header is set and payload is of valid JSON
    format.”

    Reply
  2. I actually found that I could install Adobe Creative Cloud if I changed the scope to user from machine. I didn’t realize that the following was also in the error.
    {“error”:{“code”:”ModelValidationFailure”,”message”:”Requested value ‘machine’ was not found.”

    The icon generation fails for every app I tested with. The API also doesn’t seem to accept machine scope so unsure how to requested accepted values.

    Reply

Leave a Comment