├── README.md
├── ADMX–OneDrive.admx-KFM.json
├── DeviceConfiguration_Add_Windows_Custom_CredentialGuard.ps1
├── DeviceConfiguration_Add_Windows_Custom_SystemServices.ps1
├── DeviceConfiguration_Add_Windows_Custom_Password-PINreset.ps1
├── DeviceConfiguration_Add_Windows_Update_Insider_FastRing.ps1
├── DeviceConfiguration_Add_Windows_Custom_LocalPoliciesSecurityOptions.ps1
├── Edge crash WDAC fix.ps1
├── WindowsAutopilot_CreateProfile.ps1
├── Application_LOB_Add_MSTeams.ps1
└── Application_LOB_Add - Google.ps1
/README.md:
--------------------------------------------------------------------------------
1 | # IntunePowerShellAutomation
2 | Intune Powershell Automation Scripts with Intune Graph API
3 |
--------------------------------------------------------------------------------
/ADMX–OneDrive.admx-KFM.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pelarsen/IntunePowerShellAutomation/HEAD/ADMX–OneDrive.admx-KFM.json
--------------------------------------------------------------------------------
/DeviceConfiguration_Add_Windows_Custom_CredentialGuard.ps1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pelarsen/IntunePowerShellAutomation/HEAD/DeviceConfiguration_Add_Windows_Custom_CredentialGuard.ps1
--------------------------------------------------------------------------------
/DeviceConfiguration_Add_Windows_Custom_SystemServices.ps1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pelarsen/IntunePowerShellAutomation/HEAD/DeviceConfiguration_Add_Windows_Custom_SystemServices.ps1
--------------------------------------------------------------------------------
/DeviceConfiguration_Add_Windows_Custom_Password-PINreset.ps1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pelarsen/IntunePowerShellAutomation/HEAD/DeviceConfiguration_Add_Windows_Custom_Password-PINreset.ps1
--------------------------------------------------------------------------------
/DeviceConfiguration_Add_Windows_Update_Insider_FastRing.ps1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pelarsen/IntunePowerShellAutomation/HEAD/DeviceConfiguration_Add_Windows_Update_Insider_FastRing.ps1
--------------------------------------------------------------------------------
/DeviceConfiguration_Add_Windows_Custom_LocalPoliciesSecurityOptions.ps1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pelarsen/IntunePowerShellAutomation/HEAD/DeviceConfiguration_Add_Windows_Custom_LocalPoliciesSecurityOptions.ps1
--------------------------------------------------------------------------------
/Edge crash WDAC fix.ps1:
--------------------------------------------------------------------------------
1 | New-Item -Path HKCU:\Software\Microsoft\Internet Explorer\Spartan –Force
2 | $registryPath = "HKCU:\Software\Microsoft\Internet Explorer\Spartan"
3 |
4 | #Fix Edge on 1803 with WDAG or Applocker enabled
5 | $Name = "RAC_LaunchFlags"
6 | $value = "00000035"
7 | IF(!(Test-Path $registryPath))
8 | {
9 | New-Item -Path $registryPath -Force | Out-Null
10 | New-ItemProperty -Path $registryPath -Name $name -Value $value `
11 | -PropertyType String -Force | Out-Null}
12 | ELSE {
13 | New-ItemProperty -Path $registryPath -Name $name -Value $value `
14 | -PropertyType String -Force | Out-Null}
15 |
16 |
--------------------------------------------------------------------------------
/WindowsAutopilot_CreateProfile.ps1:
--------------------------------------------------------------------------------
1 | <#
2 |
3 | .COPYRIGHT
4 | Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
5 | See LICENSE in the project root for license information.
6 |
7 | #>
8 |
9 | ####################################################
10 |
11 | function Get-AuthToken {
12 |
13 | <#
14 | .SYNOPSIS
15 | This function is used to authenticate with the Graph API REST interface
16 | .DESCRIPTION
17 | The function authenticate with the Graph API Interface with the tenant name
18 | .EXAMPLE
19 | Get-AuthToken
20 | Authenticates you with the Graph API interface
21 | .NOTES
22 | NAME: Get-AuthToken
23 | #>
24 |
25 | [cmdletbinding()]
26 |
27 | param
28 | (
29 | [Parameter(Mandatory=$true)]
30 | $User
31 | )
32 |
33 | $userUpn = New-Object "System.Net.Mail.MailAddress" -ArgumentList $User
34 |
35 | $tenant = $userUpn.Host
36 |
37 | Write-Host "Checking for AzureAD module..."
38 |
39 | $AadModule = Get-Module -Name "AzureAD" -ListAvailable
40 |
41 | if ($AadModule -eq $null) {
42 |
43 | Write-Host "AzureAD PowerShell module not found, looking for AzureADPreview"
44 | $AadModule = Get-Module -Name "AzureADPreview" -ListAvailable
45 |
46 | }
47 |
48 | if ($AadModule -eq $null) {
49 | write-host
50 | write-host "AzureAD Powershell module not installed..." -f Red
51 | write-host "Install by running 'Install-Module AzureAD' or 'Install-Module AzureADPreview' from an elevated PowerShell prompt" -f Yellow
52 | write-host "Script can't continue..." -f Red
53 | write-host
54 | exit
55 | }
56 |
57 | # Getting path to ActiveDirectory Assemblies
58 | # If the module count is greater than 1 find the latest version
59 |
60 | if($AadModule.count -gt 1){
61 |
62 | $Latest_Version = ($AadModule | select version | Sort-Object)[-1]
63 |
64 | $aadModule = $AadModule | ? { $_.version -eq $Latest_Version.version }
65 |
66 | # Checking if there are multiple versions of the same module found
67 |
68 | if($AadModule.count -gt 1){
69 |
70 | $aadModule = $AadModule | select -Unique
71 |
72 | }
73 |
74 | $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
75 | $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll"
76 |
77 | }
78 |
79 | else {
80 |
81 | $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
82 | $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll"
83 |
84 | }
85 |
86 | [System.Reflection.Assembly]::LoadFrom($adal) | Out-Null
87 |
88 | [System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null
89 |
90 | $clientId = "d1ddf0e4-d672-4dae-b554-9d5bdfd93547"
91 |
92 | $redirectUri = "urn:ietf:wg:oauth:2.0:oob"
93 |
94 | $resourceAppIdURI = "https://graph.microsoft.com"
95 |
96 | $authority = "https://login.microsoftonline.com/$Tenant"
97 |
98 | try {
99 |
100 | $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority
101 |
102 | # https://msdn.microsoft.com/en-us/library/azure/microsoft.identitymodel.clients.activedirectory.promptbehavior.aspx
103 | # Change the prompt behaviour to force credentials each time: Auto, Always, Never, RefreshSession
104 |
105 | $platformParameters = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList "Auto"
106 |
107 | $userId = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier" -ArgumentList ($User, "OptionalDisplayableId")
108 |
109 | $authResult = $authContext.AcquireTokenAsync($resourceAppIdURI,$clientId,$redirectUri,$platformParameters,$userId).Result
110 |
111 | # If the accesstoken is valid then create the authentication header
112 |
113 | if($authResult.AccessToken){
114 |
115 | # Creating header for Authorization token
116 |
117 | $authHeader = @{
118 | 'Content-Type'='application/json'
119 | 'Authorization'="Bearer " + $authResult.AccessToken
120 | 'ExpiresOn'=$authResult.ExpiresOn
121 | }
122 |
123 | return $authHeader
124 |
125 | }
126 |
127 | else {
128 |
129 | Write-Host
130 | Write-Host "Authorization Access Token is null, please re-run authentication..." -ForegroundColor Red
131 | Write-Host
132 | break
133 |
134 | }
135 |
136 | }
137 |
138 | catch {
139 |
140 | write-host $_.Exception.Message -f Red
141 | write-host $_.Exception.ItemName -f Red
142 | write-host
143 | break
144 |
145 | }
146 |
147 | }
148 |
149 | ####################################################
150 |
151 | Function Add-windowsAutopilotDeploymentProfiles(){
152 |
153 | <#
154 | .SYNOPSIS
155 | This function is used to add an device configuration policy using the Graph API REST interface
156 | .DESCRIPTION
157 | The function connects to the Graph API Interface and adds a device configuration policy
158 | .EXAMPLE
159 | Add-DeviceConfigurationPolicy -JSON $JSON
160 | Adds a device configuration policy in Intune
161 | .NOTES
162 | NAME: Add-DeviceConfigurationPolicy
163 | #>
164 |
165 | [cmdletbinding()]
166 |
167 | param
168 | (
169 | $JSON
170 | )
171 |
172 | $graphApiVersion = "Beta"
173 | $DCP_resource = "deviceManagement/windowsAutopilotDeploymentProfiles"
174 | Write-Verbose "Resource: $DCP_resource"
175 |
176 | try {
177 |
178 | if($JSON -eq "" -or $JSON -eq $null){
179 |
180 | write-host "No JSON specified, please specify valid JSON for the Autopilot Policy..." -f Red
181 |
182 | }
183 |
184 | else {
185 |
186 | Test-JSON -JSON $JSON
187 |
188 | $uri = "https://graph.microsoft.com/$graphApiVersion/$($DCP_resource)"
189 | Invoke-RestMethod -Uri $uri -Headers $authToken -Method Post -Body $JSON -ContentType "application/json"
190 |
191 | }
192 |
193 | }
194 |
195 | catch {
196 |
197 | $ex = $_.Exception
198 | $errorResponse = $ex.Response.GetResponseStream()
199 | $reader = New-Object System.IO.StreamReader($errorResponse)
200 | $reader.BaseStream.Position = 0
201 | $reader.DiscardBufferedData()
202 | $responseBody = $reader.ReadToEnd();
203 | Write-Host "Response content:`n$responseBody" -f Red
204 | Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)"
205 | write-host
206 | break
207 |
208 | }
209 |
210 | }
211 |
212 | ####################################################
213 |
214 | Function Test-JSON(){
215 |
216 | <#
217 | .SYNOPSIS
218 | This function is used to test if the JSON passed to a REST Post request is valid
219 | .DESCRIPTION
220 | The function tests if the JSON passed to the REST Post is valid
221 | .EXAMPLE
222 | Test-JSON -JSON $JSON
223 | Test if the JSON is valid before calling the Graph REST interface
224 | .NOTES
225 | NAME: Test-AuthHeader
226 | #>
227 |
228 | param (
229 |
230 | $JSON
231 |
232 | )
233 |
234 | try {
235 |
236 | $TestJSON = ConvertFrom-Json $JSON -ErrorAction Stop
237 | $validJson = $true
238 |
239 | }
240 |
241 | catch {
242 |
243 | $validJson = $false
244 | $_.Exception
245 |
246 | }
247 |
248 | if (!$validJson){
249 |
250 | Write-Host "Provided JSON isn't in valid JSON format" -f Red
251 | break
252 |
253 | }
254 |
255 | }
256 |
257 | ####################################################
258 |
259 | #region Authentication
260 |
261 | write-host
262 |
263 | # Checking if authToken exists before running authentication
264 | if($global:authToken){
265 |
266 | # Setting DateTime to Universal time to work in all timezones
267 | $DateTime = (Get-Date).ToUniversalTime()
268 |
269 | # If the authToken exists checking when it expires
270 | $TokenExpires = ($authToken.ExpiresOn.datetime - $DateTime).Minutes
271 |
272 | if($TokenExpires -le 0){
273 |
274 | write-host "Authentication Token expired" $TokenExpires "minutes ago" -ForegroundColor Yellow
275 | write-host
276 |
277 | # Defining User Principal Name if not present
278 |
279 | if($User -eq $null -or $User -eq ""){
280 |
281 | $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication"
282 | Write-Host
283 |
284 | }
285 |
286 | $global:authToken = Get-AuthToken -User $User
287 |
288 | }
289 | }
290 |
291 | # Authentication doesn't exist, calling Get-AuthToken function
292 |
293 | else {
294 |
295 | if($User -eq $null -or $User -eq ""){
296 |
297 | $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication"
298 | Write-Host
299 |
300 | }
301 |
302 | # Getting the authorization token
303 | $global:authToken = Get-AuthToken -User $User
304 |
305 | }
306 |
307 | #endregion
308 |
309 | ####################################################
310 |
311 | $AutoPilotProfile = @"
312 |
313 |
314 | {
315 | "@odata.context": "https://graph.microsoft.com/beta/$metadata#deviceManagement/windowsAutopilotDeploymentProfiles/$entity",
316 | "@odata.type": "#microsoft.graph.azureADWindowsAutopilotDeploymentProfile",
317 | "id": "1647e8a1-d391-44bc-839e-bfcf5845ca28",
318 | "displayName": "Windows AutoPilot Default Profile Graph",
319 | "description": "",
320 | "language": "",
321 | "createdDateTime": "2017-10-20T05:47:54.8669437Z",
322 | "lastModifiedDateTime": "2018-10-21T09:51:59.7606979Z",
323 | "enrollmentStatusScreenSettings": null,
324 | "extractHardwareHash": true,
325 | "deviceNameTemplate": "OSD-%RAND:5%",
326 | "outOfBoxExperienceSettings": {
327 | "hidePrivacySettings": true,
328 | "hideEULA": true,
329 | "userType": "standard",
330 | "deviceUsageType": "singleUser",
331 | "skipKeyboardSelectionPage": false,
332 | "hideEscapeLink": true
333 | }
334 | }
335 |
336 | "@
337 |
338 | ####################################################
339 |
340 | $AutoPilotProfileShared = @"
341 |
342 | {
343 | "@odata.context": "https://graph.microsoft.com/beta/$metadata#deviceManagement/windowsAutopilotDeploymentProfiles/$entity",
344 | "@odata.type": "#microsoft.graph.azureADWindowsAutopilotDeploymentProfile",
345 | "id": "91cb14fc-9d13-4cba-99d4-580f091e6843",
346 | "displayName": "Windows AutoPilot Shared Device Graph",
347 | "description": "",
348 | "language": "da-DK",
349 | "createdDateTime": "2018-06-08T11:47:49.5770529Z",
350 | "lastModifiedDateTime": "2018-10-21T09:53:48.2334846Z",
351 | "enrollmentStatusScreenSettings": null,
352 | "extractHardwareHash": false,
353 | "deviceNameTemplate": "SHARED-%RAND:5%",
354 | "outOfBoxExperienceSettings": {
355 | "hidePrivacySettings": true,
356 | "hideEULA": true,
357 | "userType": "standard",
358 | "deviceUsageType": "shared",
359 | "skipKeyboardSelectionPage": true,
360 | "hideEscapeLink": true
361 | }
362 | }
363 |
364 | "@
365 |
366 | ####################################################
367 |
368 | Add-windowsAutopilotDeploymentProfiles -Json $AutoPilotProfile
369 | Add-windowsAutopilotDeploymentProfiles -Json $AutoPilotProfileShared
370 |
371 |
--------------------------------------------------------------------------------
/Application_LOB_Add_MSTeams.ps1:
--------------------------------------------------------------------------------
1 |
2 | <#
3 |
4 | .COPYRIGHT
5 | Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
6 | See LICENSE in the project root for license information.
7 |
8 | #>
9 |
10 | ####################################################
11 |
12 | function Get-AuthToken {
13 |
14 | <#
15 | .SYNOPSIS
16 | This function is used to authenticate with the Graph API REST interface
17 | .DESCRIPTION
18 | The function authenticate with the Graph API Interface with the tenant name
19 | .EXAMPLE
20 | Get-AuthToken
21 | Authenticates you with the Graph API interface
22 | .NOTES
23 | NAME: Get-AuthToken
24 | #>
25 |
26 | [cmdletbinding()]
27 |
28 | param
29 | (
30 | [Parameter(Mandatory=$true)]
31 | $User
32 | )
33 |
34 | $userUpn = New-Object "System.Net.Mail.MailAddress" -ArgumentList $User
35 |
36 | $tenant = $userUpn.Host
37 |
38 | Write-Host "Checking for AzureAD module..."
39 |
40 | $AadModule = Get-Module -Name "AzureAD" -ListAvailable
41 |
42 | if ($AadModule -eq $null) {
43 |
44 | Write-Host "AzureAD PowerShell module not found, looking for AzureADPreview"
45 | $AadModule = Get-Module -Name "AzureADPreview" -ListAvailable
46 |
47 | }
48 |
49 | if ($AadModule -eq $null) {
50 | write-host
51 | write-host "AzureAD Powershell module not installed..." -f Red
52 | write-host "Install by running 'Install-Module AzureAD' or 'Install-Module AzureADPreview' from an elevated PowerShell prompt" -f Yellow
53 | write-host "Script can't continue..." -f Red
54 | write-host
55 | exit
56 | }
57 |
58 | # Getting path to ActiveDirectory Assemblies
59 | # If the module count is greater than 1 find the latest version
60 |
61 | if($AadModule.count -gt 1){
62 |
63 | $Latest_Version = ($AadModule | select version | Sort-Object)[-1]
64 |
65 | $aadModule = $AadModule | ? { $_.version -eq $Latest_Version.version }
66 |
67 | # Checking if there are multiple versions of the same module found
68 |
69 | if($AadModule.count -gt 1){
70 |
71 | $aadModule = $AadModule | select -Unique
72 |
73 | }
74 |
75 | $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
76 | $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll"
77 |
78 | }
79 |
80 | else {
81 |
82 | $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
83 | $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll"
84 |
85 | }
86 |
87 | [System.Reflection.Assembly]::LoadFrom($adal) | Out-Null
88 |
89 | [System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null
90 |
91 | $clientId = "d1ddf0e4-d672-4dae-b554-9d5bdfd93547"
92 |
93 | $redirectUri = "urn:ietf:wg:oauth:2.0:oob"
94 |
95 | $resourceAppIdURI = "https://graph.microsoft.com"
96 |
97 | $authority = "https://login.microsoftonline.com/$Tenant"
98 |
99 | try {
100 |
101 | $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority
102 |
103 | # https://msdn.microsoft.com/en-us/library/azure/microsoft.identitymodel.clients.activedirectory.promptbehavior.aspx
104 | # Change the prompt behaviour to force credentials each time: Auto, Always, Never, RefreshSession
105 |
106 | $platformParameters = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList "Auto"
107 |
108 | $userId = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier" -ArgumentList ($User, "OptionalDisplayableId")
109 |
110 | $authResult = $authContext.AcquireTokenAsync($resourceAppIdURI,$clientId,$redirectUri,$platformParameters,$userId).Result
111 |
112 | # If the accesstoken is valid then create the authentication header
113 |
114 | if($authResult.AccessToken){
115 |
116 | # Creating header for Authorization token
117 |
118 | $authHeader = @{
119 | 'Content-Type'='application/json'
120 | 'Authorization'="Bearer " + $authResult.AccessToken
121 | 'ExpiresOn'=$authResult.ExpiresOn
122 | }
123 |
124 | return $authHeader
125 |
126 | }
127 |
128 | else {
129 |
130 | Write-Host
131 | Write-Host "Authorization Access Token is null, please re-run authentication..." -ForegroundColor Red
132 | Write-Host
133 | break
134 |
135 | }
136 |
137 | }
138 |
139 | catch {
140 |
141 | write-host $_.Exception.Message -f Red
142 | write-host $_.Exception.ItemName -f Red
143 | write-host
144 | break
145 |
146 | }
147 |
148 | }
149 |
150 | ####################################################
151 |
152 | function CloneObject($object){
153 |
154 | $stream = New-Object IO.MemoryStream;
155 | $formatter = New-Object Runtime.Serialization.Formatters.Binary.BinaryFormatter;
156 | $formatter.Serialize($stream, $object);
157 | $stream.Position = 0;
158 | $formatter.Deserialize($stream);
159 | }
160 |
161 | ####################################################
162 |
163 | function WriteHeaders($authToken){
164 |
165 | foreach ($header in $authToken.GetEnumerator())
166 | {
167 | if ($header.Name.ToLower() -eq "authorization")
168 | {
169 | continue;
170 | }
171 |
172 | Write-Host -ForegroundColor Gray "$($header.Name): $($header.Value)";
173 | }
174 | }
175 |
176 | ####################################################
177 |
178 | function MakeGetRequest($collectionPath){
179 |
180 | $uri = "$baseUrl$collectionPath";
181 | $request = "GET $uri";
182 |
183 | if ($logRequestUris) { Write-Host $request; }
184 | if ($logHeaders) { WriteHeaders $authToken; }
185 |
186 | try
187 | {
188 | $response = Invoke-RestMethod $uri -Method Get -Headers $authToken;
189 | $response;
190 | }
191 | catch
192 | {
193 | Write-Host -ForegroundColor Red $request;
194 | Write-Host -ForegroundColor Red $_.Exception.Message;
195 | throw;
196 | }
197 | }
198 |
199 | ####################################################
200 |
201 | function MakePatchRequest($collectionPath, $body){
202 |
203 | MakeRequest "PATCH" $collectionPath $body;
204 |
205 | }
206 |
207 | ####################################################
208 |
209 | function MakePostRequest($collectionPath, $body){
210 |
211 | MakeRequest "POST" $collectionPath $body;
212 |
213 | }
214 |
215 | ####################################################
216 |
217 | function MakeRequest($verb, $collectionPath, $body){
218 |
219 | $uri = "$baseUrl$collectionPath";
220 | $request = "$verb $uri";
221 |
222 | $clonedHeaders = CloneObject $authToken;
223 | $clonedHeaders["content-length"] = $body.Length;
224 | $clonedHeaders["content-type"] = "application/json";
225 |
226 | if ($logRequestUris) { Write-Host $request; }
227 | if ($logHeaders) { WriteHeaders $clonedHeaders; }
228 | if ($logContent) { Write-Host -ForegroundColor Gray $body; }
229 |
230 | try
231 | {
232 | $response = Invoke-RestMethod $uri -Method $verb -Headers $clonedHeaders -Body $body;
233 | $response;
234 | }
235 | catch
236 | {
237 | Write-Host -ForegroundColor Red $request;
238 | Write-Host -ForegroundColor Red $_.Exception.Message;
239 | throw;
240 | }
241 | }
242 |
243 | ####################################################
244 |
245 | function UploadAzureStorageChunk($sasUri, $id, $body){
246 |
247 | $uri = "$sasUri&comp=block&blockid=$id";
248 | $request = "PUT $uri";
249 |
250 | $iso = [System.Text.Encoding]::GetEncoding("iso-8859-1");
251 | $encodedBody = $iso.GetString($body);
252 | $headers = @{
253 | "x-ms-blob-type" = "BlockBlob"
254 | };
255 |
256 | if ($logRequestUris) { Write-Host $request; }
257 | if ($logHeaders) { WriteHeaders $headers; }
258 |
259 | try
260 | {
261 | $response = Invoke-WebRequest $uri -Method Put -Headers $headers -Body $encodedBody;
262 | }
263 | catch
264 | {
265 | Write-Host -ForegroundColor Red $request;
266 | Write-Host -ForegroundColor Red $_.Exception.Message;
267 | throw;
268 | }
269 |
270 | }
271 |
272 | ####################################################
273 |
274 | function FinalizeAzureStorageUpload($sasUri, $ids){
275 |
276 | $uri = "$sasUri&comp=blocklist";
277 | $request = "PUT $uri";
278 |
279 | $xml = '';
280 | foreach ($id in $ids)
281 | {
282 | $xml += "$id";
283 | }
284 | $xml += '';
285 |
286 | if ($logRequestUris) { Write-Host $request; }
287 | if ($logContent) { Write-Host -ForegroundColor Gray $xml; }
288 |
289 | try
290 | {
291 | Invoke-RestMethod $uri -Method Put -Body $xml;
292 | }
293 | catch
294 | {
295 | Write-Host -ForegroundColor Red $request;
296 | Write-Host -ForegroundColor Red $_.Exception.Message;
297 | throw;
298 | }
299 | }
300 |
301 | ####################################################
302 |
303 | function UploadFileToAzureStorage($sasUri, $filepath){
304 |
305 | # Chunk size = 1 MiB
306 | $chunkSizeInBytes = 1024 * 1024;
307 |
308 | # Read the whole file and find the total chunks.
309 | #[byte[]]$bytes = Get-Content $filepath -Encoding byte;
310 | # Using ReadAllBytes method as the Get-Content used alot of memory on the machine
311 | [byte[]]$bytes = [System.IO.File]::ReadAllBytes($filepath);
312 | $chunks = [Math]::Ceiling($bytes.Length / $chunkSizeInBytes);
313 |
314 | # Upload each chunk.
315 | $ids = @();
316 | $cc = 1
317 |
318 | for ($chunk = 0; $chunk -lt $chunks; $chunk++)
319 | {
320 | $id = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($chunk.ToString("0000")));
321 | $ids += $id;
322 |
323 | $start = $chunk * $chunkSizeInBytes;
324 | $end = [Math]::Min($start + $chunkSizeInBytes - 1, $bytes.Length - 1);
325 | $body = $bytes[$start..$end];
326 |
327 | Write-Progress -Activity "Uploading File to Azure Storage" -status "Uploading chunk $cc of $chunks" `
328 | -percentComplete ($cc / $chunks*100)
329 | $cc++
330 |
331 | $uploadResponse = UploadAzureStorageChunk $sasUri $id $body;
332 |
333 |
334 | }
335 |
336 | Write-Progress -Completed -Activity "Uploading File to Azure Storage"
337 |
338 | Write-Host
339 |
340 | # Finalize the upload.
341 | $uploadResponse = FinalizeAzureStorageUpload $sasUri $ids;
342 | }
343 |
344 | ####################################################
345 |
346 | function GenerateKey{
347 |
348 | try
349 | {
350 | $aes = [System.Security.Cryptography.Aes]::Create();
351 | $aesProvider = New-Object System.Security.Cryptography.AesCryptoServiceProvider;
352 | $aesProvider.GenerateKey();
353 | $aesProvider.Key;
354 | }
355 | finally
356 | {
357 | if ($aesProvider -ne $null) { $aesProvider.Dispose(); }
358 | if ($aes -ne $null) { $aes.Dispose(); }
359 | }
360 | }
361 |
362 | ####################################################
363 |
364 | function GenerateIV{
365 |
366 | try
367 | {
368 | $aes = [System.Security.Cryptography.Aes]::Create();
369 | $aes.IV;
370 | }
371 | finally
372 | {
373 | if ($aes -ne $null) { $aes.Dispose(); }
374 | }
375 | }
376 |
377 | ####################################################
378 |
379 | function EncryptFileWithIV($sourceFile, $targetFile, $encryptionKey, $hmacKey, $initializationVector){
380 |
381 | $bufferBlockSize = 1024 * 4;
382 | $computedMac = $null;
383 |
384 | try
385 | {
386 | $aes = [System.Security.Cryptography.Aes]::Create();
387 | $hmacSha256 = New-Object System.Security.Cryptography.HMACSHA256;
388 | $hmacSha256.Key = $hmacKey;
389 | $hmacLength = $hmacSha256.HashSize / 8;
390 |
391 | $buffer = New-Object byte[] $bufferBlockSize;
392 | $bytesRead = 0;
393 |
394 | $targetStream = [System.IO.File]::Open($targetFile, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write, [System.IO.FileShare]::Read);
395 | $targetStream.Write($buffer, 0, $hmacLength + $initializationVector.Length);
396 |
397 | try
398 | {
399 | $encryptor = $aes.CreateEncryptor($encryptionKey, $initializationVector);
400 | $sourceStream = [System.IO.File]::Open($sourceFile, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::Read);
401 | $cryptoStream = New-Object System.Security.Cryptography.CryptoStream -ArgumentList @($targetStream, $encryptor, [System.Security.Cryptography.CryptoStreamMode]::Write);
402 |
403 | $targetStream = $null;
404 | while (($bytesRead = $sourceStream.Read($buffer, 0, $bufferBlockSize)) -gt 0)
405 | {
406 | $cryptoStream.Write($buffer, 0, $bytesRead);
407 | $cryptoStream.Flush();
408 | }
409 | $cryptoStream.FlushFinalBlock();
410 | }
411 | finally
412 | {
413 | if ($cryptoStream -ne $null) { $cryptoStream.Dispose(); }
414 | if ($sourceStream -ne $null) { $sourceStream.Dispose(); }
415 | if ($encryptor -ne $null) { $encryptor.Dispose(); }
416 | }
417 |
418 | try
419 | {
420 | $finalStream = [System.IO.File]::Open($targetFile, [System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::Read)
421 |
422 | $finalStream.Seek($hmacLength, [System.IO.SeekOrigin]::Begin) > $null;
423 | $finalStream.Write($initializationVector, 0, $initializationVector.Length);
424 | $finalStream.Seek($hmacLength, [System.IO.SeekOrigin]::Begin) > $null;
425 |
426 | $hmac = $hmacSha256.ComputeHash($finalStream);
427 | $computedMac = $hmac;
428 |
429 | $finalStream.Seek(0, [System.IO.SeekOrigin]::Begin) > $null;
430 | $finalStream.Write($hmac, 0, $hmac.Length);
431 | }
432 | finally
433 | {
434 | if ($finalStream -ne $null) { $finalStream.Dispose(); }
435 | }
436 | }
437 | finally
438 | {
439 | if ($targetStream -ne $null) { $targetStream.Dispose(); }
440 | if ($aes -ne $null) { $aes.Dispose(); }
441 | }
442 |
443 | $computedMac;
444 | }
445 |
446 | ####################################################
447 |
448 | function EncryptFile($sourceFile, $targetFile){
449 |
450 | $encryptionKey = GenerateKey;
451 | $hmacKey = GenerateKey;
452 | $initializationVector = GenerateIV;
453 |
454 | # Create the encrypted target file and compute the HMAC value.
455 | $mac = EncryptFileWithIV $sourceFile $targetFile $encryptionKey $hmacKey $initializationVector;
456 |
457 | # Compute the SHA256 hash of the source file and convert the result to bytes.
458 | $fileDigest = (Get-FileHash $sourceFile -Algorithm SHA256).Hash;
459 | $fileDigestBytes = New-Object byte[] ($fileDigest.Length / 2);
460 | for ($i = 0; $i -lt $fileDigest.Length; $i += 2)
461 | {
462 | $fileDigestBytes[$i / 2] = [System.Convert]::ToByte($fileDigest.Substring($i, 2), 16);
463 | }
464 |
465 | # Return an object that will serialize correctly to the file commit Graph API.
466 | $encryptionInfo = @{};
467 | $encryptionInfo.encryptionKey = [System.Convert]::ToBase64String($encryptionKey);
468 | $encryptionInfo.macKey = [System.Convert]::ToBase64String($hmacKey);
469 | $encryptionInfo.initializationVector = [System.Convert]::ToBase64String($initializationVector);
470 | $encryptionInfo.mac = [System.Convert]::ToBase64String($mac);
471 | $encryptionInfo.profileIdentifier = "ProfileVersion1";
472 | $encryptionInfo.fileDigest = [System.Convert]::ToBase64String($fileDigestBytes);
473 | $encryptionInfo.fileDigestAlgorithm = "SHA256";
474 |
475 | $fileEncryptionInfo = @{};
476 | $fileEncryptionInfo.fileEncryptionInfo = $encryptionInfo;
477 |
478 | $fileEncryptionInfo;
479 |
480 | }
481 |
482 | ####################################################
483 |
484 | function WaitForFileProcessing($fileUri, $stage){
485 |
486 | $attempts= 60;
487 | $waitTimeInSeconds = 1;
488 |
489 | $successState = "$($stage)Success";
490 | $pendingState = "$($stage)Pending";
491 | $failedState = "$($stage)Failed";
492 | $timedOutState = "$($stage)TimedOut";
493 |
494 | $file = $null;
495 | while ($attempts -gt 0)
496 | {
497 | $file = MakeGetRequest $fileUri;
498 |
499 | if ($file.uploadState -eq $successState)
500 | {
501 | break;
502 | }
503 | elseif ($file.uploadState -ne $pendingState)
504 | {
505 | throw "File upload state is not success: $($file.uploadState)";
506 | }
507 |
508 | Start-Sleep $waitTimeInSeconds;
509 | $attempts--;
510 | }
511 |
512 | if ($file -eq $null)
513 | {
514 | throw "File request did not complete in the allotted time.";
515 | }
516 |
517 | $file;
518 |
519 | }
520 |
521 | ####################################################
522 |
523 | function GetAndroidAppBody($displayName, $publisher, $description, $filename, $identityName, $identityVersion, $versionName, $minimumSupportedOperatingSystem){
524 |
525 | $body = @{ "@odata.type" = "#microsoft.graph.androidLOBApp" };
526 | $body.categories = @();
527 | $body.displayName = $displayName;
528 | $body.publisher = $publisher;
529 | $body.description = $description;
530 | $body.fileName = $filename;
531 | $body.identityName = $identityName;
532 | $body.identityVersion = $identityVersion;
533 |
534 | if ($minimumSupportedOperatingSystem -eq $null){
535 |
536 | $body.minimumSupportedOperatingSystem = @{ "v4_4" = $true };
537 |
538 | }
539 |
540 | else {
541 |
542 | $body.minimumSupportedOperatingSystem = $minimumSupportedOperatingSystem;
543 |
544 | }
545 |
546 | $body.informationUrl = $null;
547 | $body.isFeatured = $false;
548 | $body.privacyInformationUrl = $null;
549 | $body.developer = "";
550 | $body.notes = "";
551 | $body.owner = "";
552 | $body.versionCode = $identityVersion;
553 | $body.versionName = $versionName;
554 |
555 | $body;
556 | }
557 |
558 | ####################################################
559 |
560 | function GetiOSAppBody($displayName, $publisher, $description, $filename, $bundleId, $identityVersion, $versionNumber, $expirationDateTime){
561 |
562 | $body = @{ "@odata.type" = "#microsoft.graph.iosLOBApp" };
563 | $body.applicableDeviceType = @{ "iPad" = $true; "iPhoneAndIPod" = $true }
564 | $body.categories = @();
565 | $body.displayName = $displayName;
566 | $body.publisher = $publisher;
567 | $body.description = $description;
568 | $body.fileName = $filename;
569 | $body.bundleId = $bundleId;
570 | $body.identityVersion = $identityVersion;
571 | if ($minimumSupportedOperatingSystem -eq $null)
572 | {
573 | $body.minimumSupportedOperatingSystem = @{ "v9_0" = $true };
574 | }
575 | else
576 | {
577 | $body.minimumSupportedOperatingSystem = $minimumSupportedOperatingSystem;
578 | }
579 |
580 | $body.informationUrl = $null;
581 | $body.isFeatured = $false;
582 | $body.privacyInformationUrl = $null;
583 | $body.developer = "";
584 | $body.notes = "";
585 | $body.owner = "";
586 | $body.expirationDateTime = $expirationDateTime;
587 | $body.versionNumber = $versionNumber;
588 |
589 | $body;
590 | }
591 |
592 | ####################################################
593 |
594 | function GetMSIAppBody($displayName, $publisher, $description, $filename, $identityVersion, $ProductCode){
595 |
596 | $body = @{ "@odata.type" = "#microsoft.graph.windowsMobileMSI" };
597 | $body.displayName = $displayName;
598 | $body.publisher = $publisher;
599 | $body.description = $description;
600 | $body.fileName = $filename;
601 | $body.identityVersion = $identityVersion;
602 | $body.informationUrl = $null;
603 | $body.isFeatured = $false;
604 | $body.privacyInformationUrl = $null;
605 | $body.developer = "";
606 | $body.notes = "";
607 | $body.owner = "";
608 | $body.productCode = "$ProductCode";
609 | $body.productVersion = "$identityVersion";
610 |
611 | $body;
612 | }
613 |
614 | ####################################################
615 |
616 | function GetAppFileBody($name, $size, $sizeEncrypted, $manifest){
617 |
618 | $body = @{ "@odata.type" = "#microsoft.graph.mobileAppContentFile" };
619 | $body.name = $name;
620 | $body.size = $size;
621 | $body.sizeEncrypted = $sizeEncrypted;
622 | $body.manifest = $manifest;
623 |
624 | $body;
625 | }
626 |
627 | ####################################################
628 |
629 | function GetAppCommitBody($contentVersionId, $LobType){
630 |
631 | $body = @{ "@odata.type" = "#$LobType" };
632 | $body.committedContentVersion = $contentVersionId;
633 |
634 | $body;
635 |
636 | }
637 |
638 | ####################################################
639 |
640 | Function Get-MSIFileInformation(){
641 |
642 | # https://www.scconfigmgr.com/2014/08/22/how-to-get-msi-file-information-with-powershell/
643 |
644 | param(
645 | [parameter(Mandatory=$true)]
646 | [ValidateNotNullOrEmpty()]
647 | [System.IO.FileInfo]$Path,
648 |
649 | [parameter(Mandatory=$true)]
650 | [ValidateNotNullOrEmpty()]
651 | [ValidateSet("ProductCode", "ProductVersion", "ProductName", "Manufacturer", "ProductLanguage", "FullVersion")]
652 | [string]$Property
653 | )
654 | Process {
655 |
656 | try {
657 | # Read property from MSI database
658 | $WindowsInstaller = New-Object -ComObject WindowsInstaller.Installer
659 | $MSIDatabase = $WindowsInstaller.GetType().InvokeMember("OpenDatabase", "InvokeMethod", $null, $WindowsInstaller, @($Path.FullName, 0))
660 | $Query = "SELECT Value FROM Property WHERE Property = '$($Property)'"
661 | $View = $MSIDatabase.GetType().InvokeMember("OpenView", "InvokeMethod", $null, $MSIDatabase, ($Query))
662 | $View.GetType().InvokeMember("Execute", "InvokeMethod", $null, $View, $null)
663 | $Record = $View.GetType().InvokeMember("Fetch", "InvokeMethod", $null, $View, $null)
664 | $Value = $Record.GetType().InvokeMember("StringData", "GetProperty", $null, $Record, 1)
665 |
666 | # Commit database and close view
667 | $MSIDatabase.GetType().InvokeMember("Commit", "InvokeMethod", $null, $MSIDatabase, $null)
668 | $View.GetType().InvokeMember("Close", "InvokeMethod", $null, $View, $null)
669 | $MSIDatabase = $null
670 | $View = $null
671 |
672 | # Return the value
673 | return $Value
674 | }
675 |
676 | catch {
677 |
678 | Write-Warning -Message $_.Exception.Message;
679 | break;
680 |
681 | }
682 |
683 | }
684 |
685 | End {
686 | # Run garbage collection and release ComObject
687 | [System.Runtime.Interopservices.Marshal]::ReleaseComObject($WindowsInstaller) | Out-Null
688 | [System.GC]::Collect()
689 | }
690 |
691 | }
692 |
693 | ####################################################
694 |
695 | Function Test-SourceFile(){
696 |
697 | param
698 | (
699 | [parameter(Mandatory=$true)]
700 | [ValidateNotNullOrEmpty()]
701 | $SourceFile
702 | )
703 |
704 | try {
705 |
706 | if(!(test-path "$SourceFile")){
707 |
708 | Write-Host "Source File '$sourceFile' doesn't exist..." -ForegroundColor Red
709 | throw
710 |
711 | }
712 |
713 | }
714 |
715 | catch {
716 |
717 | Write-Host -ForegroundColor Red $_.Exception.Message;
718 | Write-Host
719 | break;
720 |
721 | }
722 |
723 | }
724 |
725 | ####################################################
726 |
727 | Function Get-ApkInformation {
728 |
729 | <#
730 | .SYNOPSIS
731 | This function is used to get information about an Android APK file using the Android SDK - https://developer.android.com/studio/index.html
732 | .DESCRIPTION
733 | This function is used to get information about an Android APK file using the Android SDK - https://developer.android.com/studio/index.html
734 | .EXAMPLE
735 | Get-ApkInformation -sourceFile c:\source\application.apk
736 | Function will return two object, object[0] is the identityName and object[1] is the identityVersion
737 | .NOTES
738 | NAME: Get-ApkInformation
739 | #>
740 |
741 | [cmdletbinding()]
742 |
743 | param
744 | (
745 | [Parameter(Mandatory=$true)]
746 | $sourceFile,
747 | [Parameter(Mandatory=$true)]
748 | $AndroidSDK
749 | )
750 |
751 | if(!(test-path $AndroidSDK)){
752 |
753 | Write-Host
754 | Write-Host "Android SDK isn't installed..." -ForegroundColor Red
755 | Write-Host "Please install Android Studio and install the SDK from https://developer.android.com/studio/index.html"
756 | Write-Host
757 | break
758 |
759 | }
760 |
761 | if(((gci $AndroidSDK | select name).Name).count -gt 1){
762 |
763 | $BuildTools = ((gci $AndroidSDK | select name).Name | sort -Descending)[0]
764 |
765 | }
766 |
767 | else {
768 |
769 | $BuildTools = ((gci $AndroidSDK | select name).Name)
770 |
771 | }
772 |
773 | $aaptPath = "$AndroidSDK\$BuildTools"
774 |
775 | [ScriptBlock]$command = {
776 |
777 | cmd.exe /c "$aaptPath\aapt.exe" dump badging "$sourceFile"
778 |
779 | }
780 |
781 | $aaptRun = Invoke-Command -ScriptBlock $command
782 |
783 | $AndroidPackage = $aaptRun | ? { ($_).startswith("package") }
784 |
785 | $PackageInfo = $AndroidPackage.split(" ")
786 |
787 | $PackageInfo[1].Split("'")[1]
788 | $PackageInfo[2].Split("'")[1]
789 | $PackageInfo[3].Split("'")[1]
790 |
791 | if ($logContent) { Write-Host -ForegroundColor Gray $PackageInfo[1].Split("'")[1]; }
792 | if ($logContent) { Write-Host -ForegroundColor Gray $PackageInfo[2].Split("'")[1]; }
793 | if ($logContent) { Write-Host -ForegroundColor Gray $PackageInfo[3].Split("'")[1]; }
794 |
795 | }
796 |
797 | ####################################################
798 |
799 | function Upload-AndroidLob(){
800 |
801 | <#
802 | .SYNOPSIS
803 | This function is used to upload an Android LOB Application to the Intune Service
804 | .DESCRIPTION
805 | This function is used to upload an Android LOB Application to the Intune Service
806 | .EXAMPLE
807 | Upload-AndroidLob -sourceFile "C:\Software\package.apk" -publisher "Publisher Name" -description "Description of Application" -identityName "com.package" -identityVersion "1" -versionName "10.1.1"
808 | This example uses all parameters required to add an Android Application into the Intune Service
809 | Upload-AndroidLob -sourceFile "C:\Software\package.apk" -publisher "Publisher Name" -description "Description of Application"
810 | This example uses the required parameters to add an Android Application into the Intune Service. This example will require the Android SDK to get identityName and identityVersion
811 | .NOTES
812 | NAME: Upload-AndroidLOB
813 | #>
814 |
815 | [cmdletbinding()]
816 |
817 | param
818 | (
819 | [parameter(Mandatory=$true,Position=1)]
820 | [ValidateNotNullOrEmpty()]
821 | [string]$SourceFile,
822 |
823 | [parameter(Mandatory=$false)]
824 | [string]$displayName,
825 |
826 | [parameter(Mandatory=$true,Position=2)]
827 | [ValidateNotNullOrEmpty()]
828 | [string]$publisher,
829 |
830 | [parameter(Mandatory=$true,Position=3)]
831 | [ValidateNotNullOrEmpty()]
832 | [string]$description,
833 |
834 | [parameter(Mandatory=$false)]
835 | [string]$identityName,
836 |
837 | [parameter(Mandatory=$false)]
838 | [string]$identityVersion,
839 |
840 | [parameter(Mandatory=$false)]
841 | [string]$versionName
842 |
843 | )
844 |
845 | try
846 | {
847 |
848 | $LOBType = "microsoft.graph.androidLOBApp"
849 |
850 | Write-Host "Testing if SourceFile '$SourceFile' Path is valid..." -ForegroundColor Yellow
851 | Test-SourceFile "$SourceFile"
852 |
853 | if(!$identityName){
854 |
855 | Write-Host
856 | Write-Host "Opening APK file to get identityName to pass to the service..." -ForegroundColor Yellow
857 |
858 | $APKInformation = Get-ApkInformation -AndroidSDK $AndroidSDKLocation -sourceFile "$SourceFile"
859 |
860 | $identityName = $APKInformation[0]
861 |
862 | }
863 |
864 | if(!$identityVersion){
865 |
866 | Write-Host
867 | Write-Host "Opening APK file to get identityVersion to pass to the service..." -ForegroundColor Yellow
868 |
869 | $APKInformation = Get-ApkInformation -AndroidSDK $AndroidSDKLocation -sourceFile "$SourceFile"
870 |
871 | $identityVersion = $APKInformation[1]
872 |
873 | }
874 |
875 | if(!$versionName){
876 |
877 | Write-Host
878 | Write-Host "Opening APK file to get versionName to pass to the service..." -ForegroundColor Yellow
879 |
880 | $APKInformation = Get-ApkInformation -AndroidSDK $AndroidSDKLocation -sourceFile "$SourceFile"
881 |
882 | $versionName = $APKInformation[2]
883 |
884 | }
885 |
886 |
887 | # Creating temp file name from Source File path
888 | $tempFile = [System.IO.Path]::GetDirectoryName("$SourceFile") + "\" + [System.IO.Path]::GetFileNameWithoutExtension("$SourceFile") + "_temp.bin"
889 |
890 | # Creating filename variable from Source File Path
891 | $filename = [System.IO.Path]::GetFileName("$SourceFile")
892 |
893 | if(!($displayName)){
894 |
895 | $displayName = $filename
896 |
897 | }
898 |
899 | # Create a new Android LOB app.
900 | Write-Host
901 | Write-Host "Creating JSON data to pass to the service..." -ForegroundColor Yellow
902 | $mobileAppBody = GetAndroidAppBody "$displayName" "$Publisher" "$Description" "$filename" "$identityName" "$identityVersion" "$versionName";
903 |
904 | Write-Host
905 | Write-Host "Creating application in Intune..." -ForegroundColor Yellow
906 | $mobileApp = MakePostRequest "mobileApps" ($mobileAppBody | ConvertTo-Json);
907 |
908 | # Get the content version for the new app (this will always be 1 until the new app is committed).
909 | Write-Host
910 | Write-Host "Creating Content Version in the service for the application..." -ForegroundColor Yellow
911 | $appId = $mobileApp.id;
912 | $contentVersionUri = "mobileApps/$appId/$LOBType/contentVersions";
913 | $contentVersion = MakePostRequest $contentVersionUri "{}";
914 |
915 | # Encrypt file and Get File Information
916 | Write-Host
917 | Write-Host "Ecrypting the file '$SourceFile'..." -ForegroundColor Yellow
918 | $encryptionInfo = EncryptFile "$sourceFile" "$tempFile";
919 | $Size = (Get-Item "$sourceFile").Length
920 | $EncrySize = (Get-Item "$tempFile").Length
921 |
922 | Write-Host
923 | Write-Host "Creating the manifest file used to install the application on the device..." -ForegroundColor Yellow
924 |
925 | [xml]$manifestXML = 'com.leadapps.android.radio.ncp101.0.5.4A_Online_Radio_1.0.5.4.apk3'
926 |
927 | $manifestXML.AndroidManifestProperties.Package = "$identityName" # com.application.test
928 | $manifestXML.AndroidManifestProperties.PackageVersionCode = "$identityVersion" # 10
929 | $manifestXML.AndroidManifestProperties.PackageVersionName = "$identityVersion" # 1.0.5.4
930 | $manifestXML.AndroidManifestProperties.ApplicationName = "$filename" # name.apk
931 |
932 | $manifestXML_Output = $manifestXML.OuterXml.ToString()
933 |
934 | $Bytes = [System.Text.Encoding]::ASCII.GetBytes($manifestXML_Output)
935 | $EncodedText =[Convert]::ToBase64String($Bytes)
936 |
937 | # Create a new file for the app.
938 | Write-Host
939 | Write-Host "Creating a new file entry in Azure for the upload..." -ForegroundColor Yellow
940 | $contentVersionId = $contentVersion.id;
941 | $fileBody = GetAppFileBody "$filename" $Size $EncrySize "$EncodedText";
942 | $filesUri = "mobileApps/$appId/$LOBType/contentVersions/$contentVersionId/files";
943 | $file = MakePostRequest $filesUri ($fileBody | ConvertTo-Json);
944 |
945 | # Wait for the service to process the new file request.
946 | Write-Host
947 | Write-Host "Waiting for the file entry URI to be created..." -ForegroundColor Yellow
948 | $fileId = $file.id;
949 | $fileUri = "mobileApps/$appId/$LOBType/contentVersions/$contentVersionId/files/$fileId";
950 | $file = WaitForFileProcessing $fileUri "AzureStorageUriRequest";
951 |
952 | # Upload the content to Azure Storage.
953 | Write-Host
954 | Write-Host "Uploading file to Azure Storage URI..." -ForegroundColor Yellow
955 |
956 | $sasUri = $file.azureStorageUri;
957 | UploadFileToAzureStorage $file.azureStorageUri $tempFile;
958 |
959 | # Commit the file.
960 | Write-Host
961 | Write-Host "Committing the file into Azure Storage..." -ForegroundColor Yellow
962 | $commitFileUri = "mobileApps/$appId/$LOBType/contentVersions/$contentVersionId/files/$fileId/commit";
963 | MakePostRequest $commitFileUri ($encryptionInfo | ConvertTo-Json);
964 |
965 | # Wait for the service to process the commit file request.
966 | Write-Host
967 | Write-Host "Waiting for the service to process the commit file request..." -ForegroundColor Yellow
968 | $file = WaitForFileProcessing $fileUri "CommitFile";
969 |
970 | # Commit the app.
971 | Write-Host
972 | Write-Host "Committing the application to the Intune Service..." -ForegroundColor Yellow
973 | $commitAppUri = "mobileApps/$appId";
974 | $commitAppBody = GetAppCommitBody $contentVersionId $LOBType;
975 | MakePatchRequest $commitAppUri ($commitAppBody | ConvertTo-Json);
976 |
977 | Write-Host "Removing Temporary file '$tempFile'..." -f Gray
978 | Remove-Item -Path "$tempFile" -Force
979 | Write-Host
980 |
981 | Write-Host "Sleeping for $sleep seconds to allow patch completion..." -f Magenta
982 | Start-Sleep $sleep
983 | Write-Host
984 |
985 | }
986 | catch
987 | {
988 | Write-Host "";
989 | Write-Host -ForegroundColor Red "Aborting with exception: $($_.Exception.ToString())";
990 | }
991 | }
992 |
993 | ####################################################
994 |
995 | function Upload-iOSLob(){
996 |
997 | <#
998 | .SYNOPSIS
999 | This function is used to upload an iOS LOB Application to the Intune Service
1000 | .DESCRIPTION
1001 | This function is used to upload an iOS LOB Application to the Intune Service
1002 | .EXAMPLE
1003 | Upload-iOSLob -sourceFile "C:\Software\package.ipa" -displayName "package.ipa" -publisher "Publisher Name" -description "Description of Application" -bundleId "com.package" -identityVersion "1" -versionNumber "3.0.0" -expirationDateTime "2018-02-14T20:53:52Z"
1004 | This example uses all parameters required to add an iOS Application into the Intune Service
1005 | .NOTES
1006 | NAME: Upload-iOSLOB
1007 | #>
1008 |
1009 | [cmdletbinding()]
1010 |
1011 | param
1012 | (
1013 | [parameter(Mandatory=$true,Position=1)]
1014 | [ValidateNotNullOrEmpty()]
1015 | [string]$SourceFile,
1016 |
1017 | [parameter(Mandatory=$true,Position=2)]
1018 | [ValidateNotNullOrEmpty()]
1019 | [string]$displayName,
1020 |
1021 | [parameter(Mandatory=$true,Position=3)]
1022 | [ValidateNotNullOrEmpty()]
1023 | [string]$publisher,
1024 |
1025 | [parameter(Mandatory=$true,Position=4)]
1026 | [ValidateNotNullOrEmpty()]
1027 | [string]$description,
1028 |
1029 | [parameter(Mandatory=$true,Position=5)]
1030 | [ValidateNotNullOrEmpty()]
1031 | [string]$bundleId,
1032 |
1033 | [parameter(Mandatory=$true,Position=6)]
1034 | [ValidateNotNullOrEmpty()]
1035 | [string]$identityVersion,
1036 |
1037 | [parameter(Mandatory=$true,Position=7)]
1038 | [ValidateNotNullOrEmpty()]
1039 | [string]$versionNumber,
1040 |
1041 | [parameter(Mandatory=$true,Position=8)]
1042 | [ValidateNotNullOrEmpty()]
1043 | [string]$expirationDateTime
1044 | )
1045 |
1046 | try
1047 | {
1048 |
1049 | $LOBType = "microsoft.graph.iosLOBApp"
1050 |
1051 | Write-Host "Testing if SourceFile '$SourceFile' Path is valid..." -ForegroundColor Yellow
1052 | Test-SourceFile "$SourceFile"
1053 |
1054 | # Checking expirationdatetime of SourceFile to check if it can be uploaded
1055 | [datetimeoffset]$Expiration = $expirationDateTime
1056 |
1057 | $Date = get-date
1058 |
1059 | if($Expiration -lt $Date){
1060 |
1061 | Write-Error "$SourceFile has expired Follow the guidelines provided by Apple to extend the expiration date, then try adding the app again"
1062 | throw
1063 |
1064 | }
1065 |
1066 | # Creating temp file name from Source File path
1067 | $tempFile = [System.IO.Path]::GetDirectoryName("$SourceFile") + "\" + [System.IO.Path]::GetFileNameWithoutExtension("$SourceFile") + "_temp.bin"
1068 |
1069 | # Creating filename variable from Source File Path
1070 | $filename = [System.IO.Path]::GetFileName("$SourceFile")
1071 |
1072 | # Create a new iOS LOB app.
1073 | Write-Host
1074 | Write-Host "Creating JSON data to pass to the service..." -ForegroundColor Yellow
1075 | $mobileAppBody = GetiOSAppBody "$displayName" "$Publisher" "$Description" "$filename" "$bundleId" "$identityVersion" "$versionNumber" "$expirationDateTime";
1076 |
1077 | Write-Host
1078 | Write-Host "Creating application in Intune..." -ForegroundColor Yellow
1079 |
1080 | $mobileApp = MakePostRequest "mobileApps" ($mobileAppBody | ConvertTo-Json);
1081 |
1082 | # Get the content version for the new app (this will always be 1 until the new app is committed).
1083 | Write-Host
1084 | Write-Host "Creating Content Version in the service for the application..." -ForegroundColor Yellow
1085 | $appId = $mobileApp.id;
1086 | $contentVersionUri = "mobileApps/$appId/$LOBType/contentVersions";
1087 | $contentVersion = MakePostRequest $contentVersionUri "{}";
1088 |
1089 | # Encrypt file and Get File Information
1090 | Write-Host
1091 | Write-Host "Ecrypting the file '$SourceFile'..." -ForegroundColor Yellow
1092 | $encryptionInfo = EncryptFile $sourceFile $tempFile;
1093 | $Size = (Get-Item "$sourceFile").Length
1094 | $EncrySize = (Get-Item "$tempFile").Length
1095 |
1096 | Write-Host
1097 | Write-Host "Creating the manifest file used to install the application on the device..." -ForegroundColor Yellow
1098 |
1099 | [string]$manifestXML = 'itemsassetskindsoftware-packageurl{UrlPlaceHolder}metadataAppRestrictionPolicyTemplate http://management.microsoft.com/PolicyTemplates/AppRestrictions/iOS/v1AppRestrictionTechnologyWindows Intune Application Restrictions Technology for iOSIntuneMAMVersionCFBundleSupportedPlatformsiPhoneOSMinimumOSVersion9.0bundle-identifierbundleidbundle-versionbundleversionkindsoftwaresubtitleLaunchMeSubtitletitlebundletitle'
1100 |
1101 | $manifestXML = $manifestXML.replace("bundleid","$bundleId")
1102 | $manifestXML = $manifestXML.replace("bundleversion","$identityVersion")
1103 | $manifestXML = $manifestXML.replace("bundletitle","$displayName")
1104 |
1105 | $Bytes = [System.Text.Encoding]::ASCII.GetBytes($manifestXML)
1106 | $EncodedText =[Convert]::ToBase64String($Bytes)
1107 |
1108 | # Create a new file for the app.
1109 | Write-Host
1110 | Write-Host "Creating a new file entry in Azure for the upload..." -ForegroundColor Yellow
1111 | $contentVersionId = $contentVersion.id;
1112 | $fileBody = GetAppFileBody "$filename" $Size $EncrySize "$EncodedText";
1113 | $filesUri = "mobileApps/$appId/$LOBType/contentVersions/$contentVersionId/files";
1114 | $file = MakePostRequest $filesUri ($fileBody | ConvertTo-Json);
1115 |
1116 | # Wait for the service to process the new file request.
1117 | Write-Host
1118 | Write-Host "Waiting for the file entry URI to be created..." -ForegroundColor Yellow
1119 | $fileId = $file.id;
1120 | $fileUri = "mobileApps/$appId/$LOBType/contentVersions/$contentVersionId/files/$fileId";
1121 | $file = WaitForFileProcessing $fileUri "AzureStorageUriRequest";
1122 |
1123 | # Upload the content to Azure Storage.
1124 | Write-Host
1125 | Write-Host "Uploading file to Azure Storage..." -f Yellow
1126 |
1127 | $sasUri = $file.azureStorageUri;
1128 | UploadFileToAzureStorage $file.azureStorageUri $tempFile;
1129 |
1130 | # Commit the file.
1131 | Write-Host
1132 | Write-Host "Committing the file into Azure Storage..." -ForegroundColor Yellow
1133 | $commitFileUri = "mobileApps/$appId/$LOBType/contentVersions/$contentVersionId/files/$fileId/commit";
1134 | MakePostRequest $commitFileUri ($encryptionInfo | ConvertTo-Json);
1135 |
1136 | # Wait for the service to process the commit file request.
1137 | Write-Host
1138 | Write-Host "Waiting for the service to process the commit file request..." -ForegroundColor Yellow
1139 | $file = WaitForFileProcessing $fileUri "CommitFile";
1140 |
1141 | # Commit the app.
1142 | Write-Host
1143 | Write-Host "Committing the file into Azure Storage..." -ForegroundColor Yellow
1144 | $commitAppUri = "mobileApps/$appId";
1145 | $commitAppBody = GetAppCommitBody $contentVersionId $LOBType;
1146 | MakePatchRequest $commitAppUri ($commitAppBody | ConvertTo-Json);
1147 |
1148 | Write-Host "Removing Temporary file '$tempFile'..." -f Gray
1149 | Remove-Item -Path "$tempFile" -Force
1150 | Write-Host
1151 |
1152 | Write-Host "Sleeping for $sleep seconds to allow patch completion..." -f Magenta
1153 | Start-Sleep $sleep
1154 | Write-Host
1155 |
1156 | }
1157 | catch
1158 | {
1159 | Write-Host "";
1160 | Write-Host -ForegroundColor Red "Aborting with exception: $($_.Exception.ToString())";
1161 | }
1162 | }
1163 |
1164 | ####################################################
1165 |
1166 | function Upload-MSILob(){
1167 |
1168 | <#
1169 | .SYNOPSIS
1170 | This function is used to upload an MSI LOB Application to the Intune Service
1171 | .DESCRIPTION
1172 | This function is used to upload an MSI LOB Application to the Intune Service
1173 | .EXAMPLE
1174 | Upload-MSILob "C:\Software\Orca\Orca.Msi" -publisher "Microsoft" -description "Orca"
1175 | This example uses all parameters required to add an MSI Application into the Intune Service
1176 | .NOTES
1177 | NAME: Upload-MSILOB
1178 | #>
1179 |
1180 | [cmdletbinding()]
1181 |
1182 | param
1183 | (
1184 | [parameter(Mandatory=$true,Position=1)]
1185 | [ValidateNotNullOrEmpty()]
1186 | [string]$SourceFile,
1187 |
1188 | [parameter(Mandatory=$true,Position=2)]
1189 | [ValidateNotNullOrEmpty()]
1190 | [string]$publisher,
1191 |
1192 | [parameter(Mandatory=$true,Position=3)]
1193 | [ValidateNotNullOrEmpty()]
1194 | [string]$description
1195 | )
1196 |
1197 | try {
1198 |
1199 | $LOBType = "microsoft.graph.windowsMobileMSI"
1200 |
1201 | Write-Host "Testing if SourceFile '$SourceFile' Path is valid..." -ForegroundColor Yellow
1202 | Test-SourceFile "$SourceFile"
1203 |
1204 | $MSIPath = "$SourceFile"
1205 |
1206 | # Creating temp file name from Source File path
1207 | $tempFile = [System.IO.Path]::GetDirectoryName("$SourceFile") + "\" + [System.IO.Path]::GetFileNameWithoutExtension("$SourceFile") + "_temp.bin"
1208 |
1209 | Write-Host
1210 | Write-Host "Creating JSON data to pass to the service..." -ForegroundColor Yellow
1211 |
1212 | $FileName = [System.IO.Path]::GetFileName("$MSIPath")
1213 |
1214 | $PN = (Get-MSIFileInformation -Path "$MSIPath" -Property ProductName | Out-String).trimend()
1215 | $PC = (Get-MSIFileInformation -Path "$MSIPath" -Property ProductCode | Out-String).trimend()
1216 | $PV = (Get-MSIFileInformation -Path "$MSIPath" -Property ProductVersion | Out-String).trimend()
1217 | $PL = (Get-MSIFileInformation -Path "$MSIPath" -Property ProductLanguage | Out-String).trimend()
1218 |
1219 | # Create a new MSI LOB app.
1220 | $mobileAppBody = GetMSIAppBody -displayName "$PN" -publisher "$publisher" -description "$description" -filename "$FileName" -identityVersion "$PV" -ProductCode "$PC"
1221 |
1222 | Write-Host
1223 | Write-Host "Creating application in Intune..." -ForegroundColor Yellow
1224 | $mobileApp = MakePostRequest "mobileApps" ($mobileAppBody | ConvertTo-Json);
1225 |
1226 | # Get the content version for the new app (this will always be 1 until the new app is committed).
1227 | Write-Host
1228 | Write-Host "Creating Content Version in the service for the application..." -ForegroundColor Yellow
1229 | $appId = $mobileApp.id;
1230 | $contentVersionUri = "mobileApps/$appId/$LOBType/contentVersions";
1231 | $contentVersion = MakePostRequest $contentVersionUri "{}";
1232 |
1233 | # Encrypt file and Get File Information
1234 | Write-Host
1235 | Write-Host "Ecrypting the file '$SourceFile'..." -ForegroundColor Yellow
1236 | $encryptionInfo = EncryptFile $sourceFile $tempFile;
1237 | $Size = (Get-Item "$sourceFile").Length
1238 | $EncrySize = (Get-Item "$tempFile").Length
1239 |
1240 | Write-Host
1241 | Write-Host "Creating the manifest file used to install the application on the device..." -ForegroundColor Yellow
1242 |
1243 | [xml]$manifestXML = ''
1244 |
1245 | $manifestXML.MobileMsiData.MsiUpgradeCode = "$PC"
1246 |
1247 | $manifestXML_Output = $manifestXML.OuterXml.ToString()
1248 |
1249 | $Bytes = [System.Text.Encoding]::ASCII.GetBytes($manifestXML_Output)
1250 | $EncodedText =[Convert]::ToBase64String($Bytes)
1251 |
1252 | # Create a new file for the app.
1253 | Write-Host
1254 | Write-Host "Creating a new file entry in Azure for the upload..." -ForegroundColor Yellow
1255 | $contentVersionId = $contentVersion.id;
1256 | $fileBody = GetAppFileBody "$FileName" $Size $EncrySize "$EncodedText";
1257 | $filesUri = "mobileApps/$appId/$LOBType/contentVersions/$contentVersionId/files";
1258 | $file = MakePostRequest $filesUri ($fileBody | ConvertTo-Json);
1259 |
1260 | # Wait for the service to process the new file request.
1261 | Write-Host
1262 | Write-Host "Waiting for the file entry URI to be created..." -ForegroundColor Yellow
1263 | $fileId = $file.id;
1264 | $fileUri = "mobileApps/$appId/$LOBType/contentVersions/$contentVersionId/files/$fileId";
1265 | $file = WaitForFileProcessing $fileUri "AzureStorageUriRequest";
1266 |
1267 | # Upload the content to Azure Storage.
1268 | Write-Host
1269 | Write-Host "Uploading file to Azure Storage..." -f Yellow
1270 |
1271 | $sasUri = $file.azureStorageUri;
1272 | UploadFileToAzureStorage $file.azureStorageUri $tempFile;
1273 |
1274 | # Commit the file.
1275 | Write-Host
1276 | Write-Host "Committing the file into Azure Storage..." -ForegroundColor Yellow
1277 | $commitFileUri = "mobileApps/$appId/$LOBType/contentVersions/$contentVersionId/files/$fileId/commit";
1278 | MakePostRequest $commitFileUri ($encryptionInfo | ConvertTo-Json);
1279 |
1280 | # Wait for the service to process the commit file request.
1281 | Write-Host
1282 | Write-Host "Waiting for the service to process the commit file request..." -ForegroundColor Yellow
1283 | $file = WaitForFileProcessing $fileUri "CommitFile";
1284 |
1285 | # Commit the app.
1286 | Write-Host
1287 | Write-Host "Committing the file into Azure Storage..." -ForegroundColor Yellow
1288 | $commitAppUri = "mobileApps/$appId";
1289 | $commitAppBody = GetAppCommitBody $contentVersionId $LOBType;
1290 | MakePatchRequest $commitAppUri ($commitAppBody | ConvertTo-Json);
1291 |
1292 | Write-Host "Removing Temporary file '$tempFile'..." -f Gray
1293 | Remove-Item -Path "$tempFile" -Force
1294 | Write-Host
1295 |
1296 | Write-Host "Sleeping for $sleep seconds to allow patch completion..." -f Magenta
1297 | Start-Sleep $sleep
1298 | Write-Host
1299 |
1300 | }
1301 |
1302 | catch {
1303 |
1304 | Write-Host "";
1305 | Write-Host -ForegroundColor Red "Aborting with exception: $($_.Exception.ToString())";
1306 |
1307 | }
1308 |
1309 | }
1310 |
1311 | ####################################################
1312 |
1313 | #region Authentication
1314 |
1315 | write-host
1316 |
1317 | # Checking if authToken exists before running authentication
1318 | if($global:authToken){
1319 |
1320 | # Setting DateTime to Universal time to work in all timezones
1321 | $DateTime = (Get-Date).ToUniversalTime()
1322 |
1323 | # If the authToken exists checking when it expires
1324 | $TokenExpires = ($authToken.ExpiresOn.datetime - $DateTime).Minutes
1325 |
1326 | if($TokenExpires -le 0){
1327 |
1328 | write-host "Authentication Token expired" $TokenExpires "minutes ago" -ForegroundColor Yellow
1329 | write-host
1330 |
1331 | # Defining Azure AD tenant name, this is the name of your Azure Active Directory (do not use the verified domain name)
1332 |
1333 | if($User -eq $null -or $User -eq ""){
1334 |
1335 | $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication"
1336 | Write-Host
1337 |
1338 | }
1339 |
1340 | $global:authToken = Get-AuthToken -User $User
1341 |
1342 | }
1343 | }
1344 |
1345 | # Authentication doesn't exist, calling Get-AuthToken function
1346 |
1347 | else {
1348 |
1349 | if($User -eq $null -or $User -eq ""){
1350 |
1351 | $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication"
1352 | Write-Host
1353 |
1354 | }
1355 |
1356 | # Getting the authorization token
1357 | $global:authToken = Get-AuthToken -User $User
1358 |
1359 | }
1360 |
1361 | #endregion
1362 |
1363 | ####################################################
1364 |
1365 | # Path to Android SDK Location to find aapt.exe tool if you don't specify identityName or identityVersion
1366 | # Note: Don't specify direct location to build folder number, just to the build-tools folder as the script will find the latest SDK installed
1367 | $AndroidSDKLocation = "C:\AndroidSDK\build-tools"
1368 |
1369 | $baseUrl = "https://graph.microsoft.com/beta/deviceAppManagement/"
1370 |
1371 | $logRequestUris = $true;
1372 | $logHeaders = $false;
1373 | $logContent = $true;
1374 |
1375 | $sleep = 30
1376 |
1377 | ####################################################
1378 |
1379 | #### MSI Install microsoft Teams 64 bit
1380 | $output = "$PSScriptRoot\teams64bit.msi"
1381 | Start-BitsTransfer -Source http://aka.ms/teams64bitmsi -Destination $output
1382 | Upload-MSILob "$output" -publisher "Microsoft" -description "Microsoft Teams 64Bit"
1383 |
1384 | #### MSI Install microsoft Teams 32 bit
1385 | $output = "$PSScriptRoot\teams32bit.msi"
1386 | Start-BitsTransfer -Source http://aka.ms/teams32bitmsi -Destination $output
1387 | Upload-MSILob "$output" -publisher "Microsoft" -description "Microsoft Teams 32Bit"
1388 |
1389 |
--------------------------------------------------------------------------------
/Application_LOB_Add - Google.ps1:
--------------------------------------------------------------------------------
1 |
2 | <#
3 |
4 | .COPYRIGHT
5 | Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
6 | See LICENSE in the project root for license information.
7 |
8 | #>
9 |
10 | ####################################################
11 |
12 | function Get-AuthToken {
13 |
14 | <#
15 | .SYNOPSIS
16 | This function is used to authenticate with the Graph API REST interface
17 | .DESCRIPTION
18 | The function authenticate with the Graph API Interface with the tenant name
19 | .EXAMPLE
20 | Get-AuthToken
21 | Authenticates you with the Graph API interface
22 | .NOTES
23 | NAME: Get-AuthToken
24 | #>
25 |
26 | [cmdletbinding()]
27 |
28 | param
29 | (
30 | [Parameter(Mandatory=$true)]
31 | $User
32 | )
33 |
34 | $userUpn = New-Object "System.Net.Mail.MailAddress" -ArgumentList $User
35 |
36 | $tenant = $userUpn.Host
37 |
38 | Write-Host "Checking for AzureAD module..."
39 |
40 | $AadModule = Get-Module -Name "AzureAD" -ListAvailable
41 |
42 | if ($AadModule -eq $null) {
43 |
44 | Write-Host "AzureAD PowerShell module not found, looking for AzureADPreview"
45 | $AadModule = Get-Module -Name "AzureADPreview" -ListAvailable
46 |
47 | }
48 |
49 | if ($AadModule -eq $null) {
50 | write-host
51 | write-host "AzureAD Powershell module not installed..." -f Red
52 | write-host "Install by running 'Install-Module AzureAD' or 'Install-Module AzureADPreview' from an elevated PowerShell prompt" -f Yellow
53 | write-host "Script can't continue..." -f Red
54 | write-host
55 | exit
56 | }
57 |
58 | # Getting path to ActiveDirectory Assemblies
59 | # If the module count is greater than 1 find the latest version
60 |
61 | if($AadModule.count -gt 1){
62 |
63 | $Latest_Version = ($AadModule | select version | Sort-Object)[-1]
64 |
65 | $aadModule = $AadModule | ? { $_.version -eq $Latest_Version.version }
66 |
67 | # Checking if there are multiple versions of the same module found
68 |
69 | if($AadModule.count -gt 1){
70 |
71 | $aadModule = $AadModule | select -Unique
72 |
73 | }
74 |
75 | $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
76 | $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll"
77 |
78 | }
79 |
80 | else {
81 |
82 | $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
83 | $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll"
84 |
85 | }
86 |
87 | [System.Reflection.Assembly]::LoadFrom($adal) | Out-Null
88 |
89 | [System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null
90 |
91 | $clientId = "d1ddf0e4-d672-4dae-b554-9d5bdfd93547"
92 |
93 | $redirectUri = "urn:ietf:wg:oauth:2.0:oob"
94 |
95 | $resourceAppIdURI = "https://graph.microsoft.com"
96 |
97 | $authority = "https://login.microsoftonline.com/$Tenant"
98 |
99 | try {
100 |
101 | $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority
102 |
103 | # https://msdn.microsoft.com/en-us/library/azure/microsoft.identitymodel.clients.activedirectory.promptbehavior.aspx
104 | # Change the prompt behaviour to force credentials each time: Auto, Always, Never, RefreshSession
105 |
106 | $platformParameters = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList "Auto"
107 |
108 | $userId = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier" -ArgumentList ($User, "OptionalDisplayableId")
109 |
110 | $authResult = $authContext.AcquireTokenAsync($resourceAppIdURI,$clientId,$redirectUri,$platformParameters,$userId).Result
111 |
112 | # If the accesstoken is valid then create the authentication header
113 |
114 | if($authResult.AccessToken){
115 |
116 | # Creating header for Authorization token
117 |
118 | $authHeader = @{
119 | 'Content-Type'='application/json'
120 | 'Authorization'="Bearer " + $authResult.AccessToken
121 | 'ExpiresOn'=$authResult.ExpiresOn
122 | }
123 |
124 | return $authHeader
125 |
126 | }
127 |
128 | else {
129 |
130 | Write-Host
131 | Write-Host "Authorization Access Token is null, please re-run authentication..." -ForegroundColor Red
132 | Write-Host
133 | break
134 |
135 | }
136 |
137 | }
138 |
139 | catch {
140 |
141 | write-host $_.Exception.Message -f Red
142 | write-host $_.Exception.ItemName -f Red
143 | write-host
144 | break
145 |
146 | }
147 |
148 | }
149 |
150 | ####################################################
151 |
152 | function CloneObject($object){
153 |
154 | $stream = New-Object IO.MemoryStream;
155 | $formatter = New-Object Runtime.Serialization.Formatters.Binary.BinaryFormatter;
156 | $formatter.Serialize($stream, $object);
157 | $stream.Position = 0;
158 | $formatter.Deserialize($stream);
159 | }
160 |
161 | ####################################################
162 |
163 | function WriteHeaders($authToken){
164 |
165 | foreach ($header in $authToken.GetEnumerator())
166 | {
167 | if ($header.Name.ToLower() -eq "authorization")
168 | {
169 | continue;
170 | }
171 |
172 | Write-Host -ForegroundColor Gray "$($header.Name): $($header.Value)";
173 | }
174 | }
175 |
176 | ####################################################
177 |
178 | function MakeGetRequest($collectionPath){
179 |
180 | $uri = "$baseUrl$collectionPath";
181 | $request = "GET $uri";
182 |
183 | if ($logRequestUris) { Write-Host $request; }
184 | if ($logHeaders) { WriteHeaders $authToken; }
185 |
186 | try
187 | {
188 | $response = Invoke-RestMethod $uri -Method Get -Headers $authToken;
189 | $response;
190 | }
191 | catch
192 | {
193 | Write-Host -ForegroundColor Red $request;
194 | Write-Host -ForegroundColor Red $_.Exception.Message;
195 | throw;
196 | }
197 | }
198 |
199 | ####################################################
200 |
201 | function MakePatchRequest($collectionPath, $body){
202 |
203 | MakeRequest "PATCH" $collectionPath $body;
204 |
205 | }
206 |
207 | ####################################################
208 |
209 | function MakePostRequest($collectionPath, $body){
210 |
211 | MakeRequest "POST" $collectionPath $body;
212 |
213 | }
214 |
215 | ####################################################
216 |
217 | function MakeRequest($verb, $collectionPath, $body){
218 |
219 | $uri = "$baseUrl$collectionPath";
220 | $request = "$verb $uri";
221 |
222 | $clonedHeaders = CloneObject $authToken;
223 | $clonedHeaders["content-length"] = $body.Length;
224 | $clonedHeaders["content-type"] = "application/json";
225 |
226 | if ($logRequestUris) { Write-Host $request; }
227 | if ($logHeaders) { WriteHeaders $clonedHeaders; }
228 | if ($logContent) { Write-Host -ForegroundColor Gray $body; }
229 |
230 | try
231 | {
232 | $response = Invoke-RestMethod $uri -Method $verb -Headers $clonedHeaders -Body $body;
233 | $response;
234 | }
235 | catch
236 | {
237 | Write-Host -ForegroundColor Red $request;
238 | Write-Host -ForegroundColor Red $_.Exception.Message;
239 | throw;
240 | }
241 | }
242 |
243 | ####################################################
244 |
245 | function UploadAzureStorageChunk($sasUri, $id, $body){
246 |
247 | $uri = "$sasUri&comp=block&blockid=$id";
248 | $request = "PUT $uri";
249 |
250 | $iso = [System.Text.Encoding]::GetEncoding("iso-8859-1");
251 | $encodedBody = $iso.GetString($body);
252 | $headers = @{
253 | "x-ms-blob-type" = "BlockBlob"
254 | };
255 |
256 | if ($logRequestUris) { Write-Host $request; }
257 | if ($logHeaders) { WriteHeaders $headers; }
258 |
259 | try
260 | {
261 | $response = Invoke-WebRequest $uri -Method Put -Headers $headers -Body $encodedBody;
262 | }
263 | catch
264 | {
265 | Write-Host -ForegroundColor Red $request;
266 | Write-Host -ForegroundColor Red $_.Exception.Message;
267 | throw;
268 | }
269 |
270 | }
271 |
272 | ####################################################
273 |
274 | function FinalizeAzureStorageUpload($sasUri, $ids){
275 |
276 | $uri = "$sasUri&comp=blocklist";
277 | $request = "PUT $uri";
278 |
279 | $xml = '';
280 | foreach ($id in $ids)
281 | {
282 | $xml += "$id";
283 | }
284 | $xml += '';
285 |
286 | if ($logRequestUris) { Write-Host $request; }
287 | if ($logContent) { Write-Host -ForegroundColor Gray $xml; }
288 |
289 | try
290 | {
291 | Invoke-RestMethod $uri -Method Put -Body $xml;
292 | }
293 | catch
294 | {
295 | Write-Host -ForegroundColor Red $request;
296 | Write-Host -ForegroundColor Red $_.Exception.Message;
297 | throw;
298 | }
299 | }
300 |
301 | ####################################################
302 |
303 | function UploadFileToAzureStorage($sasUri, $filepath){
304 |
305 | # Chunk size = 1 MiB
306 | $chunkSizeInBytes = 1024 * 1024;
307 |
308 | # Read the whole file and find the total chunks.
309 | #[byte[]]$bytes = Get-Content $filepath -Encoding byte;
310 | # Using ReadAllBytes method as the Get-Content used alot of memory on the machine
311 | [byte[]]$bytes = [System.IO.File]::ReadAllBytes($filepath);
312 | $chunks = [Math]::Ceiling($bytes.Length / $chunkSizeInBytes);
313 |
314 | # Upload each chunk.
315 | $ids = @();
316 | $cc = 1
317 |
318 | for ($chunk = 0; $chunk -lt $chunks; $chunk++)
319 | {
320 | $id = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($chunk.ToString("0000")));
321 | $ids += $id;
322 |
323 | $start = $chunk * $chunkSizeInBytes;
324 | $end = [Math]::Min($start + $chunkSizeInBytes - 1, $bytes.Length - 1);
325 | $body = $bytes[$start..$end];
326 |
327 | Write-Progress -Activity "Uploading File to Azure Storage" -status "Uploading chunk $cc of $chunks" `
328 | -percentComplete ($cc / $chunks*100)
329 | $cc++
330 |
331 | $uploadResponse = UploadAzureStorageChunk $sasUri $id $body;
332 |
333 |
334 | }
335 |
336 | Write-Progress -Completed -Activity "Uploading File to Azure Storage"
337 |
338 | Write-Host
339 |
340 | # Finalize the upload.
341 | $uploadResponse = FinalizeAzureStorageUpload $sasUri $ids;
342 | }
343 |
344 | ####################################################
345 |
346 | function GenerateKey{
347 |
348 | try
349 | {
350 | $aes = [System.Security.Cryptography.Aes]::Create();
351 | $aesProvider = New-Object System.Security.Cryptography.AesCryptoServiceProvider;
352 | $aesProvider.GenerateKey();
353 | $aesProvider.Key;
354 | }
355 | finally
356 | {
357 | if ($aesProvider -ne $null) { $aesProvider.Dispose(); }
358 | if ($aes -ne $null) { $aes.Dispose(); }
359 | }
360 | }
361 |
362 | ####################################################
363 |
364 | function GenerateIV{
365 |
366 | try
367 | {
368 | $aes = [System.Security.Cryptography.Aes]::Create();
369 | $aes.IV;
370 | }
371 | finally
372 | {
373 | if ($aes -ne $null) { $aes.Dispose(); }
374 | }
375 | }
376 |
377 | ####################################################
378 |
379 | function EncryptFileWithIV($sourceFile, $targetFile, $encryptionKey, $hmacKey, $initializationVector){
380 |
381 | $bufferBlockSize = 1024 * 4;
382 | $computedMac = $null;
383 |
384 | try
385 | {
386 | $aes = [System.Security.Cryptography.Aes]::Create();
387 | $hmacSha256 = New-Object System.Security.Cryptography.HMACSHA256;
388 | $hmacSha256.Key = $hmacKey;
389 | $hmacLength = $hmacSha256.HashSize / 8;
390 |
391 | $buffer = New-Object byte[] $bufferBlockSize;
392 | $bytesRead = 0;
393 |
394 | $targetStream = [System.IO.File]::Open($targetFile, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write, [System.IO.FileShare]::Read);
395 | $targetStream.Write($buffer, 0, $hmacLength + $initializationVector.Length);
396 |
397 | try
398 | {
399 | $encryptor = $aes.CreateEncryptor($encryptionKey, $initializationVector);
400 | $sourceStream = [System.IO.File]::Open($sourceFile, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::Read);
401 | $cryptoStream = New-Object System.Security.Cryptography.CryptoStream -ArgumentList @($targetStream, $encryptor, [System.Security.Cryptography.CryptoStreamMode]::Write);
402 |
403 | $targetStream = $null;
404 | while (($bytesRead = $sourceStream.Read($buffer, 0, $bufferBlockSize)) -gt 0)
405 | {
406 | $cryptoStream.Write($buffer, 0, $bytesRead);
407 | $cryptoStream.Flush();
408 | }
409 | $cryptoStream.FlushFinalBlock();
410 | }
411 | finally
412 | {
413 | if ($cryptoStream -ne $null) { $cryptoStream.Dispose(); }
414 | if ($sourceStream -ne $null) { $sourceStream.Dispose(); }
415 | if ($encryptor -ne $null) { $encryptor.Dispose(); }
416 | }
417 |
418 | try
419 | {
420 | $finalStream = [System.IO.File]::Open($targetFile, [System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::Read)
421 |
422 | $finalStream.Seek($hmacLength, [System.IO.SeekOrigin]::Begin) > $null;
423 | $finalStream.Write($initializationVector, 0, $initializationVector.Length);
424 | $finalStream.Seek($hmacLength, [System.IO.SeekOrigin]::Begin) > $null;
425 |
426 | $hmac = $hmacSha256.ComputeHash($finalStream);
427 | $computedMac = $hmac;
428 |
429 | $finalStream.Seek(0, [System.IO.SeekOrigin]::Begin) > $null;
430 | $finalStream.Write($hmac, 0, $hmac.Length);
431 | }
432 | finally
433 | {
434 | if ($finalStream -ne $null) { $finalStream.Dispose(); }
435 | }
436 | }
437 | finally
438 | {
439 | if ($targetStream -ne $null) { $targetStream.Dispose(); }
440 | if ($aes -ne $null) { $aes.Dispose(); }
441 | }
442 |
443 | $computedMac;
444 | }
445 |
446 | ####################################################
447 |
448 | function EncryptFile($sourceFile, $targetFile){
449 |
450 | $encryptionKey = GenerateKey;
451 | $hmacKey = GenerateKey;
452 | $initializationVector = GenerateIV;
453 |
454 | # Create the encrypted target file and compute the HMAC value.
455 | $mac = EncryptFileWithIV $sourceFile $targetFile $encryptionKey $hmacKey $initializationVector;
456 |
457 | # Compute the SHA256 hash of the source file and convert the result to bytes.
458 | $fileDigest = (Get-FileHash $sourceFile -Algorithm SHA256).Hash;
459 | $fileDigestBytes = New-Object byte[] ($fileDigest.Length / 2);
460 | for ($i = 0; $i -lt $fileDigest.Length; $i += 2)
461 | {
462 | $fileDigestBytes[$i / 2] = [System.Convert]::ToByte($fileDigest.Substring($i, 2), 16);
463 | }
464 |
465 | # Return an object that will serialize correctly to the file commit Graph API.
466 | $encryptionInfo = @{};
467 | $encryptionInfo.encryptionKey = [System.Convert]::ToBase64String($encryptionKey);
468 | $encryptionInfo.macKey = [System.Convert]::ToBase64String($hmacKey);
469 | $encryptionInfo.initializationVector = [System.Convert]::ToBase64String($initializationVector);
470 | $encryptionInfo.mac = [System.Convert]::ToBase64String($mac);
471 | $encryptionInfo.profileIdentifier = "ProfileVersion1";
472 | $encryptionInfo.fileDigest = [System.Convert]::ToBase64String($fileDigestBytes);
473 | $encryptionInfo.fileDigestAlgorithm = "SHA256";
474 |
475 | $fileEncryptionInfo = @{};
476 | $fileEncryptionInfo.fileEncryptionInfo = $encryptionInfo;
477 |
478 | $fileEncryptionInfo;
479 |
480 | }
481 |
482 | ####################################################
483 |
484 | function WaitForFileProcessing($fileUri, $stage){
485 |
486 | $attempts= 60;
487 | $waitTimeInSeconds = 1;
488 |
489 | $successState = "$($stage)Success";
490 | $pendingState = "$($stage)Pending";
491 | $failedState = "$($stage)Failed";
492 | $timedOutState = "$($stage)TimedOut";
493 |
494 | $file = $null;
495 | while ($attempts -gt 0)
496 | {
497 | $file = MakeGetRequest $fileUri;
498 |
499 | if ($file.uploadState -eq $successState)
500 | {
501 | break;
502 | }
503 | elseif ($file.uploadState -ne $pendingState)
504 | {
505 | throw "File upload state is not success: $($file.uploadState)";
506 | }
507 |
508 | Start-Sleep $waitTimeInSeconds;
509 | $attempts--;
510 | }
511 |
512 | if ($file -eq $null)
513 | {
514 | throw "File request did not complete in the allotted time.";
515 | }
516 |
517 | $file;
518 |
519 | }
520 |
521 | ####################################################
522 |
523 | function GetAndroidAppBody($displayName, $publisher, $description, $filename, $identityName, $identityVersion, $versionName, $minimumSupportedOperatingSystem){
524 |
525 | $body = @{ "@odata.type" = "#microsoft.graph.androidLOBApp" };
526 | $body.categories = @();
527 | $body.displayName = $displayName;
528 | $body.publisher = $publisher;
529 | $body.description = $description;
530 | $body.fileName = $filename;
531 | $body.identityName = $identityName;
532 | $body.identityVersion = $identityVersion;
533 |
534 | if ($minimumSupportedOperatingSystem -eq $null){
535 |
536 | $body.minimumSupportedOperatingSystem = @{ "v4_4" = $true };
537 |
538 | }
539 |
540 | else {
541 |
542 | $body.minimumSupportedOperatingSystem = $minimumSupportedOperatingSystem;
543 |
544 | }
545 |
546 | $body.informationUrl = $null;
547 | $body.isFeatured = $false;
548 | $body.privacyInformationUrl = $null;
549 | $body.developer = "";
550 | $body.notes = "";
551 | $body.owner = "";
552 | $body.versionCode = $identityVersion;
553 | $body.versionName = $versionName;
554 |
555 | $body;
556 | }
557 |
558 | ####################################################
559 |
560 | function GetiOSAppBody($displayName, $publisher, $description, $filename, $bundleId, $identityVersion, $versionNumber, $expirationDateTime){
561 |
562 | $body = @{ "@odata.type" = "#microsoft.graph.iosLOBApp" };
563 | $body.applicableDeviceType = @{ "iPad" = $true; "iPhoneAndIPod" = $true }
564 | $body.categories = @();
565 | $body.displayName = $displayName;
566 | $body.publisher = $publisher;
567 | $body.description = $description;
568 | $body.fileName = $filename;
569 | $body.bundleId = $bundleId;
570 | $body.identityVersion = $identityVersion;
571 | if ($minimumSupportedOperatingSystem -eq $null)
572 | {
573 | $body.minimumSupportedOperatingSystem = @{ "v9_0" = $true };
574 | }
575 | else
576 | {
577 | $body.minimumSupportedOperatingSystem = $minimumSupportedOperatingSystem;
578 | }
579 |
580 | $body.informationUrl = $null;
581 | $body.isFeatured = $false;
582 | $body.privacyInformationUrl = $null;
583 | $body.developer = "";
584 | $body.notes = "";
585 | $body.owner = "";
586 | $body.expirationDateTime = $expirationDateTime;
587 | $body.versionNumber = $versionNumber;
588 |
589 | $body;
590 | }
591 |
592 | ####################################################
593 |
594 | function GetMSIAppBody($displayName, $publisher, $description, $filename, $identityVersion, $ProductCode){
595 |
596 | $body = @{ "@odata.type" = "#microsoft.graph.windowsMobileMSI" };
597 | $body.displayName = $displayName;
598 | $body.publisher = $publisher;
599 | $body.description = $description;
600 | $body.fileName = $filename;
601 | $body.identityVersion = $identityVersion;
602 | $body.informationUrl = $null;
603 | $body.isFeatured = $false;
604 | $body.privacyInformationUrl = $null;
605 | $body.developer = "";
606 | $body.notes = "";
607 | $body.owner = "";
608 | $body.productCode = "$ProductCode";
609 | $body.productVersion = "$identityVersion";
610 |
611 | $body;
612 | }
613 |
614 | ####################################################
615 |
616 | function GetAppFileBody($name, $size, $sizeEncrypted, $manifest){
617 |
618 | $body = @{ "@odata.type" = "#microsoft.graph.mobileAppContentFile" };
619 | $body.name = $name;
620 | $body.size = $size;
621 | $body.sizeEncrypted = $sizeEncrypted;
622 | $body.manifest = $manifest;
623 |
624 | $body;
625 | }
626 |
627 | ####################################################
628 |
629 | function GetAppCommitBody($contentVersionId, $LobType){
630 |
631 | $body = @{ "@odata.type" = "#$LobType" };
632 | $body.committedContentVersion = $contentVersionId;
633 |
634 | $body;
635 |
636 | }
637 |
638 | ####################################################
639 |
640 | Function Get-MSIFileInformation(){
641 |
642 | # https://www.scconfigmgr.com/2014/08/22/how-to-get-msi-file-information-with-powershell/
643 |
644 | param(
645 | [parameter(Mandatory=$true)]
646 | [ValidateNotNullOrEmpty()]
647 | [System.IO.FileInfo]$Path,
648 |
649 | [parameter(Mandatory=$true)]
650 | [ValidateNotNullOrEmpty()]
651 | [ValidateSet("ProductCode", "ProductVersion", "ProductName", "Manufacturer", "ProductLanguage", "FullVersion")]
652 | [string]$Property
653 | )
654 | Process {
655 |
656 | try {
657 | # Read property from MSI database
658 | $WindowsInstaller = New-Object -ComObject WindowsInstaller.Installer
659 | $MSIDatabase = $WindowsInstaller.GetType().InvokeMember("OpenDatabase", "InvokeMethod", $null, $WindowsInstaller, @($Path.FullName, 0))
660 | $Query = "SELECT Value FROM Property WHERE Property = '$($Property)'"
661 | $View = $MSIDatabase.GetType().InvokeMember("OpenView", "InvokeMethod", $null, $MSIDatabase, ($Query))
662 | $View.GetType().InvokeMember("Execute", "InvokeMethod", $null, $View, $null)
663 | $Record = $View.GetType().InvokeMember("Fetch", "InvokeMethod", $null, $View, $null)
664 | $Value = $Record.GetType().InvokeMember("StringData", "GetProperty", $null, $Record, 1)
665 |
666 | # Commit database and close view
667 | $MSIDatabase.GetType().InvokeMember("Commit", "InvokeMethod", $null, $MSIDatabase, $null)
668 | $View.GetType().InvokeMember("Close", "InvokeMethod", $null, $View, $null)
669 | $MSIDatabase = $null
670 | $View = $null
671 |
672 | # Return the value
673 | return $Value
674 | }
675 |
676 | catch {
677 |
678 | Write-Warning -Message $_.Exception.Message;
679 | break;
680 |
681 | }
682 |
683 | }
684 |
685 | End {
686 | # Run garbage collection and release ComObject
687 | [System.Runtime.Interopservices.Marshal]::ReleaseComObject($WindowsInstaller) | Out-Null
688 | [System.GC]::Collect()
689 | }
690 |
691 | }
692 |
693 | ####################################################
694 |
695 | Function Test-SourceFile(){
696 |
697 | param
698 | (
699 | [parameter(Mandatory=$true)]
700 | [ValidateNotNullOrEmpty()]
701 | $SourceFile
702 | )
703 |
704 | try {
705 |
706 | if(!(test-path "$SourceFile")){
707 |
708 | Write-Host "Source File '$sourceFile' doesn't exist..." -ForegroundColor Red
709 | throw
710 |
711 | }
712 |
713 | }
714 |
715 | catch {
716 |
717 | Write-Host -ForegroundColor Red $_.Exception.Message;
718 | Write-Host
719 | break;
720 |
721 | }
722 |
723 | }
724 |
725 | ####################################################
726 |
727 | Function Get-ApkInformation {
728 |
729 | <#
730 | .SYNOPSIS
731 | This function is used to get information about an Android APK file using the Android SDK - https://developer.android.com/studio/index.html
732 | .DESCRIPTION
733 | This function is used to get information about an Android APK file using the Android SDK - https://developer.android.com/studio/index.html
734 | .EXAMPLE
735 | Get-ApkInformation -sourceFile c:\source\application.apk
736 | Function will return two object, object[0] is the identityName and object[1] is the identityVersion
737 | .NOTES
738 | NAME: Get-ApkInformation
739 | #>
740 |
741 | [cmdletbinding()]
742 |
743 | param
744 | (
745 | [Parameter(Mandatory=$true)]
746 | $sourceFile,
747 | [Parameter(Mandatory=$true)]
748 | $AndroidSDK
749 | )
750 |
751 | if(!(test-path $AndroidSDK)){
752 |
753 | Write-Host
754 | Write-Host "Android SDK isn't installed..." -ForegroundColor Red
755 | Write-Host "Please install Android Studio and install the SDK from https://developer.android.com/studio/index.html"
756 | Write-Host
757 | break
758 |
759 | }
760 |
761 | if(((gci $AndroidSDK | select name).Name).count -gt 1){
762 |
763 | $BuildTools = ((gci $AndroidSDK | select name).Name | sort -Descending)[0]
764 |
765 | }
766 |
767 | else {
768 |
769 | $BuildTools = ((gci $AndroidSDK | select name).Name)
770 |
771 | }
772 |
773 | $aaptPath = "$AndroidSDK\$BuildTools"
774 |
775 | [ScriptBlock]$command = {
776 |
777 | cmd.exe /c "$aaptPath\aapt.exe" dump badging "$sourceFile"
778 |
779 | }
780 |
781 | $aaptRun = Invoke-Command -ScriptBlock $command
782 |
783 | $AndroidPackage = $aaptRun | ? { ($_).startswith("package") }
784 |
785 | $PackageInfo = $AndroidPackage.split(" ")
786 |
787 | $PackageInfo[1].Split("'")[1]
788 | $PackageInfo[2].Split("'")[1]
789 | $PackageInfo[3].Split("'")[1]
790 |
791 | if ($logContent) { Write-Host -ForegroundColor Gray $PackageInfo[1].Split("'")[1]; }
792 | if ($logContent) { Write-Host -ForegroundColor Gray $PackageInfo[2].Split("'")[1]; }
793 | if ($logContent) { Write-Host -ForegroundColor Gray $PackageInfo[3].Split("'")[1]; }
794 |
795 | }
796 |
797 | ####################################################
798 |
799 | function Upload-AndroidLob(){
800 |
801 | <#
802 | .SYNOPSIS
803 | This function is used to upload an Android LOB Application to the Intune Service
804 | .DESCRIPTION
805 | This function is used to upload an Android LOB Application to the Intune Service
806 | .EXAMPLE
807 | Upload-AndroidLob -sourceFile "C:\Software\package.apk" -publisher "Publisher Name" -description "Description of Application" -identityName "com.package" -identityVersion "1" -versionName "10.1.1"
808 | This example uses all parameters required to add an Android Application into the Intune Service
809 | Upload-AndroidLob -sourceFile "C:\Software\package.apk" -publisher "Publisher Name" -description "Description of Application"
810 | This example uses the required parameters to add an Android Application into the Intune Service. This example will require the Android SDK to get identityName and identityVersion
811 | .NOTES
812 | NAME: Upload-AndroidLOB
813 | #>
814 |
815 | [cmdletbinding()]
816 |
817 | param
818 | (
819 | [parameter(Mandatory=$true,Position=1)]
820 | [ValidateNotNullOrEmpty()]
821 | [string]$SourceFile,
822 |
823 | [parameter(Mandatory=$false)]
824 | [string]$displayName,
825 |
826 | [parameter(Mandatory=$true,Position=2)]
827 | [ValidateNotNullOrEmpty()]
828 | [string]$publisher,
829 |
830 | [parameter(Mandatory=$true,Position=3)]
831 | [ValidateNotNullOrEmpty()]
832 | [string]$description,
833 |
834 | [parameter(Mandatory=$false)]
835 | [string]$identityName,
836 |
837 | [parameter(Mandatory=$false)]
838 | [string]$identityVersion,
839 |
840 | [parameter(Mandatory=$false)]
841 | [string]$versionName
842 |
843 | )
844 |
845 | try
846 | {
847 |
848 | $LOBType = "microsoft.graph.androidLOBApp"
849 |
850 | Write-Host "Testing if SourceFile '$SourceFile' Path is valid..." -ForegroundColor Yellow
851 | Test-SourceFile "$SourceFile"
852 |
853 | if(!$identityName){
854 |
855 | Write-Host
856 | Write-Host "Opening APK file to get identityName to pass to the service..." -ForegroundColor Yellow
857 |
858 | $APKInformation = Get-ApkInformation -AndroidSDK $AndroidSDKLocation -sourceFile "$SourceFile"
859 |
860 | $identityName = $APKInformation[0]
861 |
862 | }
863 |
864 | if(!$identityVersion){
865 |
866 | Write-Host
867 | Write-Host "Opening APK file to get identityVersion to pass to the service..." -ForegroundColor Yellow
868 |
869 | $APKInformation = Get-ApkInformation -AndroidSDK $AndroidSDKLocation -sourceFile "$SourceFile"
870 |
871 | $identityVersion = $APKInformation[1]
872 |
873 | }
874 |
875 | if(!$versionName){
876 |
877 | Write-Host
878 | Write-Host "Opening APK file to get versionName to pass to the service..." -ForegroundColor Yellow
879 |
880 | $APKInformation = Get-ApkInformation -AndroidSDK $AndroidSDKLocation -sourceFile "$SourceFile"
881 |
882 | $versionName = $APKInformation[2]
883 |
884 | }
885 |
886 |
887 | # Creating temp file name from Source File path
888 | $tempFile = [System.IO.Path]::GetDirectoryName("$SourceFile") + "\" + [System.IO.Path]::GetFileNameWithoutExtension("$SourceFile") + "_temp.bin"
889 |
890 | # Creating filename variable from Source File Path
891 | $filename = [System.IO.Path]::GetFileName("$SourceFile")
892 |
893 | if(!($displayName)){
894 |
895 | $displayName = $filename
896 |
897 | }
898 |
899 | # Create a new Android LOB app.
900 | Write-Host
901 | Write-Host "Creating JSON data to pass to the service..." -ForegroundColor Yellow
902 | $mobileAppBody = GetAndroidAppBody "$displayName" "$Publisher" "$Description" "$filename" "$identityName" "$identityVersion" "$versionName";
903 |
904 | Write-Host
905 | Write-Host "Creating application in Intune..." -ForegroundColor Yellow
906 | $mobileApp = MakePostRequest "mobileApps" ($mobileAppBody | ConvertTo-Json);
907 |
908 | # Get the content version for the new app (this will always be 1 until the new app is committed).
909 | Write-Host
910 | Write-Host "Creating Content Version in the service for the application..." -ForegroundColor Yellow
911 | $appId = $mobileApp.id;
912 | $contentVersionUri = "mobileApps/$appId/$LOBType/contentVersions";
913 | $contentVersion = MakePostRequest $contentVersionUri "{}";
914 |
915 | # Encrypt file and Get File Information
916 | Write-Host
917 | Write-Host "Ecrypting the file '$SourceFile'..." -ForegroundColor Yellow
918 | $encryptionInfo = EncryptFile "$sourceFile" "$tempFile";
919 | $Size = (Get-Item "$sourceFile").Length
920 | $EncrySize = (Get-Item "$tempFile").Length
921 |
922 | Write-Host
923 | Write-Host "Creating the manifest file used to install the application on the device..." -ForegroundColor Yellow
924 |
925 | [xml]$manifestXML = 'com.leadapps.android.radio.ncp101.0.5.4A_Online_Radio_1.0.5.4.apk3'
926 |
927 | $manifestXML.AndroidManifestProperties.Package = "$identityName" # com.application.test
928 | $manifestXML.AndroidManifestProperties.PackageVersionCode = "$identityVersion" # 10
929 | $manifestXML.AndroidManifestProperties.PackageVersionName = "$identityVersion" # 1.0.5.4
930 | $manifestXML.AndroidManifestProperties.ApplicationName = "$filename" # name.apk
931 |
932 | $manifestXML_Output = $manifestXML.OuterXml.ToString()
933 |
934 | $Bytes = [System.Text.Encoding]::ASCII.GetBytes($manifestXML_Output)
935 | $EncodedText =[Convert]::ToBase64String($Bytes)
936 |
937 | # Create a new file for the app.
938 | Write-Host
939 | Write-Host "Creating a new file entry in Azure for the upload..." -ForegroundColor Yellow
940 | $contentVersionId = $contentVersion.id;
941 | $fileBody = GetAppFileBody "$filename" $Size $EncrySize "$EncodedText";
942 | $filesUri = "mobileApps/$appId/$LOBType/contentVersions/$contentVersionId/files";
943 | $file = MakePostRequest $filesUri ($fileBody | ConvertTo-Json);
944 |
945 | # Wait for the service to process the new file request.
946 | Write-Host
947 | Write-Host "Waiting for the file entry URI to be created..." -ForegroundColor Yellow
948 | $fileId = $file.id;
949 | $fileUri = "mobileApps/$appId/$LOBType/contentVersions/$contentVersionId/files/$fileId";
950 | $file = WaitForFileProcessing $fileUri "AzureStorageUriRequest";
951 |
952 | # Upload the content to Azure Storage.
953 | Write-Host
954 | Write-Host "Uploading file to Azure Storage URI..." -ForegroundColor Yellow
955 |
956 | $sasUri = $file.azureStorageUri;
957 | UploadFileToAzureStorage $file.azureStorageUri $tempFile;
958 |
959 | # Commit the file.
960 | Write-Host
961 | Write-Host "Committing the file into Azure Storage..." -ForegroundColor Yellow
962 | $commitFileUri = "mobileApps/$appId/$LOBType/contentVersions/$contentVersionId/files/$fileId/commit";
963 | MakePostRequest $commitFileUri ($encryptionInfo | ConvertTo-Json);
964 |
965 | # Wait for the service to process the commit file request.
966 | Write-Host
967 | Write-Host "Waiting for the service to process the commit file request..." -ForegroundColor Yellow
968 | $file = WaitForFileProcessing $fileUri "CommitFile";
969 |
970 | # Commit the app.
971 | Write-Host
972 | Write-Host "Committing the application to the Intune Service..." -ForegroundColor Yellow
973 | $commitAppUri = "mobileApps/$appId";
974 | $commitAppBody = GetAppCommitBody $contentVersionId $LOBType;
975 | MakePatchRequest $commitAppUri ($commitAppBody | ConvertTo-Json);
976 |
977 | Write-Host "Removing Temporary file '$tempFile'..." -f Gray
978 | Remove-Item -Path "$tempFile" -Force
979 | Write-Host
980 |
981 | Write-Host "Sleeping for $sleep seconds to allow patch completion..." -f Magenta
982 | Start-Sleep $sleep
983 | Write-Host
984 |
985 | }
986 | catch
987 | {
988 | Write-Host "";
989 | Write-Host -ForegroundColor Red "Aborting with exception: $($_.Exception.ToString())";
990 | }
991 | }
992 |
993 | ####################################################
994 |
995 | function Upload-iOSLob(){
996 |
997 | <#
998 | .SYNOPSIS
999 | This function is used to upload an iOS LOB Application to the Intune Service
1000 | .DESCRIPTION
1001 | This function is used to upload an iOS LOB Application to the Intune Service
1002 | .EXAMPLE
1003 | Upload-iOSLob -sourceFile "C:\Software\package.ipa" -displayName "package.ipa" -publisher "Publisher Name" -description "Description of Application" -bundleId "com.package" -identityVersion "1" -versionNumber "3.0.0" -expirationDateTime "2018-02-14T20:53:52Z"
1004 | This example uses all parameters required to add an iOS Application into the Intune Service
1005 | .NOTES
1006 | NAME: Upload-iOSLOB
1007 | #>
1008 |
1009 | [cmdletbinding()]
1010 |
1011 | param
1012 | (
1013 | [parameter(Mandatory=$true,Position=1)]
1014 | [ValidateNotNullOrEmpty()]
1015 | [string]$SourceFile,
1016 |
1017 | [parameter(Mandatory=$true,Position=2)]
1018 | [ValidateNotNullOrEmpty()]
1019 | [string]$displayName,
1020 |
1021 | [parameter(Mandatory=$true,Position=3)]
1022 | [ValidateNotNullOrEmpty()]
1023 | [string]$publisher,
1024 |
1025 | [parameter(Mandatory=$true,Position=4)]
1026 | [ValidateNotNullOrEmpty()]
1027 | [string]$description,
1028 |
1029 | [parameter(Mandatory=$true,Position=5)]
1030 | [ValidateNotNullOrEmpty()]
1031 | [string]$bundleId,
1032 |
1033 | [parameter(Mandatory=$true,Position=6)]
1034 | [ValidateNotNullOrEmpty()]
1035 | [string]$identityVersion,
1036 |
1037 | [parameter(Mandatory=$true,Position=7)]
1038 | [ValidateNotNullOrEmpty()]
1039 | [string]$versionNumber,
1040 |
1041 | [parameter(Mandatory=$true,Position=8)]
1042 | [ValidateNotNullOrEmpty()]
1043 | [string]$expirationDateTime
1044 | )
1045 |
1046 | try
1047 | {
1048 |
1049 | $LOBType = "microsoft.graph.iosLOBApp"
1050 |
1051 | Write-Host "Testing if SourceFile '$SourceFile' Path is valid..." -ForegroundColor Yellow
1052 | Test-SourceFile "$SourceFile"
1053 |
1054 | # Checking expirationdatetime of SourceFile to check if it can be uploaded
1055 | [datetimeoffset]$Expiration = $expirationDateTime
1056 |
1057 | $Date = get-date
1058 |
1059 | if($Expiration -lt $Date){
1060 |
1061 | Write-Error "$SourceFile has expired Follow the guidelines provided by Apple to extend the expiration date, then try adding the app again"
1062 | throw
1063 |
1064 | }
1065 |
1066 | # Creating temp file name from Source File path
1067 | $tempFile = [System.IO.Path]::GetDirectoryName("$SourceFile") + "\" + [System.IO.Path]::GetFileNameWithoutExtension("$SourceFile") + "_temp.bin"
1068 |
1069 | # Creating filename variable from Source File Path
1070 | $filename = [System.IO.Path]::GetFileName("$SourceFile")
1071 |
1072 | # Create a new iOS LOB app.
1073 | Write-Host
1074 | Write-Host "Creating JSON data to pass to the service..." -ForegroundColor Yellow
1075 | $mobileAppBody = GetiOSAppBody "$displayName" "$Publisher" "$Description" "$filename" "$bundleId" "$identityVersion" "$versionNumber" "$expirationDateTime";
1076 |
1077 | Write-Host
1078 | Write-Host "Creating application in Intune..." -ForegroundColor Yellow
1079 |
1080 | $mobileApp = MakePostRequest "mobileApps" ($mobileAppBody | ConvertTo-Json);
1081 |
1082 | # Get the content version for the new app (this will always be 1 until the new app is committed).
1083 | Write-Host
1084 | Write-Host "Creating Content Version in the service for the application..." -ForegroundColor Yellow
1085 | $appId = $mobileApp.id;
1086 | $contentVersionUri = "mobileApps/$appId/$LOBType/contentVersions";
1087 | $contentVersion = MakePostRequest $contentVersionUri "{}";
1088 |
1089 | # Encrypt file and Get File Information
1090 | Write-Host
1091 | Write-Host "Ecrypting the file '$SourceFile'..." -ForegroundColor Yellow
1092 | $encryptionInfo = EncryptFile $sourceFile $tempFile;
1093 | $Size = (Get-Item "$sourceFile").Length
1094 | $EncrySize = (Get-Item "$tempFile").Length
1095 |
1096 | Write-Host
1097 | Write-Host "Creating the manifest file used to install the application on the device..." -ForegroundColor Yellow
1098 |
1099 | [string]$manifestXML = 'itemsassetskindsoftware-packageurl{UrlPlaceHolder}metadataAppRestrictionPolicyTemplate http://management.microsoft.com/PolicyTemplates/AppRestrictions/iOS/v1AppRestrictionTechnologyWindows Intune Application Restrictions Technology for iOSIntuneMAMVersionCFBundleSupportedPlatformsiPhoneOSMinimumOSVersion9.0bundle-identifierbundleidbundle-versionbundleversionkindsoftwaresubtitleLaunchMeSubtitletitlebundletitle'
1100 |
1101 | $manifestXML = $manifestXML.replace("bundleid","$bundleId")
1102 | $manifestXML = $manifestXML.replace("bundleversion","$identityVersion")
1103 | $manifestXML = $manifestXML.replace("bundletitle","$displayName")
1104 |
1105 | $Bytes = [System.Text.Encoding]::ASCII.GetBytes($manifestXML)
1106 | $EncodedText =[Convert]::ToBase64String($Bytes)
1107 |
1108 | # Create a new file for the app.
1109 | Write-Host
1110 | Write-Host "Creating a new file entry in Azure for the upload..." -ForegroundColor Yellow
1111 | $contentVersionId = $contentVersion.id;
1112 | $fileBody = GetAppFileBody "$filename" $Size $EncrySize "$EncodedText";
1113 | $filesUri = "mobileApps/$appId/$LOBType/contentVersions/$contentVersionId/files";
1114 | $file = MakePostRequest $filesUri ($fileBody | ConvertTo-Json);
1115 |
1116 | # Wait for the service to process the new file request.
1117 | Write-Host
1118 | Write-Host "Waiting for the file entry URI to be created..." -ForegroundColor Yellow
1119 | $fileId = $file.id;
1120 | $fileUri = "mobileApps/$appId/$LOBType/contentVersions/$contentVersionId/files/$fileId";
1121 | $file = WaitForFileProcessing $fileUri "AzureStorageUriRequest";
1122 |
1123 | # Upload the content to Azure Storage.
1124 | Write-Host
1125 | Write-Host "Uploading file to Azure Storage..." -f Yellow
1126 |
1127 | $sasUri = $file.azureStorageUri;
1128 | UploadFileToAzureStorage $file.azureStorageUri $tempFile;
1129 |
1130 | # Commit the file.
1131 | Write-Host
1132 | Write-Host "Committing the file into Azure Storage..." -ForegroundColor Yellow
1133 | $commitFileUri = "mobileApps/$appId/$LOBType/contentVersions/$contentVersionId/files/$fileId/commit";
1134 | MakePostRequest $commitFileUri ($encryptionInfo | ConvertTo-Json);
1135 |
1136 | # Wait for the service to process the commit file request.
1137 | Write-Host
1138 | Write-Host "Waiting for the service to process the commit file request..." -ForegroundColor Yellow
1139 | $file = WaitForFileProcessing $fileUri "CommitFile";
1140 |
1141 | # Commit the app.
1142 | Write-Host
1143 | Write-Host "Committing the file into Azure Storage..." -ForegroundColor Yellow
1144 | $commitAppUri = "mobileApps/$appId";
1145 | $commitAppBody = GetAppCommitBody $contentVersionId $LOBType;
1146 | MakePatchRequest $commitAppUri ($commitAppBody | ConvertTo-Json);
1147 |
1148 | Write-Host "Removing Temporary file '$tempFile'..." -f Gray
1149 | Remove-Item -Path "$tempFile" -Force
1150 | Write-Host
1151 |
1152 | Write-Host "Sleeping for $sleep seconds to allow patch completion..." -f Magenta
1153 | Start-Sleep $sleep
1154 | Write-Host
1155 |
1156 | }
1157 | catch
1158 | {
1159 | Write-Host "";
1160 | Write-Host -ForegroundColor Red "Aborting with exception: $($_.Exception.ToString())";
1161 | }
1162 | }
1163 |
1164 | ####################################################
1165 |
1166 | function Upload-MSILob(){
1167 |
1168 | <#
1169 | .SYNOPSIS
1170 | This function is used to upload an MSI LOB Application to the Intune Service
1171 | .DESCRIPTION
1172 | This function is used to upload an MSI LOB Application to the Intune Service
1173 | .EXAMPLE
1174 | Upload-MSILob "C:\Software\Orca\Orca.Msi" -publisher "Microsoft" -description "Orca"
1175 | This example uses all parameters required to add an MSI Application into the Intune Service
1176 | .NOTES
1177 | NAME: Upload-MSILOB
1178 | #>
1179 |
1180 | [cmdletbinding()]
1181 |
1182 | param
1183 | (
1184 | [parameter(Mandatory=$true,Position=1)]
1185 | [ValidateNotNullOrEmpty()]
1186 | [string]$SourceFile,
1187 |
1188 | [parameter(Mandatory=$true,Position=2)]
1189 | [ValidateNotNullOrEmpty()]
1190 | [string]$publisher,
1191 |
1192 | [parameter(Mandatory=$true,Position=3)]
1193 | [ValidateNotNullOrEmpty()]
1194 | [string]$description
1195 | )
1196 |
1197 | try {
1198 |
1199 | $LOBType = "microsoft.graph.windowsMobileMSI"
1200 |
1201 | Write-Host "Testing if SourceFile '$SourceFile' Path is valid..." -ForegroundColor Yellow
1202 | Test-SourceFile "$SourceFile"
1203 |
1204 | $MSIPath = "$SourceFile"
1205 |
1206 | # Creating temp file name from Source File path
1207 | $tempFile = [System.IO.Path]::GetDirectoryName("$SourceFile") + "\" + [System.IO.Path]::GetFileNameWithoutExtension("$SourceFile") + "_temp.bin"
1208 |
1209 | Write-Host
1210 | Write-Host "Creating JSON data to pass to the service..." -ForegroundColor Yellow
1211 |
1212 | $FileName = [System.IO.Path]::GetFileName("$MSIPath")
1213 |
1214 | $PN = (Get-MSIFileInformation -Path "$MSIPath" -Property ProductName | Out-String).trimend()
1215 | $PC = (Get-MSIFileInformation -Path "$MSIPath" -Property ProductCode | Out-String).trimend()
1216 | $PV = (Get-MSIFileInformation -Path "$MSIPath" -Property ProductVersion | Out-String).trimend()
1217 | $PL = (Get-MSIFileInformation -Path "$MSIPath" -Property ProductLanguage | Out-String).trimend()
1218 |
1219 | # Create a new MSI LOB app.
1220 | $mobileAppBody = GetMSIAppBody -displayName "$PN" -publisher "$publisher" -description "$description" -filename "$FileName" -identityVersion "$PV" -ProductCode "$PC"
1221 |
1222 | Write-Host
1223 | Write-Host "Creating application in Intune..." -ForegroundColor Yellow
1224 | $mobileApp = MakePostRequest "mobileApps" ($mobileAppBody | ConvertTo-Json);
1225 |
1226 | # Get the content version for the new app (this will always be 1 until the new app is committed).
1227 | Write-Host
1228 | Write-Host "Creating Content Version in the service for the application..." -ForegroundColor Yellow
1229 | $appId = $mobileApp.id;
1230 | $contentVersionUri = "mobileApps/$appId/$LOBType/contentVersions";
1231 | $contentVersion = MakePostRequest $contentVersionUri "{}";
1232 |
1233 | # Encrypt file and Get File Information
1234 | Write-Host
1235 | Write-Host "Ecrypting the file '$SourceFile'..." -ForegroundColor Yellow
1236 | $encryptionInfo = EncryptFile $sourceFile $tempFile;
1237 | $Size = (Get-Item "$sourceFile").Length
1238 | $EncrySize = (Get-Item "$tempFile").Length
1239 |
1240 | Write-Host
1241 | Write-Host "Creating the manifest file used to install the application on the device..." -ForegroundColor Yellow
1242 |
1243 | [xml]$manifestXML = ''
1244 |
1245 | $manifestXML.MobileMsiData.MsiUpgradeCode = "$PC"
1246 |
1247 | $manifestXML_Output = $manifestXML.OuterXml.ToString()
1248 |
1249 | $Bytes = [System.Text.Encoding]::ASCII.GetBytes($manifestXML_Output)
1250 | $EncodedText =[Convert]::ToBase64String($Bytes)
1251 |
1252 | # Create a new file for the app.
1253 | Write-Host
1254 | Write-Host "Creating a new file entry in Azure for the upload..." -ForegroundColor Yellow
1255 | $contentVersionId = $contentVersion.id;
1256 | $fileBody = GetAppFileBody "$FileName" $Size $EncrySize "$EncodedText";
1257 | $filesUri = "mobileApps/$appId/$LOBType/contentVersions/$contentVersionId/files";
1258 | $file = MakePostRequest $filesUri ($fileBody | ConvertTo-Json);
1259 |
1260 | # Wait for the service to process the new file request.
1261 | Write-Host
1262 | Write-Host "Waiting for the file entry URI to be created..." -ForegroundColor Yellow
1263 | $fileId = $file.id;
1264 | $fileUri = "mobileApps/$appId/$LOBType/contentVersions/$contentVersionId/files/$fileId";
1265 | $file = WaitForFileProcessing $fileUri "AzureStorageUriRequest";
1266 |
1267 | # Upload the content to Azure Storage.
1268 | Write-Host
1269 | Write-Host "Uploading file to Azure Storage..." -f Yellow
1270 |
1271 | $sasUri = $file.azureStorageUri;
1272 | UploadFileToAzureStorage $file.azureStorageUri $tempFile;
1273 |
1274 | # Commit the file.
1275 | Write-Host
1276 | Write-Host "Committing the file into Azure Storage..." -ForegroundColor Yellow
1277 | $commitFileUri = "mobileApps/$appId/$LOBType/contentVersions/$contentVersionId/files/$fileId/commit";
1278 | MakePostRequest $commitFileUri ($encryptionInfo | ConvertTo-Json);
1279 |
1280 | # Wait for the service to process the commit file request.
1281 | Write-Host
1282 | Write-Host "Waiting for the service to process the commit file request..." -ForegroundColor Yellow
1283 | $file = WaitForFileProcessing $fileUri "CommitFile";
1284 |
1285 | # Commit the app.
1286 | Write-Host
1287 | Write-Host "Committing the file into Azure Storage..." -ForegroundColor Yellow
1288 | $commitAppUri = "mobileApps/$appId";
1289 | $commitAppBody = GetAppCommitBody $contentVersionId $LOBType;
1290 | MakePatchRequest $commitAppUri ($commitAppBody | ConvertTo-Json);
1291 |
1292 | Write-Host "Removing Temporary file '$tempFile'..." -f Gray
1293 | Remove-Item -Path "$tempFile" -Force
1294 | Write-Host
1295 |
1296 | Write-Host "Sleeping for $sleep seconds to allow patch completion..." -f Magenta
1297 | Start-Sleep $sleep
1298 | Write-Host
1299 |
1300 | }
1301 |
1302 | catch {
1303 |
1304 | Write-Host "";
1305 | Write-Host -ForegroundColor Red "Aborting with exception: $($_.Exception.ToString())";
1306 |
1307 | }
1308 |
1309 | }
1310 |
1311 | ####################################################
1312 |
1313 | #region Authentication
1314 |
1315 | write-host
1316 |
1317 | # Checking if authToken exists before running authentication
1318 | if($global:authToken){
1319 |
1320 | # Setting DateTime to Universal time to work in all timezones
1321 | $DateTime = (Get-Date).ToUniversalTime()
1322 |
1323 | # If the authToken exists checking when it expires
1324 | $TokenExpires = ($authToken.ExpiresOn.datetime - $DateTime).Minutes
1325 |
1326 | if($TokenExpires -le 0){
1327 |
1328 | write-host "Authentication Token expired" $TokenExpires "minutes ago" -ForegroundColor Yellow
1329 | write-host
1330 |
1331 | # Defining Azure AD tenant name, this is the name of your Azure Active Directory (do not use the verified domain name)
1332 |
1333 | if($User -eq $null -or $User -eq ""){
1334 |
1335 | $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication"
1336 | Write-Host
1337 |
1338 | }
1339 |
1340 | $global:authToken = Get-AuthToken -User $User
1341 |
1342 | }
1343 | }
1344 |
1345 | # Authentication doesn't exist, calling Get-AuthToken function
1346 |
1347 | else {
1348 |
1349 | if($User -eq $null -or $User -eq ""){
1350 |
1351 | $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication"
1352 | Write-Host
1353 |
1354 | }
1355 |
1356 | # Getting the authorization token
1357 | $global:authToken = Get-AuthToken -User $User
1358 |
1359 | }
1360 |
1361 | #endregion
1362 |
1363 | ####################################################
1364 |
1365 | # Path to Android SDK Location to find aapt.exe tool if you don't specify identityName or identityVersion
1366 | # Note: Don't specify direct location to build folder number, just to the build-tools folder as the script will find the latest SDK installed
1367 | $AndroidSDKLocation = "C:\AndroidSDK\build-tools"
1368 |
1369 | $baseUrl = "https://graph.microsoft.com/beta/deviceAppManagement/"
1370 |
1371 | $logRequestUris = $true;
1372 | $logHeaders = $false;
1373 | $logContent = $true;
1374 |
1375 | $sleep = 30
1376 |
1377 | ####################################################
1378 |
1379 | #### MSI Install Google Chrome Enterprise x64
1380 | $output = "$PSScriptRoot\googlechromestandaloneenterprise64.msi"
1381 | Start-BitsTransfer -Source https://dl.google.com/edgedl/chrome/install/GoogleChromeStandaloneEnterprise64.msi -Destination $output
1382 | Upload-MSILob "$output" -publisher "Google" -description "Google Chrome Enterprise x64"
1383 |
1384 | #### MSI Install Google Chrome Enterprise x32
1385 | $output = "$PSScriptRoot\googlechromestandaloneenterprise.msi"
1386 | Start-BitsTransfer -Source https://dl.google.com/edgedl/chrome/install/GoogleChromeStandaloneEnterprise.msi -Destination $output
1387 | Upload-MSILob "$output" -publisher "Google" -description "Google Chrome Enterprise x32"
--------------------------------------------------------------------------------