Posts
  • CarlosAg Blog

    New Articles for Building IIS Manager Extensions Published in IIS.NET

    • 1 Comments

    Gurpreet Singh who is a developer in my team published last week a couple of articles on how to extend IIS Manager 7:

    1) The first one talks about how to write an IIS Manager extension in general and walks you through the process using Visual Studio: http://learn.iis.net/page.aspx/441/understanding-ui-extension-authoring/

    2) The second one shows how to extend the IIS Reports feature in Admin Pack to add your own report to it and shows this using Log Parser: http://learn.iis.net/page.aspx/464/walkthrough-for-creating-an-iis-report/

  • CarlosAg Blog

    See you at TechEd Developers 2007 in Barcelona!

    • 0 Comments

    Today I'm flying to Barcelona to attend TechEd Developer 2007. I will be talking about IIS 7 Extensibility and showing some of the cool stuff we have been doing for the last couple of years, including Configuration Extensibility, building Managed Read More...

    Hope to see you there!

  • CarlosAg Blog

    Using Nested Azure Logic Apps … or Invoking Flows from another Logic App

    • 0 Comments

    Logic Apps has built-in functionality to allow organizing and splitting your workflows in small manageable units that can then be invoked from another workflow. At this moment that functionality is not exposed through the User Interface, but it is still possible to do that.

    The high level steps to enable that is to:

    1. Create the Child Logic App that will be invoked by the parent logic app and any logic to it.
    2. Create an Access Key in the Child Logic App so that the Parent Logic App can use that as the user name and password to invoke it.
    3. Create the Parent Logic App that uses an action of type “Workflow” and specify the Basic Credentials with the access keys created above.
    4. That is all…

     

    Now the biggest challenge right now is that the User Interface does not currently support managing Access Keys for flows as well as adding an Action for it, so we will be using the great ARMClient that David Ebbo built to do that easily through command line.

     

    Create a Child Logic App

    Here you can build any logic app the way you would like, in my case I called the Resource Group “logicNewRG”. The most important thing here is to Copy the full URL of the Endpoint since you will be using that to invoke this workflow from the Parent Logic App. You can do that in the Blade that shows the Endpoint, in my case since I deployed it to North Central US it looks something like: https://northcentralus.logic.azure.com/subscriptions/049c02d1-000-0000-0000-0000000/resourceGroups/logicNewRG/providers/Microsoft.Logic/workflows/ChildLogicApp

    image 

     

    Create an Access Key for the Logic App

    This is the most complicated part today since there is currently no support for the UI to manage the access keys, however it is simple enough to do that through command line.

    Install ARM Client: Using Chocolatey it is very easy to install ARM Client, you can just run: choco install armclient

    Once you do that you can run the following:

    List the Subscriptions
    armclient GET /subscriptions?api-version=2014-04-01
    set SUB=/subscriptions/049c02d1....e734c


    Create the Access Key sending a PUT and use a POST to list the generated keys
    armclient PUT %SUB%/resourceGroups/logicNewRG/providers/Microsoft.Logic/workflows/ChildLogicApp/accessKeys/mykey?api-version=2015-02-01-preview "{}"

    armclient POST %SUB%/resourceGroups/logicNewRG/providers/Microsoft.Logic/workflows/ChildLogicApp/accessKeys/mykey/list?api-version=2015-02-01-preview

    And that will return the actual keys: (note that there are two so you can rollover your keys and have no downtime easily):

    {
      "primarySecretKey": "uzdaaa18wbccccccc….FpdQ",
      "secondarySecretKey": "4Kpdddp7Rccc….DPyUVX6HeKw"
    }

     

     

    Create the Parent Logic App

    To create the parent logic app you will need to edit manually the Code in the designer for the actual invocation of the Workflow by entering an action of type “Workflow”.

        "actions": {
            "flow"
    : {
                "type": "Workflow",
                "inputs": {
                    "apiVersion": "2015-02-01-preview",
                    "method": "GET",

                    "uri": "https://northcentralus.logic.azure.com/subscriptions/049c02d1...734c/resourceGroups/logicNewRG/providers/Microsoft.Logic/workflows/ChildLogicApp",


                    "trigger": {
                        "Name": "Parentflow"

                        "outputs": {
                            "somedata": {
                                "type": "string",
                                "value": "@{guid()}"
                            }
                        } 
                    },


                    "authentication"
    : {
                        "Type"
    : "Basic",
                        "UserName": "mykey",
                        "Password": "uzdEC...PfUFpdQ"
                    }

                }
            }
        }
    ,

     

    Passing data to the child logic app

    Notice that in this case I’m also passing some data, like a generated GUID to the flow that then can be referenced in the child logic app with something like: @triggers().outputs.somedata.

    Returning data back to the Parent Logic App

    You can send data back to the parent workflow by using the Outputs in the child logic app, such as:

        "outputs": {
            "endTime"
    : {
                "type": "String",
                "value": "Child Flow completed at: @{utcnow()}"
            }
        }
  • CarlosAg Blog

    How to display a DateTime in WinDbg using SOS

    • 1 Comments

    One of the things that I’ve always struggled in the past while looking at some Managed Code and analyzing a crash dump in WinDbg using SOS was dumping a System.DateTime. Sure enough you can use DumpVC and get the actual “data” inside it, but that is not very readable. In the past I used the trick of using .formats for displaying it, but that only works when you are looking at one DateTime at a time, but it is incredible painful when you need to look to many. So finally decided to write a quick “script” to dump the DateTime with a single command.

    So just for fun and to contrast it, lets look at the “hard way I used to do this before”, if you don’t care and want the better way just ignore “The Hard Way”section, so for this in my crash dump the DateTime lives at: 0000003692816498:

    The New Way

    As you probably will see below in “The Hard Way” and after doing that a few times, you get motivated to find a better way, and that is why I decided to write a quick little WinDbg scripts using the “Debugger Command Programs” that make this process very nice. Now I can run one line and get that super easy:

    0:000> $$>a<e:\Scripts\DumpDate.txt 0000003692816498
    2014-10-21 21:50:27 (local)

    Notice that in this case my script will actually dump the right date, including the fact that it is in local time. See the bottom for the actual script, or download the script from my web site at: http://www.carlosag.net/downloads/DumpDate.txt

    The Hard Way

    First you need to find the MT of DateTime, and like “everyone knows” that is in mscorlib.dll, then you call DumpVC, then you remove the flags from DateTime data to get the ticks (remember the magic number 0x3FFFFFFFFFFFFFFF)… and then finally you call the nice and handy “.formats”… easy, right?

    0:000> !Name2EE mscorlib.dll System.DateTime
    Module:      00007ffab1741000
    Assembly:    mscorlib.dll
    Token:       000000000200005b
    MethodTable: 00007ffab1dc7af8
    EEClass:     00007ffab17439d8
    Name:        System.DateTime

    0:000> !DumpVC 00007ffab1dc7af8 0000003692816498
    Name:        System.DateTime
    MethodTable: 00007ffab1dc7af8
    EEClass:     00007ffab17439d8
    Size:        24(0x18) bytes
    File:        D:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
    Fields:
                  MT    Field   Offset                 Type VT     Attr            Value Name
    00007ffab1dcac18  40000dc        0        System.UInt64  1 instance 5247181268704488069 dateData
    00007ffab1db3768  40000d8       50       System.Int32[]  0   shared           static DaysToMonth365
                                     >> Domain:Value  00000..0 <<
    00007ffab1db3768  40000d9       58       System.Int32[]  0   shared           static DaysToMonth366
                                     >> Domain:Value  00000..0 <<
    00007ffab1dc7af8  40000da       40      System.DateTime  1   shared           static MinValue
                                     >> Domain:Value  00000..0 <<
    00007ffab1dc7af8  40000db       48      System.DateTime  1   shared           static MaxValue
                                     >> Domain:Value  000000..768 <<


    0:000> ? 0n5247181268704488069 & 0x3FFFFFFFFFFFFFFF
    Evaluate expression: 635495250277100165 = 08d1bb90`2936ea85

    0:000> .formats 08d1bb90`2936ea85
    Evaluate expression:
      Hex:     08d1bb90`2936ea85
      Decimal: 635495250277100165
      Octal:   0043215671005115565205
      Binary:  00001000 11010001 10111011 10010000 00101001 00110110 11101010 10000101
      Chars:   ....)6..
      Time:    Tue Oct 21 14:50:27.710 3614 (UTC - 7:00)
      Float:   low 4.06155e-014 high 1.26228e-033
      Double:  3.43715e-266

    And also always remember to decrease 1,600 years from the date since the managed dates are not based on the same “starting year”, and they will always be off by 1,600 years. Now imagine what you are trying to do is look at 10 or 20 DateTime objects, it can become cumbersome.

     

    Summary

    It was quite fun getting to do this script, I learned more than I ever thought I wanted to know about DateTime and its internal representation and dealing with leap years and more. I’m sure the script could be written in a much better way (maybe using named variables/addresses as opposed to pseudo registers, etc) but I needed to get it done quickly. The actual task I was trying to achieve was to dump all HttpContext in ASP.NET and see what was the time when they were created (_utcTimestamp), will post a different blog at some point showing a handy script to dump HTTP Requests, System.Net.Connection, and other common objects that I get to have the pleasure to debug issues on the server side.

    The Script

    $$ WinDbg Program to Dump a System.Date...

    $$  requires specifying the DateTime Address

    $$

    $$ Written by: CarlosAg (http://www.carlosag.net/)

    $$

    $$ Run as: $$>a<DumpDate.txt <DateTimeAddress>

    $$

    $$ Example : $$>a<e:\shares\public\AzureUX\scripts\DumpDate.txt 000007fef7411c48       

    $$ Uses Pseudo Registers t11-t19

     

    ad/q *

     

    $$ Read the argument

    r$t11=poi(${$arg1});

     

    $$   Now for the Date Time Magic... and fun...

    $$ DateTime stores in a QuadWord Binary format using the last two digits to signal UTC and other flags

    $$ Is UTC? dq & 0x4000000000000000

    $$  so lets get rid of those to get the ticks  dq ... time ... Mask with 0x3FFFFFFFFFFFFFFF

    $$  ticks in one millisecond = 10,0000, that means...

    $$ seconds== ((0n10000) * (0n1000))                            == 0n10000000 

    $$ minutes== ((0n10000) * (0n1000) * (0n60))                   == 0n600000000

    $$ hours  == ((0n10000) * (0n1000) * (0n60) * (0n60))          == 0n36000000000

    $$ days   == ((0n10000) * (0n1000) * (0n60) * (0n60) * (0n24)) == 0n864000000000

    $$

     

    $$ First lets get rid of the UTC/Flags stuff to get just the ticks

    r$t11=@$t11&0x3FFFFFFFFFFFFFFF;

     

    $$ Now get the # of Days == day count...

    r$t12=(@$t11/0n864000000000);

     

    $$ Easy... we can get the Hours

    r$t13=(@$t11 % 0n864000000000)/0n36000000000;

    $$ and Minutes

    r$t14=((@$t11 % 0n864000000000) % 0n36000000000)/0n600000000;

    $$ and Seconds

    r$t15=(((@$t11 % 0n864000000000) % 0n36000000000) % 0n600000000)/0n10000000;

     

    $$ Now for the heavy duty of figuring out days...  leap years and more fun

    $$ DaysPerYear = 365

    $$ DaysPer4Years = DaysPerYear * 4 + 1   == 1,461

    $$ DaysPer100Years = DaysPer4Years * 25 - 1 == 36,524

    $$ DaysPer400Years = DaysPer100Years * 4 + 1 == 146,097

     

    $$ t16 will have the Years...

    $$  the following lines will try to get the right number of years

    $$  which is tricky due to leap years and so the math...

    $$  first figure out the # of "400 years" + the "100 years" + "4 years" + "1 years" + 1

    $$ Days... == y400

    r$t16=(@$t12/0n146097);

    $$ n... - diff 400years

    r$t12=@$t12-(@$t16*0n146097);

     

    $$ Days... == y100

    r$t17=(@$t12/0n36524);

    $$ n... - diff 100years

    r$t12=@$t12-(@$t17*0n36524);

     

    $$ Days... == y4

    r$t18=(@$t12/0n1461);

    $$ n... - diff 4years

    r$t12=@$t12-(@$t18*0n1461);

     

    $$ Days... == y1

    r$t19=(@$t12/0n365);

     

    $$ Last year has an extra day, so decrement result if 4

    .if(@$t19==0n4){

          r$t19=0n3;

    }

     

    $$ Here now we have in t12 the day number in the current year...

    $$ n... - diff 1years

    r$t12=@$t12-(@$t19*0n365);

     

    $$ Finally!!! we know the right year

    r$t16=(@$t16*0n400)+(@$t17*0n100)+(@$t18*0n4)+(@$t19)+1;

     

    $$ Now determine if this is a Leap Year... we'll need that to get the right month/day

    r$t18=0n0;

    .if(@$t19==0n3){

          .if(@$t18!=0n24){

                r$t18=0n1;

          }

          .if(@$t17==0n3){

                r$t18=0n1;

          }

    }

     

    $$ Month and Day ...

    r$t19=0n0;

    .if(@$t18==0n0){

          $$ .printf "non-leap year";

          r$t19=12;

          .if(@$t12<=0n31){

                r$t19=0n1;

                r$t12=@$t12-0n0+1;

          }

          .elsif(@$t12<=0n59){

                r$t19=0n2;

                r$t12=@$t12-0n31+1;

          }

          .elsif(@$t12<=0n90){

                r$t19=0n3;

                r$t12=@$t12-0n59+1;

          }

          .elsif(@$t12<=0n120){

                r$t19=0n4;

                r$t12=@$t12-0n90+1;

          }

          .elsif(@$t12<=0n151){

                r$t19=0n5;

                r$t12=@$t12-0n120+1;

          }

          .elsif(@$t12<=0n181){

                r$t19=0n6;

                r$t12=@$t12-0n151+1;

          }

          .elsif(@$t12<=0n212){

                r$t19=0n7;

                r$t12=@$t12-0n181+1;

          }

          .elsif(@$t12<=0n243){

                r$t19=0n8;

                r$t12=@$t12-0n212+1;

          }

          .elsif(@$t12<=0n273){

                r$t19=0n9;

                r$t12=@$t12-0n243+1;

          }

          .elsif(@$t12<=0n304){

                r$t19=0n10;

                r$t12=@$t12-0n273+1;

          }

          .elsif(@$t12<=0n334){

                r$t19=0n11;

                r$t12=@$t12-0n304+1;

          }

    }

    .else{

          $$ .printf "leap year";

          r$t19=12;

          .if(@$t12<=0n31){

                r$t19=0n1;

                r$t12=@$t12-0n0+1;

          }

          .elsif(@$t12<=0n60){

                r$t19=0n2;

                r$t12=@$t12-0n31+1;

          }

          .elsif(@$t12<=0n91){

                r$t19=0n3;

                r$t12=@$t12-0n60+1;

          }

          .elsif(@$t12<=0n121){

                r$t19=0n4;

                r$t12=@$t12-0n91+1;

          }

          .elsif(@$t12<=0n152){

                r$t19=0n5;

                r$t12=@$t12-0n121+1;

          }

          .elsif(@$t12<=0n182){

                r$t19=0n6;

                r$t12=@$t12-0n152+1;

          }

          .elsif(@$t12<=0n213){

                r$t19=0n7;

                r$t12=@$t12-0n182+1;

          }

          .elsif(@$t12<=0n244){

                r$t19=0n8;

                r$t12=@$t12-0n213+1;

          }

          .elsif(@$t12<=0n274){

                r$t19=0n9;

                r$t12=@$t12-0n244+1;

          }

          .elsif(@$t12<=0n305){

                r$t19=0n10;

                r$t12=@$t12-0n274+1;

          }

          .elsif(@$t12<=0n335){

                r$t19=0n11;

                r$t12=@$t12-0n305+1;

          }

    }

     

    $$ Finally we have all the pieces!!! just print them...

    $$ yy-MM-dd Hour:Minute:Second

    .printf"%d-%d-%d %d:%d:%d",@$t16,@$t19,@$t12,@$t13,@$t14,@$t15;

     

    $$ FlagsMask             = 0xC000000000000000

    $$ KindUtc               = 0x4000000000000000;

    $$ KindLocal             = 0x8000000000000000;

    r$t17=poi(${$arg1})&0xC000000000000000;

    .if(@$t17==0x4000000000000000){

          .printf" (local)";

    }

    .elsif(@$t17==0x8000000000000000){

          .printf" (UTC);

    }

Page 10 of 10 (94 items) «678910