Ever ran a report against the vSMS_ServiceWindowtable of SCCM and realized the Schedules object was…. well, not very readable?
Have no fear! Here is a c# solution.
My solution is based off of this pseudocode: How to Configure Hardware Inventory Settings
Here is the SQL Query I use:
select c.CollectionID ,c.SiteID ,c.CollectionName ,c.CollectionType ,c.ServiceWindowsCount ,c.LimitToCollectionID ,c.LimitToCollectionName ,c.ObjectPath ,sw.Name ,sw.ServiceWindowType ,sw.Description ,sw.Enabled ,sw.Schedules from v_Collections c JOIN vSMS_ServiceWindow sw on sw.SiteID = c.SiteID
I left out the piece which queries a database, and returns data rows. If you are reading this, I assume you can manage to figure that piece out.
using System; using System.Data; using System.Diagnostics; namespace LIB.SCCM.Models { /// <summary> /// SCCM Table - vSMS_ServiceWindow /// </summary> /// [DebuggerDisplay("{Name} - {Description}")] public class ServiceWindow { public ServiceWindow(DataRow row) { this.Name = row.Field<string>("Name"); this.Description = row.Field<string>("Description"); this.WindowType = (ServiceWindowType)row.Field<int>("ServiceWindowType"); this.Enabled = row.Field<bool>("Enabled"); //Parse out the funky schedule... var Schedule_HEX = row.Field<string>("Schedules"); //Split the hex string into two pieces. string StartTime_HEX = Schedule_HEX.Substring(0, 8); string Recurrence_HEX = Schedule_HEX.Substring(8, 8); //Parse a long from the provided hex values, then convert that to a binary string... Lastly, Pad left, until there are 32 total bits. var StartTime_BIN = Convert.ToString(long.Parse(StartTime_HEX, System.Globalization.NumberStyles.HexNumber), 2).PadLeft(32, '0'); var Recurrence_BIN = Convert.ToString(long.Parse(Recurrence_HEX, System.Globalization.NumberStyles.HexNumber), 2).PadLeft(32, '0'); //Parse out the start date. int Min = Convert.ToInt32(StartTime_BIN.Substring(0, 6), 2); int Hour = Convert.ToInt32(StartTime_BIN.Substring(6, 5), 2); int Day = Convert.ToInt32(StartTime_BIN.Substring(11, 5), 2); int Month = Convert.ToInt32(StartTime_BIN.Substring(16, 4), 2); int Year = Convert.ToInt32(StartTime_BIN.Substring(20, 6), 2) + 1970; int Duration = Convert.ToInt32(StartTime_BIN.Substring(26, 6), 2); //Convert those values into a valid date time. Seconds are not supported in sccm schedules. this.StartTime = new DateTime(Year, Month, Day, Hour, Min, 0); //Parse out the duration. int Duration_Hours = Convert.ToInt32(Recurrence_BIN.Substring(0, 5), 2); int Duration_Mins = Convert.ToInt32(Recurrence_BIN.Substring(5, 5), 2); //Store those values as the duration Timespan. SCCM does not support seconds in schedules. this.Duration = new TimeSpan(Duration_Hours, Duration_Mins, 0); //Is GMT Flag is the last digit. bool isGMT = Convert.ToBoolean(Convert.ToInt32(Recurrence_BIN.Substring(31, 1))); //Parse out the flags... int Flags = Convert.ToInt32(Recurrence_BIN.Substring(10, 3), 2); switch (Flags) { case 1: //NonRecurring Schedule this.RecurrenceType = RecurrenceType.NONE; break; case 2: //Recurring on predefined interval. { this.RecurrenceType = RecurrenceType.DAILY; //this.RecurrenceType = RecurrenceType. int rec_Mins = Convert.ToInt32(Recurrence_BIN.Substring(13, 6), 2); int rec_Hours = Convert.ToInt32(Recurrence_BIN.Substring(19, 5), 2); int rec_Days = Convert.ToInt32(Recurrence_BIN.Substring(24, 5), 2); TimeSpan RecurEvery = new TimeSpan(rec_Days, rec_Hours, rec_Mins); } break; case 3: //Recurring on weekly basis. { this.RecurrenceType = RecurrenceType.WEEKLY; int rec_wDay_int = Convert.ToInt32(Recurrence_BIN.Substring(13, 3), 2); int rec_num_weeks = Convert.ToInt32(Recurrence_BIN.Substring(16, 3), 2); //The SCCM value for day of week starts at 1. .Net value starts at 0. DayOfWeek rec_DayOfWeek = (DayOfWeek)(rec_wDay_int - 1); } break; case 4: //Recur monthly, by weekday. { this.RecurrenceType = RecurrenceType.MONTHLYBYWEEKDAY; int WeekDay = Convert.ToInt32(Recurrence_BIN.Substring(13, 3), 2); //What day of the week this will trigger on. DayOfWeek rec_DayOfWeek = (DayOfWeek)(WeekDay - 1); //How many months between reoccurences int rec_Every_N_Months = Convert.ToInt32(Recurrence_BIN.Substring(16, 4), 2); //Which Week, ie, First, second, last, etc... // 0 = Last, 1 = First, 2 = 2nd, 3 = 3rd, 4 = 4th. int WeekOrder = Convert.ToInt32(Recurrence_BIN.Substring(20, 3), 2); } break; case 5: //Monthly By Date - Custom schedule only! { //I didn't finish parsing this piece out... becase, it is not used in my environment. this.RecurrenceType = RecurrenceType.MONTHLYBYDATE; //strDate = Next 5 chars of strBinRecurrence convert bin2dec //strNumMonths = Next 4 chars of strBinRecurrence convert bin2dec //strUnused = Next 9 chars of strBinRecurrence convert bin2dec //'Should be 0 (not used by HINV schedules) //bIsGMT = Last char of strBinRecurrence convert bin2bool //'0=False,1=True (should be 0, not used by HINV schedules) //Select Case strDate // Case "0" // strFriendlyRecurrence = "Occurs the last day of every " // Case Else // strFriendlyRecurrence = "Occurs day " & strDate &_ // " of every " //End Case //strFriendlyRecurrence = strFriendlyRecurrence & strNumMonths &_ // " month(s)" } break; } } public string Name { get; set; } public string Description { get; set; } public TimeSpan Duration { get; set; } public bool Enabled { get; set; } public RecurrenceType RecurrenceType { get; set; } public ServiceWindowType WindowType { get; set; } public DateTime StartTime { get; set; } } }