Simon Mourier's WebLog

.Net tools and sample code

  • Introducing SkedView: how to view BizTalk orchestrations without Visual Studio installed!

    This is a very lightweight .net 1.1 winform application that graphically displays a BizTalk Server 2004 orchestration from an assembly in a given path or in the Global Assembly Cache (GAC) just like in Health and Activity Tracking (HAT) or Visual Studio.Net, but *without* Visual Studio installed. It is especially useful in production server environment for example to quickly check currently deployed orchestrations. It needs BizTalk server 2004 (but not Visual Studio) to be installed of course.


    Binaries and source code package is available here or here.

    It uses undocumented BizTalk winform controls, so it may not work in the future. Use at your own risks! I am also preparing a version that does not need BizTalk assemblies at all. If you are interested, please drop me a note, I would be happy to know about that.

    PS: Oh, by the way, make sure you stop by the cool "BizTalk 2004 Administration Management Tool" written by Paul Somers available here

  • Introducing Visual SourceSafe Web Explorer and Web Service

    My good friend Omid has already written one available here http://blogs.msdn.com/obayani/archive/2003/06/11/8549.aspx, but it has some limitations and especially in terms of performance. If you want to index your SourceSafe database using SharePoint Portal Server 2003 for example (or any other valid web crawler), it may not work very well.

    Here are the basic features of this one:

    * based on ASP.Net IHttpHandler technology. Every file, project or version is accessible using a unique Url.
    * get file or project information (including length and last write time)
    * get file's history (versions)
    * get file's content (as well as item's old versions content)
    * a Web Service is also provided to get the same item or project information, history and content using SOAP

    And here are the specific features:

    * the web site running the handler can run as NT AUTHORITY\NETWORK_SERVICE (the default for W3WP.exe ASP.Net host process on Windows Server 2003), there is not need for a "real" account
    * no write access to the VSS database needed
    * no VSS account needed
    * no working folder needed
    * supports of client Browser's cache to minimize network usage

    There is still no support for any write operations (checkout, checkin, ...) and nothing planned for this in the future. And there is not the cool .cs coloration feature either (Omid's one does it). Of course, the VSS client (6.0d please) needs to be installed on the IIS Server. The handler has been tested on Windows Server 2003 only.

    If you use SharePoint Portal Server 2003 and you want to index your VSS database, you will need to tell the SPS search engine how to index .cs file (or .vb) for example. This is very simple. Just copy the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SPSSearch\ContentIndexCommon\Filters\Extension\.txt to a new registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SPSSearch\ContentIndexCommon\Filters\Extension\.cs (for .cs file). This way, .cs files will be indexed as plain text file, which is in general fine. If anyone is aware of a specific .cs IFilter that would skip C# keywords, please post a link here!

    This is what a .reg file to register the .cs extension would contain:

    Windows Registry Editor Version 5.00

    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SPSSearch\ContentIndexCommon\Filters\Extension\.cs]
    @=hex(7):7b,00,41,00,33,00,37,00,33,00,45,00,35,00,44,00,39,00,2d,00,37,00,41,\
      00,38,00,37,00,2d,00,31,00,31,00,44,00,33,00,2d,00,42,00,31,00,43,00,31,00,\
      2d,00,30,00,30,00,43,00,30,00,34,00,46,00,36,00,38,00,31,00,35,00,35,00,43,\
      00,7d,00,00,00,00,00,00,00


    The Visual SourceSafe Web Explorer (and associated Web Service) is downloadable here http://www.codefluent.com/smourier/vsswe.htm. Just run the .exe or the .msi file, read the Readme.Rtf, and post a comment here if you are happy with it. Huh... do not post if it does not work :-)

    PS: Oh, by the way, make sure you stop by the Visual SourceSafe team blog here http://blogs.msdn.com/checkitout/ where you will find VSS PowerToys.

  • Introducing "ActiveX Scripting WebPart" for SharePoint technologies...

    !! Update 12/15/05 !! This blog will be discontinued someday. A new blog were comments are available has been created here.

    Yes, this sounds heretic, and it probably is :-) This is a generic sample (use it at your own risk :-) WebPart for SharePoint technologies (means it works for Microsoft Windows SharePoint Services as well as Microsoft SharePoint Portal Server 2003) that runs an ActiveX Scripting code on the server.
    By default, VBScript and JScript (a.k.a JavaScript) are supported on decent Windows installations, but nothing prevents you from using Python, Perl or other languages that have an ActiveX Scripting existence. Here is an example of such a code (in VBScript) that displays the user name and the current date:

    Sub Render(writer)
        writer.Write "User: " & Context.User.Name & "<br>"
        writer.Write "Date: " & Now
    End Sub

    Binaries and Source code can be downloaded from here

    Installation:
    --------------------------------------------------------------------------------
    The WebPart can be installed using SharePoint standard deployment tools:

    "%CommonProgramFiles%\Microsoft Shared\web server extensions\60\BIN\stsadm"
     -force -o addwppack -filename ActiveScript.Web.UI.cab
     -url
    http://serverNameGoesHere
     
    Or (GAC installation)

    "%CommonProgramFiles%\Microsoft Shared\web server extensions\60\BIN\stsadm"
     -force -o addwppack -filename ActiveScript.Web.UI.cab
     -globalinstall -url
    http://serverNameGoesHere

    The WebPart caches a compiled version of the scripts. If you want to disable this cache, just add the following to your web.config:
    <appSettings>
     ...
     <add key="ScriptCachingMode" value="disabled" />
     ...
    </appSettings>


    Usage:
    --------------------------------------------------------------------------------
    Using the standard WebPart modification tools provided by the SharePoint WebPart Framework (Design Page, Browse, Modify, ToolPane, ...), you can switch the WebPart from Edit Mode to Run Mode. In Edit mode, you can type the script code directly into the provided TextArea.
    This script code can be put in the main procedure (the one that is not inside a declared procedure, sub or function). In this case, it will run probably at Page initialization. For example, the following script code will render the current user's login name *before* the first <html> declaration:

    Context.Response.Write Context.User.Name

    Or it can be placed inside predefined "Emulated" function. Supported emulated functions prototypes are (the syntax here is in VBScript):

    Sub OnInit()
    ' Code put here will run in the OnInit method
    ' of the ActiveX Scripting WebPart
    End Sub

    Sub OnLoad()
    ' Code put here will run in the OnLoad method
    ' of the ActiveX Scripting WebPart
    End Sub

    Sub OnPreRender()
    ' Code put here will run in the OnPreRender method
    ' of the ActiveX Scripting WebPart
    End Sub

    Sub Render(writer)
    ' Code put here will run in the Render method
    ' of the ActiveX Scripting WebPart
    ' The Writer object has only one Write(object obj) method
    ' see the example at the beginning
    End Sub

    Sub OnUnload()
    ' Code put here will run in the OnUnload method
    ' of the ActiveX Scripting WebPart
    End Sub


    "Emulated" ASP.Net Object Model:
    --------------------------------------------------------------------------------
    As already demonstrated before, the script code recognizes one "named object" (in ActiveX Scripting terminology) which is "Context" (sounds familiar?). From this context object, the ActiveX Scripting WebPart provides limited support for an "emulated" ASP.Net HttpContext object model. Please consult ASP.Net documentation for details on the following properties and methods.

    Legend:
     +:  Class
     R:  Read Only property
     RW: Read Write property
     M:  Method):

    + Context
      + Cache
        M  void Insert(string key, object value)
        M  object Get(string key)
        R  int Count
        M  object Remove(string key)
       
      + Request
        R  int ContentLength
        R  string CurrentExecutionFilePath
        R  bool IsAuthenticated
        R  bool IsSecureConnection
        R  string Path
        R  string PathInfo
        R  string PhysicalApplicationPath
        R  string PhysicalPath
        R  string RawUrl
        R  string RequestType
        R  int TotalBytes
        R  string UserHostAddress
        R  string UserHostName
        M  void ValidateInput()
        M  void SaveAs(string filename, bool includeHeaders)
        M  void MapPath(string virtualPath, string baseVirtualDir,
         bool allowCrossAppMapping)
        R  string UserAgent
        R  string HttpMethod
        R  string ContentType
        RW Encoding ContentEncoding
        R  string ApplicationPath
        R  string FilePath   
     
      + Response
        RW bool SuppressContent
        R  bool IsClientConnected
        RW bool Buffer
        RW bool BufferOutput
        RW string StatusDescription
        RW string Charset
        RW string Status
        RW string CacheControl
        RW string RedirectLocation
        RW int Expires
        RW DateTime ExpiresAbsolute
        RW string ContentType
        RW Encoding ContentEncoding
        RW int StatusCode
        M  void AddHeader(string name, string value)
        M  void AppendHeader(string name, string value)
        M  void AppendToLog(string param)
        M  void ApplyAppPathModifier(string virtualPath)
        M  void BinaryWrite(byte[] buffer)
        M  void Pics(string value)
        M  void SetCookie(string name, string value)
        M  void TransmitFile(string filename)
        M  void Clear()
        M  void ClearContent()
        M  void ClearHeaders()
        M  void Close()
        M  void End()
        M  void Flush()
        M  void Redirect(string url, bool endResponse)
        M  void Write(object obj)
       
      + Server
        R  string MachineName
        R  int ScriptTimeout
        M  void ClearError()
        M  object CreateObject(string progID)
        M  object CreateObjectFromClsid(string clsid)
        M  string HtmlDecode(string s)
        M  string HtmlEncode(string s)
        M  string MapPath(string path)
        M  void Transfer(string path, bool preserveForm)
        M  string UrlDecode(string s)
        M  string UrlEncode(string s)
        M  string UrlPathEncode(string s)
       
      + Session (no method implemented so far..., coding anyone ?)

      + Trace
        R  TraceMode TraceMode
        R  bool IsEnabled
        M  void Write(string message)
        M  void Warn(string message)
       
      + User
        R  string Name
        R  string AuthenticationType
        R  bool IsAuthenticated
        M  bool IsInRole(string role)


     

  • .NET Html Agility Pack: How to use malformed HTML just like it was well-formed XML...

    !! Update 06/08/18 !! Html Agility Pack has a new home on CodePlex! Available here. CodePlex is great :)

    !! Update 05/05/05 !! Visual Studio 2005 Beta2 version is available here

    !! Update 05/23/05 !! This blog will be discontinued. A new blog were comments will be available has been created here.

    Here is an agile HTML parser that builds a read/write DOM and supports plain XPATH or XSLT. It is an assembly that allows you to parse "out of the web" HTML files. The parser is very tolerant with "real world" malformed HTML. The object model is very similar to what proposes System.Xml, but for HTML documents (or streams).

    Sample applications:
    * Page fixing or generation. You can fix a page the way you want, modify the DOM, add nodes, copy nodes, you name it.
    * Web scanners. You can easily get to img/src or a/hrefs with a bunch XPATH queries.
    * Web scrapers. You can easily scrap any existing web page into an RSS feed for example, with just an XSLT file serving as the binding. An example of this is provided.

    There is no dependency on anything else than .Net's XPATH implementation. There is no dependency on Internet Explorer's dll or tidy or anything like that. There is also no adherence to XHTML or XML, although you can actually produce XML using the tool.

    For example, here is how you would fix all hrefs in an HTML file:

    HtmlDocument doc = new HtmlDocument();
    doc.Load("file.htm");
    foreach(HtmlNode link in doc.DocumentElement.SelectNodes("//a[@href"])
    {
       HtmlAttribute att = link["href"];
       att.Value = FixLink(att);
    }
    doc.Save("file.htm"); 

    You can download it here (link updated 12/12/04), full code source and doc included!

  • Introducing TraceServer: distributes your standard .Net traces on your network.

    I have just finished a tool called TraceServer (what a terrific name) that allows you to use distributes all you standard .Net Traces for new or existing applications to any remote machines listening for it. The trace distribution includes code source and stack frame information as well.

    You can have multiple servers collecting standard .Net traces for one machine, and multiple clients connected to any number of these servers, receiving their traces.

    People like me who hate debugging do need that sort of stuff!
    The source and a small doc is available here.

  • TaskSwitch.exe like: PreviewWindow(...);

    Ever wanted to known how the Windows XP powertoy TaskSwitch.exe (available here http://www.microsoft.com/windowsxp/pro/downloads/powertoys.asp) does the window preview trick? It uses a new to Windows XP and Windows .Net server API called PrintWindow. Perf is not that great though...

    The following C# code does the same. I have not copied the full interop P/Invoke code, if you're interested, drop me a note.

    public static void PreviewWindow(
     IntPtr previewWindowHandle,
     int destinationX,
     int destinationY,
     int destinationWidth,
     int destinationHeight,
     IntPtr targetDeviceContext)
    {
     // Take a snapshot of the window hwnd, stored in the memory device context hdcMem
     IntPtr hdc = GetWindowDC(previewWindowHandle);
     if (hdc != IntPtr.Zero)
     {
      IntPtr hdcMem = CreateCompatibleDC(hdc);
      if (hdcMem != IntPtr.Zero)
      {
       // get target window size
       RECT rc;
       GetWindowRect(previewWindowHandle, out rc);

       IntPtr hbitmap = CreateCompatibleBitmap(
        hdc,
        rc.right - rc.left,
        rc.bottom - rc.top);
       if (hbitmap != IntPtr.Zero)
       {
        SelectObject(hdcMem, hbitmap);

        // Do the magic
        PrintWindow(previewWindowHandle, hdcMem, 0);

        // Copy bits
        StretchBlt(
         targetDeviceContext,
         destinationX,
         destinationY,
         destinationWidth,
         destinationHeight,
         hdcMem,
         0,
         0,
         rc.right - rc.left,
         rc.bottom - rc.top,
         SRCCOPY);

        DeleteObject(hbitmap);
       }
       DeleteObject(hdcMem);
      }
      ReleaseDC(previewWindowHandle, hdc);
     }
    }

    // this is how you can use it in Winform code (beware the perf and add some error checks!)
    protected override void OnPaint(PaintEventArgs pe)
    {
     Graphics g = pe.Graphics;
     IntPtr hdc = g.GetHdc();

     // previewhandle is a choosen window in the client desktop
     Native.Preview(_previewHandle, 0, 0,  ClientSize.Width, ClientSize.Height, hdc);

     // cleanup
     g.ReleaseHdc(hdc);
    }

  • Debugging process considered harmful

    The following is a result of personal experience on a number of projects:

    * First of all, in general, you cannot install the debugger where the application you are developping will ultimately run. If you are writing a desktop application, there is no way you will be able to install a decent debugger there. If you are writing a server application, the operation team will probably not let you install the debugger of your choice on production servers! If you are lucky, you will be able to install a simplified debugger, like WinDbg that has almost no side effect. WinDbg just works for unmanaged code so far. I do not know any good standalone .Net debugger yet (w/o installing Visual Studio, that is). This is a real issue. If you have put all your debugging efforts in the Visual Studio debugger, putting your application in production is like sending a spaceship towards Mars without any communication with the ship: welcome to the unknown.

    * Now, let's get back to the development phase. You have to think that, when someone debugs, he just works for himself. Debugging may only be benefitial to one person. There is no way to transfer the work he has done (setting breakpoints, stepping into code, ...) and the knowledge he has acquired on the program he was debugging (if any...) to someone else.
    In a team development mode, the time spent by one individual on debugging is simply lost for the rest of the team.

    * When someone debugs, he just does the same things (stepping) over an over agin, loosing precious time. He is just exchanging development (creativity) time with stupid "stepping" time. This is actually depending on the competency of the guy. A good developer will use good watches, good breakpoints and advanced debugging techniques. He will therefore loose less time than a beginner developer. Thus the next point:

    * To debug efficiently, a developer needs to master a debugger, or worse a certain number of debuggers. Debuggers do not follow any real standards, beside some de facto common UI. Training should be required to be able to debug efficiently.

    * If you manage developers and just take a look at the time the average developer in your team spends in the debugger, you should do something! But you can't because Debugging trainings are very very rare and Debugging books are very rare too. Here are two decent books about debugging http://www.amazon.com/exec/obidos/tg/detail/-/0735615365/ and http://www.amazon.com/exec/obidos/tg/detail/-/1590590503 (not only for vb.net)


    This explains why I almost never debug. And I think my productivity is greatly enhanced. I trace everything. I agree this is not ideal (some call it "printf debugging"...), but that's just because no technical progress has been made in this domain. Today, putting traces everywhere is really prehistoric work. But that does not mean traces are bad, it just means nothing is there to help us add traces automatically to our code. I would like to be able to tell to the C# compiler: "put traces here and here, please remember the values of the parameters automatically, just like you do when I debug. Please add a hierarchical trace of this object, and please record all that that so I can replay it later, add filters, and so on...". That service should be provided by the CLR, IMHO.

  • IHttpHandler sample: a .ZIP File handler (again)

    Duh ... The previous post on this subject has simply disappeared (I should say I was testing w.bloggar...). Here is what was said.

    This tool (provided with source) is an IHttpHandler sample that, once installed on an Internet Information Server, allows client browsers to browse .Zip files seamlessly.

    Directories in the ZIP file are shown (by default - this setting can be switched off) the same way that IIS shows "real" directories. If the users browses any file in the .Zip archive file, the file will be downloaded naturally (with proper handling of Last-Modified Http headers).

    This handler can also use a cache directory to speed things up.

    For reading .ZIP files, it is based on the famous http://www.zlib.org accessed through P/Invoke call (it is actually a special version I have very slightly modified that does not force us to use UNSAFE C# compilation. I can provide the modified source for those who would like to have it). By the way, the code provides a full blown unzip C# interface that can be reused in non HTTP contexts. Updating and creating .ZIP file is not handled, only reading.

    Binaries and source code are available here http://www.codefluent.com/smourier/zhh.htm.

    Note: the links proposed for the demo are defined as .vsdisco file, this is to avoid defining a new association between ASP.Net's ISAPI filter (aspnet_isapi.dll) and .ZIP (less work for hosters).

    There was a question from Don Box about the performance between zlib and the Zip classes provided with J# redist. I would hardly imagine the J# implementation being faster than the zlib I used. This zlib (32bits X86) has been specially optimized with asm code. See http://www.winimage.com/zLibDll/unzip.html for more on this.

     


© 2009 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement
Microsoft
Page view tracker