- Overview
- Installation
- Automatic Dependency Downloads
- Setup
- IAP Setup
- Other Convenience Changes
- Using StoreBroker
This information has been moved from the primary README.md since users are less likely need to need to refer to this information again once it's been followed, unlike the rest of the README content.
This page is rather long, but only because we go into great detail at each step to help avoid any potential confusion. At a high level, all you're doing is:
- Downloading the module
- Getting your credentials
- Authenticating with those credentials
- Auto-generating your PDP files.
- Auto-generating your config file and then making some minor changes to it.
The following section describes how to configure your system for use with StoreBroker, and lists the available options for installing the module contents.
The easiest way to install StoreBroker is with PowerShellGallery.
Install-Module -Name StoreBroker
If you already have it installed and want to get the latest version, you can use:
Update-Module -Name StoreBroker
If you'll be installing this on a machine that frequently gets reimaged, you may wish to first call
Set-PSRepository -Name "PSGallery" -InstallationPolicy Trusted
to trust PowerShellGallery modules and thus avoid any prompting during installation.
An alternate way to download a versioned copy of StoreBroker is to get it through NuGet. This might make sense if you're incorporating it as part of a build step.
We continue to make the NuGet available since we've provided a NuGet for StoreBroker ever since StoreBroker was released back in 2016, however now that it is available for installation via PowerShellGallery, there really isn't a compelling reason to use the NuGet installation method anymore.
Assuming you have the NuGet command-line utility installed on your machine:
$desiredPath = c:\StoreBroker # Set this to whatever location you want StoreBroker to be installed to
Push-Location -Path $desiredPath
nuget install Microsoft.Windows.StoreBroker
Push-Location -Path ".\Microsoft.Windows.StoreBroker.*\StoreBroker"
Import-Module .\StoreBroker.psd1
This will install the lastest available version of the StoreBroker module as a directory named
Microsoft.Windows.StoreBroker.<version>
, and then import the module for use.
The StoreBroker NuGet package contains only the scripts needed to use StoreBroker. For any documentation, get started with the README.md.
Note that the NuGet package installation option is a snapshot of the StoreBroker module, and is more difficult to keep up-to-date. To sync your local module with the newest package, you will need to delete the folder created above and follow the installation instructions again.
The previous two approaches allow you to download versioned snapshots of StoreBroker where the files have been digitally signed by Microsoft. An alternative approach is to simply get the module directly from GitHub (either by cloning the repo or by downloading a zip of the sources).
Since the files from GitHub are not digitially signed (we only sign them when we release to
PowerShellGallery and NuGet.org), you may need to update the
PowerShell ExecutionPolicy
on your machine to be RemoteSigned
(which means that PowerShell
scripts that are local to your machine don't need to be signed in order to execute).
From an Administrator PowerShell console, run the following command:
Set-ExecutionPolicy RemoteSigned -Force
You need to choose a folder that you're going to store the module in. We recommend choosing to
use a new sub-folder within one of the folders in your $env:PSModulePath
. By default,
even if the folder doesn't exist yet, the following path is one of those folders and is the one that
we'd recommend that you use:
Join-Path -Path ([System.Environment]::GetFolderPath('MyDocuments')) -ChildPath 'WindowsPowerShell\Modules'
If it doesn't exist yet, just go ahead and create it:
New-Item -Type Directory -Force -Path (Join-Path -Path ([System.Environment]::GetFolderPath('MyDocuments')) -ChildPath 'WindowsPowerShell\Modules\StoreBroker')
If you follow that advice, then the module will automatically be available in any PowerShell
console session implicitly. If you choose to store the module somewhere else, then you will need
to run Import-Module -Force <folder>\StoreBroker
in each new console window before any
StoreBroker command will work.
The actual module code for StoreBroker is stored in a sub-folder called "StoreBroker", hence the reason that you'd have to specify the extra "\StoreBroker" in the path of the
Import-Module
command. When storing the module within a$env:PSModulePath
folder, PowerShell just figures that out for you.
There are two options for getting the code from GitHub: cloning with get and a zip download. We recommend the cloning with git option, as it is the simplest for staying up-to-date with StoreBroker changes.
Assuming you already have git
on your machine, just run:
git clone https://github.com/microsoft/StoreBroker.git <StoreBrokerCloneFolder>
You'll then want to update your PowerShell profile to just run a git pull
on that folder
every time you open your console window in order to keep it up to date.
Your PowerShell Profile is a ps1 script that PowerShell automatically runs every time a new PowerShell console window is opened.
notepad $profile
That will open your profile. If it doesn't exist, accept Notepad's prompts to create the file. From there, just add the following:
Push-Location -Path "<StoreBrokerCloneFolder>"
git pull
Pop-Location
Download the following file to get a snapshot of the current state of the module:
https://github.com/microsoft/StoreBroker/archive/master.zip
Unzip that to the <StoreBrokerFolder>
.
Because you downloaded the file the zip, you may have to "unblock" the contents and tell your operating system that you trust the zip's contents:
Get-ChildItem -Recurse -File -Path "<StoreBrokerFolder>" | ForEach-Object { Unblock-File -Path $_.FullName }
For more information on
Unblock-File
, review its documentation
Note that the ZIP installation option is a snapshot of the StoreBroker module, and is more difficult to keep up-to-date. To sync your local module with the newest package, you will need to delete the folder created above and follow the installation instructions again.
There isn't a real action required at this point for this step -- this is more for your awareness.
StoreBroker has a dependency on dll's from the following NuGet packages:
For uploading/downloading packages
WindowsAzure.Storage v8.1.1: Microsoft.WindowsAzure.Storage.dll
Microsoft.Azure.Storage.DataMovement v0.5.1: Microsoft.WindowsAzure.Storage.DataMovement.dll
During execution of a command, when StoreBroker has need for an object from one of these dll's, if it cannot find the dll, it will automatically download nuget.exe, then download the nuget package that the assembly is in, and finally cache it for the duration of your PowerShell session. If you want to avoid this step in the future, just follow the steps that it prints out to your console window:
- Copy the downloaded assembly to your module directory
- Or copy it to a directory of your choice, and then set that directory location to
the environment variable
$global:SBAlternateAssemblyDir
.
PowerShell Tip
If you use
$global:SBAlternateAssemblyDir
and want to always have that value set when you open a PowerShell window, you can add it to your PowerShell profile. By default, the full path to your profile is automatically stored by PowerShell in$profile
. From a PowerShell console runnotepad $profile
. If Notepad informs you that the file doesn't exist, let Notepad create the profile for you. Then, just add$global:SBAlternateAssemblyDir = "<path>"
to your profile.
To initially configure StoreBroker with your Developer Account:
-
You must have an Azure Active Directory (AAD) and you must have global administrator for the directory. You can create a new Azure AD from Dev Center permission for it. If you already use Office 365 or other business services from Microsoft, you already have an AAD. Otherwise, you can create a new AAD in Dev Center for no additional charge.
-
You must associate your AAD with your Dev Center account to obtain the credentials to allow StoreBroker to access your account and perform actions on your behalf.
-
The app you want to publish must already exist. The Windows Store Submission API can only publish updates to existing applications. You can create your app in Dev Center.
-
You must have already created at least one submission for your app before you can publish an update with StoreBroker. If you have not created a submission, the Update attempt will fail.
These prerequisites come directly from the API Documentation. Refer to that documentation for additional prerequisites.
In order to use any network-facing command in this module, you need to be able to authenticate against the developer account that you are trying to modify.
You only need to perform this task once per user. You'll re-use these credentials as if they were your username and password.
First you have to get three key pieces of information:
TenantId
: This is the ID of the Azure Active Directory (AAD) connected to your developer account.ClientId
andClientSecret
: Essentially a username/password for a "user" that you create for StoreBroker to be able to use the API against your developer account on your behalf.
To get those values:
-
In Dev Center, go to your Account settings, click Manage users, and associate your organization's Dev Center account with your organization's AAD. For detailed instructions, see Manage account users.
-
In the Manage users page, click Add Azure AD applications, add the Azure AD application that represents the app or service that you will use to access submissions for your Dev Center account, and assign it the Manager role. If this application already exists in your AAD, you can select it on the Add Azure AD applications page to add it to your Dev Center account. Otherwise, you can create a new AAD application on the Add Azure AD applications page. For more information, see Add and manage Azure AD applications.
-
Return to the Manage users page, click the name of your Azure AD application to go to the application settings, and copy the Tenant ID and Client ID values.
-
Click Add new key. On the following screen, copy the Key value, which corresponds to the Client secret. You will not be able to access this info again after you leave this page, so make sure to not lose it. For more information, see the information about managing keys in Add and manage Azure AD applications.
These steps are directly from the API Documentation.
The TenantId
must be cached in every PowerShell session.
The ClientId
/ ClientSecret
can be cached, or you can opt to just be prompted every time
they are needed.
In order to cache the tenantId, call:
Set-StoreBrokerAuthentication -TenantId <tenantId>
That will cache the TenantId
for that session, and it will also prompt you for the
ClientId
and ClientSecret
so it can cache those in the same session as well.
If you would rather be prompted every time for those two values, you can call:
Set-StoreBrokerAuthentication -TenantId <tenantId> -OnlyCacheTenantId
When using Set-StoreBrokerAuthentication
, it is only caching those values for the current
PowerShell session. They can be cleared by simply closing your PowerShell window, or by calling:
Clear-StoreBrokerAuthentication
If you want to be use this module without requiring any user-interaction at the console,
it is necessary to leverage Set-StoreBrokerAuthentication -Credential
and provide
the PSCredential
object yourself.
One way to do this would be the following:
$cred = Get-Credential
- Enter your credentials (
ClientId
as the username,ClientSecret
as the password) - Now you can store the password somewhere on disk securely. Doing this will encrypt the password into a plain-text file, and only the same user logged-in to the exact same computer will be able to decrypt it.
$cred.Password | ConvertFrom-SecureString | Set-Content -Path (Join-Path -Path ([System.Environment]::GetFolderPath('MyDocuments')) -ChildPath 'clientSecret.txt')
- When you want to create the credentials yourself later on and authenticate (being sure to
replace
<tenantId>
and<clientId>
with the proper values):
$clientSecret = Get-Content -Path (Join-Path -Path ([System.Environment]::GetFolderPath('MyDocuments')) -ChildPath 'clientSecret.txt') | ConvertTo-SecureString
$cred = New-Object System.Management.Automation.PSCredential "<clientId>", $clientSecret
Set-StoreBrokerAuthentication -TenantId <tenantId> -Credential $cred
PowerShell Tip
If you want to always be automatically authenticated whenever you open a PowerShell window, you can add the code above (from Step 4) to your PowerShell profile. By default, the full path to your profile is automatically stored by PowerShell in
$profile
. From a PowerShell console runnotepad $profile
. If Notepad informs you that the file doesn't exist, let Notepad create the profile for you. Then, just add those 3 lines of code from Step 4 into your profile.
For most developers / companies, the above method of authentication is sufficient. Usually, there are only a handful of people in any company that need access to the company's Developer account or need the permissions to publish updates, so having a ClientId/ClientSecret assigned to each of them is not that big of a problem.
For larger companies (like Microsoft) where there are many different apps under the same developer account being published by many different people, having to create and manage a large number of ClientId's (and ClientSecrets) becomes a security headache.
At Microsoft, we solved this problem by creating a Proxy server for the API, and we've included all
of the code and documentation in the event that you want to do the same. When using
the Proxy, the Proxy is the only one that knows the ClientId
and ClientSecret
, and it
performs all of the API requests on behalf of the user. Then you only need to block access to the
Proxy using Windows Security Groups.
By default, the Proxy supports two levels of security: r/o (restricted to GET API requests) and
r/w (all API requests).
For more information on how to deploy your own Proxy, refer to its documentation.
If you have a Proxy up and running, then to use it, simply call:
Set-StoreBrokerAuthentication -UseProxy -ProxyEndpoint <proxyUri>
where <proxyUri>
is the base part of your Uri (like https://mystorebrokerproxy
).
That setting (being configured to use the proxy) will be stored for the duration of your session.
PowerShell Tip
If you want to always be automatically authenticated whenever you open a PowerShell window, you can add that code above to your PowerShell profile. By default, the full path to your profile is automatically stored by PowerShell in
$profile
. From a PowerShell console runnotepad $profile
. If Notepad informs you that the file doesn't exist, let Notepad create the profile for you. Then, just add those 3 lines of code from Step 4 into your profile.
To stop authenticating with the proxy, at any time simply close your PowerShell console window, or call:
Clear-StoreBrokerAuthentication
The next steps require you to know the AppId for the App you are trying to use StoreBroker with.
If you have easy access to the Dev Portal, you can get it directly from there by:
- Log in to the Dev Portal
- Select the app
- Click on App Management
- Click on App Identity
- Look towards the bottom and grab the
Store ID
that is displayed. This is yourAppId
.
Alternatively, you can find this value directly with StoreBroker by running the following and
getting the id
that is shown there (it looks like this: 0ABCDEF12345
).
That's your AppId
(replace <appName>
with all or part your app's name to limit the results):
Get-Applications -GetAll | Where-Object primaryName -like "*<appName>*" | Format-Application
If you run into issues with this command, it's possible that you're having trouble with your search
with Where-Object
. Instead, just try running this:
Get-Applications -GetAll | Format-Applications
The Windows Store Submission API does not allow for the creation of new apps. To use StoreBroker, you must have already created and published an app submission via the Dev Center web portal first. Once that happens, you should be able to continue using StoreBroker as described.
A major benefit of using the StoreBroker to do your updates, is that it can submit all of the metadata (app description, feature list, captions, screenshots, etc...) automatically. However, in order to create the "payload" (json and zip) required to use the API, it needs to have a uniform way of getting that metadata content.
Enter the PDP XML format. PDP stands for Product Description Page, and the PDP.xml file is a schema that Microsoft uses internally to store all of the localizable metadata for an application. That XML file then gets localized into every language that the application has a Store listing for.
You don't have to use PDP files to store your metadata in the event that you already have a different method of localization. However, if you don't choose to use the PDP format, then you will have to write your own version of
New-SubmissionPackage
in order to create the payload (json and zip) that the other StoreBroker commands require.
You can read PDP.md for greater detail on PDP files. Right now, we just need to get you started by generating your app's PDP files based on your current published submission.
.\Extensions\ConvertFrom-ExistingSubmission.ps1 -AppId <appId> -Release <release> -PdpFileName <pdpFileName> -OutPath <outPath>
Where:
-
<appId>
is your app's ID. -
<release>
is the name of this release. Many teams name their releases asYYMM
(depending on how often they release). This value will be added to each of the PDP's that are generated, and will impact the expected location of the screenshots being referenced. More on that folder structure in the next section. -
<pdpFileName>
- The name you want to give to the PDP files -- people often usePDP.xml
. -
<outPath>
- The folder that the PDP files should be stored in. Langcode sub-folders will be created for storing the PDP files, asNew-SubmissionPackage
depends on that folder structure for determining what langcode a PDP file is associated with.
The API does not provide any ability to download the existing screenshots for an application. When the script completes, it will tell you what images it expects you to gather up manually, and the folder structure that you should be putting them in to.
Every project should have its own StoreBroker config file. The config file has two parts to it:
- The top part lets you specify parameters to
New-SubmissionPackage
that remain static, so that you don't have to specify them at the commandline each time. - The bottom part lets you specify Application submission properties that generally remain static between submissions and aren't localized.
-
Now run
New-StoreBrokerConfigFile -Path (Join-Path -Path ([System.Environment]::GetFolderPath('Desktop')) -ChildPath 'SBConfig.json') -AppId <AppId>
, substituting in your AppId, and that will generate a pre-populated config file to your desktop, based on the current configuration of your app in the Store. (Feel free to name this file whatever you want). -
Once you have the config, review all of the app properties at the bottom half of the file. These are the values for these properties as they are configured for your app in the Store today. Some users have realized that the values in the Store (and thus in this file) are not what they expected, so it's worth checking them here and fixing them if need be. (If you do change any of these properties, you'll need to use the appropriate switch to
Update-ApplicationSubmission
later on to make sure that your changes are applied). -
Now you need to set the
New-SubmissionPackage
parameter values at the top half of the file. These parameter values are very well documented within the config file, but here's an additional crib sheet for what you'll likely want to change:i.
PDPRootPath
andRelease
are related - If you'll be getting the localized PDP files dynamically during your build from a localization service/process, leave both blank and only specifyPDPRootPath
at the commandline so that you can use environment variables to reference the local path, and move on to "ii".Otherwise, it's necessary for you to provide the path that the PDP's can be found. You'll do this with a combination of these two config values. The general idea is that you have a root folder for PDP's that contains sub-folders named after each different release. The PDP's would actually be contained in the release-named sub-folders. Let's assume that your PDP files can be found here:
\\my\file\share\1606\ en-us\PDP.xml fr-fr\PDP.xml es-es\PDP.xml
In that scenario, you can either do this:
PDPRootPath: \\my\file\share\1606\ Release: <null>
or
PDPRootPath: \\my\file\share\ Release: 1606
Both methods result in accessing the files from the same location. It just depends on how you intend to maintain your PDP files. If the same share location will always be updated with the most recent PDP's, use the first method. If you will be using release-named sub-folders to organize your PDP's, then you may wish to use the second option, and you can either choose to update your config file with the new release name every time it changes, or provide it at the commandline instead. Your choice.
Remember that you have to escape any backslashes used in the config file.
ii.
PDPInclude
- Update this to have the name (or names) of the PDP files that you want to consume. If we were following the example above, we'd specifyPDP.xml
here.iii.
PDPExclude
- For most people, you'll want to leave this empty.iv.
LanguageExclude
- Add languages to here if there are language sub-folders inPDPRootPath
that your app doesn't support. We've added "default" in there for you since that's commonly in the loc output for Microsoft builds, but doesn't represent a real language (these sub-folders need to use the same lang-codes that the Store uses).v.
ImagesRootPath
- Point this to where your app screenshots are stored. Please note that this should point to a root location for the screenshots, and we expect there to be sub-folders for each release within here.If you had a folder structure like this:
\\share\MyApp\Images\201605\en-us\ Screenshot1.png Screenshot2.png \\share\MyApp\Images\201605\fr-fr\ Screenshot1.png Screenshot2.png
you would specify
\\share\MyApp\Images\
as yourImagesRootPath
, and your PDP file would set201605
as theRelease
attribute (at the very top of the file).New-SubmissionPackage
would then combine those together at runtime to get the full path to these images.Remember that you have to escape any backslashes used in the config file.
vi.
AppxPath
- Follow the guidance in the help comments to correctly specify where the appx packages for your app will be found. Since this is likely part of your build output, you'll likely specify this at the commandline with environment variables, as opposed to setting a path in the config file.vii.
OutPath
- Update this to be where you want it to drop the .json/.zip bundle. If this will be a location that uses an environment variable, then you'll need to specify it at the commandline instead.viii.
OutName
- Update this to specify the root name for your json/zip files. -
[Optional] Check this file in side-by-side with your code for version control support.
The prerequisites and authentication steps are identical here as they are for applications (as explained above), and so they will not be repeated here.
The next steps require you to know the IapId for the In-App Product ("add on") that you are trying to use with StoreBroker.
To run the next command, you'll need your AppId from above.
Run the following and get the ID
that is shown there (it looks like this: 0ABCDEF12345
).
That's your IapId
.
Get-ApplicationInAppProducts -AppId <appId> -GetAll | Format-ApplicationInAppProducts
The Windows Store Submission API does not currently support IAP's that are "Store Managed Consumables." You will not be able to use StoreBroker to manage that type of IAP until the API has been updated. Additionally, if your application has one of those IAPS's, the above command will fail with a
409
error. In this scenario, you'll need to manually get theIapId
by copying it from the URL of the Dev Center web portal when trying to edit that IAP.
A major benefit of using the StoreBroker to do your updates, is that it can submit all of the metadata (title, description, icons, etc...) automatically. However, in order to create the "payload" (json and zip) required to use the API, it needs to have a uniform way of getting that metadata content.
Enter the PDP XML format. PDP stands for Product Description Page, and the PDP.xml file is a schema that Microsoft uses internally to store all of the localizable metadata for an In-App Product. That XML file then gets localized into every language that the application has a Store listing for.
You don't have to use PDP files to store your metadata in the event that you already have a different method of localization. However, if you don't choose to use the PDP format, then you will have to write your own version of
New-InAppProductSubmissionPackage
in order to create the payload (json and zip) that the other StoreBroker commands require.
You can read PDP.md for greater detail on PDP files. Right now, we just need to get you started by generating your IAP's PDP files based on your current published (or pending) submission.
.\Extensions\ConvertFrom-ExistingIapSubmission.ps1 -IapId <iapId> -Release <release> -PdpFileName <pdpFileName> -OutPath <outPath>
Where:
-
<iapId>
is your IAP's ID. -
<release>
is the name of this release. Many teams name their releases asYYMM
(depending on how often they release). This value will be added to each of the PDP's that are generated, and will impact the expected location of the screenshots being referenced. More on that folder structure in the next section. -
<pdpFileName>
- The name you want to give to the PDP files -- people often usePDP.xml
. -
<outPath>
- The folder that the PDP files should be stored in. Langcode sub-folders will be created for storing the PDP files, asNew-InAppProductSubmissionPackage
depends on that folder structure for determining what langcode a PDP file is associated with.
The API does not provide any ability to download the existing icons for an IAP listing. When the script completes, it will tell you what icons it expects you to gather up manually, and the folder structure that you should be putting them in to.
Every IAP should have its own StoreBroker config file. The config file has two parts to it:
- The top part lets you specify parameters to
New-InAppProductSubmissionPackage
that remain static, so that you don't have to specify them at the commandline each time. - The bottom part lets you specify In-App Product submission properties that generally remain static between submissions and aren't localized.
-
Now run
New-StoreBrokerInAppProductConfigFile -Path (Join-Path -Path ([System.Environment]::GetFolderPath('Desktop')) -ChildPath 'SBConfig.json') -IapId <IapId>
, substituting in your IapId, and that will generate a pre-populated config file to your desktop, based on the current configuration of your IAP in the Store. (Feel free to name this file whatever you want). -
Once you have the config, review all of the properties at the bottom half of the file. These are the values for these properties as they are configured for your IAP in the Store today. Some users have realized that the values in the Store (and thus in this file) are not what they expected, so it's worth checking them here and fixing them if need be. (If you do change any of these properties, you'll need to use the appropriate switch to
Update-InAppProductSubmission
later on to make sure that your changes are applied). -
Now you need to set the
New-InAppProductSubmissionPackage
parameter values at the top half of the file. These parameter values are very well documented within the config file, but for more detailed information on what you'll likely want to change, refer to step 3 in Config Setup Steps above. -
[Optional] Check this file in side-by-side with your code for version control support.
Well, you did it. You're now fully setup to start using StoreBroker.
Congratulations!
While not required, there are other things that you can do to make your usage even easier.
- Global variable for your AppId: You need to provide your
appId
quite a bit when using StoreBroker. Instead of having to remember it or constantly look it up, why not just create a global variable for it in your$profile
so that you can just refer to it by name with tab-completion? Just runnotepad $profile
to open up your profile, and add the following:
$global:appName = '<appId>'
set appName
to whatever you want, and replace <appId>
with your actual
appId. Then, in any new PowerShell console window, you can just start
typing $ap<tab>
and it should auto-complete the variable name for you (no need to start with
$global:
).
- Global variable for other Ids or paths: Following similar logic as above, you might want to create global variables to reference other common Ids (flightId, IapId), paths (like the path to your StoreBroker config file), etc...
To learn how to use StoreBroker now that it's all setup, head on over to README.md.