Ambiente chiuso, nessun Internet, ma serve usare i cmdlet AD su un server membro? In questa guida pratica spostiamo e importiamo correttamente il modulo ActiveDirectory di PowerShell dal Domain Controller, evitando l’errore “The system cannot find the file specified” e garantendo piena compatibilità anche in scenari PS 7.
Panoramica del problema
In infrastrutture isolate può capitare di dover amministrare AD da un server membro che non dispone del modulo ActiveDirectory
. La tentazione più comune è copiare una o due DLL (per esempio Microsoft.ActiveDirectory.Management.dll
) o l’assembly “Microsoft.ActiveDirectory.Management” privo di estensione, ma non basta: il sistema di caricamento dei moduli di PowerShell richiede l’intera struttura del modulo (manifest .psd1
, script .psm1
, dipendenze binarie, risorse di lingua, file guida), collocata in un percorso riconosciuto dal PSModulePath. In assenza di questi requisiti, Import-Module ActiveDirectory
fallisce con “The system cannot find the file specified”.
Concetti chiave da sapere in 60 secondi
- PSModulePath: è la lista di cartelle in cui PowerShell cerca i moduli. Verificalo con
$env:PSModulePath -split ';'
. Se il modulo non è in uno di questi percorsi, non verrà trovato. - Struttura del modulo: la cartella del modulo
ActiveDirectory
include almenoActiveDirectory.psd1
,ActiveDirectory.psm1
, DLL, sottocartelle di risorse (per esempioen-US
), help. - Architettura della sessione: su sistemi x64 esistono PowerShell a 64 e a 32 bit. Avvia sempre la sessione x64 per evitare incongruenze con la copia del modulo da
System32
. - Compatibilità PS 7: il modulo
ActiveDirectory
è nato per Windows PowerShell 5.1 (Full .NET Framework). Con PS 7+ usa-UseWindowsPowerShell
, oppure un modulo compatibile specifico. - RSAT: il modulo AD fa parte degli strumenti di amministrazione remota. Offline si può installare da CAB/FoD o “prestare” dal DC copiando l’intera cartella del modulo.
Soluzione operativa (riassunto)
Passo | Azione | Note utili |
---|---|---|
Individuare | Sul DC, localizza l’intera cartella del modulo (C:\Windows\System32\WindowsPowerShell\v1.0\Modules\ActiveDirectory ). | Contiene manifest (ActiveDirectory.psd1 ), script (.psm1 ), DLL, risorse, help. |
Copiare | Trasferisci la cartella ActiveDirectory sul server di destinazione in uno dei percorsi di PSModulePath (es. C:\Program Files\WindowsPowerShell\Modules\ ). | La copia dell’intera cartella evita errori per file mancanti. |
Verificare permessi | Accertati che l’account che importerà il modulo abbia almeno lettura sulla nuova cartella e sui file. | In caso di dubbi, avvia PowerShell “Esegui come amministratore”. |
Controllare disponibilità | Esegui Get-Module -ListAvailable ActiveDirectory . | Conferma che il motore di ricerca moduli vede correttamente la cartella. |
Importare | Import-Module ActiveDirectory (oppure specifica il percorso completo se la cartella non è nel PSModulePath). | Aggiungi -Verbose per log dettagliati. |
Risolvere errori | Controlla struttura file, versioni .NET/PowerShell, log di errore ($Error ) o Event Viewer. | Vedi la sezione “Troubleshooting avanzato”. |
Procedura dettagliata passo–passo
Preparazione sul Domain Controller (sorgente)
- Apri Windows PowerShell 64 bit come amministratore.
- Individua la cartella del modulo:
$modulePath = 'C:\Windows\System32\WindowsPowerShell\v1.0\Modules\ActiveDirectory' Test-Path $modulePath
- (Opzionale) Comprimi per il trasferimento:
$zip = 'C:\Temp\ActiveDirectory-module.zip' Compress-Archive -Path "$modulePath\*" -DestinationPath $zip -Force
- Trasferisci il contenuto sul server membro usando il canale disponibile (copia offline, USB, condivisione interna).
Installazione sul server membro (destinazione)
- Scegli un percorso di moduli valido. I più comuni:
$env:PSModulePath -split ';'
Se possibile, preferisciC:\Program Files\WindowsPowerShell\Modules\
(per tutti gli utenti) e crea o estrai qui una cartellaActiveDirectory
. - Estrai o copia la cartella
ActiveDirectory
:$dest = 'C:\Program Files\WindowsPowerShell\Modules\ActiveDirectory' New-Item -ItemType Directory -Path $dest -Force | Out-Null Copia ricorsiva preservando struttura e timestamp Copy-Item -Path 'X:\Trasferimento\ActiveDirectory\*' -Destination $dest -Recurse -Force
- (Consigliato) Sblocca i file per evitare blocchi dovuti a metadati di zona:
Get-ChildItem $dest -Recurse | Unblock-File
- Verifica che il modulo sia visibile:
Get-Module -ListAvailable ActiveDirectory | Select-Object Name, Version, Path
- Importa il modulo:
Import-Module ActiveDirectory -Verbose
- Test rapido di funzionamento:
Get-Command -Module ActiveDirectory | Measure-Object Get-ADDomain | Format-List Name, DomainControllersContainer, PDCEmulator
Perché non basta copiare la sola DLL
Il modulo ActiveDirectory
è un modulo composito. Il manifest (.psd1
) definisce versione, dipendenze e file esportati; lo script di modulo (.psm1
) inizializza alias, funzioni, caricamenti di assembly; le DLL implementano i cmdlet; le cartelle en-US
/altre lingue contengono risorse e help. Copiarne una parte tronca le dipendenze e interrompe la risoluzione del modulo, causando l’errore di file mancante o di assembly non trovato.
Compatibilità: Windows PowerShell 5.1 vs PowerShell 7+
- Windows PowerShell 5.1 (Full .NET Framework): modulo supportato nativamente. Segui la procedura standard.
- PowerShell 7/7.2+ (.NET 6/7): carica il modulo tramite sessione di compatibilità Windows PowerShell:
Import-Module ActiveDirectory -UseWindowsPowerShell -Verbose in alternativa, crea la sessione compat: $session = New-PSSession -UseWindowsPowerShell Import-Module ActiveDirectory -PSSession $session
Se la tua organizzazione utilizza il modulo ActiveDirectory.Preview o equivalenti compatibili, installali/offline e preferiscili ove documentato.
Alternative offline basate su RSAT/Features
Se hai a disposizione i pacchetti RSAT/Features on Demand in rete interna o su supporto rimovibile, puoi installare il modulo senza “prestare” la cartella dal DC.
# Windows Server (Core/Full)
Add-WindowsFeature RSAT-AD-PowerShell # oppure: Install-WindowsFeature RSAT-AD-PowerShell
Windows 10/11 OFFLINE (immagine montata)
DISM /Image:D:\Mount /Add-Capability /CapabilityName:Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0
Windows 10/11 OFFLINE (sistema in esecuzione, con sorgente FoD locale)
DISM /Online /Add-Capability /CapabilityName:Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0 /Source:D:\FoD /LimitAccess
Queste opzioni sono ideali quando la conformità impone che i binari provengano da immagini firmate ufficiali.
Best practice di posizionamento e variabili d’ambiente
- Percorsi standard:
C:\Program Files\WindowsPowerShell\Modules
(tutti gli utenti)~\Documents\WindowsPowerShell\Modules
(solo utente corrente)C:\Windows\System32\WindowsPowerShell\v1.0\Modules
(di sistema)
- Evitare percorsi “esotici”: se metti la cartella altrove, aggiungi il percorso a
PSModulePath
in ambiente utente o sistema:$extra = 'D:\ModuliPersonalizzati' [Environment]::SetEnvironmentVariable( 'PSModulePath', "$($env:PSModulePath);$extra", 'Machine' )
- Sessione 64 bit: assicurati che la PowerShell usata sia x64:
[Environment]::Is64BitProcess
Se restituisceFalse
, stai usando la console a 32 bit (SysWOW64) e potresti non vedere il modulo copiato sottoSystem32
.
Sicurezza e Execution Policy
In ambienti chiusi spesso l’esecuzione è limitata. Verifica e, se necessario, allinea le policy:
Get-ExecutionPolicy -List
Sblocca file contrassegnati come scaricati:
Get-ChildItem 'C:\Program Files\WindowsPowerShell\Modules\ActiveDirectory' -Recurse | Unblock-File
(Facoltativo e secondo policy) Esegui come amministratore per bypass temporaneo nella sessione:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process -Force
Troubleshooting avanzato
Errore: “The system cannot find the file specified”
Causa tipica: cartella incompleta, percorso fuori da PSModulePath, architettura errata, file bloccati.
- Verifica struttura:
Get-ChildItem 'C:\Program Files\WindowsPowerShell\Modules\ActiveDirectory' -Recurse | Select-Object FullName
- Controlla che il manifest esista:
Test-Path 'C:\Program Files\WindowsPowerShell\Modules\ActiveDirectory\ActiveDirectory.psd1'
- Abilita logging verboso:
Import-Module ActiveDirectory -Verbose
- Traccia il caricamento dei moduli:
Trace-Command -Name Module -Expression { Import-Module ActiveDirectory } -PSHost
- Esamina l’ultimo errore in dettaglio:
$err = $Error[0] $err | Format-List * -Force $err.Exception | Format-List * -Force
Errore: “Could not load file or assembly …”
Causa: dipendenza binaria non trovata o mismatch di versione .NET/architettura.
- Conferma PowerShell x64 e .NET Framework aggiornato.
- Assicurati di aver copiato tutta la cartella, incluse eventuali sottocartelle di
Microsoft.IdentityModel
o risorse.
Il modulo non compare in Get-Module -ListAvailable
- Ispeziona i percorsi effettivi:
($env:PSModulePath -split ';') | ForEach-Object { $; Get-ChildItem $ -Directory -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName }
- Se la cartella è in un percorso personalizzato, estendi
PSModulePath
come mostrato sopra.
PowerShell 7: cmdlet Get-AD*
non funzionano
- Importa tramite compatibilità:
Import-Module ActiveDirectory -UseWindowsPowerShell
- In scenari restrittivi, crea una funzione wrapper che apra una runspace WinPS dedicata per i cmdlet AD.
Permessi e privilegi
Per importare il modulo non servono privilegi elevati; tuttavia alcuni cmdlet AD richiedono diritti amministrativi di dominio o deleghe specifiche. Se l’importazione riesce ma i cmdlet falliscono con “Access is denied”, verifica l’account usato e l’UAC.
Verifiche funzionali dopo l’import
- Elenco cmdlet disponibili:
Get-Command -Module ActiveDirectory | Sort-Object Name
- Lettura oggetti base:
Get-ADDomainController -Discover Get-ADForest | Select-Object Name, Domains
- Query su utenti (in sola lettura):
Get-ADUser -Filter * -SearchBase "CN=Users,DC=contoso,DC=local" -ResultSetSize 5 | Select-Object SamAccountName, Enabled
Automazione: script “copia & verifica”
Per ridurre gli errori manuali, ecco uno script riutilizzabile che copia il modulo in modo sicuro e ne convalida la disponibilità.
param(
[Parameter(Mandatory=$true)]
[string]$SourcePath, # es: \\DC1\Share\ActiveDirectory
[string]$TargetRoot = "C:\Program Files\WindowsPowerShell\Modules",
[switch]$Force
)
$ErrorActionPreference = 'Stop'
function Test-ADModulePath {
param([string]$Path)
$required = @(
(Join-Path $Path 'ActiveDirectory.psd1'),
(Join-Path $Path 'ActiveDirectory.psm1')
)
return ($required | ForEach-Object { Test-Path $_ }) -notcontains $false
}
$target = Join-Path $TargetRoot 'ActiveDirectory'
if (Test-Path $target -and -not $Force) {
Write-Host "Il percorso $target esiste già. Usa -Force per sovrascrivere." -ForegroundColor Yellow
} else {
New-Item -ItemType Directory -Path $target -Force | Out-Null
Copy-Item -Path (Join-Path $SourcePath '*') -Destination $target -Recurse -Force
Get-ChildItem $target -Recurse | Unblock-File
}
if (-not (Test-ADModulePath -Path $target)) {
throw "Struttura modulo incompleta in $target"
}
$paths = $env:PSModulePath -split ';'
if ($paths -notcontains $TargetRoot) {
[Environment]::SetEnvironmentVariable('PSModulePath', "$($env:PSModulePath);$TargetRoot", 'Machine')
Write-Host "Aggiunto $TargetRoot a PSModulePath (Machine). Riapri PowerShell." -ForegroundColor Cyan
}
Import-Module ActiveDirectory -Verbose
Write-Host "Import riuscito. Versione:" -ForegroundColor Green
(Get-Module ActiveDirectory).Version
Aggiornamento della guida in ambienti offline
La documentazione dei cmdlet può essere importata senza Internet usando Save-Help
su una macchina connessa e Update-Help -SourcePath
nella rete isolata.
# Su macchina connessa:
$dest = 'D:\HelpCache\ActiveDirectory'
Save-Help -Module ActiveDirectory -DestinationPath $dest -Force
Intranet/offline:
Update-Help -Module ActiveDirectory -SourcePath \intranet\HelpCache\ActiveDirectory -Force
Checklist finale (da tenere a portata di mano)
- Hai copiato l’intera cartella
ActiveDirectory
dal DC? - La cartella è in un percorso PSModulePath valido per la sessione corrente?
- La sessione è x64 e l’Execution Policy non blocca i file?
- Get-Module -ListAvailable mostra il modulo e Import-Module va a buon fine con
-Verbose
? - Su PS 7, stai usando -UseWindowsPowerShell?
- Se disponibile, hai valutato l’installazione via RSAT/FoD offline per coerenza di build e firma?
FAQ operative
Posso copiare il modulo da un server che non è un DC?
Sì, purché il server abbia installato RSAT-AD-PowerShell con la stessa architettura e una versione compatibile con i tuoi sistemi.
Serve riavviare dopo la copia?
No. Solo se modifichi PSModulePath
a livello di sistema potresti dover riaprire la console perché la variabile venga ricaricata.
La versione del modulo deve essere identica a quella del DC?
Non necessariamente, ma è consigliabile allineare alle build dell’ambiente per evitare differenze di comportamento dei cmdlet.
Import-Module funziona, ma i cmdlet falliscono con errori di rete.
Verifica connettività verso i DC e lo stato del servizio AD Web Services sul/i controller.
Voglio distribuire il modulo su più server.
Automatizza con lo script proposto e una share interna con controllo di versione; valuta la firma dei file e un ciclo di approvazione.
Conclusioni
La chiave del successo in ambienti offline è rispettare la struttura del modulo e collocarlo in un percorso valido. Evita copie parziali di DLL e punta a una procedura ripetibile: copia completa della cartella ActiveDirectory
, sblocco dei file, verifica in Get-Module -ListAvailable
, import con -Verbose
. Per scenari moderni con PS 7, sfrutta la compatibilità UseWindowsPowerShell o moduli ad hoc. Quando possibile, preferisci RSAT/FoD offline per garantire integrità e tracciabilità. Seguendo i passaggi presentati, l’importazione del modulo ActiveDirectory riesce senza accesso a Internet e senza dipendere da download esterni.
Appendice: riferimenti operativi rapidi
Attività | Comando |
---|---|
Elenco percorsi moduli | $env:PSModulePath -split ';' |
Verifica modulo disponibile | Get-Module -ListAvailable ActiveDirectory |
Import con log dettagliati | Import-Module ActiveDirectory -Verbose |
Compatibilità PS 7 | Import-Module ActiveDirectory -UseWindowsPowerShell |
Sblocco dei file | Get-ChildItem <PathModulo> -Recurse | Unblock-File |
Installazione RSAT (Server) | Add-WindowsFeature RSAT-AD-PowerShell |
Installazione RSAT (Windows 10/11 offline) | DISM /Image:D:\Mount /Add-Capability /CapabilityName:Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0 |
Traccia del caricamento | Trace-Command -Name Module -Expression { Import-Module ActiveDirectory } -PSHost |
Nota su governance e conformità
In molte organizzazioni copiare binari dal DC non è preferibile per ragioni di hardening e segregazione dei ruoli. Se la tua policy lo vieta, utilizza esclusivamente immagini FoD/RSAT firmate e archiviate nel repository software aziendale. In ogni caso, registra l’origine dei file, calcola hash (SHA-256) e conserva evidenza del processo di distribuzione per audit futuri.
Informazioni supplementari (riepilogo)
- Parte di RSAT – Il modulo AD è incluso negli strumenti RSAT. Con pacchetti CAB/Features offline:
Add-WindowsFeature RSAT-AD-PowerShell DISM /Image:D:\Mount /Add-Capability /CapabilityName:Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0
- Compatibilità PowerShell 7+ – Usa
Import-Module ActiveDirectory -UseWindowsPowerShell
o un modulo compatibile. - Sicurezza del codice firmato – Se bloccato da Execution Policy, sblocca con
Unblock-File
o usa certificati di firma interni. - Debug rapido –
Import-Module ActiveDirectory -Verbose -Debug
indica quale file non viene trovato.
Seguendo la procedura completa (copia dell’intero modulo + collocazione in un percorso valido del PSModulePath) l’importazione offline del modulo ActiveDirectory riesce senza richiedere connessione Internet o pacchetti esterni aggiuntivi.