Author Archives: Zhou Renjian

Create a Process and Read Its Output

This is a snippet of windows C++ code to create a process and read its output until some specific string is printed. This is useful for programmer to start a server and only to return until the server is started, as sometimes server may take some seconds to initialize.

BOOL CreateProcessAndWait(char* cmdline, int flag,
STARTUPINFO *si, PROCESS_INFORMATION *pi,
const char* keyString)
{
HANDLE hOutputReadTmp,hOutputRead,hOutputWrite;
HANDLE hErrorWrite;
SECURITY_ATTRIBUTES sa;

// Set up the security attributes struct.
sa.nLength= sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;

// Create the child output pipe.
if (!CreatePipe(&hOutputReadTmp, &hOutputWrite, &sa,0)) {
printf("CreatePipe\n");
}
// closes one of its std output handles.
if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite,
GetCurrentProcess(),&hErrorWrite,0,
TRUE,DUPLICATE_SAME_ACCESS))
printf("DuplicateHandle");
// Create new output read handle and the input write handles.
// Set the Properties to FALSE. Otherwise, the child inherits
// the properties and, as a result, non-closeable handles to
// the pipes are created.
if (!DuplicateHandle(GetCurrentProcess(),hOutputReadTmp,
GetCurrentProcess(),
&hOutputRead, // Address of new handle.
0,FALSE, // Make it uninheritable.
DUPLICATE_SAME_ACCESS))
printf("DupliateHandle");

ZeroMemory(si, sizeof(STARTUPINFO));
si->cb = sizeof(STARTUPINFO);
ZeroMemory(pi, sizeof(PROCESS_INFORMATION));
flag = CREATE_NEW_PROCESS_GROUP | flag;
si->dwYCountChars = 5000;
si->dwFlags |= STARTF_USECOUNTCHARS;
si->dwFlags |= STARTF_USESTDHANDLES;
si->hStdOutput = hOutputWrite;
si->hStdError = hErrorWrite;

int ret = CreateProcess(NULL,
cmdline, /* command line */
NULL, /* Security */
NULL, /* thread */
TRUE, /* inherit handles */
flag, /* start flags */
NULL, /* winenv, */
NULL, /* current directory */
si, pi);
if (ret != -1)
{
CHAR lpBuffer[256];
DWORD nBytesRead;
DWORD keyLength = strlen(keyString);
DWORD index = 0;
memset(lpBuffer, 0, sizeof(lpBuffer));

DWORD dwTimeoutThreadId;
HANDLE hTimeoutThread = CreateThread(
NULL, // no security attribute
0, // stack size, BUGBUG:Try to use the limit size!
(LPTHREAD_START_ROUTINE) TimeoutThread,
(LPVOID) pi->hProcess, // thread parameter
0, // not suspended
&dwTimeoutThreadId); // returns thread ID

if (hTimeoutThread == NULL)
{
printf("No time out thread for specific string %s.\n",
keyString);
}
else CloseHandle(hTimeoutThread);

while(TRUE)
{
if (ReadFile(hOutputRead,lpBuffer + index,
sizeof(lpBuffer) - index,
&nBytesRead,NULL) && nBytesRead)
{
if ((index + nBytesRead >= keyLength)
&& strstr(lpBuffer, keyString))
{
break;
}
if (index + nBytesRead > sizeof(lpBuffer)
- keyLength) {
// move
for (DWORD i = 0; i < keyLength; i++) {
lpBuffer[i] = lpBuffer[index + nBytesRead
- keyLength + i];
}
index = keyLength;
memset(lpBuffer + keyLength, 0,
sizeof(lpBuffer) - keyLength);
} else {
index += nBytesRead;
}
}
}
}
return ret;
}

Posted in C++, Snippet, Tricks | Comments Off on Create a Process and Read Its Output

Why JavaScript’s Date#getMonth Start From Zero?

Today, one of my colleague asked me a question about JavaScript’s document.lastModified, here was my answer for her:

javascript:dd=new Date(document.lastModified);alert(dd.getFullYear() + “.” + (dd.getMonth() + 1) + “.” + dd.getDate() + “//” + dd.getHours() + “:” + dd.getMinutes() + “:” + dd.getSeconds());

Then she asked me why #getMonth should plus one why others need not. I knew that from the ECMAScript specification, Date#getMonth start from 0 to 11, representing January to December, but I couldn’t answer her question, cause I couldn’t figure out why only #getMonth needs such a hacks which confuse a lot of developers.

After searching a lot on Internet, I got nothing and gave up to found out why. Maybe those specification designers were C or C++ developers who always thought things should start from zero.

Posted in JavaScript, Tricks | Comments Off on Why JavaScript’s Date#getMonth Start From Zero?

RSE Sucks

I do think that Remote System Explorer (RSE)? sucks for its plugin management. Too many small size (about 10k – 20k) plugins, about 42 plugins (about 30 core plugins), while all Eclipse SDK plugins number is 141.

Posted in Eclipse, Project Management | Comments Off on RSE Sucks

Backup and Restore Databases in MySQL

Just simple as following:

mysqldump -h host -u user -p –databases db > dbbackup

mysqldump -h host -u user -p

CREATE DATABASE restored;

mysql -h host -p -u user restored < dbbackup

Posted in MySQL | Comments Off on Backup and Restore Databases in MySQL

Upgrade to WordPress 2.2

My blog is based on WordPress. Today I saw that there was a new version of 2.2, and decided to upgrade. As there are chances to upgrade frequently, I wrote a shell for myself:

#!/bin/sh
cd $1 $2
cp wp-config.php wp-content/
rm -f *.php license.txt readme.html
rm -rf wp-admin/
rm -rf wp-includes/
cp $2/*.php .
cp -r $2/wp-admin .
cp -r $2/wp-includes .
cp $2/license.txt .
cp $2/readme.html .
mv wp-content/wp-config.php .
chmod 777 wp-content/uploads/

I saved the script as updatewp.sh and run it as root:

/root/updatewp.sh /www/life.zhourenjian.com/ /home/zhourenjian/wordpress/

The first argument is my wordpress blog path, and the second argument is the path of downloaded and unzipped wordpress path.

There is no wp-images or wp-content/cache in my blog folder.

And I also upgraded my Chinese blogs and upgrading caused Chinese messed. To solve that problem, I just modified wp-config.php, add following two lines after “// ** MySQL settings ** //”:

define(‘DB_CHARSET’, ‘utf8’);
define(‘DB_COLLATE’, ”);

Posted in Blog Tips | Comments Off on Upgrade to WordPress 2.2

Snippet: Open Editor a Local File in Eclipse

Here is codes to open editor a local file in Eclipse:

IFileStore fileStore = EFS.getLocalFileSystem()
.getStore(new Path(file.getParent()));
fileStore= fileStore.getChild(file.getName());
if (!fileStore.fetchInfo().isDirectory()
&& fileStore.fetchInfo().exists()) {
IWorkbenchWindow fWindow = Java2ScriptUIPlugin.getDefault()
.getWorkbench().getActiveWorkbenchWindow();
IWorkbenchPage page = fWindow.getActivePage();
try {
IDE.openEditorOnFileStore(page, fileStore);
} catch (PartInitException e) {
String msg = NLS.bind(IDEWorkbenchMessages
.OpenLocalFileAction_message_errorOnOpen,
fileStore.getName());
IDEWorkbenchPlugin.log(msg,e.getStatus());
MessageDialog.openError(fWindow.getShell(),
IDEWorkbenchMessages.OpenLocalFileAction_title, msg);
}
}

For more, please read org.eclipse.ui.internal.ide.actions.OpenLocalFileAction in org.eclipse.ui.ide_….jar

Posted in Eclipse, Snippet | Comments Off on Snippet: Open Editor a Local File in Eclipse

Tools for Smart or Normal People?

I came across this question when I read those discussion emails about how a folder should be arranged. Arranging a folder may be easy for us, just create some sub folders and put some files into them accordingly. Does it require a big discussion? Why the folder should be finely arranged? Is it worth to spend lots of time discussing this problem?

Yes, we, developers, are creating tools for others. And we do not know who those others are. Then do we just assume that others are normal people or do we think that those others should be smart people? Smart people use tools vary from those normal people. Their thoughts are quite different. Tools suited for smart people may confuse normal people. And tools for normal people may make smart people think those tools is really dummy! Tools are for some specific ones.

Now, there are requirements and solutions for the whole tool things:

  1. Smart people create tools for smart people
  2. Smart people create tools for normal people
  3. Normal people create tools for smart people
  4. Normal people create tools for normal people

Think about Google, Apple, Microsoft, Yahoo or other big companies for these tool things.

Posted in Software Requirement | Comments Off on Tools for Smart or Normal People?

“Compare With …” Bug Fix in Subversive 1.1.2

There are two known bugs in Subversive 1.1.2 at the time of this writing.

1. “Compare with? …” will fail to get content from SVN repository if the given file has history of being moved or copied from other location. The buggy codes are located in TwoWayResourceCompareInput.java under org.polarion.team.svn.ui\src\org\polarion\team\svn\ui\compare\.

To fix this bug, you can download sources from Subversive official website and then down the following updated java source: http://vip.zhourenjian.com/uploads/TwoWayResourceCompareInput.java
and compile the whole plugin org.polarion.team.svn.ui. Or you can download the compiled *.jar:
http://vip.zhourenjian.com/uploads/SVNTeamUI.jar
After SVNTeamUI.jar is downloaded, place it as …\eclipse\plugins\org.polarion.team.svn.ui_1.1.2\SVNTeamUI.jar

2. Another bug about Subversive 1.1.2 is that when a file has no extensions,? comparing it with server revision in Synchronize perspective will fail in NullPointerException. The bug is located at AbstractGetFileContentOperation.java at org.polarion.team.svn.core\src\org\polarion\team\svn\core\operation
Download the bug fixed source:
http://vip.zhourenjian.com/uploads/AbstractGetFileContentOperation.java

Posted in Bug Fix | 1 Comment

Vim Tricks

To replace a block of text into String in vim, try the following commands:

:%s/\/\/gc
:%s/\n/\n” +\r”/gc

To replace specific string into another in lots of files, e.g. replace *.java’s package name “net.sf.j2s.” into another name “org.java2script.”, follow the instructions:

  1. Select all the *.java in Explorer, and open them with single vim
  2. :map <F9> :%s/net\.sf\.j2s\./org\.java2script\./g<CR>:w<CR>:n<CR>
  3. Press <F9> many times as the count of *.java files

This tricks can also be used in similar tasks.

Posted in Tricks, Vim | Comments Off on Vim Tricks

Less User Configurations

When designing software, there is a rule:

Do NOT let user see much of its configurations.

That is to say, make the software simpler, user may feel more comfortable. And if you let user configure too much, you won’t get better user experience but worse software maintenance.

There is another say:

Do NOT add new functions until strongly-required by majority.

If new functions or new configurations are added, it will require much more energies to decide whether to remove them or not!

Keep everything simpler, and have a happier life.

Posted in Software Requirement | Comments Off on Less User Configurations