Skip to content

Commit c11ea82

Browse files
Merge branch 'dev' of https://github.com/KelvinTegelaar/CIPP-API into dev
2 parents bf9fbc5 + 25d3254 commit c11ea82

5 files changed

Lines changed: 575 additions & 89 deletions

File tree

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
function Add-CIPPPackagedApplication {
2+
<#
3+
.SYNOPSIS
4+
Adds a packaged Win32Lob application to Intune.
5+
6+
.DESCRIPTION
7+
Handles creation of Win32Lob apps with intunewin files and uploads the content.
8+
9+
.PARAMETER AppBody
10+
Hashtable or PSCustomObject containing the app configuration.
11+
12+
.PARAMETER TenantFilter
13+
Tenant ID or domain name for the Graph API call.
14+
15+
.PARAMETER AppType
16+
Type of app: 'Choco' or 'MSPApp'.
17+
18+
.PARAMETER FilePath
19+
Path to the intunewin file.
20+
21+
.PARAMETER FileName
22+
Name of the file from XML metadata.
23+
24+
.PARAMETER UnencryptedSize
25+
Unencrypted size of the file from XML metadata.
26+
27+
.PARAMETER EncryptionInfo
28+
Hashtable containing encryption information from XML.
29+
30+
.PARAMETER DisplayName
31+
Display name of the app for logging.
32+
33+
.PARAMETER APIName
34+
API name for logging (optional).
35+
36+
.PARAMETER Headers
37+
Request headers for logging (optional).
38+
39+
.EXAMPLE
40+
$AppBody = @{ '@odata.type' = '#microsoft.graph.win32LobApp'; displayName = 'My App' }
41+
$EncryptionInfo = @{ EncryptionKey = '...'; MacKey = '...'; ... }
42+
Add-CIPPPackagedApplication -AppBody $AppBody -TenantFilter 'contoso.com' -AppType 'Choco' -FilePath 'app.intunewin' -FileName 'app.intunewin' -UnencryptedSize 1024000 -EncryptionInfo $EncryptionInfo
43+
#>
44+
[CmdletBinding()]
45+
param(
46+
[Parameter(Mandatory = $true)]
47+
[object]$AppBody,
48+
49+
[Parameter(Mandatory = $true)]
50+
[string]$TenantFilter,
51+
52+
[Parameter(Mandatory = $true)]
53+
[string]$FilePath,
54+
55+
[Parameter(Mandatory = $true)]
56+
[string]$FileName,
57+
58+
[Parameter(Mandatory = $true)]
59+
[int64]$UnencryptedSize,
60+
61+
[Parameter(Mandatory = $true)]
62+
[hashtable]$EncryptionInfo,
63+
64+
[Parameter(Mandatory = $false)]
65+
[string]$DisplayName
66+
)
67+
68+
$BaseUri = 'https://graph.microsoft.com/beta/deviceAppManagement/mobileApps'
69+
70+
# Create the Win32Lob app
71+
$NewApp = New-GraphPostRequest -Uri $BaseUri -Body ($AppBody | ConvertTo-Json) -Type POST -tenantid $TenantFilter
72+
73+
# Upload intunewin content
74+
Add-CIPPWin32LobAppContent -AppId $NewApp.id -FilePath $FilePath -FileName $FileName -UnencryptedSize $UnencryptedSize -EncryptionInfo $EncryptionInfo -TenantFilter $TenantFilter -APIName $APIName -Headers $Headers
75+
76+
return $NewApp
77+
}
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
function Add-CIPPW32ScriptApplication {
2+
<#
3+
.SYNOPSIS
4+
Adds a Win32 app with PowerShell script installer to Intune.
5+
6+
.DESCRIPTION
7+
Creates a Win32 app using the PowerShell script installer feature.
8+
Uploads an intunewin file and PowerShell scripts via the scripts endpoint.
9+
10+
.PARAMETER TenantFilter
11+
Tenant ID or domain name for the Graph API call.
12+
13+
.PARAMETER Properties
14+
PSCustomObject containing all Win32 app properties:
15+
- displayName (required): Display name of the app
16+
- description: Description of the app
17+
- publisher: Publisher name
18+
- installScript (required): PowerShell install script content (plaintext)
19+
- uninstallScript: PowerShell uninstall script content (plaintext)
20+
- detectionScript: PowerShell detection script content (plaintext)
21+
- runAsAccount: 'system' or 'user' (default: 'system')
22+
- deviceRestartBehavior: 'allow', 'suppress', or 'force' (default: 'suppress')
23+
- runAs32Bit: Boolean, run scripts as 32-bit on 64-bit clients (default: false)
24+
- enforceSignatureCheck: Boolean, enforce script signature validation (default: false)
25+
26+
.PARAMETER FilePath
27+
Path to the intunewin file.
28+
29+
.PARAMETER FileName
30+
Name of the file from XML metadata.
31+
32+
.PARAMETER UnencryptedSize
33+
Unencrypted size of the file from XML metadata.
34+
35+
.PARAMETER EncryptionInfo
36+
Hashtable containing encryption information from XML.
37+
38+
.EXAMPLE
39+
$Properties = @{
40+
displayName = 'My Script App'
41+
installScript = 'Write-Host "Installing..."'
42+
}
43+
$EncryptionInfo = @{ EncryptionKey = '...'; MacKey = '...'; ... }
44+
Add-CIPPW32ScriptApplication -TenantFilter 'contoso.com' -Properties $Properties -FilePath 'app.intunewin' -FileName 'app.intunewin' -UnencryptedSize 1024000 -EncryptionInfo $EncryptionInfo
45+
#>
46+
[CmdletBinding()]
47+
param(
48+
[Parameter(Mandatory = $true)]
49+
[string]$TenantFilter,
50+
51+
[Parameter(Mandatory = $true)]
52+
[PSCustomObject]$Properties,
53+
54+
[Parameter(Mandatory = $true)]
55+
[string]$FilePath,
56+
57+
[Parameter(Mandatory = $true)]
58+
[string]$FileName,
59+
60+
[Parameter(Mandatory = $true)]
61+
[int64]$UnencryptedSize,
62+
63+
[Parameter(Mandatory = $true)]
64+
[hashtable]$EncryptionInfo
65+
)
66+
67+
# Build Win32 app body
68+
$intuneBody = @{
69+
'@odata.type' = '#microsoft.graph.win32LobApp'
70+
displayName = $Properties.displayName
71+
description = $Properties.description
72+
publisher = $Properties.publisher
73+
fileName = $FileName
74+
setupFilePath = 'N/A'
75+
minimumSupportedWindowsRelease = '1607'
76+
returnCodes = @(
77+
@{ returnCode = 0; type = 'success' }
78+
@{ returnCode = 1707; type = 'success' }
79+
@{ returnCode = 3010; type = 'softReboot' }
80+
@{ returnCode = 1641; type = 'hardReboot' }
81+
@{ returnCode = 1618; type = 'retry' }
82+
)
83+
}
84+
85+
# Add install experience
86+
$intuneBody.installExperience = @{
87+
'@odata.type' = 'microsoft.graph.win32LobAppInstallExperience'
88+
runAsAccount = if ($Properties.runAsAccount) { $Properties.runAsAccount } else { 'system' }
89+
deviceRestartBehavior = if ($Properties.deviceRestartBehavior) { $Properties.deviceRestartBehavior } else { 'suppress' }
90+
maxRunTimeInMinutes = 60
91+
}
92+
93+
# Create the app
94+
$Baseuri = 'https://graph.microsoft.com/beta/deviceAppManagement/mobileApps'
95+
$NewApp = New-GraphPostRequest -Uri $Baseuri -Body ($intuneBody | ConvertTo-Json -Depth 10) -Type POST -tenantid $TenantFilter
96+
Start-Sleep -Milliseconds 200
97+
98+
# Upload intunewin file using shared helper
99+
Add-CIPPWin32LobAppContent -AppId $NewApp.id -FilePath $FilePath -FileName $FileName -UnencryptedSize $UnencryptedSize -EncryptionInfo $EncryptionInfo -TenantFilter $TenantFilter
100+
101+
# Upload PowerShell scripts via the scripts endpoint
102+
$RunAs32Bit = if ($null -ne $Properties.runAs32Bit) { [bool]$Properties.runAs32Bit } else { $false }
103+
$EnforceSignatureCheck = if ($null -ne $Properties.enforceSignatureCheck) { [bool]$Properties.enforceSignatureCheck } else { $false }
104+
105+
$InstallScriptId = $null
106+
$UninstallScriptId = $null
107+
108+
if ($Properties.installScript) {
109+
$InstallScriptContent = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($Properties.installScript))
110+
$InstallScriptBody = @{
111+
'@odata.type' = '#microsoft.graph.win32LobAppInstallPowerShellScript'
112+
displayName = 'install.ps1'
113+
enforceSignatureCheck = $EnforceSignatureCheck
114+
runAs32Bit = $RunAs32Bit
115+
content = $InstallScriptContent
116+
} | ConvertTo-Json
117+
118+
$InstallScriptResponse = New-GraphPostRequest -Uri "$Baseuri/$($NewApp.id)/microsoft.graph.win32LobApp/contentVersions/1/scripts" -Body $InstallScriptBody -Type POST -tenantid $TenantFilter
119+
$InstallScriptId = $InstallScriptResponse.id
120+
121+
# Wait for script to be committed
122+
do {
123+
$ScriptState = New-GraphGetRequest -Uri "$Baseuri/$($NewApp.id)/microsoft.graph.win32LobApp/contentVersions/1/scripts/$InstallScriptId" -tenantid $TenantFilter
124+
if ($ScriptState.state -like '*fail*') {
125+
throw "Failed to commit install script: $($ScriptState.state)"
126+
}
127+
Start-Sleep -Milliseconds 300
128+
} while ($ScriptState.state -eq 'commitPending')
129+
}
130+
131+
if ($Properties.uninstallScript) {
132+
$UninstallScriptContent = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($Properties.uninstallScript))
133+
$UninstallScriptBody = @{
134+
'@odata.type' = '#microsoft.graph.win32LobAppUninstallPowerShellScript'
135+
displayName = 'uninstall.ps1'
136+
enforceSignatureCheck = $EnforceSignatureCheck
137+
runAs32Bit = $RunAs32Bit
138+
content = $UninstallScriptContent
139+
} | ConvertTo-Json
140+
141+
$UninstallScriptResponse = New-GraphPostRequest -Uri "$Baseuri/$($NewApp.id)/microsoft.graph.win32LobApp/contentVersions/1/scripts" -Body $UninstallScriptBody -Type POST -tenantid $TenantFilter
142+
$UninstallScriptId = $UninstallScriptResponse.id
143+
144+
# Wait for script to be committed
145+
do {
146+
$ScriptState = New-GraphGetRequest -Uri "$Baseuri/$($NewApp.id)/microsoft.graph.win32LobApp/contentVersions/1/scripts/$UninstallScriptId" -tenantid $TenantFilter
147+
if ($ScriptState.state -like '*fail*') {
148+
throw "Failed to commit uninstall script: $($ScriptState.state)"
149+
}
150+
Start-Sleep -Milliseconds 300
151+
} while ($ScriptState.state -eq 'commitPending')
152+
}
153+
154+
# Build final commit body with active script references
155+
$CommitBody = @{
156+
'@odata.type' = '#microsoft.graph.win32LobApp'
157+
committedContentVersion = '1'
158+
}
159+
160+
if ($InstallScriptId) {
161+
$CommitBody['activeInstallScript'] = @{ targetId = $InstallScriptId }
162+
}
163+
164+
if ($UninstallScriptId) {
165+
$CommitBody['activeUninstallScript'] = @{ targetId = $UninstallScriptId }
166+
}
167+
168+
# Add detection rules if provided
169+
if ($Properties.detectionScript) {
170+
$DetectionScriptContent = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($Properties.detectionScript))
171+
$CommitBody['detectionRules'] = @(
172+
@{
173+
'@odata.type' = '#microsoft.graph.win32LobAppPowerShellScriptDetection'
174+
scriptContent = $DetectionScriptContent
175+
enforceSignatureCheck = $EnforceSignatureCheck
176+
runAs32Bit = $RunAs32Bit
177+
}
178+
)
179+
}
180+
181+
# Commit the app with script references
182+
$null = New-GraphPostRequest -Uri "$Baseuri/$($NewApp.id)" -tenantid $TenantFilter -Body ($CommitBody | ConvertTo-Json -Depth 10) -Type PATCH
183+
184+
return $NewApp
185+
186+
}

0 commit comments

Comments
 (0)