cancel
Showing results for 
Search instead for 
Did you mean: 
Reply
bboardman
Advocate I
Advocate I

Exporting and Importing a PowerApp

Is there any way besides the Import/Export function in the PowerApps designer to Export and package a PowerApp and Import it?  Can this be done from PowerShell?

1 ACCEPTED SOLUTION

Accepted Solutions
DileepGolla
Advocate V
Advocate V

Hi Everyone,

I did not find any existing idea about this so I created one in the portal.

https://powerusers.microsoft.com/t5/PowerApps-Ideas/PowerShell-Cmdlet-to-publish-deploy-the-form-to-...

Thanks,

Dileep

View solution in original post

4 REPLIES 4
v-xida-msft
Community Support
Community Support

Hi @bboardman,

 

Do you want to Export or Import a PowerApps app with packaging without the Import/Export function in PowerApps?

Do you want to use PowerShell script to Emport/Import a PowerApps app within your PowerApps?

 

If you want to Export or Import a PowerApps app with packaging without the Import/Export function, I afraid that there is no way to achieve your needs in PowerApps currently.

 

Currently, we could only Export/Import a PowerApps app with packaging using Import/Export option within PowerApps designer. Please check the following blog:

https://powerapps.microsoft.com/en-us/blog/powerapps-packaging/

 

If you want to use PowerShell script to Emport/Import a PowerApps app within your PowerApps, I afraid that there is also no way to achieve your needs in PowerApps currently. The supported PowerSheell Cmdlet within PowerApps, please check the following article:

https://docs.microsoft.com/en-us/powerapps/administrator/powerapps-powershell

 

If you would like this feature to be added in PowerApps, please submit an idea to PowerApps Ideas Forum:

https://powerusers.microsoft.com/t5/PowerApps-Ideas/idb-p/PowerAppsIdeas

 

Best regards,

Kris

 

 

Community Support Team _ Kris Dai
If this post helps, then please consider Accept it as the solution to help the other members find it more quickly.

Thank you for your reply.

DileepGolla
Advocate V
Advocate V

Hi Everyone,

I did not find any existing idea about this so I created one in the portal.

https://powerusers.microsoft.com/t5/PowerApps-Ideas/PowerShell-Cmdlet-to-publish-deploy-the-form-to-...

Thanks,

Dileep

View solution in original post

AlyaKoniPA
New Member

You are able to import the package like the portal make.powerapps.com is doing it.

 

$UsedBapApiHost = "api.bap.microsoft.com"

Import-Module "Microsoft.PowerApps.Administration.PowerShell"

function Get-AudienceForHostName
{
[CmdletBinding()]
Param(
[string] $Uri
)
$hostMapping = @{
"management.azure.com" = "https://management.azure.com/";
"api.powerapps.com" = "https://service.powerapps.com/";
"tip1.api.powerapps.com" = "https://service.powerapps.com/";
"tip2.api.powerapps.com" = "https://service.powerapps.com/";
"graph.windows.net" = "https://graph.windows.net/";
"api.bap.microsoft.com" = "https://service.powerapps.com/";
"tip1.api.bap.microsoft.com" = "https://service.powerapps.com/";
"tip2.api.bap.microsoft.com" = "https://service.powerapps.com/";
"api.flow.microsoft.com" = "https://service.flow.microsoft.com/";
"tip1.api.flow.microsoft.com" = "https://service.flow.microsoft.com/";
"tip2.api.flow.microsoft.com" = "https://service.flow.microsoft.com/";
}
$uriObject = New-Object System.Uri($Uri)
$audhost = $uriObject.Host
if ($hostMapping[$audhost] -ne $null)
{
return $hostMapping[$audhost];
}
Write-Verbose "Unknown host $audhost. Using https://management.azure.com/ as a default";
return "https://management.azure.com/";
}

function Invoke-Request(
[CmdletBinding()]

[Parameter(Mandatory=$True)]
[string] $Uri,

[Parameter(Mandatory=$True)]
[string] $Method,

[object] $Body = $null,

[Hashtable] $Headers = @{},

[switch] $ParseContent,

[switch] $ThrowOnFailure
)
{
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$audience = Get-AudienceForHostName -Uri $Uri
$token = Get-JwtToken -Audience $audience
$Headers["Authorization"] = "Bearer $token";
$Headers["User-Agent"] = "PowerShell cmdlets 1.0";
try {
if ($Body -eq $null -or $Body -eq "")
{
$response = Invoke-WebRequest -Uri $Uri -Headers $Headers -Method $Method -UseBasicParsing
}
else 
{
$jsonBody = ConvertTo-Json $Body -Depth 20
$response = Invoke-WebRequest -Uri $Uri -Headers $Headers -Method $Method -ContentType "application/json; charset=UTF-8" -Body $jsonBody -UseBasicParsing
}
if ($ParseContent)
{
if ($response.Content)
{
return ConvertFrom-Json $response.Content;
}
}
return $response
} catch {
$response = $_.Exception.Response
if ($_.ErrorDetails)
{
$errorResponse = ConvertFrom-Json $_.ErrorDetails;
$code = $response.StatusCode
$message = $errorResponse.Error.Message
Write-Verbose "Status Code: '$code'. Message: '$message'" 
}
if ($ThrowOnFailure)
{
throw;
}
else 
{
return $response
}
}
}

function Configure-ImportResourcesObject(
$Resources,
$EnvironmentName = $null,
[bool]$DefaultToExportSuggestions = $false,
[bool] $NewApp = $false,
[string] $ResourceName
)
{
$includedResourceIds = @()
$includedSuggestedResourceIds = @()
$includedResources = $Resources
$numResources = 0
$env = Get-AdminPowerAppEnvironment -EnvironmentName $EnvironmentName
$environmentDisplayName = $env.DisplayName
$selectedCommonDataServiceOption = $null
foreach ($resource in Get-Member -InputObject $includedResources -MemberType NoteProperty)
{
$numResources = $numResources + 1 
$property = 'Name'
$propertyvalue = $resource.$property
If($includedResources.$propertyvalue.id -ne $null -and $includedResources.$propertyvalue.id -ne "")
{
$includedResourceIds = $includedResourceIds + $includedResources.$propertyvalue.id
}
If(!$includedSuggestedResourceIds.$propertyvalue.suggestedId)
{
$includedSuggestedResourceIds = $includedSuggestedResourceIds + $includedSuggestedResourceIds.$propertyvalue.suggestedId
}
$type = $null
if ($includedResources.$propertyvalue.type -eq "Microsoft.PowerApps/apps")
{
$result = $null
$selection = $null

if($NewApp)
{
$type = "New"
$includedResources.$propertyvalue.details.displayName = $ResourceName
}
else 
{
$type = "Update"
$selectedResource = $result.selectedResource
$includedResources.$propertyvalue | Add-Member -MemberType NoteProperty -name id -value $selectedResource.id
$includedResources.$propertyvalue | Add-Member -MemberType NoteProperty -name name -value $selectedResource.name
} 
}
if ($includedResources.$propertyvalue.type -eq "Microsoft.Flow/flows")
{
$result = $null
$selection = $null

if($NewApp)
{
$type = "New"
$includedResources.$propertyvalue.details.displayName = $ResourceName
}
else 
{
$type = "Update"
$selectedResource = $result.selectedResource
$includedResources.$propertyvalue | Add-Member -MemberType NoteProperty -name id -value $selectedResource.id
$includedResources.$propertyvalue | Add-Member -MemberType NoteProperty -name name -value $selectedResource.name
}
}
if ($includedResources.$propertyvalue.type -eq "Microsoft.PowerApps/apis")
{
if ($includedResources.$propertyvalue.name -eq $null)
{
if (-Not $NewApp) 
{
$type = "Existing"
$selectedResource = $result.selectedResource
$includedResources.$propertyvalue | Add-Member -MemberType NoteProperty -name id -value $selectedResource.id
$includedResources.$propertyvalue | Add-Member -MemberType NoteProperty -name name -value $selectedResource.name
}
}
else { 
$type = "Existing"
}
}
if ($includedResources.$propertyvalue.type -eq "Microsoft.PowerApps/apis/connections")
{
if (-Not $NewApp) 
{
$type = "Existing"
$selectedResource = $result.selectedResource
$includedResources.$propertyvalue | Add-Member -MemberType NoteProperty -name id -value $selectedResource.id
$includedResources.$propertyvalue | Add-Member -MemberType NoteProperty -name name -value $selectedResource.name
}
}
if ($includedResources.$propertyvalue.type -eq "Microsoft.CommonDataModel/environments/namespaces/enumerations" -or $includedResources.$propertyvalue.type -eq "Microsoft.CommonDataModel/environments/namespaces/entities")
{ 
if ($includedResources.$propertyvalue.configurableBy -eq "User")
{
if($DefaultToExportSuggestions -and ($includedResources.$propertyvalue.suggestedCreationType -ne $null))
{
$type = $includedResources.$propertyvalue.suggestedCreationType
}
else {
If($selectedCommonDataServiceOption -eq $null)
{
$selectedCommonDataServiceOption = "Overwrite"
$type = $selectedCommonDataServiceOption
}
else {
$type = $selectedCommonDataServiceOption
}
}
}
else {
$type = $includedResources.$propertyvalue.suggestedCreationType
}
}
If($type)
{ 
If($includedResources.$propertyvalue.suggestedCreationType)
{
$includedResources.$propertyvalue.suggestedCreationType = $type
}
else
{
$includedResources.$propertyvalue | Add-Member -MemberType NoteProperty -name suggestedCreationType -value $type
}
$includedResources.$propertyvalue | Add-Member -MemberType NoteProperty -name selectedCreationType -value $type
}
}
$responseObject = @{
resources = $includedResources
resourceIds = $includedResourceIds
suggestedResourceIds = $includedSuggestedResourceIds
} 
return $responseObject
}

function Upload-FileToBlogStorage(
[string] $EnvironmentName,
[string] $FilePath,
[string] $ApiVersion = "2016-11-01"
)
{
try {
$fileBinary = [IO.File]::ReadAllBytes($FilePath);
$encoding = [System.Text.Encoding]::GetEncoding("iso-8859-1");
$file = $encoding.GetString($fileBinary)
} catch {
Write-Host "Failed to read the file"
throw
}
$generateResourceStorageUrl = "https://$UsedBapApiHost/providers/Microsoft.BusinessAppPlatform/environments/" + $EnvironmentName + "/generateResourceStorage`?api-version=" + $ApiVersion
$generateResourceStorageResponse = Invoke-Request -Uri $generateResourceStorageUrl -Method POST -ParseContent -ThrowOnFailure
$originalBlobUri = $generateResourceStorageResponse.sharedAccessSignature
$uri = [System.Uri] $originalBlobUri 
$filename = Split-Path $FilePath -Leaf
$uriHost = $uri.Host
$uriPath = $uri.AbsolutePath
$uriQuery = $uri.Query
$tempBlobUri = "https://$uriHost$uriPath/$fileName$uriQuery"
$commitBlobUri = "$tempBlobUri&comp=blocklist"
$uploadBlobUri = "$tempBlobUri&comp=block"
$BlockId = "BlockId"
$Bytes = [System.Text.Encoding]::Unicode.GetBytes($BlockId)
$EncodedBlockId =[Convert]::ToBase64String($Bytes)
$uploadBlobUri = "$uploadBlobUri&blockid=$EncodedBlockId"
try {
$uploadFiletoBLog = Invoke-WebRequest -Uri $uploadBlobUri -Method Put -ContentType "application/json" -Body $file -UseBasicParsing
$commitBody = "<?xml version=`"1.0`" encoding=`"utf-8`"?><BlockList><Latest>$EncodedBlockId</Latest></BlockList>"
$commitFiletoBLog = Invoke-WebRequest -Uri $commitBlobUri -Method Put -ContentType "application/json; charset=UTF-8" -Body $commitBody -UseBasicParsing
} catch {
Write-Host "Failed to upload the file to blob storage"
throw
}
return $tempBlobUri
}

function Get-ImportPackageResources(
[string] $EnvironmentName,
[string] $ImportPackageBlobUri,
[string] $ApiVersion = "2016-11-01"
)
{
$listParametersUri = "https://$UsedBapApiHost/providers/Microsoft.BusinessAppPlatform/environments/" + $EnvironmentName + "/listImportParameters`?api-version=" + $ApiVersion
$listParametersBody = @{ 
packageLink = @{
value = $ImportPackageBlobUri
} 
}
$listParametersResponse = Invoke-Request -Uri $listParametersUri -Method POST -Body $listParametersBody -ThrowOnFailure
$statusUri= $listParametersResponse.Headers['Location']
while($listParametersResponse.StatusCode -ne 200) 
{
Start-Sleep -s 5
$listParametersResponse = Invoke-Request -Uri $statusUri -Method GET -ThrowOnFailure
}
$parsedListParametersResponse = ConvertFrom-Json $listParametersResponse.Content
return $parsedListParametersResponse
}

function Import-Package(
[string] $EnvironmentName,
[string] $ImportPackageFilePath,
[string] $ApiVersion = "2016-11-01",
[bool] $DefaultToExportSuggestions = $false,
[bool] $NewApp = $false,
[string] $ResourceName
)
{
$blobUri = Upload-FileToBlogStorage -EnvironmentName $EnvironmentName -FilePath $ImportPackageFilePath -ApiVersion $ApiVersion
$parsedListParametersResponse = Get-ImportPackageResources -EnvironmentName $EnvironmentName -ImportPackageBlobUri $blobUri -ApiVersion $ApiVersion
$includedResources = Configure-ImportResourcesObject -resources $parsedListParametersResponse.properties.resources -EnvironmentName $EnvironmentName -DefaultToExportSuggestions $DefaultToExportSuggestions -NewApp $NewApp -ResourceName $ResourceName
$validateImportPackageUri = "https://$UsedBapApiHost/providers/Microsoft.BusinessAppPlatform/environments/" + $EnvironmentName + "/validateImportPackage`?api-version=" + $ApiVersion
$validateImportPackageBody = @{ 
details = $parsedListParametersResponse.properties.details
packageLink = $parsedListParametersResponse.properties.packageLink
resources = $includedResources.resources
}
$validateImportPackageResponse = Invoke-Request -Uri $validateImportPackageUri -Method POST -Body $validateImportPackageBody -ThrowOnFailure
$parsedValidateImportResponse = ConvertFrom-Json $validateImportPackageResponse.Content
if(($parsedValidateImportResponse.errors).Length -gt 0)
{
Write-Host "Package failed validation with the following errors \n" + $parsedValidateImportResponse.errors
throw
}
$importPackageUri = "https://$UsedBapApiHost/providers/Microsoft.BusinessAppPlatform/environments/" + $EnvironmentName + "/importPackage`?api-version=" + $ApiVersion
$importPackageResponse = Invoke-Request -Uri $importPackageUri -Method POST -Body $validateImportPackageBody -ThrowOnFailure
$importStatusUri = $importPackageResponse.Headers['Location']
while($importPackageResponse.StatusCode -ne 200) 
{
Start-Sleep -s 5
$importPackageResponse = Invoke-Request -Uri $importStatusUri -Method GET -ThrowOnFailure
}
$parsedImportPackageResponse = ConvertFrom-Json $importPackageResponse.Content
if(($parsedImportPackageResponse.properties.errors).Length -gt 0)
{
Write-Host "Package failed import with the following errors " + $parsedImportPackageResponse.properties.errors
}
return $parsedImportPackageResponse
}


Use the script like:

$PowerAppEnv = Get-AdminPowerAppEnvironment -Default
$PowerAppEnvName = $PowerAppEnv.EnvironmentName
$PowerApp = Get-AdminPowerApp $appTitle
$impAppResp = Import-Package -EnvironmentName $PowerAppEnvName -ImportPackageFilePath "$PathToZipFile" -ResourceName $appTitle -NewApp (-Not $PowerApp)
$impAppResp = Publish-PowerApp $appTitle

 

Helpful resources

Announcements
PA User Group

Welcome to the User Group Public Preview

Check out new user group experience and if you are a leader please create your group

MBAS Attendee Badge

Claim Your Badge & Digital Swag!

Check out how to claim yours today!

secondImage

Are Your Ready?

Test your skills now with the Cloud Skill Challenge.

Top Solution Authors
Top Kudoed Authors
Users online (52,466)