Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added detection and requirement rules to the Set-IntuneWin32Apps.ps1 #133

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 41 additions & 1 deletion Public/Set-IntuneWin32App.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,16 @@ function Set-IntuneWin32App {
.PARAMETER CompanyPortalFeaturedApp
Specify whether to have the Win32 application featured in Company Portal or not.

.PARAMETER DetectionRule
Provide an array of a single or multiple OrderedDictionary objects as detection rules that will be used for the Win32 application.

.PARAMETER RequirementRule
Provide an OrderedDictionary object as requirement rule that will be used for the Win32 application.

.PARAMETER AdditionalRequirementRule
Provide an array of OrderedDictionary objects as additional requirement rule, e.g. for file, registry or script rules, that will be used for the Win32 application.


.NOTES
Author: Nickolaj Andersen
Contact: @NickolajA
Expand Down Expand Up @@ -96,7 +106,19 @@ function Set-IntuneWin32App {
[bool]$CompanyPortalFeaturedApp,

[parameter(Mandatory = $false, HelpMessage = "Specify whether to allow the Win32 application to be uninstalled from the Company Portal app when assigned as available.")]
[bool]$AllowAvailableUninstall
[bool]$AllowAvailableUninstall,

[parameter(Mandatory = $false, HelpMessage = "Provide an array of a single or multiple OrderedDictionary objects as detection rules that will be used for the Win32 application.")]
[ValidateNotNullOrEmpty()]
[System.Collections.Specialized.OrderedDictionary[]]$DetectionRule,

[parameter(Mandatory = $false, HelpMessage = "Provide an OrderedDictionary object as requirement rule that will be used for the Win32 application.")]
[ValidateNotNullOrEmpty()]
[System.Collections.Specialized.OrderedDictionary]$RequirementRule,

[parameter(Mandatory = $false, HelpMessage = "Provide an array of OrderedDictionary objects as additional requirement rule, e.g. for file, registry or script rules, that will be used for the Win32 application.")]
[ValidateNotNullOrEmpty()]
[System.Collections.Specialized.OrderedDictionary[]]$AdditionalRequirementRule
)
Begin {
# Ensure required authentication header variable exists
Expand Down Expand Up @@ -158,6 +180,24 @@ function Set-IntuneWin32App {
if ($PSBoundParameters["AllowAvailableUninstall"]) {
$Win32AppBody.Add("allowAvailableUninstall", $AllowAvailableUninstall)
}
if ($PSBoundParameters["DetectionRule"]) {
# Validate that correct detection rules have been passed on command line, only 1 PowerShell script based detection rule is allowed
if (($DetectionRule.'@odata.type' -contains "#microsoft.graph.win32LobAppPowerShellScriptDetection") -and (@($DetectionRules).'@odata.type'.Count -gt 1)) {
Write-Warning -Message "Multiple PowerShell Script detection rules were detected, this is not a supported configuration"; break
}

# Add detection rules to Win32 app body object
Write-Verbose -Message "Detection rule objects passed validation checks, attempting to add to existing Win32 app body"
$Win32AppBody.Add("detectionRules", $DetectionRule)
}

if ($PSBoundParameters["RequirementRule"]) {
$Win32AppBody.Add("RequirementRule", $RequirementRule)
}

if ($PSBoundParameters["AdditionalRequirementRule"]) {
$Win32AppBody.Add("requirementRules", $AdditionalRequirementRule)
}

try {
# Attempt to call Graph and update Win32 app
Expand Down
103 changes: 70 additions & 33 deletions Public/Update-IntuneWin32AppPackageFile.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -35,27 +35,36 @@ function Update-IntuneWin32AppPackageFile {
[parameter(Mandatory = $true, HelpMessage = "Specify a local path to where the win32 app .intunewin file is located.")]
[ValidateNotNullOrEmpty()]
[ValidateScript({
# Check if file name contains any invalid characters
if ((Split-Path -Path $_ -Leaf).IndexOfAny([IO.Path]::GetInvalidFileNameChars()) -ge 0) {
throw "File name '$(Split-Path -Path $_ -Leaf)' contains invalid characters"
}
else {
# Check if full path exist
if (Test-Path -Path $_) {
# Check if file extension is intunewin
if ([System.IO.Path]::GetExtension((Split-Path -Path $_ -Leaf)) -like ".intunewin") {
return $true
# Check if file name contains any invalid characters
if ((Split-Path -Path $_ -Leaf).IndexOfAny([IO.Path]::GetInvalidFileNameChars()) -ge 0) {
throw "File name '$(Split-Path -Path $_ -Leaf)' contains invalid characters"
}
else {
# Check if full path exist
if (Test-Path -Path $_) {
# Check if file extension is intunewin
if ([System.IO.Path]::GetExtension((Split-Path -Path $_ -Leaf)) -like ".intunewin") {
return $true
}
else {
throw "Given file name '$(Split-Path -Path $_ -Leaf)' contains an unsupported file extension. Supported extension is '.intunewin'"
}
}
else {
throw "Given file name '$(Split-Path -Path $_ -Leaf)' contains an unsupported file extension. Supported extension is '.intunewin'"
throw "File or folder does not exist"
}
}
else {
throw "File or folder does not exist"
}
}
})]
[string]$FilePath
})]
[string]$FilePath,

[parameter(Mandatory = $false, HelpMessage = "Specify the UseAzCopy parameter switch when adding an application with source files larger than 500MB.")]
[ValidateNotNullOrEmpty()]
[switch]$UseAzCopy,

[parameter(Mandatory = $false, HelpMessage = "Specify whether the AzCopy content transfer progress should use -WindowStyle Hidden or -NoNewWindow parameters for Start-Process. NoNewWindow will show transfer output, Hidden will not show progress but will support multi-threaded jobs.")]
[ValidateNotNullOrEmpty()]
[ValidateSet("Hidden", "NoNewWindow")]
[string]$AzCopyWindowStyle = "NoNewWindow"
)
Begin {
# Ensure required authentication header variable exists
Expand Down Expand Up @@ -97,12 +106,12 @@ function Update-IntuneWin32AppPackageFile {
# Create a new file entry in Intune for the upload of the .intunewin file
Write-Verbose -Message "Constructing Win32 app content file body for uploading of .intunewin file"
$Win32AppFileBody = [ordered]@{
"@odata.type" = "#microsoft.graph.mobileAppContentFile"
"name" = $IntuneWinXMLMetaData.ApplicationInfo.FileName
"size" = [int64]$IntuneWinXMLMetaData.ApplicationInfo.UnencryptedContentSize
"@odata.type" = "#microsoft.graph.mobileAppContentFile"
"name" = $IntuneWinXMLMetaData.ApplicationInfo.FileName
"size" = [int64]$IntuneWinXMLMetaData.ApplicationInfo.UnencryptedContentSize
"sizeEncrypted" = (Get-Item -Path $IntuneWinFilePath).Length
"manifest" = $null
"isDependency" = $false
"manifest" = $null
"isDependency" = $false
}

# Create the contentVersions files resource
Expand All @@ -115,19 +124,47 @@ function Update-IntuneWin32AppPackageFile {
Write-Verbose -Message "Waiting for Intune service to process contentVersions/files request"
$FilesUri = "mobileApps/$($Win32App.id)/microsoft.graph.win32LobApp/contentVersions/$($Win32AppContentVersionRequest.id)/files/$($Win32AppFileContentRequest.id)"
$ContentVersionsFiles = Wait-IntuneWin32AppFileProcessing -Stage "AzureStorageUriRequest" -Resource $FilesUri

# Upload .intunewin file to Azure Storage blob
Invoke-AzureStorageBlobUpload -StorageUri $ContentVersionsFiles.azureStorageUri -FilePath $IntuneWinFilePath -Resource $FilesUri
if ($PSBoundParameters["UseAzCopy"]) {
$ContentSize = [System.Math]::Round($Win32AppFileBody.size / 1MB, 2)
if ($ContentSize -lt 100) {
Write-Verbose -Message "Content size is less than 100MB, falling back to using native method for file transfer"
Invoke-AzureStorageBlobUpload -StorageUri $ContentVersionsFiles.azureStorageUri -FilePath $IntuneWinFilePath -Resource $FilesUri
}
else {
try {
Write-Verbose -Message "Using AzCopy.exe method for file transfer"
$SplatArgs = @{
StorageUri = $ContentVersionsFiles.azureStorageUri
FilePath = $IntuneWinFilePath
Resource = $FilesUri
WindowStyle = $AzCopyWindowStyle
ErrorAction = "Stop"
}
Invoke-AzureCopyUtility @SplatArgs
}
catch [System.Exception] {
Write-Verbose -Message "AzCopy.exe transfer method failed with exception message: $($_.Exception.Message)"
Write-Verbose -Message "Falling back to native method"
Invoke-AzureStorageBlobUpload -StorageUri $ContentVersionsFiles.azureStorageUri -FilePath $IntuneWinFilePath -Resource $FilesUri
}
}
}
else {
Write-Verbose -Message "Using native method for file transfer"
Invoke-AzureStorageBlobUpload -StorageUri $ContentVersionsFiles.azureStorageUri -FilePath $IntuneWinFilePath -Resource $FilesUri
}

# Retrieve encryption meta data from .intunewin file
$IntuneWinEncryptionInfo = [ordered]@{
"encryptionKey" = $IntuneWinXMLMetaData.ApplicationInfo.EncryptionInfo.EncryptionKey
"macKey" = $IntuneWinXMLMetaData.ApplicationInfo.EncryptionInfo.macKey
"encryptionKey" = $IntuneWinXMLMetaData.ApplicationInfo.EncryptionInfo.EncryptionKey
"macKey" = $IntuneWinXMLMetaData.ApplicationInfo.EncryptionInfo.macKey
"initializationVector" = $IntuneWinXMLMetaData.ApplicationInfo.EncryptionInfo.initializationVector
"mac" = $IntuneWinXMLMetaData.ApplicationInfo.EncryptionInfo.mac
"profileIdentifier" = "ProfileVersion1"
"fileDigest" = $IntuneWinXMLMetaData.ApplicationInfo.EncryptionInfo.fileDigest
"fileDigestAlgorithm" = $IntuneWinXMLMetaData.ApplicationInfo.EncryptionInfo.fileDigestAlgorithm
"mac" = $IntuneWinXMLMetaData.ApplicationInfo.EncryptionInfo.mac
"profileIdentifier" = "ProfileVersion1"
"fileDigest" = $IntuneWinXMLMetaData.ApplicationInfo.EncryptionInfo.fileDigest
"fileDigestAlgorithm" = $IntuneWinXMLMetaData.ApplicationInfo.EncryptionInfo.fileDigestAlgorithm
}
$IntuneWinFileEncryptionInfo = @{
"fileEncryptionInfo" = $IntuneWinEncryptionInfo
Expand All @@ -140,13 +177,13 @@ function Update-IntuneWin32AppPackageFile {
# Wait for Intune service to process the commit file request
Write-Verbose -Message "Waiting for Intune service to process the commit file request"
$CommitFileRequest = Wait-IntuneWin32AppFileProcessing -Stage "CommitFile" -Resource $FilesUri

# Update committedContentVersion property for Win32 app
Write-Verbose -Message "Updating committedContentVersion property with ID '$($Win32AppContentVersionRequest.id)' for Win32 app with ID: $($Win32App.id)"
$Win32AppFileCommitBody = [ordered]@{
"@odata.type" = "#microsoft.graph.win32LobApp"
"@odata.type" = "#microsoft.graph.win32LobApp"
"committedContentVersion" = $Win32AppContentVersionRequest.id
"largeIcon" = $Win32App.largeIcon
"largeIcon" = $Win32App.largeIcon
}
$Win32AppFileCommitBodyRequest = Invoke-IntuneGraphRequest -APIVersion "Beta" -Resource "mobileApps/$($Win32App.id)" -Method "PATCH" -Body ($Win32AppFileCommitBody | ConvertTo-Json)

Expand Down