戰地連結︰ Home My Flickr NBA.com About

2010年2月25日星期四

Viewing detailed Workflow history list (Hidden List)

Overview

When writing MOSS 2007 Workflow, you can log events (e.g. Log exceptions detail for debugging) to workflow history, which can be view in the task item page.

However, the task item page only shows simplified version of workflow history item. To view detailed workflow history list. You will have to enter the URL of the hidden list, in the format shown below:
http://[servername]/[sitename]/lists/Workflow%20History

For example if your site’s default page is:

http://servername/sites/sitename/default.aspx

then the detailed workflow history list URL will be:

http://servername/sites/sitename/lists/Workflow%20History

2010年2月3日星期三

Getting selected RadioButton value

Overview

Stephen Gray has a post about getting selected RadioButton value in Flex. It points out the use of RadioButtonGroup.

Reference

Flex getting selected RadioButton value

Steps

Source from Stephen Gray’s blog post:

  1. Create a “RadioButtonGroup” MXML tag and give a id to it.
  2. Assign the RadioButtons’ “groupName” attribute to point to the RadioButtonGroup at step 1 (remember to use “{}”)
    <mx:RadioButtonGroup id="myRadioButtonGroup" enabled="true" />
    <mx:RadioButton label="I like RadioButtons" groupName="{myRadioButtonGroup}" left="505" top="64" selected="true" value="true"/>
    <mx:RadioButton label="I don't like RadioButtons" groupName="{myRadioButtonGroup}" left="348" top="62" value="false"/>
  3. Access the selected value by the RadioButtonGroup
    Alert.show(myRadioButtonGroup.selectedValue.toString());

2009年10月9日星期五

PHP crash with some MySql functions

Overview

I has been playing with a WAMP web site using Joomla 1.5 as the CMS. Actually I am just doing the setup when I encounter this issue. When I reached the “Database Configuration” step in Joomla installation, Apache keeps crashing when I proceeded, and the Event Log said that:

Faulting application httpd.exe, version 2.2.11.0, faulting module > php5ts.dll, version 5.2.10.10, fault address 0x0000ac6a.

Again, with some Googling I found that I am not alone and there are several solutions for this issue, which is caused by wrong "libMySql.dll" module used.

Both MySQL and PHP provides the "libMySql.dll" module. When using PHP, we should use the "libMySql.dll" module provided by PHP, but not MySQL.

Reference

PHP Installation, MySQL

php使用MySql函数导致Apache(iis)崩溃的问题

PHP Crash when use some mysql function

Steps

There are several ways to solve this problem, I use the first method:

  • Rename the "libMySql.dll" file located at your MySQL “<InstallDir>/bin” folder
  • Remove your MySQL “<InstallDir>/bin” folder path from the system’s path environment variable
  • Copy the "libMySql.dll" file from your PHP install folder to “%SystemRoot%/system32” folder

2009年10月7日星期三

Unlock files used by processes

Overview

I think most of the Windows users have seen the screen saying that “Cannot delete XXX: It is being used by another person or program”. This is quite annoying as you don’t have a clue what is actually locking the file. Now I would like to share some of the programs I used (or heard) to solve this problem.

Reference

Unlocker - http://ccollomb.free.fr/unlocker/

It is a very nice program which add a extensions to your Windows Explorer, so that you can right-click on any file/folder and select the “unlocker” option. It will shows all processes locking the file for your to decide what to do next. However the latest version (1.8.7) does not supports 64-bit OS.

LockHunter - http://lockhunter.com/

LockHunter is a similar tool to Unlocker, Windows Explorer extensions. However it works for both 32-bit and 64-bit OS, and it delete files to recycle bin.

Process Explorer - http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx

Finding what files (handles) is used by a process is just one of the features of Process Explorer. As it actually shows much more information than the list of handles used. Because it is more powerful, it is also more complicated to use.

To use Process Explorer for unlocking files from processes, following the steps below:

  1. Select "Find" –> "Find Handle or DLL"
  2. Enter the full path of the file as the Handle substring, click "Search"
  3. For each of the search results that match the file you want to delete, right-click on the handle and choose "Close Handle"
  4. Done! However I recommend using “LockHunter” if you ONLY want to unlock files. ;-)

2009年9月16日星期三

Single Sign-on for ASP.NET 3.5 and Legacy ASP

Overview

I got a task on setting Single Sign-on (SSO) for a ASP.NET site and legacy ASP site. For this, Ting Huang has written a very nice post on wwwcoder.com. The idea behind is to create a “bare bone” API for the FormsAuthentication class (without the need of HttpContext), and wrap it in a COM object, which can be used by ASP page. However the post is regarding ASP.NET 1.1 and I am using ASP.NET 3.5, for which the FormsAuthentication class is quite different.

With some more googling I found the way to manually create the authentication ticket, encrypt it and save it to cookie. Using these technique I can make a ASP page create a authenticate cookie which can be consumed and recognized by a ASP.NET web application.

Reference

  1. Creating a Single Sign-on for ASP.NET Application and Legacy ASP Application (Part II)
  2. Single Sign-On for everyone
  3. AppDomainSetup.ConfigurationFile Property

Steps

Write the “bare bone” API for the FormsAuthentication class

using System;

using System.Web.Security;

 

namespace SingleSignon

{

    public class AuthAPI

    {

        public AuthAPI()

        { }

 

        public string FormsCookieName

        {

            get { return FormsAuthentication.FormsCookieName; }

        }

 

        public void Initialize()

        {

            FormsAuthentication.Initialize();

        }

 

        public string SetAuthCookie(

              string userName,

              bool createPersistentCookie)

        {

            try

            {

                FormsAuthentication.SetAuthCookie(userName, createPersistentCookie);

                return "success";

            }

            catch (Exception e)

            {

                return "error: " + e.Message;

            }

        }

 

        public string GetAuthCookieValue(

              string userName,

              bool createPersistentCookie

            )

        {

            try

            {

                FormsAuthenticationTicket newticket = new FormsAuthenticationTicket(userName, createPersistentCookie, 30);

                return FormsAuthentication.Encrypt(newticket);

            }

            catch (Exception e)

            {

                return "error: " + e.StackTrace;

            }

        }

 

        public void GetAuthTicketInfo(

            string cookieValue,

            out string cookiePath,

            out string expireDate,

            out bool expired,

            out bool isPersistent,

            out string issueDate,

            out string userName,

            out string userData,

            out int version

            )

        {

            FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookieValue);

            cookiePath = ticket.CookiePath;

            expireDate = ticket.Expiration.ToShortDateString();

            expired = ticket.Expired;

            isPersistent = ticket.IsPersistent;

            issueDate = ticket.IssueDate.ToShortDateString();

            userName = ticket.Name;

            userData = ticket.UserData;

            version = ticket.Version;

        }

    }

}

Setup web.config file for Forms Authentication

<authentication mode="Forms">

  <forms name="DEMO" loginUrl="login.aspx" protection="All" timeout="30" path="/" />

</authentication>

<authorization>

  <deny users="?" />

</authorization>

<machineKey validationKey='9804…CB69' decryptionKey='FEA…D648' validation='SHA1'/>

Be reminded to set the "machineKey" for the ASP.NET web application and share it with legacy ASP site.

Add “AuthAPI” assembly to Global Assembly Cache (GAC) and register it as a COM object

The legacy ASP site is going to use the AuthAPI through COM interface, so we should first register the API as a COM object. To do this, we have to:

  1. Sign the assembly
  2. Add the assembly to GAC. I use the “gacutil.exe” tool at
    C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil.exe
  3. Register the assembly as a COM object. Use “regasm” tool at
    C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\regasm

Indeed you can use the "Post-build event command line" in Visual Studio to do these actions every time you rebuild the assembly. Just remember to unregister the COM object and uninstall the assembly from GAC first.

Setup/Create the “dllhost.exe.config” file for the legacy ASP site

You may wonder how the “AuthAPI” load the Forms authentication settings, does it read from the web.config file of the ASP.NET web app? No, actually it does not have any linkage to the web app. So how can we know which config file is the AuthAPI looking for? We can get the file path from “AppDomain.CurrentDomain.SetupInformation.ConfigurationFile”, and it turns out to be a config file at “C:\WINDOWS\system32\dllhost.exe.config”. It make sense as “dllhost.exe” is the “DCOM DLL Host Process”.

OK so we have to edit this “dllhost.exe.config” file to configure the FormsAuthentication component of “AuthAPI”. You may not see this file in “C:\WINDOWS\system32\”, so just create it and put the Forms authentication configuration in it.

Sample of “dllhost.exe.config” file

<configuration>

  <configSections>

    <sectionGroup name="system.web.extensions" type="System.Web...">

      <!-- Copy all settings from web.config file -->

    </sectionGroup>

  </configSections>

  <system.web>

    <!-- Copy Forms Authentication settings and Machine key from web.config file -->

  </system.web>

</configuration>

Use “AuthAPI” in legacy ASP site to create a Cookie with valid authentication ticket

Now we have the COM object setup and configured, we can use it in our legacy ASP site. The following code shows the function of creating a authentication ticket and putting it into a Cookie. If the ASP.NET web app and the legacy ASP site share the same domain. The Cookie will be shared between them and the Single Sign-on is achieved!

<body>
 
    <%          
            Set ulogin = Server.CreateObject("SingleSignon.AuthAPI")
            userName = "TestUser"
            Call ulogin.Initialize()
            response.write("FormsCookieName: " + ulogin.FormsCookieName() + "<br>")
            
            authCookieValue = ulogin.GetAuthCookieValue(userName, true)
            response.write("AuthCookieValue: " + authCookieValue)
            
            Call AddCookie ( ulogin.FormsCookieName(), "", authCookieValue, 30, "")
            set ulogin = nothing
    %>
 
</body>

2009年9月9日星期三

Disabling Time Synchronization under Virtual PC 2007

Overview

VPC with Virtual Machine Additions installed will automatically synchronize its time with host. Virtual PC Guy tells us how to disable it in his post.

Reference

Disabling Time Synchronization under Virtual PC 2007

Steps

  1. Shut down the VPC (I found that cannot use “Save state”)
  2. Open the .VMC file with notepad and add the "components" element in it:

    <integration>

      <microsoft>

        <mouse>

          <allow type="boolean">true</allow>

        </mouse>

        <!--Add the "components" element-->

        <components>

          <host_time_sync>

            <enabled type="boolean">false</enabled>

          </host_time_sync>

        </components>

  3. Save the .VMC file and restart VPC, done!

Associate XSD to XML file to enable IntelliSense

Overview

We .Net developers use IntelliSense extensively in our everyone work. I am happy using IntelliSense for XML files like web.config file. Then one day I come across a XML file with schema not available out-of-the-box from VS (think about NHibernate hbm files). How can I use IntelliSense with it?

Reference

XML Schemas dialog in Visual Studio 2008

Steps

To use schema(s) for a XML file

  1. Open a XML file in Visual Studio 2008
  2. In menu bar, select "XML" => "Schemas…"
  3. In the "XML Schemas" windows, select "Use this Schema" in the "Use" column next to your desired schema
  4. Click OK, done!

The "XML Schemas" windows will search for schema files (.XSD) in your project or in folder %VS 2008 install folder%\xml\Schemas. You can also manually add schemas files using the "Add…" button