How-to: legacy
Read a CRM 2011 org. A CRM 2011 org has no Web API, so every other crm
command fails against it; crm legacy reaches it over a read-only SOAP
transport instead. Tested on CRM 2011 UR15 (5.0.9690.3557), Linux. See the
CLI reference for every flag.
crm legacy only reads. It sends an allowlisted set of messages (WhoAmI,
RetrieveVersion, the three metadata reads and paged RetrieveMultiple) over
NTLM, and refuses anything else (Create,
Update, Delete, Associate, Disassociate, or an unlisted request) before
it opens a connection. The reasoning is in
ADR 0031.
Create the profile
crm profile add --url https://crm.contoso.local/contoso \
--username alice --domain CONTOSO --name legacy2011
profile add tests the connection with the Web API first. When that answers 404
on an NTLM profile and the org answers RetrieveVersion over its SOAP endpoint
with a 5.x build, the profile is saved with platform: crm2011 and
read_only: true, and its output carries a platform key. Credentials resolve
as for any profile (OS keyring, then a 0600 plaintext fallback, or
--password).
A crm2011 profile is always read-only: crm profile edit legacy2011
--no-read-only refuses, with no terminal confirmation to bypass it. A server-side
read-only role is still the real boundary, so use a dedicated account with one
for any org that is not a development org: the allowlist stops the CLI from
writing, not the account from being able to.
Run the commands
crm --json legacy version --profile legacy2011
crm --json legacy whoami --profile legacy2011
legacy version returns the build string:
{ "ok": true, "data": { "version": "5.0.9690.3557" },
"meta": { "profile": "legacy2011", "url": "https://crm.contoso.local/contoso/XRMServices/2011/Organization.svc/web" } }
legacy whoami returns user_id, business_unit_id and organization_id. Both
use the standard envelope, with meta.url set to the SOAP endpoint (not a Web
API URL).
Read metadata
crm --json legacy metadata --profile legacy2011 # every entity
crm --json legacy metadata account contact --profile legacy2011 # per-entity detail
crm --json legacy metadata --option-sets --profile legacy2011 # global option sets
With no entity, data is a list of logical_name, custom and
object_type_code. With entity names, data is {"entities": [...], "errors":
[...]}, each entity carrying its attributes, relationships and option sets. The
run is continue-and-report (ADR 0007):
an entity that faults (a misspelt logical name, say) lands in errors, the other
entities still read, and the exit code is 1. --option-sets takes no entity.
Read solution components
crm --json legacy components --profile legacy2011 # every kind
crm --json legacy components web-resources processes --out ./dump --profile legacy2011
data has one list per kind plus errors. Each kind is read with a SOAP
RetrieveMultiple (FetchXML) that follows the server's paging cookie to the last
page, so a large org is read whole. The two limits it avoids: the OData v2
OrganizationData.svc caps pages at 50, and a FetchXML aggregate stops at the
server's 50,000-record limit, so no aggregate is used.
- Continue-and-report per kind. A kind that faults keeps the rows it already
read, is listed in
errors, and the next kind still runs; the exit code is 1. Under--out, a payload that cannot be written or decoded fails its kind the same way, withcode: null. An auth failure (401) or an unreachable org is not per kind: it stops the run with the standard error envelope, since every later read would fail the same way. processesare workflow definitions only (type 1), not activations or templates.- Plug-in assemblies stored on disk or in the GAC have no database binary:
each is listed with
binary: "unavailable"and abinary_reason, never skipped. --out DIRwrites web resource content, process XAML and form XML to files underDIRand replaces each payload key with<payload>_file(a path relative toDIR). Without it the payload stays inline in the JSON.
What is refused
- A v9 or cloud command on a
crm2011profile (crm entity get,crm query odata, ...) fails with exit 1 and an error namingcrm legacy. crm legacyon any other profile refuses and says it needs acrm2011profile.- A SOAP fault becomes the standard error with the fault's
ErrorCodeas hex (0x80040217maps tonot_found), so exit codes follow the same contract. A fault the request caused (a SOAPClientfault) reports status 400 and is not retryable, though SOAP sent it as HTTP 500.
Connection retries
A failure with no HTTP response (connect timeout, connection refused, a stalled TLS handshake) retries up to 4 attempts with 1, 2 and 4 second backoff, which covers an org behind a client VPN whose first connection often times out. Any HTTP response, a 500 included, is never retried, and neither is a TLS certificate failure, which fails the same way every time.
Caveats
- The transport uses the org's
/XRMServices/2011/Organization.svc/webendpoint, which accepts plain HTTP NTLM on the tested build. Microsoft documents that endpoint for web resources, not for external clients, so it is checked per org and not guaranteed. The mainOrganization.svcendpoint needs WS-Trust SPNEGO message security and is not supported. - IFD or claims authentication, CRM 4.0 and CRM 2013 or later are out of scope.