Onega

a lot of VC++ posts, a few C# posts, and some miscellaneous stuff

Friday, June 23, 2006

read text file via jscript

Here are two code snippets to read text file, it seems that FileSystemObject
is convenient than ADODB.Stream when the file is not stored in Unicode.
function LoadLogMsg(input_filename)
{// read a text file and return a string
var Stream = new ActiveXObject("ADODB.Stream")
//Stream.Mode = 3;// read write
Stream.Type = 2;// adTypeText
Stream.Charset = "iso-8859-1"; //default is unicode
Stream.Open();
Stream.LoadFromFile(input_filename);
//Stream.Position = 0;
var log_msg = Stream.ReadText(-1);//adReadAll
Stream.Close();
WScript.Echo (log_msg);
return log_msg;
}

function LoadLogMsg2(input_filename)
{//read a text file and return a string
var fso = new ActiveXObject("Scripting.FileSystemObject");
var f = fso.GetFile(input_filename);
var a = f.OpenAsTextStream( 1); //forreading
var log_msg = a.ReadAll();
a.Close();
return log_msg;
}

Wednesday, June 07, 2006

Statically linked DLL build by VC++ 8.0 still depends on VC++ runtime

I have build a InProc COM DLL via DLL, it is statically linked with ATL and C++ runtime, depends.exe also reported that it does not depends on VC++ dlls, but its manifest file still referred to VC++ 8.0 CRT and I have to copy some VC++ 8.0 redistributes to target machine in order to use it. I have defined #define _WIN32_WINNT 0x0500 in stdafx.h. For an application build by VC++ 8.0 with  _WIN32_WINNT defined, I dont need to redistribute VC++ 8.0 files.

NetMessageBufferSend from ASP

MSDN says this function can only be called by a user in Administrators group, but in fact I can create a ATL service project implement some simple ATL object to wrapper this API for ASP.

Tuesday, June 06, 2006

A function to detect if a window is visible

In a discussion with author of StarDict, we found out that it was not straightforward to check if a window was visible or not. Several APIs have been tried, and  at last I came up with the following solution. It is still not perfect, so I am happy to get feedback from others.

 

bool is_window_visible( HWND main_window) {

                   

RECT rc;

::GetWindowRect(main_window,&rc);

POINT pt;

pt.x = rc.left+1;

pt.y = rc.top+1;

HWND hwnd1 = WindowFromPoint(pt);

pt.x = rc.left+1;

pt.y = rc.bottom-1;

HWND hwnd2 = WindowFromPoint(pt);

pt.x = rc.right-1;

pt.y = rc.top+1;

HWND hwnd3 = WindowFromPoint(pt);

pt.x = rc.right-1;

pt.y = rc.bottom-1;

HWND hwnd4 = WindowFromPoint(pt); 

 

if( main_window == hwnd1

 && main_window == hwnd2

 && main_window == hwnd3

  && main_window == hwnd4 )

  return true;

  else

  return false;    

}

 

Monday, June 05, 2006

build StarDict

Steps to build StarDict project

Notes by Onega(www.fruitfruit.com)

Install devcpp-4.9.9.2_setup.exe

 

Open D:\share\opensource\StarDict\stardict-2.4.7\stardict.dev in Dev-C++

 

Modify project options

Add the following include directories

Includes=D:\share\opensource\gtk\glib-dev-2.8.4\include\glib-2.0;

D:\share\opensource\gtk\glib-dev-2.8.4\lib\glib-2.0\include;

D:\share\opensource\gettext-dev-0.14.5\include;

D:\share\opensource\algorithm\zlib-1.2.3-src\src\zlib\1.2.3\zlib-1.2.3;

D:\share\opensource\gtk\gtk+-dev-2.8.9\include\gtk-2.0;

D:\share\opensource\gtk\cairo-dev-1.0.2\include\cairo;

D:\share\opensource\gtk\pango-dev-1.10.1\include\pango-1.0;

D:\share\opensource\gtk\gtk+-dev-2.8.9\lib\gtk-20\include;

D:\share\opensource\gtk\atk-dev-1.10.3\include\atk-1.0

 

Add the following library files ( I have to build zlib via cygwin, other libraries are available in their dev package)

Libs=D:\share\opensource\gtk\gtk+-dev-2.8.9\lib;

D:\share\opensource\gtk\atk-dev-1.10.3\lib;

D:\share\opensource\gtk\cairo-dev-1.0.2\lib;

D:\share\opensource\gtk\glib-dev-2.8.4\lib;

D:\share\opensource\gtk\pango-dev-1.10.1\lib;

D:\share\opensource\gettext-dev-0.14.5\lib;

D:\share\opensource\algorithm\zlib-1.2.3-src\src\zlib\1.2.3\zlib-1.2.3

 

 

compile zlib via cygwin

Start cygwin console

Change to zlib directory

Copy make file from D:\share\opensource\algorithm\zlib-1.2.3-src\src\zlib\1.2.3\zlib-1.2.3\win32\Makefile.gcc to

D:\share\opensource\algorithm\zlib-1.2.3-src\src\zlib\1.2.3\zlib-1.2.3\Makefile.gcc

Change current directory

Cd /cygdrive/d/share/opensource/algorithm/zlib-1.2.3-src/src/zlib/1.2.3/zlib-1.2.3

Make it

make -fMakefile.gcc

DONE

run output file as a post build step

If you just put $(TargetPath) as command of post build event, the it does not work.
Here is a working solution.

Create a vbscript file under your project folder (post_build.vbs)

if WScript.Arguments.Count > 0 Then
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.run WScript.Arguments.Item(0)
set WshShell = nothing
End if

Set the following command line in post build command:
cscript.exe $(ProjectDir)\post_build.vbs $(TargetPath)

You can also use script in pre-build event, the advantage is that a build
won't be stopped by error of pre-build event, such as failure to stop a
service when you are working on a service project.

Another sample is copying 3rd party files at post-build event:
if not exist $(TargetDir)TestRunnerd.dll copy \cppunit\lib\vc90\TestRunnerd.dll $(TargetDir)

a VC++ Class to redirect console output to a file

//class to redirect console output to a file, based on http://bdn.borland.com/article/0,1410,10387,00.html

#include <fstream>

#include <memory>

#include "atlaux2.h" //need to download it from internet

#include <sstream>

#include <process.h>

//Onega on Windows XP SP2, VC++ 8.0

typedef unsigned (__stdcall *start_address )( void * );

class RedirectProcess:public CAuxStdThunk<RedirectProcess>

{

public:

                RedirectProcess( LPCTSTR application_name, LPCTSTR command_line):

                m_application_name(application_name), m_command_line(command_line)

                {

                                InitThunk( (TMFP)&RedirectProcess::thread_procedure,this);

                }

                ~RedirectProcess()

                {

                                OutputDebugString(__FUNCTION__);

                }

                unsigned __stdcall thread_procedure(void *p)

                {

                                pipe_method1(m_application_name.c_str(), m_command_line.c_str());

                                std::basic_stringstream<TCHAR> ts;

                                ts<< _T("Process ID:") << getpid()

                                  <<_T(" Thread id:")<<GetCurrentThreadId()

                                                <<_T(", exe: ")<<m_application_name

                                                <<_T(", command line:")<<m_command_line

                                <<_T(" sample made by Onega (www.fruitfruit.com) ");

                                OutputDebugString(ts.str().c_str());

                                ts.clear();

                                delete this;

                                return 0;

                }

private:

                std::basic_string<TCHAR> m_application_name;

                std::basic_string<TCHAR> m_command_line;

                void pipe_method1(LPCTSTR exe, LPCTSTR cmd_line)

                {

                                std::ofstream log_file;

                                log_file.open("c:\\onega.txt");

                                //http://bdn.borland.com/article/0,1410,10387,00.html

                                int buf_length = 4096;

                                std::auto_ptr<TCHAR> buf(new TCHAR[buf_length+1]);

                                STARTUPINFO si;

                                SECURITY_ATTRIBUTES sa;

                                SECURITY_DESCRIPTOR sd;               //security information for pipes

                                PROCESS_INFORMATION pi;

                                HANDLE newstdin,newstdout,read_stdout,write_stdin;  //pipe handles

 

                                //if (IsWinNT())        //initialize security descriptor (Windows NT)

                                {

                                                InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION);

                                                SetSecurityDescriptorDacl(&sd, true, NULL, false);

                                                sa.lpSecurityDescriptor = &sd;

                                }

                                //else sa.lpSecurityDescriptor = NULL;

                                sa.nLength = sizeof(SECURITY_ATTRIBUTES);

                                sa.bInheritHandle = true;         //allow inheritable handles

 

                                if (!CreatePipe(&newstdin,&write_stdin,&sa,0))   //create stdin pipe

                                {

                                                log_file<< "CreatePipe failed, error code:"<<GetLastError()<< " at line "<< __LINE__;

                                                return;

                                }

                                if (!CreatePipe(&read_stdout,&newstdout,&sa,0))  //create stdout pipe

                                {

                                                log_file<< "CreatePipe failed, error code:"<<GetLastError()<< " at line "<< __LINE__;

                                                CloseHandle(newstdin);

                                                CloseHandle(write_stdin);

                                                return;

                                }

 

                                GetStartupInfo(&si);      //set startupinfo for the spawned process

                                /*

                                The dwFlags member tells CreateProcess how to make the process.

                                STARTF_USESTDHANDLES validates the hStd* members. STARTF_USESHOWWINDOW

                                validates the wShowWindow member.

                                */

                                si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;

                                si.wShowWindow = SW_HIDE;

                                si.hStdOutput = newstdout;

                                si.hStdError = newstdout;     //set the new handles for the child process

                                si.hStdInput = newstdin;

                                //TCHAR app_spawn[] = _T("D:\\share\\test\\vc8\\console\\boost\\unittest\\test1\\Debug\\test1.exe"); //sample, modify for your

                                //spawn the child process

                                if (!CreateProcess(exe,(LPTSTR)cmd_line,NULL,NULL,TRUE,CREATE_NEW_CONSOLE,

                                                NULL,NULL,&si,&pi))

                                {

                                                log_file<< "CreateProcess failed, error code:"<<GetLastError()<< " at line "<< __LINE__;

                                                //getch();

                                                CloseHandle(newstdin);

                                                CloseHandle(newstdout);

                                                CloseHandle(read_stdout);

                                                CloseHandle(write_stdin);

                                                return;

                                }

 

                                unsigned long exit=0;  //process exit code

                                unsigned long bread;   //bytes read

                                unsigned long avail;   //bytes available

                                for(;;)      //main program loop

                                {

                                                GetExitCodeProcess(pi.hProcess,&exit);      //while the process is running

                                                if (exit != STILL_ACTIVE)

                                                                break;

                                                PeekNamedPipe(read_stdout,buf.get() ,buf_length,&bread,&avail,NULL);

                                                //check to see if there is any data to read from stdout

                                                if (bread != 0)

                                                {

                                                                if (avail > buf_length)

                                                                {

                                                                                while (bread >= buf_length)

                                                                                {

                                                                                                memset(buf.get(),0, buf_length + 1);

                                                                                                ReadFile(read_stdout,buf.get(),buf_length,&bread,NULL);  //read the stdout pipe

                                                                                                log_file<< (LPCSTR)buf.get();

                                                                                                OutputDebugString((LPCSTR)buf.get());

                                                                                }

                                                                }

                                                                else {

                                                                                memset(buf.get(),0, buf_length + 1);

                                                                                ReadFile(read_stdout,buf.get(),buf_length,&bread,NULL);

                                                                                log_file<< (LPCSTR)buf.get();

                                                                                OutputDebugString((LPCSTR)buf.get());

                                                                }

                                                }

                                                else

                                                {

                                                                //must not call sleep, otherwise the code will fail to capture output

                                                                //Sleep(1);

                                                }

                                }

                                CloseHandle(pi.hThread);

                                CloseHandle(pi.hProcess);

                                CloseHandle(newstdin);            //clean stuff up

                                CloseHandle(newstdout);

                                CloseHandle(read_stdout);

                                CloseHandle(write_stdin);

                                if(exe)

                                                log_file<<exe;

                                if(cmd_line)

                                                log_file<< cmd_line;

                                log_file<< " program closed "<<__FUNCTION__;

                                log_file.flush();

                                log_file.close();

                }

};

 

//////usage

void Cpipe_cmd2Dlg::OnBnClickedOk()

{

                CString exe, cmd_line;

                GetDlgItemText(IDC_EDIT1, exe);

                GetDlgItemText(IDC_EDIT2, cmd_line);

                if(exe.GetLength()==0)

                                exe = "c:\\winnt\\system32\\ipconfig.exe";

    //pipe_method1(exe, cmd_line);

    RedirectProcess *ptr_thread;

    ptr_thread = new RedirectProcess(exe,cmd_line);

    HANDLE hthread = (HANDLE)_beginthreadex(NULL, 0, (start_address)ptr_thread->GetThunk(), 0, 0, 0);

    DWORD dwret = WaitForSingleObject(hthread, 1000 * 60);

    CloseHandle(hthread);

    AfxMessageBox(_T("Program end"));

                //OnOK();

}

Thursday, June 01, 2006

use CAuxStdThunk with _beginthreadex

There is some guess that CAuxStdThunk could be used along with _beginthreadex, but nobody posted anything after googling, so I share a small code snippet here.

 

typedef unsigned (__stdcall *start_address )( void * );

class RedirectProcess:public CAuxStdThunk<RedirectProcess>

{

public:

        RedirectProcess( LPCTSTR application_name, LPCTSTR command_line):

        m_application_name(application_name), m_command_line(command_line)

        {

                InitThunk( (TMFP)&RedirectProcess::thread_procedure,this);

        }

        ~RedirectProcess()

        {

                OutputDebugString(__FUNCTION__);

        }

        unsigned __stdcall thread_procedure(void *p)

        {

                std::basic_stringstream<TCHAR> ts;

                ts<< _T("Process ID:") << getpid()

                  <<_T(" Thread id:")<<GetCurrentThreadId()

                        <<_T(", exe: ")<<m_application_name

                        <<_T(", command line:")<<m_command_line

                <<_T(" sample made by Onega (www.fruitfruit.com) ");

                OutputDebugString(ts.str().c_str());

                ts.clear();

                delete this;

                return 0;

        }

private:

        std::basic_string<TCHAR> m_application_name;

        std::basic_string<TCHAR> m_command_line;

};

 

RedirectProcess *ptr_thread; // must be created in heap

ptr_thread = new RedirectProcess(exe,cmd_line); // need to pass two parameters

 

_beginthreadex(NULL, 0, (start_address)ptr_thread->GetThunk(), 0, 0, 0);