Skip to content

Commit

Permalink
1.3.6
Browse files Browse the repository at this point in the history
  • Loading branch information
NickolajA committed Oct 2, 2022
1 parent 644deff commit d5c2a19
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 11 deletions.
2 changes: 1 addition & 1 deletion IntuneWin32App.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
RootModule = 'IntuneWin32App.psm1'

# Version number of this module.
ModuleVersion = '1.3.5'
ModuleVersion = '1.3.6'

# Supported PSEditions
# CompatiblePSEditions = @()
Expand Down
104 changes: 104 additions & 0 deletions Private/Invoke-AzureCopyUtility.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
function Invoke-AzureCopyUtility {
<#
.SYNOPSIS
Upload and commit .intunewin file into Azure Storage blob container.
.DESCRIPTION
Upload and commit .intunewin file into Azure Storage blob container.
.PARAMETER StorageUri
Specify the Storage Account Uri.
.PARAMETER FilePath
Specify the path to the file for upload.
.PARAMETER Resource
Specify the Storage Account files Uri for renewal if process takes a long time.
.NOTES
Author: Nickolaj Andersen
Contact: @NickolajA
Created: 2022-10-02
Updated: 2022-10-02
Version history:
1.0.0 - (2022-10-02) Function created
#>
param(
[parameter(Mandatory = $true, HelpMessage = "Specify the Storage Account Uri.")]
[ValidateNotNullOrEmpty()]
[string]$StorageUri,

[parameter(Mandatory = $true, HelpMessage = "Specify the path to the file for upload.")]
[ValidateNotNullOrEmpty()]
[string]$FilePath,

[parameter(Mandatory = $true, HelpMessage = "Specify the Storage Account files Uri for renewal if process takes a long time.")]
[ValidateNotNullOrEmpty()]
[string]$Resource
)
Process {
# Download URL for AzCopy.exe
$DownloadURL = "https://aka.ms/downloadazcopy-v10-windows"

# Start the timer for SAS URI renewal
$SASRenewalTimer = [System.Diagnostics.Stopwatch]::StartNew()

# Construct expected path to AzCopy utility
$AzCopyPath = Resolve-Path -Path (Join-Path -Path $env:TEMP -ChildPath "AzCopy\azcopy_windows_amd64*") -ErrorAction "SilentlyContinue" | Select-Object -ExpandProperty "Path"

if ($AzCopyPath -eq $null) {
try {
# Download AzCopy.exe if not present in context temporary folder
Write-Verbose -Message "Unable to detect AzCopy.exe in specified location, attempting to download to: $($env:TEMP)"
Start-DownloadFile -URL $DownloadURL -Path $env:TEMP -Name "AzCopy.zip" -ErrorAction "Stop"

try {
# Expand downloaded zip archive
$AzCopyExtractedPath = (Join-Path -Path $env:TEMP -ChildPath "AzCopy")
Expand-Archive -Path (Join-Path -Path $env:TEMP -ChildPath "AzCopy.zip") -DestinationPath $AzCopyExtractedPath -ErrorAction "Stop"
}
catch [System.Exception] {
throw "$($MyInvocation.MyCommand): Failed to extract AzCopy.exe with error message: $($_.Exception.Message)"
}
}
catch [System.Exception] {
throw "$($MyInvocation.MyCommand): Failed to download AzCopy.exe from '$($DownloadURL)' with error message: $($_.Exception.Message)"
}
}

# Attempt to resolve path to AzCopy.exe in extracted content
$AzCopyPath = Join-Path -Path (Resolve-Path -Path (Join-Path -Path $env:TEMP -ChildPath "AzCopy\azcopy_windows_amd64*") | Select-Object -ExpandProperty "Path") -ChildPath "AzCopy.exe"
if ($AzCopyPath -ne $null) {
try {
$TransferOperation = Start-Process -FilePath $AzCopyPath -ArgumentList "cp `"$($FilePath)`" `"$($StorageUri)`" --output-type `"json`"" -PassThru -NoNewWindow -ErrorAction "Stop"
do {
# Wait for 10 seconds until next loop conditional statement check occurs
Start-Sleep -Seconds 10

# Ensure the SAS Uri is renewed
if ($SASRenewalTimer.ElapsedMilliseconds -ge 450000) {
Write-Verbose -Message "SAS Uri renewal is required, attempting to renew"
$RenewedSASUri = Invoke-AzureStorageBlobUploadRenew -Resource $Resource
$SASRenewalTimer.Restart()
}
}
until ($TransferOperation.HasExited -eq $true)
}
catch [System.Exception] {
throw "$($MyInvocation.MyCommand): AzCopy.exe file transfer failed. Error message: $($_.Exception.Message)"
}
finally {
Write-Verbose -Message "AzCopy.exe file transfer completed"
}
}
else {
throw "$($MyInvocation.MyCommand): AzCopy.exe could not be found, this transfer method cannot be used"
}
}
End {
# Stop timer
$SASRenewalTimer.Stop()
}
}
4 changes: 3 additions & 1 deletion Private/Invoke-IntuneGraphRequest.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ function Invoke-IntuneGraphRequest {
1.0.0 - (2020-01-04) Function created
1.0.1 - (2020-04-29) Added support for DELETE operations
1.0.2 - (2021-08-31) Updated to use new authentication header
1.0.3 - (2022-10-02) Changed content type for requests to support UTF8
#>
param(
[parameter(Mandatory = $true)]
Expand All @@ -38,7 +39,8 @@ function Invoke-IntuneGraphRequest {

[parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$ContentType = "application/json"
#[string]$ContentType = "application/json"
[string]$ContentType = "application/json; charset=utf-8"
)
try {
# Construct full URI
Expand Down
50 changes: 43 additions & 7 deletions Public/Add-IntuneWin32App.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,14 @@ function Add-IntuneWin32App {
.PARAMETER Icon
Provide a Base64 encoded string of the PNG/JPG/JPEG file.
.PARAMETER UseAzCopy
Specify the UseAzCopy parameter switch when adding an application with source files larger than 500MB.
.NOTES
Author: Nickolaj Andersen
Contact: @NickolajA
Created: 2020-01-04
Updated: 2022-09-02
Updated: 2022-10-02
Version history:
1.0.0 - (2020-01-04) Function created
Expand All @@ -81,6 +84,9 @@ function Add-IntuneWin32App {
1.0.5 - (2021-08-31) Updated to use new authentication header
1.0.6 - (2021-08-31) Added AppVersion optional parameter
1.0.7 - (2022-09-02) Removed break command that would prevent the Win32 app body JSON output from being display in case an error occured
1.0.8 - (2022-10-02) Added UseAzCopy parameter switch to override the native transfer method. Specify the UseAzCopy parameter switch when uploading large applications.
Added fallback removal code for the cleanup operation at the end of this function, since OneDrive's Files On Demand feature sometimes blocks the
expanded .intunewin file cleanup process.
#>
[CmdletBinding(SupportsShouldProcess=$true, DefaultParameterSetName = "MSI")]
param(
Expand Down Expand Up @@ -193,7 +199,12 @@ function Add-IntuneWin32App {
[parameter(Mandatory = $false, ParameterSetName = "MSI", HelpMessage = "Provide a Base64 encoded string of the PNG/JPG/JPEG file.")]
[parameter(Mandatory = $false, ParameterSetName = "EXE")]
[ValidateNotNullOrEmpty()]
[string]$Icon
[string]$Icon,

[parameter(Mandatory = $false, ParameterSetName = "MSI", HelpMessage = "Specify the UseAzCopy parameter switch when adding an application with source files larger than 500MB.")]
[parameter(Mandatory = $false, ParameterSetName = "EXE")]
[ValidateNotNullOrEmpty()]
[switch]$UseAzCopy
)
Begin {
# Ensure required authentication header variable exists
Expand Down Expand Up @@ -403,9 +414,23 @@ function Add-IntuneWin32App {
Write-Verbose -Message "Waiting for Intune service to process contentVersions/files request"
$FilesUri = "mobileApps/$($Win32MobileAppRequest.id)/microsoft.graph.win32LobApp/contentVersions/$($Win32MobileAppContentVersionRequest.id)/files/$($Win32MobileAppFileContentRequest.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"]) {
try {
Write-Verbose -Message "Using AzCopy.exe method for file transfer"
Invoke-AzureCopyUtility -StorageUri $ContentVersionsFiles.azureStorageUri -FilePath $IntuneWinFilePath -Resource $FilesUri -ErrorAction "Stop"
}
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]@{
Expand Down Expand Up @@ -443,10 +468,21 @@ function Add-IntuneWin32App {
Write-Output -InputObject $Win32MobileAppRequest
}

# Cleanup extracted .intunewin file in Extract folder
Remove-Item -Path (Split-Path -Path $IntuneWinFilePath -Parent) -Recurse -Force -Confirm:$false | Out-Null
try {
# Cleanup extracted .intunewin file in Extract folder
Remove-Item -Path (Split-Path -Path $IntuneWinFilePath -Parent) -Recurse -Force -Confirm:$false | Out-Null
}
catch [System.Exception] {
# Fallback method if OneDrive's Files On Demand feature is blocking access
$FileItems = Get-ChildItem -LiteralPath $IntuneWinFilePath -Recurse
foreach ($FileItem in $FileItems) {
$FileItem.Delete()
}
$ParentItem = Get-Item -LiteralPath $IntuneWinFilePath
$ParentItem.Delete($true)
}
}
}
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion Public/New-IntuneWin32AppPackage.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ function New-IntuneWin32AppPackage {
if (Test-Path -Path $OutputFolder) {
Write-Verbose -Message "Successfully detected specified output folder: $($OutputFolder)"

if (-not(Test-Path -Path $IntuneWinAppUtilPath)) {
if (-not(Test-Path -Path $IntuneWinAppUtilPath)) {
if (-not($PSBoundParameters["IntuneWinAppUtilPath"])) {
# Download IntuneWinAppUtil.exe if not present in context temporary folder
Write-Verbose -Message "Unable to detect IntuneWinAppUtil.exe in specified location, attempting to download to: $($env:TEMP)"
Expand Down
15 changes: 14 additions & 1 deletion Public/New-IntuneWin32AppRequirementRule.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,14 @@ function New-IntuneWin32AppRequirementRule {
Author: Nickolaj Andersen
Contact: @NickolajA
Created: 2020-01-27
Updated: 2022-09-02
Updated: 2022-10-02
Version history:
1.0.0 - (2020-01-27) Function created
1.0.1 - (2021-03-22) Added new minimum supported operating system versions to parameter validation
1.0.2 - (2021-08-31) Added new minimum supported operating system versions to parameter validation
1.0.3 - (2022-09-02) minimumSupportedOperatingSystem property is replaced by minimumSupportedWindowsRelease
1.0.4 - (2022-10-02) minimumFreeDiskSpaceInMB, MinimumMemoryInMB, MinimumNumberOfProcessors and minimumCpuSpeedInMHz now adds a 'null' string
#>
[CmdletBinding(SupportsShouldProcess = $true)]
param(
Expand Down Expand Up @@ -96,15 +97,27 @@ function New-IntuneWin32AppRequirementRule {
if ($PSBoundParameters["MinimumFreeDiskSpaceInMB"]) {
$RequirementRule.Add("minimumFreeDiskSpaceInMB", $MinimumFreeDiskSpaceInMB)
}
else {
$RequirementRule.Add("minimumFreeDiskSpaceInMB", "null")
}
if ($PSBoundParameters["MinimumMemoryInMB"]) {
$RequirementRule.Add("minimumMemoryInMB", $MinimumMemoryInMB)
}
else {
$RequirementRule.Add("minimumMemoryInMB", "null")
}
if ($PSBoundParameters["MinimumNumberOfProcessors"]) {
$RequirementRule.Add("minimumNumberOfProcessors", $MinimumNumberOfProcessors)
}
else {
$RequirementRule.Add("minimumNumberOfProcessors", "null")
}
if ($PSBoundParameters["MinimumCPUSpeedInMHz"]) {
$RequirementRule.Add("minimumCpuSpeedInMHz", $MinimumCPUSpeedInMHz)
}
else {
$RequirementRule.Add("minimumCpuSpeedInMHz", "null")
}

return $RequirementRule
}
Expand Down
5 changes: 5 additions & 0 deletions ReleaseNotes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Release notes for IntuneWin32App module

## 1.3.6
- Add-IntuneWin32App function now has a new parameter switch named UseAzCopy. When this switch is used, AzCopy.exe is used to transfer the files to the storage account instead of the native method.
- New-IntuneWin32AppRequirementRule has been updated to construct the proper objects. The minimumFreeDiskSpaceInMB, MinimumMemoryInMB, MinimumNumberOfProcessors and minimumCpuSpeedInMHz objets when not specified as parameters now adds a 'null' string instead of $null (not being part of the object returned).
- Private function Invoke-IntuneGraphRequest has been updated with UTF-8 encoding content type support. From this version and on, when the script file is properly encoded with UTF-8 with BOM, special characters should now work as expected.

## 1.3.5
- Connect-MSIntuneGraph function has been updated to store the TenantID parameter in a global variable named $Global:AccessTokenTenantID.
- Private function Invoke-AzureStorageBlobUpload used in Add-IntuneWin32App function now refreshes an access token 10 minutes before it's about to expire. This should prevent uploads of large applications from failing due to the access token has expired.
Expand Down

0 comments on commit d5c2a19

Please sign in to comment.