About neohope

一直在努力,还没想过要放弃...

ActiveX控件使用SDI特性(下)

放假回来,接着写:)

这两个类的使用步骤如下:
1、使用向导生成MFC ActiveX控件,(假设控件类为NControlCtrl)
2、工程中添加上面两个文件,ActivDoc.cpp和ActivDoc.h
3、将控件的基类,从COleControl换为CActiveXDocControl,在NControlCtrl.h中添加ActivDoc.h的引用
4、将NControlCtrl控件类中的COleControl全部替换为CActiveXDocControl
5、去掉NControlCtrl的OnDraw函数
5、将自己的Document类,View类,Frame类,添加到项目中,(假设为NDocument,NView,NFrame)
6、在NControlCtrl类中,添加NDocument,NView,NFrame的引用
7、在类的构造函数中,添加一行代码

	AddDocTemplate(new CActiveXDocTemplate(
		RUNTIME_CLASS(NDocument), 
		RUNTIME_CLASS(NMainFrame), 
		RUNTIME_CLASS(NView)));

8、这样SDI就可以用了。如果你原来的项目比较复杂的话,就要将资源文件进行拷贝及合并了,注意ID不要重复哦。

后记:
尝试了直接将NMainFrame进行分栏,但整个框架对于NDocument和NView比较依赖,会有报错。
最近比较忙,只好有空再搞下了。

Windows服务模板

最近写了几个Windows服务,整理了一下服务模板,以备以后使用。
说实话,这些代码是n年前写的了,用了也n久了,但还是发现了一个明显的bug。
其中,有些内容,写的并不好,如静态指针pThis,大家还是尽量不要使用了。

1、服务入口myXXX.cpp

//===================================================
//XXX入口函数

//===================================================
#include <windows.h>
#include <tchar.h>
#include <stdio.h>

#include "XXX.h"

//===================================================
//入口函数
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
	UNREFERENCED_PARAMETER(hInstance);
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(nCmdShow);

	//获取可执行文件路径
	TCHAR szPath[MAX_PATH];
	TCHAR szLog[MAX_PATH];
	GetModuleFileName(NULL,szPath,MAX_PATH);

	//生成日志目录
	TCHAR *p = _tcsrchr(szPath, '\\');
	if(p!=NULL)*p='\0';
	if (_tcslen(szPath) + _tcslen(TEXT("Log\\")) <= MAX_PATH)
	{
		_stprintf_s(szLog, TEXT("%s\\%s"), szPath, TEXT("Log\\"));
	}
	else
	{
		return -1;
	}

	//判断运行参数
	XXX myService(szLog, true);
	myService.ParseParameters(lpCmdLine);

	return 0;
}

//===================================================

&#91;/code&#93;

2、服务类XXX.h
&#91;code lang="cpp"&#93;
//===================================================
//XXX 服务类封装
#include <windows.h>

//===================================================
//预定义
#define MAX_THREAD_COUNT 64

//===================================================
//XXX CLASS
class XXX
{
private:
	HANDLE	hSemaphore;
	CRITICAL_SECTION cs;

	bool		m_bLog;
	const		TCHAR	*m_szLogPath;
	LPCTSTR		lpServiceName;
	LPCTSTR		lpDisplayName;
	
	SERVICE_STATUS_HANDLE	gSvcStatusHandle;
	SERVICE_STATUS		gSvcStatus;
	HANDLE			ghSvcStopEvent;

	static	XXX	*pThis;
	bool	m_bFinished;

//构造与析构函数
public:
	XXX();
	XXX(const TCHAR *cLogPath,const bool bLog);
	~XXX();

//服务相关函数
private:
	static	void WINAPI ServiceMain(DWORD dwArgc,LPTSTR *lpszArgv);
	static	void WINAPI SvcCtrlHandler(DWORD dwCtrl);

	void	SvcInitAndRun(DWORD dwArgc,LPTSTR *lpszArgv);
	void	Show_Me_Err();

public:
	int		AddService();
	int		DelService();
	void	LogEvent(LPCTSTR lpMsg);
	void	ParseParameters(LPSTR lpCmdLine);
};

//===================================================

2、服务类XXX.cpp

//===================================================
//XXX服务类的封装实现

//===================================================
//头文件
#include "XXX.h"

//===================================================
//静态成员
XXX *XXX::pThis = NULL;

//===================================================
//构造函数
XXX::XXX(const TCHAR *cLogPath,const bool bLog)
{
	hSemaphore=NULL;

	m_bLog=bLog;
	lpServiceName=TEXT("XXX");
	lpDisplayName=TEXT("XXX");

	ghSvcStopEvent=NULL;
	m_szLogPath=cLogPath;
	m_bFinished = false;

	pThis=this;
}

//===================================================
//析构函数
XXX::~XXX()
{
}

//===================================================
//入口函数
void XXX::ParseParameters(LPSTR lpCmdLine)
{
	//判断运行参数
	//设置SERVICE_TABLE_ENTRY
	SERVICE_TABLE_ENTRY DispatchTable[]=
	{
		{TEXT("XXX"),(LPSERVICE_MAIN_FUNCTION)ServiceMain},
		{NULL,NULL}
	};

	//处理输入参数
	if((0==_stricmp(lpCmdLine,"/i")) || 0==_stricmp(lpCmdLine,"-i"))
	{
		//安装服务"/i -i"
		AddService();
		return;
	}
	else if((0==_stricmp(lpCmdLine,"/u")) || 0==_stricmp(lpCmdLine,"-u"))
	{
		//删除服务"/u -u"
		DelService();
		return;
	}
	else if((0==_stricmp(lpCmdLine,"/h")) || 0==_stricmp(lpCmdLine,"-h"))
	{
		//提示运行参数"/h -h"
		MessageBox(NULL,TEXT(" Install Service  : -i /i\n UnInstall Service: -u /u"),TEXT("XXX"),MB_OK);
		return;
	}
	else
	{
		//设置调试断点
		//DebugBreak();

		//StartServiceCtrlDispatcher运行服务
		if(!StartServiceCtrlDispatcher(DispatchTable))
		{
			LogEvent(TEXT("XXX: Failed To Start!"));
		}
		else
		{
			LogEvent(TEXT("XXX: Started!"));
		}
	}

	return;
}

//===================================================
//添加服务
int XXX::AddService()
{
	//SCMD与Service的句柄
	SC_HANDLE	hSCManager=NULL;
	SC_HANDLE	hService=NULL;

	//连接到SCM,打开SCMD
	hSCManager=OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE);
	if(NULL==hSCManager)
	{
		MessageBox(NULL,TEXT("OpenSCManager Failed"),TEXT("XXX"),MB_OK);
		Show_Me_Err();
		return 1;
	}

	//检查服务是否安装
	hService=OpenService(hSCManager,lpServiceName,SERVICE_ALL_ACCESS);
	if(NULL==hService)
	{
		//若服务不存在,创建服务
		TCHAR szFilePath[MAX_PATH];
		GetModuleFileName(GetModuleHandle(NULL),szFilePath,MAX_PATH);

		//自动启动
		hService=CreateService(hSCManager,lpServiceName,lpDisplayName,SERVICE_ALL_ACCESS,
				SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
				SERVICE_AUTO_START,SERVICE_ERROR_NORMAL,szFilePath,NULL,NULL,NULL,NULL,NULL);

		if(NULL==hService)
		{
			MessageBox(NULL,TEXT("CreateService Failed"),TEXT("XXX"),MB_OK);
			Show_Me_Err();
			CloseServiceHandle(hSCManager);
			return 1;
		}
	}
	else
	{
		MessageBox(NULL,TEXT("Service Already Installed!"),TEXT("XXX"),MB_OK);
		CloseServiceHandle(hService);
		CloseServiceHandle(hSCManager);
		return 1;
	}

	//关闭句柄
	CloseServiceHandle(hService);
	CloseServiceHandle(hSCManager);

	LogEvent(TEXT("XXX: AddService Successed!"));
	//ForDebug
	//MessageBox(NULL,TEXT("AddService Successed!"),TEXT("XXX"),MB_OK);
	return 0;
}

//===================================================
//删除服务
int XXX::DelService()
{
	//SCMD与Service的句柄
	SC_HANDLE	hSCManager=NULL;
	SC_HANDLE	hService=NULL;
	SERVICE_STATUS	ServiceStatus;

	//获取SCM句柄,打开SCMD
	hSCManager=OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE);
	if(NULL==hSCManager)
	{
		MessageBox(NULL,TEXT("OpenSCManager Failed"),TEXT("XXX"),MB_OK);
		Show_Me_Err();
		return 1;
	}

	//打开服务句柄
	hService=OpenService(hSCManager,lpServiceName,SERVICE_ALL_ACCESS|DELETE);
	if(NULL==hService)
	{
		MessageBox(NULL,TEXT("OpenService Failed"),TEXT("XXX"),MB_OK);
		Show_Me_Err();
		CloseServiceHandle(hSCManager);
		return 1;
	}

	//查询服务状态
	if(0==QueryServiceStatus(hService,&ServiceStatus))
	{
		MessageBox(NULL,TEXT("QueryServiceStatus Failed"),TEXT("XXX"),MB_OK);
		Show_Me_Err();
		CloseServiceHandle(hService);
		CloseServiceHandle(hSCManager);
		return 1;
	}
	else
	{
		//如果服务正在运行,则停止
		if(SERVICE_STOPPED!=ServiceStatus.dwCurrentState)
		{
			if(0==ControlService(hService,SERVICE_CONTROL_STOP,&ServiceStatus))
			{
				MessageBox(NULL,TEXT("ControlService Failed"),TEXT("XXX"),MB_OK);
				Show_Me_Err();
				CloseServiceHandle(hService);
				CloseServiceHandle(hSCManager);
				return 1;
			}
		}

		//删除服务
		if(0==DeleteService(hService))
		{
			MessageBox(NULL,TEXT("DeleteService Fialed!"),TEXT("XXX"),MB_OK);
			Show_Me_Err();
			CloseServiceHandle(hService);
			CloseServiceHandle(hSCManager);
			return 1;
		}
	}

	CloseServiceHandle(hService);
	CloseServiceHandle(hSCManager);

	LogEvent(TEXT("XXX: DelService Successed!"));
	//ForDebug
	//MessageBox(NULL,TEXT("DelService Successed!"),TEXT("XXX"),MB_OK);
	return 0;
}

//===================================================
//服务入口函数
void WINAPI XXX::ServiceMain(DWORD dwArgc,LPTSTR *lpszArgv)
{
	//注册服务控制程序
	pThis->gSvcStatusHandle=RegisterServiceCtrlHandler(pThis->lpServiceName,SvcCtrlHandler);
	if(0==pThis->gSvcStatusHandle)
	{
		//注册失败,返回
		pThis->LogEvent(TEXT("XXX: RegisterServiceCtrlHandler Failed"));
		return;
	}

	//设置服务状态SERVICE_START_PENDING
	pThis->gSvcStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS;
	pThis->gSvcStatus.dwCurrentState=SERVICE_START_PENDING;
	pThis->gSvcStatus.dwControlsAccepted=0;
	pThis->gSvcStatus.dwWin32ExitCode=NO_ERROR;
	pThis->gSvcStatus.dwServiceSpecificExitCode=0;
	pThis->gSvcStatus.dwCheckPoint=0;
	pThis->gSvcStatus.dwWaitHint=10000;
	SetServiceStatus(pThis->gSvcStatusHandle,&(pThis->gSvcStatus));

	//运行服务函数
	pThis->SvcInitAndRun(dwArgc, lpszArgv);

	//停止服务
	pThis->gSvcStatus.dwCurrentState=SERVICE_STOPPED;
	pThis->gSvcStatus.dwWaitHint=0;
	pThis->gSvcStatus.dwControlsAccepted=SERVICE_ACCEPT_STOP;
	pThis->gSvcStatus.dwCheckPoint=0;
	SetServiceStatus(pThis->gSvcStatusHandle,&(pThis->gSvcStatus));
}

//===================================================
//服务函数
void XXX::SvcInitAndRun(DWORD dwArgc,LPTSTR *lpszArgv)
{
	UNREFERENCED_PARAMETER(dwArgc);
	UNREFERENCED_PARAMETER(lpszArgv);

	//创建事件
	ghSvcStopEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
	if(ghSvcStopEvent==NULL)
	{
		//创建事件失败,停止服务,返回
		gSvcStatus.dwCurrentState=SERVICE_STOPPED;
		gSvcStatus.dwWaitHint=0;
		gSvcStatus.dwControlsAccepted=SERVICE_ACCEPT_STOP;
		gSvcStatus.dwCheckPoint=0;
		SetServiceStatus(gSvcStatusHandle,&gSvcStatus);
		return;
	}

	//设置服务状态SERVICE_RUNNING
	gSvcStatus.dwCurrentState=SERVICE_RUNNING;
	gSvcStatus.dwWaitHint=0;
	gSvcStatus.dwControlsAccepted=SERVICE_ACCEPT_STOP;
	gSvcStatus.dwCheckPoint=0;
	SetServiceStatus(gSvcStatusHandle,&gSvcStatus);

	//设置断点
	while (!IsDebuggerPresent()) 
	{ 
		Sleep(100); 
	} 
	DebugBreak();

	//创建信号量
	hSemaphore=CreateSemaphore(NULL,MAX_THREAD_COUNT,MAX_THREAD_COUNT,TEXT("NAS_TEST_SEMAPHORE"));
	if(NULL==hSemaphore)  
	{
		return;
	}

	//初始化关键区
	InitializeCriticalSection(&cs);

	//处理请求
	while(!m_bFinished)
	{
		//进入关键区
		EnterCriticalSection(&cs);
		while (!m_bFinished)
		{
			if(WAIT_TIMEOUT==WaitForSingleObject(ghSvcStopEvent,100))
			{
				//这里处理你的线程逻辑
				//每个线程启动的时候WaitForSingleObject占用一个信号量
				//线程退出时ReleaseSemaphore释放信号量

			}
			else
			{
				LogEvent(TEXT("XXX is gonging down."));
				m_bFinished = true;
			}
		}
		//退出关键区
		LeaveCriticalSection(&cs);

		if (!m_bFinished)
		{
			//等待线程0.2秒
			Sleep(200);
		}
	}

	//等待所有线程结束
	WaitForMultipleObjects(MAX_THREAD_COUNT, &hSemaphore, true, 10000L);
	//WaitForMultipleObjects(1,&hSemaphore,true,INFINITE);

	//释放信号量
	CloseHandle(hSemaphore);
	
	//释放关键区
	DeleteCriticalSection(&cs);

	return;
}

//===================================================
//服务控制函数
void WINAPI XXX::SvcCtrlHandler(DWORD dwCtrl)
{
	switch(dwCtrl)
	{
		case SERVICE_CONTROL_STOP:
			//设置服务状态SERVICE_ACCEPT_STOP
			pThis->gSvcStatus.dwCurrentState=SERVICE_STOP_PENDING;
			pThis->gSvcStatus.dwControlsAccepted=SERVICE_ACCEPT_STOP;
			pThis->gSvcStatus.dwCheckPoint=0;
			pThis->gSvcStatus.dwWaitHint=10000;
			SetServiceStatus(pThis->gSvcStatusHandle,&(pThis->gSvcStatus));
			//触发事件
			SetEvent(pThis->ghSvcStopEvent);
			break;
		case SERVICE_CONTROL_PAUSE:
			break;
		case SERVICE_CONTROL_CONTINUE:
			break;
		case SERVICE_CONTROL_INTERROGATE:
			break;
		case SERVICE_CONTROL_SHUTDOWN:
			break;
		default:
			pThis->LogEvent(TEXT("XXX: Bad Service Request!"));
	}
}

//===================================================
//在事件查看器中记录消息
void XXX::LogEvent(LPCTSTR lpMsg)
{
	HANDLE	hEventSource;
	LPCTSTR	lpszStrings[1];

	lpszStrings[0]=lpMsg;

	//在“事件查看器->应用程序->信息”中进行记录
	hEventSource=RegisterEventSource(NULL,lpServiceName);
	if(NULL!=hEventSource)
	{
		ReportEvent(hEventSource,EVENTLOG_INFORMATION_TYPE,0,0,NULL,1,0,lpszStrings,NULL);
		DeregisterEventSource(hEventSource);
	}
}

//===================================================
//输出GetLastErr()信息
void XXX::Show_Me_Err()
{
	if(!m_bLog)return;

	DWORD	dwErrNo;
	LPTSTR	lpBuffer;
	dwErrNo=GetLastError();
	FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_FROM_SYSTEM,
		NULL,dwErrNo,LANG_NEUTRAL,(LPTSTR)&lpBuffer,0,NULL);
	MessageBox(NULL,lpBuffer,TEXT("XXX GetLastError"),MB_OK);
	LocalFree(lpBuffer);
}

//===================================================

C#写WindowsService

1、新建一个Windows Service项目,重命名服务类名

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.ServiceProcess;
using System.Threading;

namespace ServiceTestCS
{
    public partial class ServiceTestCS : ServiceBase
    {
        //安装卸载时,最好用绝对路径哦
        //Installutil NASTestCS
        //Installutil -u NASTestCS

        private const int waitInterval = 200;
        private AutoResetEvent stopEvent = new AutoResetEvent(false);
        private AutoResetEvent pauseContinueEvent = new AutoResetEvent(false);
        private Thread workingThread = null;

        public NASTestCS()
        {
            InitializeComponent();
            this.CanPauseAndContinue = true;
            this.CanShutdown = true;
        }

        protected override void OnStart(string[] args)
        {
            #if DEBUG
            /*
            //等待调试器,但调试Windows服务时,提示没有加载符号
            while (!Debugger.IsAttached)
            {
                Thread.Sleep(waitInterval);
            }
            */
            Debugger.Launch();
            #endif

            workingThread = new Thread(new ThreadStart(MaiLoop));
            workingThread.Start();
        }

        protected override void OnStop()
        {
            stopEvent.Set();
        }

        protected override void OnShutdown()
        {
            stopEvent.Set();
        }

        protected override void OnPause()
        {
            pauseContinueEvent.Set();
        }

        protected override void OnContinue()
        {
            pauseContinueEvent.Set();
        }

        protected void MaiLoop()
        {
            Boolean bEnd = false;
            while (!bEnd)
            {
                //处理你的正常事务
                //但要保证下面的代码,可以定期被调用到
                //......

                //截获停止事件
                if(stopEvent.WaitOne(waitInterval))
                {
                    bEnd = true;
                    break;
                }

                //截获暂停事件
                if (pauseContinueEvent.WaitOne(waitInterval))
                {
                    //等待继续时间
                    while (!pauseContinueEvent.WaitOne(waitInterval))
                    {
                        //少占用一些资源
                        Thread.Sleep(waitInterval);

                        //暂停时也可以退出
                        if (stopEvent.WaitOne(waitInterval))
                        {
                            bEnd = true;
                            break;
                        }
                    }
                }
            }
        }
    }
}

2、服务设计界面右击,添加Service Installer
配置Service Installer,配置服务类名称,显示名称,启动类型,登录用户,服务依赖等
但如果要可以与桌面交互的话,需要添加代码实现。
双击serviceInstaller,添加下面方法:

        using System.Management;

        private void serviceInstaller_AfterInstall(object sender, InstallEventArgs e)
        {
            //要用LocalSystem用户登录才有效哦
            ManagementObject wmiService = new ManagementObject(string.Format("Win32_Service.Name='{0}'", this.serviceInstaller.ServiceName));
            ManagementBaseObject changeMethod = wmiService.GetMethodParameters("Change");
            changeMethod["DesktopInteract"] = true;
            ManagementBaseObject OutParam = wmiService.InvokeMethod("Change", changeMethod, null);
        }

3、安装与反安装,用命令行实现

rem 安装服务
%PATH_TO_INSTALLUTIL%\installutil.exe %PATH_TO_SERVICE%\NASTestCS.exe
rem 卸载服务
%PATH_TO_INSTALLUTIL%\installutil.exe -u %PATH_TO_SERVICE%\NASTestCS.exe

Java程序如何加密

今天在想Java程序加密的事情,现在市面上的方法,无非是混淆代码,jar包签名等,瞬间就能被破解掉。

我想到了一个很挫的方法,和PE文件加壳脱壳一样,class文件/jar文件为什么不可以呢?

但这样做的话,是有限制的,就是客户必须使用你自己定制的JVM及容器,否则是无法运行的。

具体方法如下:
1、生成class文件后,按一定规则进行加密处理。偷懒的话,直接对称加密好了。
2、生成jar包的时候,同样按一定规则进行加密处理。偷懒的话,zip的时候,增加一个强壮的密码就好了。
3、下载并编译OpenJDK,在读取jar包内容,和class文件的地方,要进行脱壳处理。按上面的思路,就是解压缩和解密处理。
4、当然,定制部分的dll和exe,需要进行PE加壳处理

当然,上面这种方式的话,和加壳脱壳还是有很大的区别的,就是不能自行解压,并要依赖于JVM甚至容器的定制。

如果要真正实现自解压处理的话,就要多做几步:

具体方法如下:
1、编译生成class文件,按一定规则进行加密处理。偷懒的话,直接对称加密好了。
2、生成jar包的时候,同样按一定规则进行加密处理。偷懒的话,zip的时候,增加一个强壮的密码就好了。
3、将需要的所有jar包,按你喜欢的方法,生成一个jar包列表,并打成一个巨大的资源文件。
4、写一个java引导文件,用于处理运行参数,比如入口程序等。
5、写一个自定义classloader+jni+dll,用于读取巨大的资源文件中的jar包及class文件
6、用普通的jvm启动程序,初始化时用引导文件+自定义classloader
7、引导文件+自定义classloader将需要的文件直接解压到内存中,提供给jvm使用
8、dll部分要进行PE加壳处理

使用命名管道实现进程间通信(下)

1、服务端C#

        private const String MY_PIPE_NAME = "__MY__PIPE__TEST__";
        private const int BUFFER_SIZE = 1024;
        NamedPipeServerStream pipe;
        StreamWriter writer;
        String msg = "Message is comming";

        private void PipeCreate()
        {
            if (pipe != null && pipe.IsConnected)
            {
                pipe.Close();
            }

            pipe = new NamedPipeServerStream(MY_PIPE_NAME, PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.None);
            

            if (pipe == null)
            {
                textBox1.Text = textBox1.Text + "Pipe is null";
                return;
            }

            if (pipe.IsConnected)
            {
                textBox1.Text = textBox1.Text + "Pipe is already connected";
                return;
            }

            pipe.WaitForConnection();

            textBox1.Text = textBox1.Text + "Pipe is ready to connect\r\n";
        }

        private void PipeWrite()
        {
            if (pipe!=null && pipe.IsConnected)
            {
                if(writer==null)
                {
                    //关闭BOM(Byte Order Mark 0xfeff)
                    UnicodeEncoding unicodeWithoutBom = new System.Text.UnicodeEncoding(false, false);
                    writer = new StreamWriter(pipe, unicodeWithoutBom);
                    //写完后直接flush,会阻塞
                    writer.AutoFlush = true;
                }
                writer.Write(msg);

                textBox1.Text = textBox1.Text + "Pipe message sent \r\n";
            }
            else
            {
                textBox1.Text = textBox1.Text + "Pipe is not connected \r\n";
            }
        }

        private void PipeClose()
        {
            if (pipe!=null && pipe.IsConnected)
            {
                writer.Close();
                pipe.Close();

                writer = null;
                pipe = null;
            }
        }

2、客户端C#

        private const String MY_PIPE_NAME =  "__MY__PIPE__TEST__";
        private const int BUFFER_SIZE = 1024;
        NamedPipeClientStream pipe;
        StreamReader reader;

        private void PipeConnect()
        {
            if (pipe != null && pipe.IsConnected)
            {
                pipe.Close();
            }
            pipe = new NamedPipeClientStream(".", MY_PIPE_NAME, PipeDirection.InOut);

            if (pipe != null)
            {
                if (!pipe.IsConnected)
                {
                    pipe.Connect();
                    textBox1.Text = textBox1.Text + "\r\npipe is connected";
                }
                else
                {
                    textBox1.Text = textBox1.Text + "\r\npipe is already connected";
                }
            }
            else
            {
                textBox1.Text = textBox1.Text + "\r\npipe is null";
            }

            
        }

        private void PipeRead()
        {
            if (pipe.IsConnected)
            {
                if (reader == null)
                {
                    reader = new StreamReader(pipe, Encoding.Unicode);
                }

                char[] buffer = new char[BUFFER_SIZE];
                int byteRead = reader.Read(buffer, 0, BUFFER_SIZE);
                String msgTxt = new String(buffer, 0, byteRead);
                textBox1.Text = textBox1.Text + "\r\nPipe msg received: " + msgTxt;
            }
            else
            {
                textBox1.Text = textBox1.Text + "\r\nPipe is not connected";
            }
        }

        private void PipeClose()
        {
            if (reader != null)
            {
                reader.Close();
                reader = null;
            }
            if (pipe != null && pipe.IsConnected)
            {
                pipe.Close();
            }

            textBox1.Text = textBox1.Text + "\r\npipe is closed";
        }

使用命名管道实现进程间通信(上)

1、服务端MFC

#define MY_PIPE_NAME L"\\\\.\\pipe\\__MY__PIPE__TEST__"
#define BUFSIZE 1024

HANDLE m_hPipe;
BOOL m_bConnected;
int m_bMsgNum;

//使用ConnectNamedPipe会阻塞,直到客户端进行连接
//不使用ConnectNamedPipe则不会阻塞,但一样可以做后续操作
void XXX::PipeCreate()
{
	m_hPipe = CreateNamedPipe(
		MY_PIPE_NAME,             // pipe name 
		PIPE_ACCESS_DUPLEX,       // read/write access 
		PIPE_TYPE_MESSAGE |       // message type pipe 
		PIPE_READMODE_MESSAGE |   // message-read mode 
		PIPE_WAIT,                // blocking mode 
		1,                        // max. instances  
		BUFSIZE,                  // output buffer size 
		BUFSIZE,                  // input buffer size 
		0,                        // client time-out 
		NULL);                    // default security attribute 

	if (m_hPipe == INVALID_HANDLE_VALUE)
	{
		::MessageBox(NULL, L"CreateNamedPipe Error", L"CreateNamedPipe", MB_OK);
	}
	else
	{
		::MessageBox(NULL, L"CreateNamedPipe OK", L"CreateNamedPipe", MB_OK);
	}

	m_bConnected = ConnectNamedPipe(m_hPipe, NULL);

	if (m_bConnected)
	{
		::MessageBox(NULL, L"ConnectNamedPipe OK", L"ConnectNamedPipe", MB_OK);
	}
	else
	{
		::MessageBox(NULL, L"ConnectNamedPipe Error", L"ConnectNamedPipe", MB_OK);

	}

	m_bMsgNum = 0;
}

//WriteFile会阻塞,等待客户端读取完毕
void XXX::PipeWrite()
{
	DWORD	dwWritten;
	TCHAR	buffer[BUFSIZE];
	int n = sizeof(buffer);

	_stprintf_s(buffer, L"This the %d message", m_bMsgNum++);
	if (!WriteFile(m_hPipe, buffer, n, &dwWritten, NULL))
	{
		::MessageBox(NULL, L"WriteFile Failed", L"WriteFile", MB_OK);
	}
}

//两边都关闭,才可以重新建立管道
void XXX::PipeClose()
{
	if (m_bConnected)
	{
		DisconnectNamedPipe(m_hPipe);
		m_bConnected = FALSE;
	}
	
	if (m_hPipe!=NULL && m_hPipe != INVALID_HANDLE_VALUE)
	{ 
		CloseHandle(m_hPipe);
		m_hPipe=NULL;
	}
}

2、客户端MFC

#define MY_PIPE_NAME L"\\\\.\\pipe\\__MY__PIPE__TEST__"
#define BUFSIZE 1024
HANDLE m_hPipe;
BOOL m_bConnected;

//WaitNamedPipe会等待ConnectNamedPipe
void XXX::PipeConnect()
{
	if (WaitNamedPipe(MY_PIPE_NAME, NMPWAIT_WAIT_FOREVER) == 0)
	{
		MessageBox(L"WaitNamedPipe failed");
		return;
	}

	m_hPipe = CreateFile(MY_PIPE_NAME,
		GENERIC_READ,
		0,
		NULL, OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);

	if (m_hPipe == INVALID_HANDLE_VALUE)
	{
		m_bConnected = FALSE;
		::MessageBox(NULL, L"CreateFile Error", L"CreateNamedPipe", MB_OK);
	}
	else
	{
		m_bConnected = TRUE;
		::MessageBox(NULL, L"CreateFile OK", L"CreateNamedPipe", MB_OK);
	}
}

//ReadFile会阻塞等待写入
void XXX::PipeRead()
{
	DWORD	dwBytesRead;
	TCHAR	buffer[BUFSIZE];
	int bufsize = sizeof(buffer);

	memset(buffer, 0x00, bufsize);
	if (m_bConnected)
	{
		//C#程序不处理的话,第一次读会读到BOM(Byte Order Mark 0xfeff)
		if (ReadFile(m_hPipe, buffer, bufsize, &dwBytesRead, NULL))
		{
			::MessageBox(NULL, buffer, L"ReadFile", MB_OK);
		}
	}
}

//两边都关闭,才可以重新建立管道
void XXX::PipeClose()
{
	if (m_hPipe!=NULL && m_hPipe != INVALID_HANDLE_VALUE)
	{ 
		CloseHandle(m_hPipe);
		m_hPipe=NULL;
	}
}

匿名管道重定向命令行输出

首先是MFC,注意事项:
1、管道读写是FIFO
2、读写指针,要记得关闭
3、编译时用了UNICODE,但CMD读取回来时ANSI,所以要转换一下字符集

	SECURITY_ATTRIBUTES sa;
	ZeroMemory(&sa, sizeof(sa));
	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
	sa.lpSecurityDescriptor = NULL;
	sa.bInheritHandle = TRUE;

	HANDLE hRead, hWrite;
	if (!CreatePipe(&hRead, &hWrite, &sa, 0)) {
		MessageBox(L"Error On CreatePipe()");
		return;
	}

	STARTUPINFO si;
	ZeroMemory(&si, sizeof(si));
	si.cb = sizeof(STARTUPINFO);
	GetStartupInfo(&si);
	si.hStdError = hWrite;
	si.hStdOutput = hWrite;
	si.wShowWindow = SW_HIDE;
	si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
	PROCESS_INFORMATION pi;
	ZeroMemory(&pi, sizeof(pi));
	if (!::CreateProcess(L"C:\\Windows\\System32\\cmd.exe", L"/c dir /b D:\\Downloads"
		, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi)) {
		showMeErrorInfo();	
		return;
	}
	CloseHandle(hWrite);

	char buffer[4096] = { 0 };
	DWORD bytesRead;
	while (true) {
		if (ReadFile(hRead, buffer, 4095, &bytesRead, NULL) == NULL)
		{
			break;
		}
		
		UINT CodePage = 0;
		DWORD dwNum;
		dwNum = MultiByteToWideChar(CodePage, 0, buffer, -1, NULL, 0);
		if (dwNum)
		{
			wchar_t *pwText;
			pwText = new TCHAR[dwNum];
			if (pwText)
			{
				MultiByteToWideChar(CodePage, 0, buffer, -1, pwText, dwNum);
			}
			//m_Edit.SetWindowText(pwText);
			delete[]pwText;
			pwText = NULL;
		}
		UpdateData(false);
		Sleep(200);
	}
	CloseHandle(hRead);

C#的话,就简单多了:

            ProcessStartInfo startInfo = new ProcessStartInfo();
            startInfo.FileName = "C:\\Windows\\System32\\cmd.exe";
            startInfo.Arguments = "/c dir /b D:\\Downloads";
            startInfo.RedirectStandardOutput = true;
            //startInfo.RedirectStandardError = true;
            startInfo.UseShellExecute = false;
            startInfo.CreateNoWindow = false;
           
            Process p=Process.Start(startInfo);

            String cmdOut = "";
            while(!p.HasExited)
            { 
                cmdOut = p.StandardOutput.ReadLine();
                textBox1.Text += cmdOut + "\r\n";
                p.WaitForExit(10);
            }
            cmdOut = p.StandardOutput.ReadToEnd() + "\r\n";
            textBox1.Text += cmdOut ;

使用WM_COPYDATA实现跨进程通讯(下)

请注意:
A、SendMessage在接收方处理完毕前不会返回,会产生严重阻塞
B、由于使用了非托管内存,要注意进行清理

1、发送方WinForm

        public const int WM_COPYDATA = 0x004A;
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        private struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public int cbData;
            public IntPtr lpData;
        }

        public void sendData(String msg, Boolean isUnicode)
        {
            COPYDATASTRUCT cds = new COPYDATASTRUCT();
            cds.cbData = (msg.Length + 1) * (isUnicode ? 2:1);
            cds.lpData = (isUnicode ? Marshal.StringToCoTaskMemUni(msg) : Marshal.StringToCoTaskMemAnsi(msg));

            IntPtr cdsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(cds));
            Marshal.StructureToPtr(cds, cdsPtr, false);

            IntPtr clientWnd = Win32Helper.GetCurrentWindowHandle();
            SendMessage(clientWnd, WM_COPYDATA, IntPtr.Zero, cdsPtr);

            Marshal.FreeHGlobal(cdsPtr);
            Marshal.FreeCoTaskMem(cds.lpData);
        }

2、接收方WinForm

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        private struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public int cbData;
            public string lpData;
        }

        public const int WM_COPYDATA = 0x004A;
        protected override void WndProc(ref System.Windows.Forms.Message msg)
        {
            string msgTxt = "";
            COPYDATASTRUCT cds = new COPYDATASTRUCT();
            switch (msg.Msg)
            {
                case WM_COPYDATA:
                    if(msg.LParam!=IntPtr.Zero)
                    {
                        cds = (COPYDATASTRUCT)msg.GetLParam(cds.GetType());
                        String msgstr = cds.lpData;
                        //MessageBox.Show(msgstr);
                    }
                    break;
                default:
                    base.WndProc(ref msg);
                    break;
            }
        }

使用WM_COPYDATA实现跨进程通讯(上)

1、发送方MFC

void XXX::SendCopyDataMessage(CString strWinTitle, CString strMsg)
{
	HWND hdlg;
	hdlg = ::FindWindow(NULL, strWinTitle);
	if (NULL != hdlg)
	{
		COPYDATASTRUCT cds = { 0 };
		cds.dwData = 0;
		cds.cbData = (strMsg.GetLength()+1)*sizeof(TCHAR);
		cds.lpData = strMsg.GetBuffer(strMsg.GetLength());
		::SendMessage(hdlg, WM_COPYDATA, (WPARAM)this->m_hWnd, (LPARAM)&cds);
		strMsg.ReleaseBuffer();
	}
}

2、接收方MFC

BOOL XXX::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
	CString strMsg;
	if (pCopyDataStruct && pCopyDataStruct->cbData)
	{
		strMsg = (LPCTSTR)(pCopyDataStruct->lpData);
		MessageBox(strMsg, L"WM_COPYDATA",  MB_OK);
	}

	return CDialogEx::OnCopyData(pWnd, pCopyDataStruct);
}