> For the complete documentation index, see [llms.txt](https://docs.licensespring.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.licensespring.com/sdks/tutorials/best-practices/virtualization-detection.md).

# Virtualization detection

LicenseSpring SDKs can detect virtualized, containerized, and cloud environments, and enforce a client-side policy that refuses to run when that policy is violated. This lets you tie a license to physical hardware even when raw hardware identifiers would otherwise reflect a VM rather than the host machine.

{% hint style="warning" %}
**Legacy detector deprecated (SDK v8.9.0).** The original approach described in earlier versions of this page — `ExtendedOptions::enableVMDetection`/`isVMDetectionEnabled`, `Configuration::isVM`/`getDetectedVMName`, and the separate Windows-only **`LicenseSpringVMD.dll`** ("Virtual Machine Detection" library) — is now `[[deprecated]]`. LicenseSpring no longer builds or ships that DLL, and the standalone `VMDetection` module has been removed from the SDK source tree. These calls remain only for minor-version source compatibility: on Windows they now report "no VM" unless an integrator still deploys their own copy of that DLL. The in-tree POSIX heuristic detector is unaffected and keeps running as before.

**Use `VirtualizationPolicy` for all new integrations.**
{% endhint %}

## Migrating from the legacy detector (C++ SDK)

| Legacy (deprecated)                        | Replacement                                                                                              | Notes                                                                                                                                      |
| ------------------------------------------ | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `ExtendedOptions::enableVMDetection(true)` | `ExtendedOptions::setVirtualizationPolicy(policy)`                                                       | Legacy detector needed a separate `LicenseSpringVMD.dll` on Windows. The new policy uses the cross-platform `vm_detection` module instead. |
| `ExtendedOptions::isVMDetectionEnabled()`  | `ExtendedOptions::getVirtualizationPolicy()`                                                             | Policy is enforced once at least one environment class or platform is disallowed, rather than a single on/off flag.                        |
| `Configuration::isVM()`                    | `Configuration::checkVirtualizationPolicy()`                                                             | New call throws on violation instead of returning a bool.                                                                                  |
| `Configuration::getDetectedVMName()`       | `VirtualizationPolicy::getDisallowedPlatforms()` set on the policy, matched by the `vm_detection` module | No direct 1:1 replacement, detected platform names now feed policy matching rather than a free-form getter.                                |
| `VMDNotAvailableException`                 | Handled via `VirtualizationPolicy::disallowUndetermined()` + `VirtualEnvironmentNotAllowedException`     | Missing/failed detection module is now a policy choice, not always an error.                                                               |
| `VMIsNotAllowedException`                  | Unchanged — still reflects the **server-side** "Prevent Virtual Machine" license setting                 | Distinct from the new client-side `VirtualEnvironmentNotAllowedException`.                                                                 |
| Ship `LicenseSpringVMD.dll` (Windows only) | Ship `vm_detection.dll` / `libvm_detection.so` / `libvm_detection.dylib` (all platforms)                 | Platform-specific name, loaded automatically when present alongside the app.                                                               |

## Prerequisites

You should have completed the [Getting Started](#) tutorial.

* Initialized `LicenseManager` (or `LicenseHandler`) with the appropriate settings.
* Created a `LicenseID` using either `LicenseID::fromKey` or `LicenseID::fromUser`, depending on your activation method.
* Implemented basic license management: activation and license checks.

## Detected environment classes

Rather than a single VM name, the SDK classifies environments into `VirtualEnvironment` classes. A machine can match several at once, for instance a container running inside a cloud instance.

| Class                | Covers                                                                                                                                                      |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `VirtualMachine`     | VMware, VirtualBox, QEMU/KVM, Microsoft Hyper-V, Xen Project, Parallels Desktop, Windows Virtual PC, Virtual Iron, bhyve, Project ACRN, QNX Hypervisor, UTM |
| `Container`          | Docker, LXC, OpenVZ, FreeBSD Jail, Linux containers                                                                                                         |
| `CompatibilityLayer` | Wine, WSL / WSL2                                                                                                                                            |
| `HostHypervisor`     | The machine itself exposes a hypervisor interface (can run guests)                                                                                          |
| `CloudInstance`      | AWS, Microsoft Azure, GCP, and similar                                                                                                                      |

## Configuring a policy

{% tabs %}
{% tab title="C++" %}

```cpp
VirtualizationPolicy policy;
policy.disallow(VirtualEnvironment::VirtualMachine);
policy.disallow(VirtualEnvironment::CloudInstance, false);
policy.setVMLikelihoodThreshold(VMLikelihood::Likely);
policy.disallowUndetermined(false);                        // default: allow if module is missing
policy.setDisallowedPlatforms({ "wine", "virtualbox" });   // optional, fine-grained

ExtendedOptions options;
options.setVirtualizationPolicy(policy);

std::shared_ptr<Configuration> configuration = Configuration::Create(
    EncryptStr("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"),
    EncryptStr("XXXXXXXXX-XXXXX-XXXXXXXXXXXXX_XXXXXX_XXXXXX"),
    EncryptStr("XXXXXX"),
    appName, appVersion, options);
```

{% endtab %}

{% tab title="C#" %}
Coming soon.
{% endtab %}

{% tab title="Swift" %}
Coming soon.
{% endtab %}

{% tab title="Python" %}

{% endtab %}

{% tab title="Java" %}

{% endtab %}

{% tab title="Go" %}

{% endtab %}

{% tab title="JavaScript" %}

{% endtab %}
{% endtabs %}

A default-constructed `VirtualizationPolicy` disallows nothing. Enforcement only turns on once at least one environment class or platform is disallowed.

## Deploying the detection module

Enforcement requires the LicenseSpring VM detection module alongside your application binary, loaded by its platform-specific name:

* Windows: `vm_detection.dll`
* Linux: `libvm_detection.so`
* macOS: `libvm_detection.dylib`

If the module is missing, the machine is treated as undetermined, or rejected if `disallowUndetermined(true)` is set on the policy.

## Enforcing the policy

* `Configuration::checkVirtualizationPolicy()`  - call explicitly, for example before activation.
* `License::localCheck()` - enforced automatically on every local check.

Both throw `VirtualEnvironmentNotAllowedException` when the machine violates the configured policy.

{% tabs %}
{% tab title="C++" %}

```cpp
try
{
    configuration->checkVirtualizationPolicy();
}
catch (const VirtualEnvironmentNotAllowedException &ex)
{
    // Machine violates the configured VirtualizationPolicy.
}
```

{% endtab %}

{% tab title="C#" %}
Coming soon.
{% endtab %}

{% tab title="Swift" %}
Coming soon.
{% endtab %}
{% endtabs %}

## Server-side "Prevent Virtual Machine" setting

Independent of the client-side policy above, a license can prevent activation on virtual machines through the LicenseSpring platform. Enabling **Prevent Virtual Machine** in the license settings blocks activation attempts within virtualized environments, so the software runs only on approved physical devices.

{% tabs %}
{% tab title="C++" %}

```cpp
if (license->isVMAllowed())
{
    // ...
}
```

{% endtab %}

{% tab title="C#" %}
Coming soon.
{% endtab %}

{% tab title="Swift" %}
Coming soon.
{% endtab %}
{% endtabs %}

`VMIsNotAllowedException` is thrown when this platform-side policy is violated, distinct from `VirtualEnvironmentNotAllowedException`, which reflects the client-side `VirtualizationPolicy`.

## Exceptions reference

| Exception                               | Thrown when                                                                                                             |
| --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `VirtualEnvironmentNotAllowedException` | The machine violates the client-side `VirtualizationPolicy` (`checkVirtualizationPolicy()` or `License::localCheck()`). |
| `VMIsNotAllowedException`               | The server-side license setting is violated.                                                                            |
| `VMDNotAvailableException` (deprecated) | Windows only: DLL not found, tampered with, or detection failed.                                                        |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.licensespring.com/sdks/tutorials/best-practices/virtualization-detection.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
