# Scripting API for packages

> Learn how you can use C# to manage packages in your projects.

You can use the Package Manager scripting API to interact with the Package Manager using C# scripts. For example, you might want to install a specific package or version depending on the platform of the target machine.

Using the scripting API for package management relies on the [PackageManager.Client](/engine/6000.5/script-reference/unityeditor/packagemanager/client.md) class. Use this class to find packages, browse the list of packages, and install and uninstall packages through scripting.

Another important class is [PackageManager.PackageInfo](/engine/6000.5/script-reference/unityeditor/packagemanager/packageinfo.md), which contains the state of a package, including metadata obtained from the package manifest and the registry. For example, you can get a [list of versions](/engine/6000.5/script-reference/unityeditor/packagemanager/versionsinfo.md) available for the package, or the [list of any errors](/engine/6000.5/script-reference/unityeditor/packagemanager/packageinfo/errors.md) that might occur while locating or installing the package.

## Adding a package to the project

This example demonstrates how to use the [Client](/engine/6000.5/script-reference/unityeditor/packagemanager/client.md) class to install or add a package to the project.

You can use [Client.Add](/engine/6000.5/script-reference/unityeditor/packagemanager/client/add.md) to add a package. When you call the `Client.Add` method, you can specify just the package name, or the name with a specific version. For example, using `Client.Add("com.unity.textmeshpro")` installs (or updates to) the latest version of the TextMesh Pro package. Using `Client.Add("com.unity.textmeshpro@1.3.0")` installs version 1.3.0 of the TextMesh Pro package.

The `Client.Add` method returns an [AddRequest](/engine/6000.5/script-reference/unityeditor/packagemanager/requests/addrequest.md) instance, which you can use to get the status, any errors, or a [Request](/engine/6000.5/script-reference/unityeditor/packagemanager/requests/request1/result.md) response that contains the [PackageInfo](/engine/6000.5/script-reference/unityeditor/packagemanager/packageinfo.md) information for the newly added package.

```lang-cs
using System;
using UnityEditor;
using UnityEditor.PackageManager.Requests;
using UnityEditor.PackageManager;
using UnityEngine;

namespace Unity.Editor.Example {
   static class AddPackageExample
   {
       static AddRequest Request;

       [MenuItem("Window/Add Package Example")]
       static void Add()
       {
           // Add a package to the project
           Request = Client.Add("com.unity.textmeshpro");
           EditorApplication.update += Progress;
       }

       static void Progress()
       {
           if (Request.IsCompleted)
           {
               if (Request.Status == StatusCode.Success)
                   Debug.Log("Installed: " + Request.Result.packageId);
               else if (Request.Status >= StatusCode.Failure)
                   Debug.Log(Request.Error.message);

               EditorApplication.update -= Progress;
           }
       }
   }
}
```

## Browsing the list of packages in a project

This example demonstrates how to use the [Client](/engine/6000.5/script-reference/unityeditor/packagemanager/client.md) class to iterate over the packages in the project.

The [Client.List](/engine/6000.5/script-reference/unityeditor/packagemanager/client/list.md) method returns a [ListRequest](/engine/6000.5/script-reference/unityeditor/packagemanager/requests/listrequest.md) instance. Use the `ListRequest` instance to get the status of the List operation, any errors, or a [Request](/engine/6000.5/script-reference/unityeditor/packagemanager/requests/request1/result.md) response that contains the [PackageCollection](/engine/6000.5/script-reference/unityeditor/packagemanager/packagecollection.md) which you can iterate.

```lang-cs
using System;
using UnityEditor;
using UnityEditor.PackageManager.Requests;
using UnityEditor.PackageManager;
using UnityEngine;

namespace Unity.Editor.Example {
   static class ListPackageExample
   {
       static ListRequest Request;

       [MenuItem("Window/List Package Example")]
       static void List()
       {
           Request = Client.List();    // List packages installed for the project
           EditorApplication.update += Progress;
       }

       static void Progress()
       {
           if (Request.IsCompleted)
           {
               if (Request.Status == StatusCode.Success)
                   foreach (var package in Request.Result)
                       Debug.Log("Package name: " + package.name);
               else if (Request.Status >= StatusCode.Failure)
                   Debug.Log(Request.Error.message);

               EditorApplication.update -= Progress;
           }
       }
   }
}
```

## Embedding a package in the project

This example demonstrates how to use the [Client](/engine/6000.5/script-reference/unityeditor/packagemanager/client.md) class to [embed](/engine/6000.5/manual/packages-list/dependencies-lp/upm-embed.md) one of the packages already installed in your project. The main method is the [Client.Embed](/engine/6000.5/script-reference/unityeditor/packagemanager/client/embed.md) method, which makes a copy of the package and stores it under the `Packages` folder of your project.

The [Client.Embed](/engine/6000.5/script-reference/unityeditor/packagemanager/client/embed.md) method returns an [EmbedRequest](/engine/6000.5/script-reference/unityeditor/packagemanager/requests/embedrequest.md) instance. Use the `EmbedRequest` instance to get the status of the Embed operation, any errors, or a [Request](/engine/6000.5/script-reference/unityeditor/packagemanager/requests/request1/result.md) response that contains the [PackageInfo](/engine/6000.5/script-reference/unityeditor/packagemanager/packageinfo.md) information for the newly embedded package.

This example also uses the [Client.List](/engine/6000.5/script-reference/unityeditor/packagemanager/client/list.md) method to access the collection of packages currently installed in your project. The method in the example picks out the first one that's neither embedded nor built-in.

The [Client.List](/engine/6000.5/script-reference/unityeditor/packagemanager/client/list.md) method returns a [ListRequest](/engine/6000.5/script-reference/unityeditor/packagemanager/requests/listrequest.md) instance. Use the `ListRequest` instance to get the status of the List operation, any errors, or a [Request](/engine/6000.5/script-reference/unityeditor/packagemanager/requests/request1/result.md) response that contains the [PackageCollection](/engine/6000.5/script-reference/unityeditor/packagemanager/packagecollection.md) which you can iterate.

```lang-cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.PackageManager.Requests;
using UnityEditor.PackageManager;
using UnityEngine;

namespace Unity.Editor.Example
{
    static class EmbedPackageExample
    {
        static String targetPackage;
        static EmbedRequest Request;
        static ListRequest LRequest;

        [MenuItem("Window/Embed Package Example")]
        static void GetPackageName()
        {
            // First get the name of an installed package
            LRequest = Client.List();
            EditorApplication.update += LProgress;
        }

        static void LProgress()
        {
            if (LRequest.IsCompleted)
            {
                if (LRequest.Status == StatusCode.Success)
                {
                    foreach (var package in LRequest.Result)
                    {
                        // Only retrieve packages that are currently installed in the
                        // project (and are neither Built-In nor already Embedded)
                        if (package.isDirectDependency && package.source
                            != PackageSource.BuiltIn && package.source
                            != PackageSource.Embedded)
                        {
                            targetPackage = package.name;
                            break;
                        }
                    }

                }
                else
                    Debug.Log(LRequest.Error.message);

                EditorApplication.update -= LProgress;

                Embed(targetPackage);

            }
        }

        static void Embed(string inTarget)
        {
            // Embed a package in the project
            Debug.Log("Embed('" + inTarget + "') called");
            Request = Client.Embed(inTarget);
            EditorApplication.update += Progress;

        }

        static void Progress()
        {
            if (Request.IsCompleted)
            {
                if (Request.Status == StatusCode.Success)
                    Debug.Log("Embedded: " + Request.Result.packageId);
                else if (Request.Status >= StatusCode.Failure)
                    Debug.Log(Request.Error.message);

                EditorApplication.update -= Progress;
            }
        }
    }
}
```

{ /*  @TODO: Don't backport this section to 2019.4  */ }

## Package Manager events

Use the [Events](/engine/6000.5/script-reference/unityeditor/packagemanager/events.md) class to register an event handler with the Package Manager. The [Events](/engine/6000.5/script-reference/unityeditor/packagemanager/events.md) class contains two events you can subscribe to, which the Package Manager raises at these points:

* Immediately before the Package Manager changes the list of dependencies ([registeringPackages](/engine/6000.5/script-reference/unityeditor/packagemanager/events/registeringpackages.md))
* After the Package Manager imports and compiles the changed list of package dependencies ([registeredPackages](/engine/6000.5/script-reference/unityeditor/packagemanager/events/registeredpackages.md))

The following examples demonstrate how to use both of these events.

### Example of using the registeringPackages event

```lang-cs
using UnityEditor.PackageManager;
using UnityEngine;

namespace Unity.Editor.Example
{
    public class EventSubscribingExample_RegisteringPackages
    {
        public EventSubscribingExample_RegisteringPackages()
        {
            // Subscribe to the event using the addition assignment operator (+=).
            // This executes the code in the handler whenever the event is fired.
            Events.registeringPackages += RegisteringPackagesEventHandler;
        }

        // The method is expected to receive a PackageRegistrationEventArgs event argument.
        void RegisteringPackagesEventHandler(PackageRegistrationEventArgs packageRegistrationEventArgs)
        {
            Debug.Log("The list of registered packages is about to change!");

           foreach (var addedPackage in packageRegistrationEventArgs.added)
            {
                Debug.Log($"Adding {addedPackage.displayName}");
            }

            foreach (var removedPackage in packageRegistrationEventArgs.removed)
            {
                Debug.Log($"Removing {removedPackage.displayName}");
            }

            // The changedFrom and changedTo collections contain the packages that are about to be updated.
            // Both collections are guaranteed to be the same size with indices matching the same package name.
            for (int i = 0; i <= packageRegistrationEventArgs.changedFrom.Count; i++)
            {
                var oldPackage = packageRegistrationEventArgs.changedFrom[i];
                var newPackage = packageRegistrationEventArgs.changedTo[i];

                Debug.Log($"Changing ${oldPackage.displayName} version from ${oldPackage.version} to ${newPackage.version}");
            }
        }
    }
}
```

### Example of using the registeredPackages event

```lang-cs
using UnityEditor;
using UnityEditor.PackageManager;
using UnityEngine;

namespace Unity.Editor.Example
{
    public class EventSubscribingExample_RegisteredPackages
    {
        // You must use '[InitializeOnLoadMethod]' or '[InitializeOnLoad]' to subscribe to this event.
        [InitializeOnLoadMethod]
        static void SubscribeToEvent()
        {
            // This causes the method to be invoked after the Editor registers the new list of packages.
            Events.registeredPackages += RegisteredPackagesEventHandler;
        }

        static void RegisteredPackagesEventHandler(PackageRegistrationEventArgs packageRegistrationEventArgs)
        {
            // Code executed here can safely assume that the Editor has finished compiling the new list of packages
            Debug.Log("The list of registered packages has changed!");
        }
    }
}
```
