Public/Add-Win32LOB.ps1
<#
.SYNOPSIS This function is used to upload a Win32 Application to the Intune Service .DESCRIPTION This function is used to upload a Win32 Application to the Intune Service .EXAMPLE Add-Win32Lob "C:\Packages\package.intunewin" -publisher "Microsoft" -description "Package" This example uses all parameters required to add an intunewin File into the Intune Service .NOTES NAME: Add-Win32LOB #> function Add-Win32Lob() { [cmdletbinding()] param ( [parameter(Mandatory = $true, Position = 1)] [ValidateNotNullOrEmpty()] [string]$SourceFile, [parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$displayName, [parameter(Mandatory = $true, Position = 2)] [ValidateNotNullOrEmpty()] [string]$publisher, [parameter(Mandatory = $true, Position = 3)] [ValidateNotNullOrEmpty()] [string]$description, [parameter(Mandatory = $true, Position = 4)] [ValidateNotNullOrEmpty()] [array] $detectionRules, [parameter(Mandatory = $true, Position = 5)] [ValidateNotNullOrEmpty()] $returnCodes, [parameter(Mandatory = $false, Position = 6)] [ValidateNotNullOrEmpty()] [string]$installCmdLine, [parameter(Mandatory = $false, Position = 7)] [ValidateNotNullOrEmpty()] [string]$uninstallCmdLine, [parameter(Mandatory = $false, Position = 8)] [ValidateSet('system', 'user')] $installExperience = "system", [parameter(Mandatory = $false)] $Sleep = 30 ) try { $LOBType = "microsoft.graph.win32LobApp" Write-Verbose "Testing if SourceFile '$SourceFile' Path is valid..." Test-SourceFile "$SourceFile" Write-Verbose Write-Verbose "Creating JSON data to pass to the service..." # Funciton to read Win32LOB file $DetectionXML = Get-IntuneWinXML "$SourceFile" -fileName "detection.xml" # If displayName input don't use Name from detection.xml file if ($displayName) { $DisplayName = $displayName } else { $DisplayName = $DetectionXML.ApplicationInfo.Name } $FileName = $DetectionXML.ApplicationInfo.FileName $SetupFileName = $DetectionXML.ApplicationInfo.SetupFile $SourceFileName = [System.IO.Path]::GetFileName($SourceFile) $Ext = [System.IO.Path]::GetExtension($SetupFileName) if ((($Ext).contains("msi") -or ($Ext).contains("Msi")) -and (!$installCmdLine -or !$uninstallCmdLine)) { # MSI $MsiExecutionContext = $DetectionXML.ApplicationInfo.MsiInfo.MsiExecutionContext $MsiPackageType = "DualPurpose" if ($MsiExecutionContext -eq "System") { $MsiPackageType = "PerMachine" } elseif ($MsiExecutionContext -eq "User") { $MsiPackageType = "PerUser" } $MsiProductCode = $DetectionXML.ApplicationInfo.MsiInfo.MsiProductCode $MsiProductVersion = $DetectionXML.ApplicationInfo.MsiInfo.MsiProductVersion $MsiPublisher = $DetectionXML.ApplicationInfo.MsiInfo.MsiPublisher $MsiRequiresReboot = $DetectionXML.ApplicationInfo.MsiInfo.MsiRequiresReboot $MsiUpgradeCode = $DetectionXML.ApplicationInfo.MsiInfo.MsiUpgradeCode if ($MsiRequiresReboot -eq "false") { $MsiRequiresReboot = $false } elseif ($MsiRequiresReboot -eq "true") { $MsiRequiresReboot = $true } $mobileAppBody = Get-Win32AppBody ` -MSI ` -displayName "$DisplayName" ` -publisher "$publisher" ` -description $description ` -filename $SourceFileName ` -SetupFileName "$SetupFileName" ` -installExperience $installExperience ` -MsiPackageType $MsiPackageType ` -MsiProductCode $MsiProductCode ` -MsiProductName $displayName ` -MsiProductVersion $MsiProductVersion ` -MsiPublisher $MsiPublisher ` -MsiRequiresReboot $MsiRequiresReboot ` -MsiUpgradeCode $MsiUpgradeCode } else { $mobileAppBody = Get-Win32AppBody -EXE -displayName "$DisplayName" -publisher "$publisher" ` -description $description -filename $SourceFileName -SetupFileName "$SetupFileName" ` -installExperience $installExperience -installCommandLine $installCmdLine ` -uninstallCommandLine $uninstallcmdline } if ($DetectionRules.'@odata.type' -contains "#microsoft.graph.win32LobAppPowerShellScriptDetection" -and @($DetectionRules).'@odata.type'.Count -gt 1) { Write-Host Write-Warning "A Detection Rule can either be 'Manually configure detection rules' or 'Use a custom detection script'" Write-Warning "It can't include both..." Write-Host break } else { $mobileAppBody | Add-Member -MemberType NoteProperty -Name 'detectionRules' -Value $detectionRules } #ReturnCodes if ($returnCodes) { $mobileAppBody | Add-Member -MemberType NoteProperty -Name 'returnCodes' -Value @($returnCodes) } else { Write-Host Write-Warning "Intunewin file requires ReturnCodes to be specified" Write-Warning "If you want to use the default ReturnCode run 'Get-DefaultReturnCodes'" Write-Host break } Write-Verbose Write-Verbose "Creating application in Intune..." $mobileApp = Invoke-PostRequest "mobileApps" ($mobileAppBody | ConvertTo-Json) # Get the content version for the new app (this will always be 1 until the new app is committed). Write-Verbose Write-Verbose "Creating Content Version in the service for the application..." $appId = $mobileApp.id $contentVersionUri = "mobileApps/$appId/$LOBType/contentVersions" $contentVersion = Invoke-PostRequest $contentVersionUri "{}" # Encrypt file and Get File Information Write-Verbose Write-Verbose "Getting Encryption Information for '$SourceFile'..." $encryptionInfo = @{} $encryptionInfo.encryptionKey = $DetectionXML.ApplicationInfo.EncryptionInfo.EncryptionKey $encryptionInfo.macKey = $DetectionXML.ApplicationInfo.EncryptionInfo.macKey $encryptionInfo.initializationVector = $DetectionXML.ApplicationInfo.EncryptionInfo.initializationVector $encryptionInfo.mac = $DetectionXML.ApplicationInfo.EncryptionInfo.mac $encryptionInfo.profileIdentifier = "ProfileVersion1" $encryptionInfo.fileDigest = $DetectionXML.ApplicationInfo.EncryptionInfo.fileDigest $encryptionInfo.fileDigestAlgorithm = $DetectionXML.ApplicationInfo.EncryptionInfo.fileDigestAlgorithm $fileEncryptionInfo = @{} $fileEncryptionInfo.fileEncryptionInfo = $encryptionInfo # Extracting encrypted file $IntuneWinFile = Get-IntuneWinFile "$SourceFile" -fileName "$filename" [int64]$Size = $DetectionXML.ApplicationInfo.UnencryptedContentSize $EncrySize = (Get-Item "$IntuneWinFile").Length # Create a new file for the app. Write-Verbose Write-Verbose "Creating a new file entry in Azure for the upload..." $contentVersionId = $contentVersion.id $fileBody = Get-AppFileBody "$FileName" $Size $EncrySize $null $filesUri = "mobileApps/$appId/$LOBType/contentVersions/$contentVersionId/files" $file = Invoke-PostRequest $filesUri ($fileBody | ConvertTo-Json) # Wait for the service to process the new file request. Write-Verbose Write-Verbose "Waiting for the file entry URI to be created..." $fileId = $file.id $fileUri = "mobileApps/$appId/$LOBType/contentVersions/$contentVersionId/files/$fileId" $file = Wait-FileProcessing $fileUri "AzureStorageUriRequest" # Upload the content to Azure Storage. Write-Verbose Write-Verbose "Uploading file to Azure Storage..." Add-FileToAzureStorage $file.azureStorageUri "$IntuneWinFile" $fileUri # Need to Add removal of IntuneWin file Remove-Item "$IntuneWinFile" -Force # Commit the file. Write-Verbose Write-Verbose "Committing the file into Azure Storage..." $commitFileUri = "mobileApps/$appId/$LOBType/contentVersions/$contentVersionId/files/$fileId/commit" Invoke-PostRequest $commitFileUri ($fileEncryptionInfo | ConvertTo-Json) # Wait for the service to process the commit file request. Write-Verbose Write-Verbose "Waiting for the service to process the commit file request..." $file = Wait-FileProcessing $fileUri "CommitFile" # Commit the app. Write-Verbose Write-Verbose "Committing the file into Azure Storage..." $commitAppUri = "mobileApps/$appId" $commitAppBody = Get-AppCommitBody $contentVersionId $LOBType Invoke-PatchRequest $commitAppUri ($commitAppBody | ConvertTo-Json) Write-Verbose "Sleeping for $Sleep seconds to allow patch completion..." Start-Sleep $Sleep Write-Verbose $FinalApplicationResponse = Invoke-GetRequest "mobileApps/$appId" return $FinalApplicationResponse } catch { Write-Host "" Write-Error "Aborting with exception: $($_.Exception.ToString())" } } |