Let me continue to explain the Chinese web services. Today it is about blog. Sina provides a wide range web services. Sina blog is one of the most popular blog services in China. From its blog main page, you will see rich contents. The most interest area in the main page is the rank of bloggers.
For example, the number 1 for the current time is Xu Xiao Ming. He is so hot that his visits and followers will blow you away comparing to most western bloggers:

and Hanhan was the number one for many years. He is the most controversial person in China. He is so popular is mainly for this critics and sharp thoughts about government and current issues. He is still 8th in the rank.
Those top ones have most influence in Chinese, especially in young people. In Chinese followers or fans are called as fensi, which is a new word based on phonetic. It is interesting to see so many new words coming out almost every day. For Chinese absence just one year, they will don't know many new words when they come back. Chinese fensi love to read their their favourite blogs. It is interesting to read a long list of comments. As well, Sina provides a list of statistics about each blog, such reads, comments, forwards (copy to bloggers' blog) and favourites.

Most people just jump to their accounts to write or view blogs. On the top of Sina blog, there are some convenient links or menu items for accessing other sina services, as well as blog settings:

There is a list of menu items for personal information:

Writing blog is also very convenient. The on-line blog has a rich list of formats, photos, and videos, as well other options:


For uploading photos, you can only upload up to 20 photos per blog. Photo and video insert tool icons have other options such as reuse previous ones and web links.
Sunday, May 08, 2011
Sina Blog
Posted by D Chu at 3:57 PM 1 comments
Sunday, May 01, 2011
Web Services for Chinese Blog and Twitter
In the past couple months I have spent many hours and effort to write Chinese blogs and twitters. Chinese is my mother language so it is natural for me to write. I know there are many web services to provide features and services specially for Chinese years ago. I even registered my account in two most popular ones, creaders.net and sina.com. However, I have spent rarely much time there. The main reason to switch my attention to those Chinese web sites was the time I went back to China last Christmas time vacation.
One thing got my attention is that almost every one in China with mobile phones have QQ. QQ becomes an alternative way to communicate. QQ's provider is a company called Tencent. Like Google and Twitter, QQ was started as a hobby app for people to communicate based on MSN text message. Soon it got Chinese people attention, and it spread out allover China. With so much people on QQ everyday, now Tencent have already attract many investors and it has been doing very well financially as well.
When I was surprised by Tencent success, I was told that Tencent was actually losing market in the blogger and twitter services in Chinese. Sina was and now is the biggest blog and twitter, or weibo in Chinese, in China. Since I already had account at Sina, I gave it a try when I was in China. I have continued my blog and weibo since then. The market is so hot there. I see that many famous people like celebrities, politicians, economic scholars, popular public speakers, naming just a few of types of people, have millions followers. Each time when they post any blog, news or a phrase, they reach to people instantly. Several times of comments, forwards, and favourites happen afterwards. I was joke to one CNet tech person, who is very active in new tech review and podcasts. I told her that if she was in weibo, she would have 100 times of followers. Unfortunately, none of western hot-people know Chinese.
Anyway, the reason I write my Chinese blogs and weibos are my exploration of web in this global environment. Now the English is not dominate language on the web. Actually, if you know another or more languages, you have great advantages over other people. For example, my weibo followers are about 55, while my twitter (@chudq) has only 18. The visits to my sina blog up to today are 2494, creaders blog are 8174. I have my principle to join those services, not just to attract people or pursue number of followers. I want to write my own idea, experience and tips, in one word: sharing. The followers are actually the people have the similar interest.
In terms of features, all Chinese web services are pretty good. For example, all Chinese blog web providers have nice editors with tones of tools for layout format. One most nice feature is HTML source code editing. I can almost write any HTML codes in my blog. This makes my control much easier. Weibo is similar as twitter. You can forward tweet, comment tweet, and group your followers. You can write private messages. The most popular feature is to add pictures and videos with tweet.

As you can see, pictures worth thousand words. With this feature, you can do your message more effectively. There are so much there. Most westerns don't know what is happening in Chinese Web services. Many webs are blocked and that's reality. However, in terms of freedom and dynamics, people are more active and I can see that Chinese people are very happy with what they have now. The media is not the correct picture. Personally speaking, I think western media give westerns wrong picture about China.
Posted by D Chu at 1:17 PM 0 comments
Labels: Blog
Tuesday, April 26, 2011
My StackOverflow Reputation Over 2K
Finally today My SO reputation points are over 2K, 2008. It is a lucky number. Actually, I have not actively raised or answered any questions recently. I just keep checking my SO site and watching some questions there. That's why my points grow very slow.

Another interesting feature of SO is that you can subscribe to some user's feed to see user's activity. It is specially beneficial to following some awesome gurus. For example, I subscribed to user bbum, who is very good in ObjC and iPhone development.
Posted by D Chu at 9:44 PM 0 comments
Labels: Web Tools
Sunday, April 17, 2011
Why is DI important?
In the past week, I was asked by this question. Most people use OO strategy to write their codes. Each class or object has its encapsulated private data member and methods. They do try to separate business logic clear and narrow down only the jobs the class cares. What is Dependency Injection(DI) and why do we use DI?
I asked a similar question to another senior developer, "where do you use DI?" He told me that he only uses it in unit test as mocked objects to avoid real access to database. That's very common in unit tests. However, that's not enough. Actually DI is a very important concept and should be a common practice in our daily coding.
I recalled my previous projects and went through the pattern I used. Here is my further explanation. Take the following codes as example:
public class MyDataReader {
...
public bool ReadData() {
var dbService = new MyDbService();
....
var data = dbService.GetObject();
....
}
}
The question code is the place where dbService object is created. How many times we have seen this type creation in our classes. The class MyDataReader has dependency on MyDbService class. In other words, it knows what db service class to use. Does MyDataReader class need to know that? Isn't that better if separate this specific logic from MyDataReaer?
Now look at the following updated codes:
public class MyDataReader {
...
public bool ReadData() {
var dbService = DIContainer.GetInstance<IDBService>();
....
var data = dbService.GetObject();
....
}
}
The only change is that MyDataReader does not have knowledge of what concrete db service is any more. It passes the job to a container class to get an instance of db service which implements the interface of IDBService. If you make changes in the container, then the instance you want to be used will be able to inject to MyDataReader class. You don't need to change MyDataReader class at all. This is a typical case of DI.
By implement DI pattern, your class will be truly OO. Less coupling is a critical principle of OO. You should always to use DI container as much as possible to separate the relationship between concrete classes. To do DI coding, you do need to create your container class and following your pattern to register the relationship between interface and class.
Fortunately, there are many great DI patterns available. I wrote blogs on Structure Map and MEF. Those are great DI Containers. For sure, you need to learn those patterns and ways they require, but I think it is worthwhile. Write better and clean codes will benefit you and your applications.
Posted by D Chu at 12:26 PM 0 comments
Labels: Design Pattern
Sunday, April 10, 2011
Two Useful Excel Functions
I often use Excel as a tool for some tests or data analysis. For example, last week I tried to comparing two columns in data base to see their difference. I found out that I had an Excel as a tool to do that. This file contains some formula for column comparison. Here is summary what I did for my future reference.
First, I copied column from table 1 to a worksheet(table1), and another column from table 2 to another worksheet(table2). Then I added a formula like this in column B:
=MATCH(A2, Table1!A2:A2409, 0)
MATCH function is useful to find first parameter value from the second parameter array, and the third parameter 0 is used to find a match. The result will be the index in the array if item is found, or #NA if nothing is found.
The result will be index number or #NA. I prefer to view the result as true or false. ISNA() is a function for this purpose.



above are snapshots of NeoOffice at my iMac.
Posted by D Chu at 2:40 PM 1 comments
Labels: Excel
Saturday, April 02, 2011
Broken MSCOMRT2.OCX Caused Excel Add-in Exception
Last week I spent almost two days to resolve one issue. Excel add-in throw exceptions after an enterprise application update was installed. This happened initially in a product our team supports. The product is from a third party application suite by company C, where one Excel add-in is part of.
The symptom of the issue is that when Excel is opened, an exception is displayed right away. This one is caused by an add-in provided by the company C.
I contacted with the company which provides support the product. What they did was to remove monthview control from the add-in. It did not cause Excel error after that, however, I realized that this was not the right way to resolve the issue. The monthview is a common control from VB 6.0 control. Soon I found this control is MSCOMRT2.OCX, and there are some plains about its broken.
Soon I got calls from other department about the similar exceptions in Excel. They use different add-in and I realized that the root is to fix the control. After many discussions with other team member, I narrowed my focus on this control. I was right on this issue. I found a fix from Microsoft support knowledge base. The fix contains a cab file with only those two files:
mscomct2.inf
mscomct2.ocx
What I did was unregister the ocx file in %systemroot%/system32 first,

Then I copy those files to the path and register the ocx:

The fix seems very simple. However, at first no one knows the root of the issue. The update deployment team was afraid of the update would cause many user apps not working. I think the team work and web search played important role to get down the solution. Based on our communications on the issues and information we got, I finally found the right package as a fix.
Posted by D Chu at 6:15 PM 0 comments
Labels: Excel
Thursday, March 24, 2011
FireFox Update (4.0) and Vimperator 3.0
My favorite web browser Firefox has been updated to 4.0. I got it today. After the installation, I found that my must-have adding Vimperator has also been updated to 3.0. The new interface for Vimperator looks nice; however, my clean UI is changed. All the toolbar, navigation bar, bookmark bar and tags are visible. I would like only tabs visible.
The command to display UI bars is different. In its help page, it still says that the following command is for displaying UI bars:
:set go+=mTB
I thought I could use it to disable UI bars. There is no go settings in this new version. What I found is that the following command can be used to hide all:
:set gui=none
:set gui=tabs
The first one is to disable all UI bars and the next one is for displaying tabs bar.
Other than that, I have not found anything changed in terms of features, except some minor changes in UI. For example, the command line displays a triangle instead colon (:). Vimperator works great!
Posted by D Chu at 8:54 PM 0 comments
Labels: Vimperator
Saturday, March 19, 2011
VIM Tip: Add Syntax file for svg graphics
Today I found a graphics from Wikipedia about stomach. The graphics is a svg file, which is actually in XML. I like this type of graphics since it is a graphics in XML format. It makes it very easy to change some parts, specially some words in the graphics. I use VIM to edit the file.
Get the Syntax File
However, my MacVIM does have syntax file. I quickly found it from VIM web site, svg.vim. I saved it to my Desktop.
Copy svg.vim to Syntax Directory
According to VIM web svg.vim instruction, this file should be copied to VIM syntax directory first. At my Mac, I open my Terminal and copy the file to my vim syntax directory. My VIM's syntax directory is at ~/.vim/syntax/, where some other syntax files are, such as ps1.vim for PowerShell scripts and m.vim for Objective-C.
Add a Line to filetype.vim
The next step is to add a line to my VIM's filetype.vim file. This file is located at my local vim directory:
In my vi editor, a line is added:
" my filetype file
if exists("did_load_filetypes")
finish
endif
augroup filetypedetect
au! BufRead,BufNewFile *.ps1 setfiletype ps1
au! BufRead,BufNewFile *.m setfiletype objc
au! BufNewFile,BufRead *.svg setfiletype svg
augroup END
Load syntax file From .vimrc
The above change seems OK, but I found that I also have a line in my vim configuration file to load the syntax files. The configuration file is ~/.vimrc, where syntax files are loaded. I added a line for svg:
" Load syntax source from file
source ~/.vim/syntax/ps1.vim
source ~/.vim/syntax/svg.vim
After that, restart my VIM and I'll syntax for the svg file I want to edit:

I should say that I would not need to do above steps to edit svg files by using VIM. However, it would be nice to have correct syntax highlighting if it is available. Finally I used my VIM to edit the svg file and changed texts from English to Chinese:

Reference
See my previous blog on VIM Syntax Settings.
Posted by D Chu at 10:49 AM 0 comments
Wednesday, March 09, 2011
XCODE4.0 is Out!
Two days before iPad 2 release, today Apple released iOS4.3 for iPhone4 & iPad, as well as massive updates(I wrote a blog today about those items). The most expected XCODE 4.0 is released. I can be purchased from Mac Apple Store at $4.99, unbelievable low price comparing to Microsoft Visual Studio ($799 from MSRP for Professional version to $3,799 for Ultimate). For registered Apple Developers($99 annual fee), it is FREE!
However, this is the first time Apple charges a fee for XCODE. Mac users get XCODE with Mac computer for free. By default is not installed. It is an optional item on CD for most Mac computers, except MacBook Air(with OS X on USB). I got Air last year and I installed XCODE from my iMac CD. It runs without any problems.
I have watched many WWDC 2011 videos from iTunes. I am very impressed by XCODE 4.0 architecture and development. This is the one I am going to get soon when I have time in coming weeks. Here are some pictures of XCODE 4.0






Posted by D Chu at 10:07 PM 0 comments
Labels: iOS Development, iPhone Development, mac Software Update
Saturday, March 05, 2011
Migration of Web Sites from IIS6 to IIS7
This note is about my experience to move a web site project from IIS6 to IIS7. The project was developed in ASP.Net in VS 2005. The requirement is to move the web site from one Windows box to another one. The only difference is IIS.
At first, I just copied all the files from IIS6 box to another box. That's the way normally I deploy a web site. However, after the set up on the new box in the same file and web site configuration, the new web site got exception when I tried to access to it from IE. After about one hour exploration, I found that it was caused by a http setting in my web.config. Rick Strahl's blog has one comment on this issue: HttpModule and HttpHander Sections in IIS 7 web.config files.
As Rick said, "you've probably seen the IIS 7 Exception that lets you know that in Integrated mode in IIS 7 you are not supposed to have an httpModules or httpHandlers section", however, my case web.config is different. The following http section caused the exception:
<add path="Reserved.ReportViewerWebControl.axd" verb="*"
type="Microsoft.Reporting.WebForms.HttpHandler, Microsoft.ReportViewer.WebForms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
validate="false"/>
After I comment it out, the web site on IIS 7 is OK. This is my note on this issue. I think Rick's view is related to the migration from IIS 6 to IIS 7.
Posted by D Chu at 3:16 PM 0 comments
Labels: ASP.NET
Tuesday, February 15, 2011
Tip: Delay Seconds in Batch Script
I found this tip to delay batch progress by seconds. PING is a commonly used MS-DOS command for checking a TCP/IP client. By using PING's -n and -w options, it simulates a time delay for its running.
IF %1.==. PING 1.1.1.1 -n 1 -w 60000 > NUL
IF NOT %1.==. PING 1.1.1.1 -n 1 -w %1 > NUL
Reference: Batch file examples - Wait.
Posted by D Chu at 2:47 PM 0 comments
Labels: Batch Scripts
Saturday, February 12, 2011
.Net Project to Copy Excel Data
In the past weeks, I have been working on a project to copy Excel data between worksheets. The source worksheet contains some formulas with links to other worksheets and add-ins. The problem is that the API functions defined in add-ins take long time to get data from a remote service. When there are hundreds and even thousands of rows in Excel, it will take to long time to refresh data. That's the reason to have a scheduled job to copy the daily data from source excel file to another one with only values. Since the output put excel file contains only values, the show time is much responsive.
- Input and output excel files;
- The links in both input and output files to be rebuilt;
- Data values to be set in input file. Those values are in range object of an excel worksheet object. The values are strings or Excel formulas;
- The range of data to be copied in the input file and destination range in the output file;
- Page layout settings: display grid lines, window display headings, page area and line breaks.
Posted by D Chu at 5:46 PM 0 comments
Thursday, February 03, 2011
My EverNote Entry: OpenRasta, OpenWrap, and OWIN
Posted by D Chu at 10:09 AM 0 comments
Labels: REST web service, Web Tools
Sunday, January 30, 2011
OWIN Framework as WebService in .Net
This blog is a late post. I was on vacation back to Beijing and Wuhan during the past Christmas time and came back on Jan 16, 2011. During my time in China, unfortunately, I could not write blog since Blogger is blocked. I knew this issue and I scheduled my posts before I left. I have been busy to pick up and organize my stuff in the past week. Now I am back to normal schedule, working, web learning, doing my project and enjoying my life.
This late post is on OWIN: Open Web Interface for .Net. I got this when I listened to Hanselminute podcast #244 one day before in last December. I wrote a note in my Evernote on this(my .Net notebook).
Afterwards, I tried Kayak, an example OWIN library. The result was very exiting. I spent about 1 hour time on a console project. With its running at work, I could access to the service from any box at my work to get HTML results. My box is Windows XP Prof, which suppose not having any IIS. To install a web server is very complicated. With OWIN or Kayak, based on this testing, I could create any web service. OWIN is a very simple framework. I'll further explorer its potentials. Most likely, I will use it as a REST based service to provide data. I have many projects or apps which depends on remote data such as SCADA historian data, SQL server or Oracle database. OWIN may be excellent solution as light weighted layer to provide data.
Posted by D Chu at 2:11 PM 0 comments
Labels: REST web service
Friday, January 21, 2011
Parse and Transform Text File by Using PowerShell (3)
In my previous blog, I described who I parsed the input text file from my debug result to generate the first report table. Now Let's continue to the second report.
Generate the Second Report
The second report is another summary report, based on the first report. It displays a list of methods and counts of their calls. In other words, it will list distinct method names in the first report, and take the max counter for each method as method call count.
I find out that to get the second report, it is not easy to use just one pipeline with a long chain of segment codes. Still, I'll continue to use pipelines with each one to generate temporary results. I'll use pipelines to get temporary results, and dynamically add properties to objects.
First, initialize some variables:
# second report
# initialize variables
$totalCount = 0
$i = 0
$ht=New-Object Collections.Hashtable
The first pipeline is used to pass the result of the above collection of objects ($results) as input. There will be no result out of the pipeline. Instead, I use the pipeline to update a hash table variable $ht, with the property of method name as its key.
The input objects are piped into the second segment which is a where clause to filter any object with its count property larger than zero.
# Filter out rows with count less or equals 0
$result | where { $_.$propertyNameForCount -gt 0 } `
Then the filtered object is passed to a block of codes, where the hash table variable $ht is updated with the object with the max count value:
| Select-Object -Property 'MethodName', $propertyNameForCount `
| %{
if ( $_ -ne $null ) {
$key1 = $_.'MethodName';
if ( $ht.ContainsKey($key1) -eq $false ) {
$ht.Add($key1, $_)
}
elseif ($_.$propertyNameForCount -gt $ht[$key1].$propertyNameForCount) {
$ht.Set_Item($key1, $_)
}
}
}
The values of the hash table $ht contain objects we need for the report. In addition to those objects, I need a total count of each method call count. This is done by a pipeline to update total count into the variable $totalCount:
$ht.Values `
| %{ `
if ( $_ -ne $null ) {
$totalCount += $_.$propertyNameForCount
}
}
After we get the total count, a new object is created in the same structure of properties as ones in the hash table, then add the new object to the hash table $ht:
# add total count to $ht1 table
$objValue = New-Object PSCustomObject
$objValue | Add-Member -type NoteProperty -Name 'MethodName' -Value '[Total count]'; # use XXX so that sorting to the last
$objValue | Add-Member -type NoteProperty -Name $propertyNameForCount -Value $totalCount;
$ht.Add("XXXX dummy key", $objValue);
Finally, the objects in the hash table are ready for the second report. The report is generated by the last pipeline: sorting by property 'MethodName', adding a sequence number as object property, and appending the table layout report to the output file:
# generate report
$ht.Values `
| Sort-Object -Property 'MethodName' `
| %{ # Add sequence column
$obj = $_;
$obj | Add-Member -type NoteProperty -Name 'No.' -Value $i;
$i++;
$obj;
} `
| ft -AutoSize -Property 'No.', 'MethodName', $propertyNameForCount >> $outputFile; # Format the result and out put to file
In summary, pipeline in PS is a nice-to-have feature. You may achieve the same result without using pipeline. I like PS pipeline's simple, fluent flow and powerful feature. As you can see, PS is also dynamic data type script language. Objects can be created on-fly and properties can be added or removed during the run-time. My parse script codes take the advantage of those two great features.
Posted by D Chu at 7:29 PM 0 comments
Labels: PowerShell
Friday, January 07, 2011
Parse and Transform Text File by Using PowerShell (2)
With the previous blog on the basic concepts and the project goals on your belt, now it is time to jump into the codes from 6000 feet height.
Define Input Variables
I could set some input parameters for my script module for easy use from command line. However, since my script is only for my own use and I have to update some values frequently when I use it, then I decided to just declare some variables with initial settings as a simple start:
$inputFile = 'C:\Tmp\test\fst_PO20100505.txt';
$outputFile = '{0}.txt' -f $inputFile;
[decimal]$durationLimit = -0.01;
Then some counter variables and a hash table variable $ht for later use are initialized:
$i = 0
$j = 1
$identityExPattern = "*duration: *" # expression pattern as a filter
$exPatternForCount = "*DAO::*" # epxression pattern for count
$identityPropertyName = "Duration"
$propertyNameForCount = "DAO count"
$ht = New-Object Collections.Hashtable;
Next I output a line a header to my output file:
# Output duration limit to the result file
'==== Result of "Duration > {0}" ====' -f $durationLimit >> $outputFile;
Those codes are straightforward. The duration limit is a filter, which is used to list only calls with duration larger than the filter value.
Generate the First Report
The first report is generated by one statement with a long list of chained segments of codes as a pipeline. The result is saved to variable $result.
The first segment in the chain is to get lines from input file:
$result = Get-Content $inputFile `
Then the second segment is a block of codes %{...}. This block takes the input to process and generate empty or a collection of objects as a result. The result can be piped to the next segment. The codes in the block is very simple, it updates the line number in a varable $i, and then takes the input object as it is. $_ is a special variable notation for the input object:
| %{ $i = $i + 1;
$_;
} `
Then each line is piped to the next where constrain statement:
| where {$_.trim().length -gt 0 -and ($_.trim().SubString(0,1) -eq "[") -and ($_.trim() -like $identityExPattern)} `This constrain clause is like a filter to remove un-expected string lines. The result of this filter will be a line which is not empty, the first none-empty char is "[" and the content of the string contains a substring of "duration: ". The interested lines are then piped into the next code block %{...}.
This block contains a lot of codes. They can be divided in to two parts. The first part is to split a line into an array variable $row, and to acuminate count of each method:
$row = (-split $_ ); # split a line into array by space
$bCount = $false;
$method = $row[7]; # example: [ 5/5/2010 9:55:03 AM duration: 0.19 ] AppUserDAO::loginUser
if ( $method -like $exPatternForCount )
{
$c = 1;
# update method in hash table with count value
if ( $ht.ContainsKey($method) )
{
$c = $ht.Get_Item($method) + 1;
$ht.Set_Item($method, $c);
}
else
{
$ht.Add($method, $c);
}
$bCount = $true;
}
The second part is to create an object based on the result of the first part: $row. The object is created by using "Select ... -InputObject ... -Property" statement. The -InputObject take the array of $row as input, and -Property defines a list of properties:
# create an object with properties: sequence, datetime, duration, DAO count, and methodName
$obj = select-object -input $row -prop `
@{Name='No.'; expression={$i;}}, `
@{Name='DateTime'; expression={[DateTime]($row[1] + ' ' + $row[2] + ' ' + $row[3]);};} , `
@{Name=$identityPropertyName; expression={([decimal]$row[5]);} }, `
@{Name=$propertyNameForCount; expression={ `
if ($bCount) { `
$ht.Get_Item($method); `
} `
else { `
0; `
} `
}
}, `
@{Name='MethodName'; expression={($method);} };
$obj; #output object
The last line of $obj will pass the object to the next segment of the pipeline.
The segment is a simple where clause, which filters out any duration smaller than the expected value:
| where { $_.Duration -gt $durationLimit } `The final pipe segment is to create another object based on input object. The purpose of this new object is for the first report, each property for a column in the report:
%{
$obj1 = Select-Object -Input $_ -Property `
@{Name='No.'; expression={$j;}}, `
@{Name='Org No.'; expression={$_.'No.';}}, `
@{Name='DateTime'; expression={$_.'DateTime';};} , `
@{Name=$identityPropertyName; expression={$_.$identityPropertyName;} }, `
@{Name=$propertyNameForCount; expression={$_.=$propertyNameForCount;} }, `
@{Name='MethodName'; expression={$_.'MethodName';} };
$j++;
$obj1; # output obj1
};The result of the above chained segments is a collection of objects for the first report. The result is assigned to variable $result, and then is output to a file:
# get the reults to output file as formatted table
$result | ft -AutoSize >> $outputFile;
Posted by D Chu at 7:28 AM 0 comments
Labels: PowerShell
Saturday, January 01, 2011
Parse and Transform Text File by Using PowerShell (1)
I have used my DebugLog class to investigate issues in Visual Studio projects. The debug messages are pushed to Visual Studio's output consol. The generated messages may be very extensive huge. For example, I had a case of a Windows application with performance issues of DAO calls. I got about 8233 lines of debug messages just from the start to the main window displayed. I copied the messages to a text file. It is 732K in size. I like to keep the raw messages there; however, it was hard to investigate issues with the extensive raw messages.
What I would like is to generate concise summary reports, for example, a list of method calls with durations in an order and a list of DAO calls with their counts. This is similar to the case to use XPath to parse and to transform an XML content to another format, such as a HTML table list.
PS came to my mind first. PS is a script based language; therefore, it is easy to give it a try. I am not an expert in PS. I just use it and learn it as I need. I spent some time to write codes and finally I completed a script module to get my expected result. Here is my review of the codes.
Basic Concepts
Before I jump deep into my PS codes, I would like to list brief explanations for some basic concepts.
Single value variables are dynamically declared in PS with prefix $. The data type can also be static in the format of [type]var.
Hashtable is a dictionary data type with a key and an associated value. The constant definition is @{[key1=value1,...]} or @{}.
# is used for comments.
Statements can be either separated by line break or terminated by ';' character. ` character is used as a continuing indicator.
Piping or pipeline is a very powerful feature in PS. By using |, twp segments of codes can be chained together, the output or results of the first segment being piped into the next segment of codes as an input. Not only strings can be piped, but objects can also be passed through the pipeline. You can write similar codes without pipelines, but by using it appropriately, your scripts may look much simple and easy to read, and you may like this unique and powerful feature of PS.
There are many great resources on web. For example, the first part of this blog tutorial on PS variables, arrays, and hashtables provides nice hands-on examples on PS basics.
The Goal of my Project
I call it as a project because I want to write script codes to reach my goal. Basically, I copy my debug messages from VS output console and save them to a text file. The goal of the project is to read the text file as input, parse each line and generate a list of reports, actually two reports in this project.
The first report is a table view of methods and their corresponding duration time. The second report is a table view of interested methods and their call counts.
Here is a partial section of the raw data:
[ 5/5/2010 3:12:58 PM ] MainSchedulingTool::posMenuItem_Click
[ 5/5/2010 3:12:58 PM ] POSelectionViewForm::POSelectionViewForm
[ 5/5/2010 3:12:58 PM ] POSelectionViewForm::poStartDateTimeFilterPicker_ValueChanged
[ 5/5/2010 3:12:58 PM duration: 0.00 ] POSelectionViewForm::poStartDateTimeFilterPicker_ValueChanged
[ 5/5/2010 3:12:58 PM ] POSelectionViewForm::poEndDateTimeFilterPicker_ValueChanged
[ 5/5/2010 3:12:58 PM duration: 0.00 ] POSelectionViewForm::poEndDateTimeFilterPicker_ValueChanged
[ 5/5/2010 3:12:58 PM ] PODAO::GetAllPOsByStatusAndOrderByEndDate
[ 5/5/2010 3:12:58 PM ] PODAO::GetPOs
[ 5/5/2010 3:12:59 PM ] PODAO::ReadPOData
[ 5/5/2010 3:12:59 PM duration: 0.00 ] PODAO::ReadPOData
[ 5/5/2010 3:12:59 PM ] PODAO::ReadPOData
[ 5/5/2010 3:12:59 PM duration: 0.00 ] PODAO::ReadPOData
[ 5/5/2010 3:12:59 PM ] PODAO::ReadPOData
[ 5/5/2010 3:12:59 PM duration: 0.00 ] PODAO::ReadPOData
[ 5/5/2010 3:12:59 PM ] PODAO::ReadPOData
[ 5/5/2010 3:12:59 PM duration: 0.00 ] PODAO::ReadPOData
...
Here an example of the first report:
No. Org No. DateTime Duration DAO count MethodName
--- ------- -------- -------- --------- ----------
1 161 5/5/2010 3:12:59 PM 0.38 1 PODAO::GetPOs
2 162 5/5/2010 3:12:59 PM 0.38 1 PODAO::GetAllPOsByStatusAndOrderByEndDate
3 164 5/5/2010 3:12:59 PM 0.41 0 POSelectionViewForm::POSelection...
4 807 5/5/2010 3:13:00 PM 1.56 1 VendorDAO::GetVendorData
5 808 5/5/2010 3:13:00 PM 1.56 1 VendorDAO::GetVendors
6 1450 5/5/2010 3:13:02 PM 1.83 2 VendorDAO::GetVendorData
7 1451 5/5/2010 3:13:02 PM 1.84 2 VendorDAO::GetVendors
8 1452 5/5/2010 3:13:02 PM 1.84 0 POSelectionViewForm::setupSortedPOList
9 2575 5/5/2010 3:13:13 PM 14.13 0 POSelectionViewForm::PopulatePOData...
10 2576 5/5/2010 3:13:13 PM 14.13 0 POSelectionViewForm::POSelection...
11 2729 5/5/2010 3:13:14 PM 0.16 0 MainSchedulingTool::setupC......
The first column is a sequence number. It is a sequence line number in the report. The second is similar to the line number in the raw text file. The remaining columns are the information about each method such date time, duration value, count of DAO method calls, and method names.
The following is an example of the second report:
No. MethodName DAO count
--- ---------- ---------
0 [Total count] 6
1 PODAO::GetAllPOsByStatusAndOrderByEndDate 1
2 PODAO::GetPOs 1
3 VendorDAO::GetVendorData 2
4 VendorDAO::GetVendors 2
...
Posted by D Chu at 7:30 AM 0 comments
Labels: PowerShell
Thursday, December 23, 2010
Great Year 2010 and Embracing the New Year 2011
Year 2010 is coming to the end. I have a great year 2010. I have been working in one company as an IT consultant for the whole year. Even though the job requirement are not very challenge, I have been always set up new heights for me and continue to learn and explore new stuff in this year. This is very productive year for me. Not only I gained so much in a wide range of areas, but I also pick some of my old skills and knowledge back, such as OPC and COM in Windows. I feel very applaud of myself when I see my accomplishments.
In addition to my work, I have spent much my after-work time on personal persuasions. I think I have made great progress in my iOS development. My application is close to the finish stage. During the development, I have gained great skills and knowledge of Objective-C, Cocoa framework, and iOS. I enjoy my journey in the year of 2010. At the same time, as always, I have been keeping up with the evolution of iOS in past two years. I watched all the technical videos of WWDC 2010, and some wonderful podcasts such as CTN, and app review shows.
The most important thing I have to say about my year in 2010 is the web or internet. In a sense, it really extend my life. Without it I would spend more time and energy to struggle. I have taken so much from the web, the open community: learning, enjoying and sharing. It has enriched my life so much. I am so grateful to live in such a wonderful time and word.
I like two phrases. One is "stay hungry and stay foolish", from Steve Jobs' 2005 Stanford Commencement Address. Another one is "You Can't Take Money to Eternity", same applies to knowledge. I want to stay as I am and to share what I have. This is the way to extend human's life.
Now it is time to embrace the New Year 2011!
Posted by D Chu at 10:10 AM 0 comments
Labels: Blog
Sunday, December 19, 2010
NULL Issues in ABContact Open Source Project
I found a nice open source project for Mac/iOS Address Book data source. The project contains several key wrapper classes: ABContact, ABGroup, and ABContactsHeler. Mac OS/iOS has extensive APIs for accessing and editing AB records, but they are all C libraries. The project provides nice Objective-C wrapper classes for those libraries.
Today, I found several bugs with multi value properties. Some NULL issues in the wrapper class ABContact.m methods have not been handled. As a result, I got EXC_BAD_ACCESS exception. Basically, if a record has no multi-value property defined, for example address property, the CFTypeRef value will be NULL. The fix is very easy: checking NULL before using CFTypeRef value. Here are my updated codes:
#pragma mark -
#pragma mark Getting MultiValue Elements
- (NSArray *) arrayForProperty: (ABPropertyID) anID
{
NSArray *items = [NSArray array];
CFTypeRef theProperty = ABRecordCopyValue(record, anID);
// the return value is NULL if no multi property is defined for the record.
// therefore, check its NULL first before getting values
// Updated by David Chu, same apply to the following methods
if (theProperty != NULL ) {
items = (NSArray *)ABMultiValueCopyArrayOfAllValues(theProperty);
CFRelease(theProperty);
[items autorelease];
}
return items;
}
- (NSArray *) labelsForProperty: (ABPropertyID) anID
{
NSMutableArray *labels = [NSMutableArray array];
CFTypeRef theProperty = ABRecordCopyValue(record, anID);
if ( theProperty != NULL ) {
for (int i = 0; i < ABMultiValueGetCount(theProperty); i++)
{
NSString *label = (NSString *)ABMultiValueCopyLabelAtIndex(theProperty, i);
[labels addObject:label];
[label release];
}
CFRelease(theProperty);
}
return labels;
}
+ (NSArray *) arrayForProperty: (ABPropertyID) anID inRecord: (ABRecordRef) record
{
NSArray *items = [NSArray array];
// Recover the property for a given record
CFTypeRef theProperty = ABRecordCopyValue(record, anID);
if (theProperty != NULL) {
items = (NSArray *)ABMultiValueCopyArrayOfAllValues(theProperty);
CFRelease(theProperty);
[items autorelease];
}
return items;
}
The original codes do not check NULL cases. With those updates, my codes resume normal. In addition to NULL checking, I also make sure there is no memory leak, as the same way as the original codes do. All the copied NSArray result are set with autorelease.
Posted by D Chu at 8:56 PM 1 comments
Labels: iPhone Development
Wednesday, December 15, 2010
XCode Splash Screen
Just finished watch a short podcast show by CTN (Cocoa Touch Netcast). It is about 2 minutes show on how to enable settings for XCode Splash screen. For example, this is my XCode splash screen:

The way offered by Robert is actually to edit the plist file in /Library.... I don't like this way to modify plist file, since it may mess up the file. Instead, I prefer to use console tool or command defaults to modify it.
First, check the default setting. Open Terminal and type the command:
or use the pipe and
grep command to search for "Splash"I did not find the setting for
XCShowSplashScreen. I have never disabled my splash screen. It looks like that the default setting is to show the splash screen if the setting is not defined in plist. Then I disabled my splash screen and use the defaults read command to read it again. After that, I saw it was set to 0.To enable it, use the
defaults write command:You may check it again by
defaults read command.
Posted by D Chu at 9:44 PM 0 comments
Labels: iPhone Development
Saturday, December 04, 2010
PowerShell Tip: Dynamic Data Type
I have used PowerShell(PS) for quite a while. I really enjoy its power and great features. I did not spent time to learn PS thoroughly or systematically(such as C/C++, .Net C# or VB, or Objective-C). I just learn it by examples and by demand. The main reason is that PS covers a wide range of areas, from DOS command to .Net and other scripts. I just don't have time to learn it in a long time span.
One of PS great features is its dynamic data type. All the variables are defined by $ prefix. You can define a variable with strong data type. However, sometimes you just need to take the advantage of its dynamic data type. For example, the following code is to get files. The result may be null, one file or a collection of files:
$fs = Get-Item -Path "*.txt"
In order to find out if the result contain any file, you have to check the cases of empty, one object or a collection of objects.
$fs = Get-Item -Path "*.txt"
if ($fs -eq $null) {
Echo "empty files"
}
if ($fs.Count -eq $null) {
Echo ("one file: {0}" -f $fs)
}
else {
Echo ("collection of files. Count: {0}" -f $fs.Count)
$fs
}
Posted by D Chu at 12:39 PM 0 comments
Labels: PowerShell
XCode 3.2.5 and iOS SDK 4.2
Xcode 3.2.5 and iOS SDK 4.2 was available on November 22, 2010. I downloaded the whole package (52GB) couple weeks ago. It took me about 2hours to get the package(not sure why my Internet or browser was so slow).

I had a little trouble to compile my app after the installation, as same I did last update (3.2.5 on September 30, 2010). I had to refresh my base frameworks. This time it was much better than the previous time. I only spent about a few minutes to make my app codes working in XCode.
Posted by D Chu at 11:39 AM 0 comments
Labels: iPhone Development