1 18/05/2026 9 min

Quando in SCCM vuoi capire se un client è davvero vivo, l’“ultimo heartbeat” non coincide sempre con un solo campo. Dipende da cosa intendi per presenza: inventario hardware recente, policy contact, discovery data record, oppure ultimo stato online registrato dal management point. La query giusta cambia in base al dato che vuoi usare come riferimento operativo.

Se ti serve una vista pratica per troubleshooting e reporting, conviene partire da ResourceID e unire le tabelle più affidabili del database site, poi scegliere il timestamp che rappresenta meglio il tuo caso. In SCCM/MECM il punto non è solo “ultimo contatto”, ma quale tipo di contatto stai misurando.

Quale “heartbeat” ti serve davvero

Il termine viene usato in modo un po’ largo. Nella pratica, le opzioni più comuni sono queste:

  • LastDDR: ultimo Discovery Data Record elaborato per il client. Utile per sapere quando il record del dispositivo è stato aggiornato nel database.
  • LastPolicyRequest: ultimo contatto per richiesta policy. È spesso più vicino all’idea di client attivo.
  • LastOnlineStatus o campi simili, se presenti nel tuo schema/edizione: indicano l’ultimo stato di online/offline registrato.
  • LastActiveTime o campi della collection membership: utili per reporting, ma non equivalenti a un heartbeat reale.

Se vuoi una metrica operativa per capire chi non parla da tempo, di solito LastPolicyRequest è più utile di LastDDR. Se invece vuoi capire se il record è fresco nel DB, allora LastDDR ha senso. Mescolare i due valori porta a falsi positivi.

Query base per ultimo contatto client

La query più semplice, leggibile e subito utile parte da v_R_System e aggiunge il timestamp di policy o discovery. Ecco una versione tipica per vedere i client con l’ultimo contatto policy, ordinati dal più vecchio al più recente:

SELECT TOP 2000
    rs.ResourceID,
    rs.Name0 AS ComputerName,
    rs.Client0 AS IsClient,
    rs.Obsolete0 AS IsObsolete,
    rs.Active0 AS IsActive,
    rs.LastLogonUserName0 AS LastUser,
    rs.LastLogonTimestamp0 AS LastLogon,
    p.LastPolicyRequest
FROM v_R_System rs
LEFT JOIN v_CH_ClientSummary p
    ON p.ResourceID = rs.ResourceID
WHERE rs.Client0 = 1
ORDER BY p.LastPolicyRequest ASC;

Questa query è adatta quando vuoi individuare i client che non hanno richiesto policy da più tempo. Il campo LastPolicyRequest può non essere popolato in modo uniforme in ambienti vecchi o con client mal gestiti, quindi il LEFT JOIN è preferibile: se fai INNER JOIN rischi di perdere proprio i dispositivi problematici.

Se il tuo ambiente non espone v_CH_ClientSummary con quel nome esatto, il punto da verificare è il layer del database site e la vista disponibile nel tuo schema. Non indovinare il nome: controllalo con una query di catalogo o da SSMS sulla lista delle viste. Il controllo minimo è questo:

SELECT name
FROM sys.views
WHERE name LIKE 'v%Client%'
ORDER BY name;

Query per ultimo heartbeat dal Discovery Data Record

Se ti serve il timestamp più vicino al “record aggiornato” nel DB, usa il DDR. In molti ambienti il campo è più stabile e più semplice da interrogare rispetto a logiche di stato applicativo. Esempio:

SELECT TOP 2000
    rs.ResourceID,
    rs.Name0 AS ComputerName,
    rs.Client0 AS IsClient,
    rs.Active0 AS IsActive,
    rs.Obsolete0 AS IsObsolete,
    ddr.LastDDR
FROM v_R_System rs
LEFT JOIN v_GS_SYSTEM_SUMMARY ddr
    ON ddr.ResourceID = rs.ResourceID
WHERE rs.Client0 = 1
ORDER BY ddr.LastDDR ASC;

Attenzione: la vista esatta può variare in base alla versione e al tipo di report che stai costruendo. In alcuni ambienti il dato equivalente è esposto in un’altra vista o in un’estensione di inventario. Se la query non torna righe o il campo è NULL, non forzare la conclusione che il client sia morto: verifica prima se il client sta ancora inviando DDR, se il sito lo ha processato e se la maintenance del database non ha già ripulito record vecchi.

Query più robusta: ultimo contatto, client attivo e stato operativo

Per il troubleshooting serio conviene mostrare più di un timestamp. Così distingui un client “vivo ma silenzioso” da un client “non più gestito” o da un record vecchio nel database. Una query più utile in produzione è questa:

SELECT TOP 5000
    rs.ResourceID,
    rs.Name0 AS ComputerName,
    rs.Client0 AS IsClient,
    rs.Active0 AS IsActive,
    rs.Obsolete0 AS IsObsolete,
    cs.LastPolicyRequest,
    cs.LastHWScan,
    cs.LastSWScan,
    rs.LastLogonTimestamp0 AS LastLogon,
    rs.LastLogonUserName0 AS LastUser
FROM v_R_System rs
LEFT JOIN v_CH_ClientSummary cs
    ON cs.ResourceID = rs.ResourceID
WHERE rs.Client0 = 1
ORDER BY
    CASE WHEN cs.LastPolicyRequest IS NULL THEN 1 ELSE 0 END,
    cs.LastPolicyRequest ASC,
    rs.Name0 ASC;

Qui il vantaggio è pratico: se LastPolicyRequest è nullo ma LastHWScan è recente, il client parla ma non completa il ciclo policy come ti aspetteresti. Se anche l’inventario è vecchio, il problema è più ampio: rete, agent, firewall, services o coda di elaborazione lato site.

Filtrare per client “vecchi” oltre una soglia

Il caso tipico non è la lista completa, ma i dispositivi che non si sentono da X giorni. In quel caso usa una soglia esplicita. Se lavori in SQL Server, la condizione più portabile è con DATEADD e GETDATE():

SELECT
    rs.Name0 AS ComputerName,
    cs.LastPolicyRequest,
    DATEDIFF(DAY, cs.LastPolicyRequest, GETDATE()) AS DaysSincePolicy
FROM v_R_System rs
LEFT JOIN v_CH_ClientSummary cs
    ON cs.ResourceID = rs.ResourceID
WHERE rs.Client0 = 1
  AND cs.LastPolicyRequest IS NOT NULL
  AND cs.LastPolicyRequest < DATEADD(DAY, -7, GETDATE())
ORDER BY cs.LastPolicyRequest ASC;

Se vuoi evitare di includere dispositivi obsoleti o già dismessi, aggiungi i filtri rs.Obsolete0 = 0 e rs.Active0 = 1. Questo è importante perché in ambienti grandi il rumore è il vero problema: senza filtro, i report finiscono pieni di oggetti che non rappresentano più endpoint reali.

Come interpretare i risultati senza farsi ingannare

Una colonna con data vecchia non significa automaticamente che il client sia spento. In SCCM un dispositivo può essere acceso, raggiungibile e comunque avere timestamp vecchi se il servizio client è rotto, se la policy non viene scaricata, o se il management point non sta aggiornando correttamente lo stato.

  • Timestamp vecchio ma ping OK: problema probabile sul client agent o sulla comunicazione con MP.
  • Timestamp vecchio e DNS/ICMP non risponde: il client può essere davvero offline o fuori rete.
  • Timestamp nullo: il record può non essere stato popolato, oppure il client non è mai stato inventariato correttamente.
  • Timestamp recente ma applicazioni non distribuite: il heartbeat non basta, va controllata la compliance delle policy e la coda lato site.

In pratica, il timestamp serve a prioritizzare, non a emettere sentenze. La triage corretta unisce SQL, console SCCM e una verifica puntuale sul client.

Query per esportare i client inattivi con nome macchina e ultimo utente

Quando devi passare il risultato a un team desktop o a un service desk, conviene includere anche il nome utente e un ordinamento già pronto per il follow-up. Questa variante è più operativa:

SELECT
    rs.Name0 AS ComputerName,
    rs.User_Name0 AS PrimaryUser,
    rs.LastLogonUserName0 AS LastLogonUser,
    rs.LastLogonTimestamp0 AS LastLogon,
    cs.LastPolicyRequest,
    cs.LastHWScan,
    rs.Client0,
    rs.Active0,
    rs.Obsolete0
FROM v_R_System rs
LEFT JOIN v_CH_ClientSummary cs
    ON cs.ResourceID = rs.ResourceID
WHERE rs.Client0 = 1
  AND rs.Active0 = 1
  AND rs.Obsolete0 = 0
ORDER BY cs.LastPolicyRequest ASC, rs.Name0 ASC;

Se devi esportare il risultato per Excel o CSV, evita di aggiungere campi inutili: più colonne non significa più valore. In ambienti grandi conviene tenere il report corto e aggiungere un secondo report solo per i casi borderline.

Se vuoi il vero ultimo contatto, usa anche le viste di stato

In alcuni casi il dato migliore non è nel summary del client ma nelle viste di stato o nei report del management point. Questo vale soprattutto quando stai indagando problemi di comunicazione intermittente, code bloccate o client che si registrano a singhiozzo.

Qui la regola è semplice: se il database site ti mostra un timestamp coerente ma il client continua a risultare “vecchio” in console, verifica la catena completa client → MP → site DB. Il problema può stare nel trasporto, non nel dato.

Verifica rapida lato client quando il timestamp non torna

Se la query indica un client fermo ma vuoi capire se il problema è reale, sul client fai un controllo minimo dei servizi e dei log. I percorsi più utili, in installazioni standard, sono questi:

C:\\Windows\\CCM\\Logs\\ClientIDManagerStartup.log
C:\\Windows\\CCM\\Logs\\PolicyAgent.log
C:\\Windows\\CCM\\Logs\\InventoryAgent.log

Il controllo pratico è cercare errori di registration, policy retrieval o inventory. Se il client è sano, in quei log vedi attività recente e codici di successo; se è rotto, trovi retry, timeout, fallimenti di autenticazione o problemi di connettività verso il management point.

Una query “di lavoro” da tenere pronta

Se devi usarne una sola per l’operatività quotidiana, scegli una query che mostri nome macchina, stato client e ultimo contatto policy, con filtro sui dispositivi realmente gestiti. Questa è una buona base:

SELECT TOP 1000
    rs.Name0 AS ComputerName,
    rs.ResourceID,
    rs.Client0 AS IsClient,
    rs.Active0 AS IsActive,
    rs.Obsolete0 AS IsObsolete,
    cs.LastPolicyRequest,
    cs.LastHWScan,
    rs.LastLogonTimestamp0 AS LastLogon
FROM v_R_System rs
LEFT JOIN v_CH_ClientSummary cs
    ON cs.ResourceID = rs.ResourceID
WHERE rs.Client0 = 1
  AND rs.Active0 = 1
  AND rs.Obsolete0 = 0
ORDER BY
    CASE WHEN cs.LastPolicyRequest IS NULL THEN 1 ELSE 0 END,
    cs.LastPolicyRequest ASC,
    rs.Name0 ASC;

Questa query non pretende di risolvere tutto, ma ti dà una fotografia pulita: chi non parla, chi è davvero gestito, chi è probabilmente un residuo. Da lì puoi passare alla console SCCM, al client e ai log con meno rumore.

Se il dato non c’è, non forzarlo

Un errore frequente è assumere che tutte le installazioni espongano gli stessi campi con gli stessi nomi. Non è così: versioni diverse, customizzazioni di inventory e report pack diversi cambiano le viste disponibili. Se una colonna non esiste, il modo corretto di chiudere il gap è verificare il catalogo SQL del site e la documentazione della tua versione, non inventare un alias “plausibile”.

In sintesi: per trovare l’ultimo heartbeat dei client SCCM, parti da LastPolicyRequest se vuoi misurare il contatto operativo, usa LastDDR se vuoi misurare la freschezza del record, e combina sempre il timestamp con lo stato del client. Una singola data, da sola, racconta solo metà della storia.