For my company purpose, I created a plugin to display how many days remaining before our main and administrator account password will expire.
I'm currently learning C#, so I used the example PluginSystemVersion to create mine.
The widget works, I can see the information, and my coworkers too.
Unfortunately, we must refresh the widget to see the measure update.
I put my code, as I'm beginner, maybe I missed something. I plan to optimize the code later as I will increase my knowledge.
I also tried to put DynamicVariables=1 in my skin, but that didn't change the behavior.
By default the widget will update every hour, for testing purpose I tried every minutes.
Code: Select all
using System;
using System.DirectoryServices;
using System.Runtime.InteropServices;
using Rainmeter;
namespace Information
{
class Measure
{
enum MeasureType
{
AdmUsername,
UserName,
NoExpiration,
ExpirationDate,
DaysRemaining,
AdmAccount,
ExpirationDateAdm,
DaysRemainingAdm
}
private MeasureType Type = MeasureType.UserName;
static public implicit operator Measure(IntPtr data)
{
return (Measure)GCHandle.FromIntPtr(data).Target;
}
private string userName, admUserName;
private DateTime dateExpiration, dateExpirationAdm;
private readonly DateTime maintenant = DateTime.Now;
private double daysRemaining, daysRemainingAdm;
private bool noExpiration = false, admAccount = false;
private DirectoryEntry sterimed;
private DirectorySearcher recherche, rechercheAdm;
private SearchResult resultat, resultatAdm;
internal Measure() {
}
internal void GetUserInfo()
{
userName = Environment.GetEnvironmentVariable("UserName");
admUserName = $"adm_{userName}";
sterimed = new DirectoryEntry($"LDAP://domain.lan/ou=Countries,dc=domain,dc=lan");
recherche = new DirectorySearcher(sterimed)
{
Filter = $"(&(objectCategory=user)(objectClass=user)(samAccountName={userName}))"
};
recherche.PropertiesToLoad.Add("msDS-UserPasswordExpiryTimeComputed");
try {
resultat = recherche.FindOne();
long value = (long)resultat.Properties["msDS-UserPasswordExpiryTimeComputed"][0];
if (value == 9223372036854775807) {
noExpiration = true;
}
dateExpiration = DateTime.FromFileTime(value);
daysRemaining = (dateExpiration - maintenant).TotalDays;
} catch (Exception e) {
daysRemaining=-1.0;
}
rechercheAdm = new DirectorySearcher(sterimed)
{
Filter = $"(&(objectCategory=user)(objectClass=user)(samAccountName={admUserName}))"
};
rechercheAdm.PropertiesToLoad.Add("msDS-UserPasswordExpiryTimeComputed");
try {
resultatAdm = rechercheAdm.FindOne();
} catch (Exception e) {
daysRemainingAdm = -1.0;
}
if (resultatAdm != null) {
admAccount = true;
try {
long valueAdm = (long)resultatAdm.Properties["msDS-UserPasswordExpiryTimeComputed"][0];
dateExpirationAdm = DateTime.FromFileTime(valueAdm);
daysRemainingAdm = (dateExpirationAdm - maintenant).TotalDays;
} catch (Exception e) {
daysRemainingAdm = -1.1;
}
}
}
internal void Reload(Rainmeter.API api, ref double maxValue)
{
string type = api.ReadString("Type", "");
switch (type.ToLowerInvariant()) {
case "admusername":
Type = MeasureType.AdmUsername;
break;
case "username":
Type = MeasureType.UserName;
break;
case "expirationdate":
Type = MeasureType.ExpirationDate;
break;
case "daysremaining":
Type = MeasureType.DaysRemaining;
break;
case "noexpiration":
Type = MeasureType.NoExpiration;
break;
case "admaccount":
Type = MeasureType.AdmAccount;
break;
case "expirationdateadm":
Type = MeasureType.ExpirationDateAdm;
break;
case "daysremainingadm":
Type = MeasureType.DaysRemainingAdm;
break;
default:
api.Log(API.LogType.Error, "SystemVersion.dll: Type=" + type + " not valid");
break;
}
}
internal double Update() {
GetUserInfo();
switch (Type)
{
case MeasureType.NoExpiration:
return noExpiration == true ? 1.0 : 0.0;
case MeasureType.AdmAccount:
return admAccount == true ? 1.0 : 0.0;
case MeasureType.DaysRemaining:
return Math.Round(daysRemaining, 1);
case MeasureType.DaysRemainingAdm:
return admAccount == true ? daysRemainingAdm : 0.0;
}
return 0.0;
}
internal string GetString() {
GetUserInfo();
switch (Type) {
case MeasureType.AdmUsername:
return admUserName;
case MeasureType.UserName:
return userName;
case MeasureType.ExpirationDate:
return dateExpiration.ToString();
case MeasureType.ExpirationDateAdm:
return admAccount == true ? dateExpirationAdm.ToString() : null;
}
return null;
}
}
public class Plugin
{
static IntPtr StringBuffer = IntPtr.Zero;
[DllExport]
public static void Initialize(ref IntPtr data, IntPtr rm) {
data = GCHandle.ToIntPtr(GCHandle.Alloc(new Measure()));
Rainmeter.API api = (Rainmeter.API)rm;
}
[DllExport]
public static void Finalize(IntPtr data)
{
GCHandle.FromIntPtr(data).Free();
if (StringBuffer != IntPtr.Zero)
{
Marshal.FreeHGlobal(StringBuffer);
StringBuffer = IntPtr.Zero;
}
}
[DllExport]
public static void Reload(IntPtr data, IntPtr rm, ref double maxValue) {
Measure measure = (Measure)GCHandle.FromIntPtr(data).Target;
measure.Reload(new Rainmeter.API(rm), ref maxValue);
}
[DllExport]
public static double Update(IntPtr data)
{
Measure measure = (Measure)GCHandle.FromIntPtr(data).Target;
return measure.Update();
}
[DllExport]
public static IntPtr GetString(IntPtr data)
{
Measure measure = (Measure)GCHandle.FromIntPtr(data).Target;
if (StringBuffer != IntPtr.Zero)
{
Marshal.FreeHGlobal(StringBuffer);
StringBuffer = IntPtr.Zero;
}
string stringValue = measure.GetString();
if (stringValue != null)
{
StringBuffer = Marshal.StringToHGlobalUni(stringValue);
}
return StringBuffer;
}
}
}