All posts tagged License

In today’s blog I am going to give you the method I use to obtain the Windows Product Activation information in Astronomy.

Q: So, where does this information come from?
A: Well, as you may know, you can obtain this information from the following script:
C:\Windows\System32\slmgr.vbs

I always felt this needed to be modified for use in .Net, so I refactored this a bit and created my own replacement method:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/// <summary>
/// Retrieves licensing information.
/// </summary>
/// <param name="managementScope">The management scope.</param>
/// <returns></returns>
public static string GetLicensingInfo(ManagementScope managementScope)
{
    // Output
    string result = "Information Unavailable";
    const string windowsAppId = "55c92734-d682-4d71-983e-d6ec3f16059f";
 
    // Default values
    const uint HR_SL_E_GRACE_TIME_EXPIRED = 0xC004F009;
    const uint HR_SL_E_NOT_GENUINE = 0xC004F200;
 
    // Set WMI query
    var query =
        new WqlObjectQuery(
            "SELECT LicenseStatus, GracePeriodRemaining " +
            "FROM SoftwareLicensingProduct " +
            "WHERE (PartialProductKey <> NULL) AND " +
            "(ApplicationId='" + windowsAppId + "')");
 
    // Get items
    using (var searcher = new ManagementObjectSearcher(managementScope, query))
     
    // Get data
    using (var colItems = searcher.Get())
    {
        foreach (ManagementBaseObject obj in colItems)
        {
            string subline;
 
            // License Status
            int licenseStatus = Convert.ToInt32(obj.GetPropertyValue("LicenseStatus"));
 
            // Time remaining: minutes / days
            int gpMin = Convert.ToInt32(obj.GetPropertyValue("GracePeriodRemaining"));
            int gpDay = gpMin / (24 * 60);
 
            // Evaluate
            switch (licenseStatus)
            {
                case 0:
                    result = "Unlicensed";
                    break;
 
                case 1:
                    result = "Licensed";
                    if (gpMin > 0)
                    {
                        subline =
                            String.Format(
                                "Activation expiration: " +
                                "{0} minute(s) ({1} day(s))", gpMin, gpDay);
                        result += "\n" + subline;
                    }
                    break;
 
                case 2:
                    result = "Initial grace period";
                    subline =
                        String.Format("Time remaining: {0} minute(s) " +
                                        "({1} day(s))", gpMin, gpDay);
                    result += "\n" + subline;
                    break;
 
                case 3:
                    result =
                        "Additional grace period (KMS license expired or " +
                        "hardware out of tolerance)";
                    subline =
                        String.Format("Time remaining: {0} minute(s) " +
                                        "({1} day(s))", gpMin, gpDay);
                    result += "\n" + subline;
                    break;
 
                case 4:
                    result = "Non-genuine grace period.";
                    subline =
                        String.Format("Time remaining: {0} minute(s) " +
                                        "({1} day(s))", gpMin, gpDay);
                    result += "\n" + subline;
                    break;
 
                case 5:
                    result = "Notification";
 
                    uint licenseStatusReason;
                    uint.TryParse(obj.GetPropertyValue("GracePeriodRemaining").ToString(),
                        out licenseStatusReason);
                         
                    // Evaluate
                    switch (licenseStatusReason)
                    {
                        case HR_SL_E_NOT_GENUINE:
                            subline =
                                String.Format(
                                    "Notification Reason: 0x{0} " +
                                    "(non-genuine).", licenseStatusReason);
                            break;
 
                        case HR_SL_E_GRACE_TIME_EXPIRED:
                            subline =
                                String.Format(
                                    "Notification Reason: 0x{0} " +
                                    "(grace time expired).", licenseStatusReason);
                            break;
 
                        default:
                            subline =
                                String.Format("Notification Reason: 0x{0}.",
                                                licenseStatusReason);
                            break;
                    }
                    result += "\n" + subline;
                    break;
 
                case 6:
                    result = "Extended grace period";
                    subline =
                        String.Format("Time remaining: {0} minute(s) " +
                                        "({1} day(s))", gpMin, gpDay);
                    result += "\n" + subline;
                    break;
 
                default:
                    result = "Unknown";
                    break;
            }
        }
    }
     
    // return
    return result;
}

An overboard implementation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/// <summary>
/// Connects to a target computer through Kerberos authentication.
/// </summary>
/// <param name="computername">The computername.</param>
/// <param name="user">The user.</param>
/// <param name="securePass">The secure pass.</param>
/// <returns>
/// A ManagementScope context for the current connection.
/// </returns>
public static ManagementScope Connect(string computername, string user,
    SecureString securePass)
{
    // Build an options object for the remote connection
    var options = new ConnectionOptions
        {
            Impersonation = ImpersonationLevel.Impersonate,
            EnablePrivileges = true
        };
 
    // Set properties
    // Check name
    if (String.IsNullOrEmpty(computername))
    {
        computername = ".";
    }
 
    // Check credentials
    // Cannot pass a blank user and password.
    if (!String.IsNullOrEmpty(user))
    {
        options.Username = user;
        options.SecurePassword = securePass;
    }
     
    // Make a connection to a remote computer.
    var managementScope =
        new ManagementScope($@"\{computername}\root\cimv2", options);
 
    try
    {
        // Connect
        managementScope.Connect();
    }
    catch (Exception ex)
    {
        throw ex;
    }
     
    // return
    return managementScope;
}
 
/// <summary>
/// Gets the license you so desperately want.
/// </summary>
public void GetMyLicense()
{
    // Get the management scope
    var myManagementScope = Connect(".", "XCALIBUR\jarzt", {my secure password});
 
    // Get the licensing
    string licensing = GetLicensingInfo(myManagementScope);
 
    // Report to client
    MessageBox.Show("My current licensing status: " + licensing);
}

So, really that’s all there is to it.

Happy coding!