How to get a list of the managed packages (including version numbers) installed in an org?
There are a couple of routes into listing packages giving both the namespace and versions of those installed in your org via the Metadata API. In summary you have two routes, that both result in the same information...
- listMetadata call followed by retrieve call. The first is to use the 'listMetadata' operation using the InstalledPackage component type, which is a good way of listing whats in your org (this will give the namespace but not the version). You will then to explicitly request further details on the components via a 'retrieve' (explicitly listing in the package.xml those components you want). The resulting .installedPackage file contains the version info you need.
- retrieve call (with wildcards). The second option is to utilise the InstalledPackage component type in a package.xml with a wildcard *. This is the most direct route and only requires one call to the Metadata API. The resulting .installedPackage file contains namespace (in its filename) and the version info you also need.
Note: If your interested in further information on install and uninstall via Ant you might find this useful.
The following should give you all you need to decide your approach either in Java or Ant.
Take for example this view of installed packages in an org...
'listMetadata' call via Java.
Here is a slightly modified Java example from the documentation.
public void listMetadata() {
try {
ListMetadataQuery query = new ListMetadataQuery();
query.setType("InstalledPackage");
//query.setFolder(null);
double asOfVersion = 28.0;
// Assuming that the SOAP binding has already been established.
FileProperties[] lmr = metadataConnection.listMetadata(
new ListMetadataQuery[] {query}, asOfVersion);
if (lmr != null) {
for (FileProperties n : lmr) {
System.out.println("Component fullName: " + n.getFullName());
System.out.println("Component type: " + n.getType());
}
}
} catch (ConnectionException ce) {
ce.printStackTrace();
}
}
'listMetadata' call via the Salesforce Ant Migration Tool.
In this toolkit is a listMetadata Ant task that wraps the above operation to list Metadata components.
<sf:listMetadata
username="${sf.username}"
password="${sf.password}"
metadataType="InstalledPackage"/>
Gives this output...
[sf:listMetadata] ************************************************************
[sf:listMetadata] FileName: installedPackages/packagea.installedPackage
[sf:listMetadata] FullName/Id: packagea/0A3G0000000UPPRKA4
[sf:listMetadata] Manageable State: null
[sf:listMetadata] Namespace Prefix: packagea
[sf:listMetadata] Created By (Name/Id): Metadata Admin/005G0000002bhKMIAY
[sf:listMetadata] Last Modified By (Name/Id): Metadata Admin/005G0000002bhKMIAY
[sf:listMetadata] ************************************************************
[sf:listMetadata] ************************************************************
[sf:listMetadata] FileName: installedPackages/packageb.installedPackage
[sf:listMetadata] FullName/Id: packageb/0A3G0000000UPPTKA4
[sf:listMetadata] Manageable State: null
[sf:listMetadata] Namespace Prefix: packageb
[sf:listMetadata] Created By (Name/Id): Metadata Admin/005G0000002bhKMIAY
[sf:listMetadata] Last Modified By (Name/Id): Metadata Admin/005G0000002bhKMIAY
[sf:listMetadata] ************************************************************
'retrieve' call via Java.
The code linked in this help topic, shows quite a complex amount of Java code to do the 'retrieve' operation. Oddly it does not specify anything in the RetrieveRequest parameter it passes. In your case you would have to add the required packages you want to retrieve (from the listMedata) to the specifiedFiles member in this class. Then using the code in the doc parse the zip file returned to find the .installedPackage files. Quite a lof code, so since your in the world of Ant, read on...
'retrieve' call via the Salesforce Ant Migration Tool.
The Bulk Retrieve Ant target provided in the toolkit wraps the 'retrieve' call above. And also generates the package.xml internally with the wildcard on the component type you provide. This for me is the best route for you if your wanting to do this in Ant. Then utilise Ant's other tasks to read the files or roll your own.
<mkdir dir="${basedir}/installedPackages"/>
<sf:bulkRetrieve
username="${sf.username}"
password="${sf.password}"
metadataType="InstalledPackage"
retrieveTarget="${basedir}/installedPackages"/>
Results in the following...
Found the most easiest way to get package name and version numbers.
SELECT DurableId, Id, IsSalesforce,MajorVersion,MinorVersion, Name,NamespacePrefix FROM Publisher
Now its clear that we can simply query this information using SOQL. This can be further queried via API using java and used in ant.
Looks like with tooling api there is a better way to get this . You can run the below query via the tooling rest api or soap api with v41.0 and above
SELECT Id, SubscriberPackageId, SubscriberPackage.NamespacePrefix,
SubscriberPackage.Name, SubscriberPackageVersion.Id,
SubscriberPackageVersion.Name, SubscriberPackageVersion.MajorVersion,
SubscriberPackageVersion.MinorVersion,
SubscriberPackageVersion.PatchVersion,
SubscriberPackageVersion.BuildNumber
FROM InstalledSubscriberPackage
ORDER BY SubscriberPackageId
This should list all the packages installed in the org with their versions .