o IT
SCCM schedule token parser
- Podrobnosti
- Vytvořeno: 26. únor 2015
- Zobrazeno: 5462
System Center Configuration Manager still surprise me from time to time. Few days ago i need to create dump from SCCM database to get detailed information's about all collections and theirs settings. All properties like LastChangeTime, LastMemberChangeTime etc. are in readable time-format. But the most important property - schedule - is scrambled in 16-char string called SMS schedule token.
This token contains information's about how often and when is the collection updated. It is used also for scheduling HW and SW inventory on the clients. And how to read this token? There are several ways how to convert it to readable format:
- On-paper manual method
using the algorithm described by Jeff Huston in this article: http://jeff.squarecontrol.com/archives/92
- WMI method
Connect to SMS provider and invoke ReadFromString or WriteToString WMI method
- Powershell
Import ConfigMgr powershell module and use New-CMSchedule or Convert-CMSchedule cmdlet
The last two options requires to have access to the SMS provider or computer with ConfigMgr powershell module. Also the output is not user friendly. Therefore I have created simple C program to do the work without any prerequisites. Here are some examples of the outputs:
Input |
Output |
Enter Schedule string. : A9788980001B4000 |
This is a custom schedule with startTime: 24 Aug 2008 at 11:42 Evaluated every 2 week(s) on Tuesday at 11:42. |
Enter Schedule string. : 0001200000100038 |
This is a simple schedule. Evaluated every 7 day(s). |
Enter Schedule string. : 7D98898000280400 |
This is a custom schedule with startTime: 24 Aug 2008 at 12:31 Evaluated the last day of every 1. month(s) at 12:31. |
There is no error control implemented so keep in mind that when you provide bad schedule token to the script, you will receive nonsense in the output. Already compiled program can be downloaded here: SCCM_ScheduleString_parser.zip
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/* FUNCTIONS */
unsigned long long int parse_DecBin(unsigned long long int number, int start, int lenght) {
int rem, binary=0, i=1, counter=32;
while (number!=0) {
rem=number%2;
number/=2;
counter--;
if ((counter < (lenght + start -1)) && (lenght > 0)) {
binary+=rem*i;
i*=10;
lenght--;
}
}
return binary;
}
int binary_decimal(int number) {
int decimal=0, i=0, rem;
while (number!=0) {
rem = number%10;
number/=10;
decimal += rem*pow(2,i);
++i;
}
return decimal;
}
/* MAIN */
int main(void) {
unsigned long long int strHex, strHexStarttime, strHexSchedule;
int strScheduleType, strStartMin, strStartHour, strStartDay, strStartMonth , strStartYear;
int strFlags;
int strMinutes, strHours, strDays, strWeekDay, strNumWeeks, strNumMonths, strWeekOrder, strDate;
char *days_of_week[] = {"","Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
const char *month[] = {"","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
const char *week_order[] = {"Last","First","Second","Third","Fourth",};
printf("Enter Schedule string. : ");
scanf("%llx", &strHex);
strHexStarttime = (strHex>>32) & 0xFFFFFFFF;
strHexSchedule = strHex & 0xFFFFFFFF;
/* PARSING Schedule StartTime */
if (strHexStarttime == 0x00012000) {
printf("This is a simple schedule.\n");
strScheduleType = 0;
}
else {
printf("This is a custom schedule with ");
strScheduleType = 1;
strStartMin = binary_decimal(parse_DecBin(strHexStarttime,1,6));
strStartHour = binary_decimal(parse_DecBin(strHexStarttime,7,5));
strStartDay = binary_decimal(parse_DecBin(strHexStarttime,12,5));
strStartMonth = binary_decimal(parse_DecBin(strHexStarttime,17,4));
strStartYear = binary_decimal(parse_DecBin(strHexStarttime,21,6)) + 1970;
printf("startTime: %d %s %d at %02d:%02d\n",strStartDay, month[strStartMonth], strStartYear, strStartHour, strStartMin);
}
/* PARSING Schedule Recurrence */
strFlags = binary_decimal(parse_DecBin(strHexSchedule,11,3));
switch (strFlags) {
// SMS_ST_NonRecurring
case 1:
printf("With no evaluation schedule");
strScheduleType = 0;
break;
// SMS_ST_RecurInterval
case 2:
strMinutes = binary_decimal(parse_DecBin(strHexSchedule,14,6));
strHours = binary_decimal(parse_DecBin(strHexSchedule,20,5));
strDays = binary_decimal(parse_DecBin(strHexSchedule,25,5));
if (strMinutes != 0){
printf("Evaluated every %d minute(s)",strMinutes);
}
else if (strHours != 0) {
printf("Evaluated every %d hour(s)",strHours);
}
else if (strDays != 0) {
printf("Evaluated every %d day(s)",strDays);
}
break;
// SMS_ST_RecurWeekly
case 3:
strWeekDay = binary_decimal(parse_DecBin(strHexSchedule,14,3));
strNumWeeks = binary_decimal(parse_DecBin(strHexSchedule,17,3));
printf("Evaluated every %d week(s) on %s",strNumWeeks,days_of_week[strWeekDay]);
break;
// SMS_ST_RecurMonthlyByWeekday
case 4:
strWeekDay = binary_decimal(parse_DecBin(strHexSchedule,14,3));
strNumMonths = binary_decimal(parse_DecBin(strHexSchedule,17,4));
strWeekOrder = binary_decimal(parse_DecBin(strHexSchedule,21,3));
printf("Evaluated the %s %s of every %d month(s)",week_order[strWeekOrder], days_of_week[strWeekDay], strNumMonths);
break;
// SMS_ST_RecurMonthlyByDate
case 5:
strDate = binary_decimal(parse_DecBin(strHexSchedule,14,5));
strNumMonths = binary_decimal(parse_DecBin(strHexSchedule,19,4));
if (strDate == 0) printf("Evaluated the last day of every %d. month(s)",strNumMonths);
else printf("Evaluated day %d of every %d. month(s)",strDate, strNumMonths);
break;
default:
printf("Wrong strFlag");
strScheduleType = 0;
}
if (strScheduleType == 1) printf(" at %d:%d.\n",strStartHour, strStartMin);
else printf(".\n");
return 0;
}