Search code examples
.netvisual-studioclickonceuid

Get ClickOnce's installation uid


I'm developing an application deployed throgh ClickOnce and I need to be able to distinguish each installation. Is there a way to get some sort of deployment id that changes for every installation (so 2 users on the same PC get 2 different id's) but stays the same if the app is updated?

Thanks


Solution

  • After some more research I wasn't able to find anything so I ended up creating the UID myself by hashing the CPU id, motherboard info and user GUID.

    Got some inspiration from a CodeProject article and a MSDN Forum question

    Public Function SHA256Hash(ByVal s As String) As String
        Dim hashFunction As SHA256 = SHA256Managed.Create
        Dim bytes() As Byte = (New ASCIIEncoding).GetBytes(s)
        Dim hash() As Byte = hashFunction.ComputeHash(bytes)
        Return GetStringFromHash(hash)
    End Function
    
    Private _HardwareID As String
    Public Function HardwareID() As String
        If String.IsNullOrWhiteSpace(_HardwareID) Then
            _HardwareID = SHA256Hash(String.Format("CPU>>{0}|BASE>>{1}|USER>>{2}", cpuID, baseID, userID))
        End If
    
        Return _HardwareID
    End Function
    
    Private Function identifier(ByVal wmiClass As String, ByVal wmiProperty As String)
        Dim result As String = String.Empty
        Dim mc As New Management.ManagementClass(wmiClass)
        Dim moc As Management.ManagementObjectCollection = mc.GetInstances()
    
        For Each mo As Management.ManagementObject In moc
            'Only get the first one
            If String.IsNullOrWhiteSpace(result) Then
                Try
                    result = mo(wmiProperty).ToString
                Catch ex As Exception
                End Try
            End If
        Next
    
        Return result
    End Function
    
    Private Function cpuID() As String
        'Uses first CPU identifier available in order of preference
        'Don't get all identifiers, as it is very time consuming
        Dim retVal As String = identifier("Win32_Processor", "UniqueID")
        If String.IsNullOrWhiteSpace(retVal) Then 'If no UniqueID, use ProcessorID
            retVal = identifier("Win32_Processor", "ProcessorId")
            If String.IsNullOrWhiteSpace(retVal) Then 'If no ProcessorId, use Name
                retVal = identifier("Win32_Processor", "Name")
                If String.IsNullOrWhiteSpace(retVal) Then 'If no Name, use Manufacturer
                    retVal = identifier("Win32_Processor", "Manufacturer")
                End If
            End If
        End If
    
        Return retVal
    End Function
    
    Private Function baseID() As String
        Return String.Concat(identifier("Win32_BaseBoard", "Model"), _
                             identifier("Win32_BaseBoard", "Manufacturer"), _
                             identifier("Win32_BaseBoard", "Name"), _
                             identifier("Win32_BaseBoard", "SerialNumber"))
    End Function
    
    Private Function userID() As String
        Return System.DirectoryServices.AccountManagement.UserPrincipal.Current.Guid.Value.ToString
    End Function