Winform引用Activex控件

今天写了两个简单的Activex控件,一个用的MFC,一个用的ATL

用MFC的控件,编译后,直接引用就可以使用了。

用ATL写的控件,编译后,可以添加到VC程序中使用,但在WinForm程序中不可以使用,从工具箱拖拽到form后会报下面的错误:

Failed to create component 'AxHost'.  The error message follows:
 'System.InvalidOperationException: Unable to initialize component.
   at System.Windows.Forms.AxHost.DepersistControl()
   at System.Windows.Forms.AxHost.ActivateAxControl()
   at System.Windows.Forms.AxHost.TransitionUpTo(Int32 state)
   at System.Windows.Forms.AxHost.CreateHandle()
   at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
   at System.Windows.Forms.Control.CreateControl()
   at System.Windows.Forms.Control.ControlCollection.Add(Control value)
   at System.Windows.Forms.Form.ControlCollection.Add(Control value)
   at System.Windows.Forms.Design.ParentControlDesigner.AddChildControl(Control newChild)
   at System.Windows.Forms.Design.ParentControlDesigner.AddControl(Control newChild, IDictionary defaultValues)
   at System.Windows.Forms.Design.ControlDesigner.InitializeNewComponent(IDictionary defaultValues)
   at System.Windows.Forms.Design.AxHostDesigner.InitializeNewComponent(IDictionary defaultValues)'

查找了半天,有人说用AxImp.exe生产一个代理类可以解决这个问题。
尝试了SDK7.0,SDK7.1,SDK8.0,SDK8.1的AxImp.exe,可以成功生成dll,但是仍然没法使用。

也有人说,可以通过降低.NetFramework版本解决这个问题,2.0,3.0,3.5我都试了下,都不行。

试了VS2010和VS2013都不行,累了,回去了。。。

明天有空再弄吧。。。

今天试了一下,微软你大爷的,同样的操作,VS2008上(XP和Win7)就是好的。。。
真够坑爹啊。。。

再次测试表明:
1、VS2008的ATL控件在高版本的VS上可以插入到WinForm
2、VS2010以上的ATL控件,不能插入到VS2008以上任何版本的WinForm

VS2010以上的ATL控件,插入VS2008时,报的错误与上面不同

Debug Assertion Failed!
Program:.......
File:......vc\atlmfc\include\atlctl.h

Expression:pClientSite == 0 || m_spClientSite == 0

For information on how ....

微软,你自己的产品,兼容性做好一些,你能死啊。。。

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);
}

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

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

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);
}

ActiveX控件使用SDI特性(上)

大家都知道,使用微软的MFC ActiveX控件向导生成的控件类,是基于COleControl的,而COleControl是基于CWnd类。这样很多MFC的特性,如CFrameWnd的特性,CSingleDocTemplate(SDI)的特性等就无法使用了。如果要把用到这些类的MFC程序封装为ActiveX插件,就会有不少麻烦。

其实这个问题,在上个世纪MFC诞生不久,就有人解决了,并提供了完整的示例代码。微软官方的这篇文章《Designing ActiveX Components with the MFC Document/View Model》,在原地址http://www.microsoft.com/mind/0497/mfc.asp已经无法找到了。

但好在这里还有完整的备份《Designing ActiveX Components with the MFC Document/View Model》

原文的作者,实现了CActiveXDocTemplate和CActiveXDocControl两个类,而用户只需要将控件的基类从COleControl换为CActiveXDocControl,并做简单修改,就可以方便的使用SDI的特性了。

整体思路其实是使用CActiveXDocControl扩展了COleControl。在CActiveXDocControl中,作者初始化了CDocManager,使用CActiveXDocTemplate控制了document、view、frame的生成,处理了OnSize事件,并使用Timer定时获取消息处理更新。

我们使用的时候,主要就是用这两个类,代码如下(两个类相互引用,所以放到了同一文件中):

1、ActivDoc.h

class CActiveXDocTemplate : public CSingleDocTemplate
{
    enum { IDR_NOTUSED = 0x7FFF };

    CWnd* m_pParentWnd;
    CFrameWnd* m_pFrameWnd;
    CString m_docFile;

public:
    CActiveXDocTemplate(CRuntimeClass* pDocClass,
        CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass);

    CFrameWnd* CreateDocViewFrame(CWnd* pParentWnd);
    void SaveDocumentFile();

    virtual CFrameWnd* CreateNewFrame(CDocument* pDoc,
        CFrameWnd* pOther);
    virtual CDocument* OpenDocumentFile(
        LPCTSTR lpszPathName, BOOL bVerifyExists = TRUE);
};

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

class CActiveXDocControl : public COleControl
{
    enum { WM_IDLEUPDATECMDUI = 0x0363 };

    static BOOL m_bDocInitialized;
    CActiveXDocTemplate* m_pDocTemplate;
    CFrameWnd* m_pFrameWnd;

    DECLARE_DYNAMIC(CActiveXDocControl)

protected:
    void AddDocTemplate(CActiveXDocTemplate* pDocTemplate);
    CDocTemplate* GetDocTemplate() { return m_pDocTemplate; }

    //{{AFX_MSG(CActiveXDocControl)
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnTimer(UINT nIDEvent);
    afx_msg void OnDestroy();
    //}}AFX_MSG
    //{{AFX_DISPATCH(CActiveXDocControl)
    //}}AFX_DISPATCH
    //{{AFX_EVENT(CActiveXDocControl)
    //}}AFX_EVENT

    DECLARE_MESSAGE_MAP()
    DECLARE_DISPATCH_MAP()
    DECLARE_EVENT_MAP()

public:
    CActiveXDocControl();
    virtual ~CActiveXDocControl();

    enum {
    //{{AFX_DISP_ID(CActiveXDocControl)
    //}}AFX_DISP_ID
    };
};

2、ActivDoc.cpp

// ActivDoc.cpp : implementation file
//

#include "stdafx.h"
#include "ActivDoc.h"

CActiveXDocTemplate::CActiveXDocTemplate(CRuntimeClass* pDocClass,
    CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass)
        : CSingleDocTemplate(IDR_NOTUSED, pDocClass, pFrameClass,
            pViewClass)
{
    ASSERT(pFrameClass);
}

CFrameWnd* CActiveXDocTemplate::CreateDocViewFrame(CWnd* pParentWnd)
{
    ASSERT(pParentWnd && IsWindow(*pParentWnd));
    ASSERT_KINDOF(CActiveXDocControl, pParentWnd);
    m_pParentWnd = pParentWnd;
    m_pFrameWnd = NULL;

    // OpenDocumentFile is a virtual method (implemented in
    // the CSingleDocTemplate base class) that creates
    // the document (either empty or loaded from the specified
    // file) and calls our CreateNewFrame function. Passing
    // NULL to the function creates a new document. Incidentally,
    // the view is created by the CFrameWnd's OnCreateClient()
    // method.

    if (!OpenDocumentFile(NULL))
        return NULL;

    // Since OpenDocumentFile sets m_pFrame, we can now use it.

    ASSERT(m_pFrameWnd);
    ASSERT_KINDOF(CFrameWnd, m_pFrameWnd);
    m_pFrameWnd->ShowWindow(SW_SHOWNORMAL);
    return m_pFrameWnd;
}

CFrameWnd* CActiveXDocTemplate::CreateNewFrame(CDocument* pDoc,
        CFrameWnd* pOther)
{
    ASSERT(pOther == NULL);
    ASSERT(m_pFrameClass != NULL);
    if (pDoc != NULL)
        ASSERT_VALID(pDoc);

    // Create a frame wired to the specified document

    CCreateContext context;
    context.m_pCurrentFrame = pOther;
    context.m_pCurrentDoc = pDoc;
    context.m_pNewViewClass = m_pViewClass;
    context.m_pNewDocTemplate = this;

    m_pFrameWnd = (CFrameWnd*)m_pFrameClass->CreateObject();
    if (m_pFrameWnd == NULL)
    {
        TRACE1("Warning: Dynamic create of frame %hs failed.\n",
            m_pFrameClass->m_lpszClassName);
        return NULL;
    }
    ASSERT_KINDOF(CFrameWnd, m_pFrameWnd);

    if (context.m_pNewViewClass == NULL)
        TRACE0("Warning: creating frame with no default view.\n");

    // The frame is created as a menu-less child of the
    // CActiveXDocControl in which it will reside.

    ASSERT_KINDOF(CActiveXDocControl, m_pParentWnd);
    if (!m_pFrameWnd->Create(NULL, "", WS_CHILD|WS_VISIBLE,
        CFrameWnd::rectDefault, m_pParentWnd, NULL, 0, &context))
    {
        TRACE0("Warning: CDocTemplate couldn't create a frame.\n");
        return NULL;
    }

    return m_pFrameWnd;
}

CDocument* CActiveXDocTemplate::OpenDocumentFile(
    LPCTSTR lpszPathName, BOOL bVerifyExists)
{
    SaveDocumentFile();
    m_docFile = lpszPathName;

    if (bVerifyExists)
    {
        DWORD dwAttrib = GetFileAttributes(m_docFile);
        if (dwAttrib == 0xFFFFFFFF ||
            dwAttrib == FILE_ATTRIBUTE_DIRECTORY)
        {
            lpszPathName = NULL;
        }
    }

    return CSingleDocTemplate::OpenDocumentFile(
        lpszPathName, TRUE);
}

void CActiveXDocTemplate::SaveDocumentFile()
{
    if (m_pOnlyDoc != NULL)
    {
        if (!m_docFile.IsEmpty())
            m_pOnlyDoc->OnSaveDocument(m_docFile);
        else
            m_pOnlyDoc->SetModifiedFlag(FALSE);
    }
}

//===================================================
// CActiveXDocControl

IMPLEMENT_DYNAMIC(CActiveXDocControl, COleControl)
BEGIN_MESSAGE_MAP(CActiveXDocControl, COleControl)
    //{{AFX_MSG_MAP(CActiveXDocControl)
    ON_WM_CREATE()
    ON_WM_SIZE()
    ON_WM_TIMER()
    ON_WM_DESTROY()
    //}}AFX_MSG_MAP
    ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
END_MESSAGE_MAP()
BEGIN_DISPATCH_MAP(CActiveXDocControl, COleControl)
    //{{AFX_DISPATCH_MAP(CActiveXDocControl)
    //}}AFX_DISPATCH_MAP
END_DISPATCH_MAP()
BEGIN_EVENT_MAP(CActiveXDocControl, COleControl)
    //{{AFX_EVENT_MAP(COleFrameCtrl)
    //}}AFX_EVENT_MAP
END_EVENT_MAP()

int CActiveXDocControl::m_bDocInitialized = FALSE;

CActiveXDocControl::CActiveXDocControl()
{
    m_pDocTemplate = NULL;
    m_pFrameWnd = NULL;

    // Since we're in an OCX, CWinApp::InitApplication() is
    // not called by the framework. Unfortunately, that method
    // performs CDocManager initialization that is necessary
    // in order for our DocTemplate to clean up after itself.
    // We simulate the same initialization by calling the
    // following code the first time we create a control.

    if (!m_bDocInitialized)
    {
        CDocManager docManager;
        docManager.AddDocTemplate(NULL);
        m_bDocInitialized = TRUE;
    }
}

CActiveXDocControl::~CActiveXDocControl()
{
    // Note that the frame, the document, and the view are
    // all deleted automatically by the framework!
    
    delete m_pDocTemplate;
}

void CActiveXDocControl::AddDocTemplate(CActiveXDocTemplate* pDocTemplate)
{
    // I've decided to call this function AddDocTemplate to
    // be consistent with naming of CWinApp::AddDocTemplate.
    // However, only one DocTemplate is allowed per control.
    
    ASSERT(pDocTemplate);
    ASSERT(m_pDocTemplate == NULL);
    m_pDocTemplate = pDocTemplate;
}

int CActiveXDocControl::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
    if (COleControl::OnCreate(lpCreateStruct) == -1)
        return -1;

    // The CActiveXDocTemplate object will create the
    // document, the view, and the frame inside the
    // control. The reason we need a handle to the frame
    // is so that we can resize it when the control is
    // resized.
    
    ASSERT(m_pDocTemplate);    // Set in call to AddDocTemplate
    m_pFrameWnd = m_pDocTemplate->CreateDocViewFrame(this);
    ASSERT_KINDOF(CFrameWnd, m_pFrameWnd);

    // By default, we'll create the control with a border,
    // since it looks better for frames containing a toolbar.

    SetBorderStyle(TRUE);
    SetTimer(WM_IDLEUPDATECMDUI, 300, NULL);
    return 0;
}

void CActiveXDocControl::OnSize(UINT nType, int cx, int cy) 
{
    COleControl::OnSize(nType, cx, cy);

    // The CFrameWnd should always fill up the entire client
    // area of the control.

    if (m_pFrameWnd != NULL)
    {
        ASSERT(IsWindow(*m_pFrameWnd));
        CRect area;
        GetClientRect(area);
        m_pFrameWnd->MoveWindow(area.left, area.top, area.right,
            area.bottom);
    }
}

void CActiveXDocControl::OnTimer(UINT nIDEvent) 
{
    // Since we're in an OCX, we don't control the message loop,
    // so CWinThread::OnIdle is never called. That means we have
    // to periodically pump the ON_UPDATE_COMMAND_UI messages
    // by hand.
    
    SendMessageToDescendants(WM_IDLEUPDATECMDUI, TRUE);
    COleControl::OnTimer(nIDEvent);
}


void CActiveXDocControl::OnDestroy() 
{
    AfxGetApp()->m_pMainWnd = NULL;
    m_pDocTemplate->SaveDocumentFile();
    COleControl::OnDestroy();
}

困了,回去再写。。。

VS2013编译VS2010的CPP项目出错

前一阵子重装了电脑,很多编译环境都丢失了,各种悲剧不说,还有一些奇奇怪怪的错误

我以前有一个VS的项目,初始是2010sp1的VC本地项目,后来升级到VS2013
但一直没时间去处理兼容性问题,就没有将项目升级到2013的格式
相当于用2013在编译2010的工程,好在是相安无事。

现在重装了,我准备重新编译一下,结果VS2013告诉我Windows SDK配置错误

warning MSB8003: Could not find WindowsSDKDir variable from the registry. TargetFrameworkVersion or PlatformToolset may be set to an invalid version number.

在网上找了很久,解决方法就两种,一是修改注册表,一是安装对应版本的SDK。
尝试了修改注册表,但没有效果,还是同样的错误。
由于时间很紧迫,一怒之下安装了VS2010+SP1,结果就好了。

现在的注册表为:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows]
"CurrentVersion"="7.1.51106"
"CurrentInstallFolder"="C:\\Program Files (x86)\\Windows Kits\\8.0"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A]
"InstallationFolder"="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\"
"ProductVersion"="7.0.30319"
"ProductName"="Microsoft Windows SDK for Visual Studio 2010"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A\WinSDK-NetFx35Tools]
"ProductVersion"="7.0.30319"
"ComponentName"="Windows SDK .NET Framework 3.5 Multi-targeting Utilities"
"InstallationFolder"="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin\\"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A\WinSDK-NetFx35Tools-x64]
"ProductVersion"="7.0.30319"
"ComponentName"="Windows SDK .NET Framework 3.5 Multi-targeting Utilities (x64)"
"InstallationFolder"="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin\\x64\\"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A\WinSDK-NetFx35Tools-x86]
"ProductVersion"="7.0.30319"
"ComponentName"="Windows SDK .NET Framework 3.5 Multi-targeting Utilities"
"InstallationFolder"="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin\\"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A\WinSDK-NetFx40Tools]
"ProductVersion"="7.0.30319"
"ComponentName"="Windows SDK Tools for .NET Framework 4.0"
"InstallationFolder"="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin\\NETFX 4.0 Tools\\"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A\WinSDK-NetFx40Tools-x64]
"ProductVersion"="7.0.30319"
"ComponentName"="Windows SDK Tools for .NET Framework 4.0 (x64)"
"InstallationFolder"="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin\\NETFX 4.0 Tools\\x64\\"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A\WinSDK-NetFx40Tools-x86]
"ProductVersion"="7.0.30319"
"ComponentName"="Windows SDK Tools for .NET Framework 4.0"
"InstallationFolder"="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin\\NETFX 4.0 Tools\\"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A\WinSDK-SDKTools]
"InstallationFolder"="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin\\"
"ProductVersion"="7.0.30319"
"ComponentName"="Windows Common Utilities"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A\WinSDK-Win32Tools]
"InstallationFolder"="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin\\"
"ProductVersion"="7.0.30319"
"ComponentName"="Windows Utilities for Win32 Development"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A\WinSDK-WindowsHeadersLibs]
"InstallationFolder"="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\"
"ProductVersion"="7.0.30319"
"ComponentName"="Windows Headers and Libraries"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A\WinSDK-WinSDKIntellisenseRefAssys]
"InstallationFolder"="C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\mmc\\v3.0\\"
"ProductVersion"="7.0.30319"
"ComponentName"="Windows Intellisense and Reference Assemblies"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.1]
"InstallationFolder"="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\"
"ProductVersion"="7.1.7600.0.30514"
"ProductName"="Microsoft Windows SDK for Windows 7 (7.1.7600.0.30514)"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.1\WinSDK-NetFx40Tools]
"ProductVersion"="7.1.7600.0.30514"
"ComponentName"="Windows SDK Tools for .NET Framework 4.0"
"InstallationFolder"="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Bin\\NETFX 4.0 Tools\\"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.1\WinSDK-NetFx40Tools-x64]
"ProductVersion"="7.1.7600.0.30514"
"ComponentName"="Windows SDK Tools for .NET Framework 4.0 (x64)"
"InstallationFolder"="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Bin\\NETFX 4.0 Tools\\x64\\"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.1\WinSDK-NetFx40Tools-x86]
"ProductVersion"="7.1.7600.0.30514"
"ComponentName"="Windows SDK Tools for .NET Framework 4.0"
"InstallationFolder"="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Bin\\NETFX 4.0 Tools\\"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.1\WinSDKBuild]
"InstallationFolder"="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\"
"ProductVersion"="7.1.7600.0.30514"
"ComponentName"="Microsoft Windows SDK Headers and Libraries"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.1\WinSDKIntellisenseNFX]
"InstallationFolder"="C:\\Windows\\Microsoft.NET\\Framework\\"
"ProductVersion"="7.1.7600.0.30514"
"ComponentName"="Microsoft Windows SDK Intellisense for .Net"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.1\WinSDKIntellisenseRefAssys]
"InstallationFolder"="C:\\Program Files\\Reference Assemblies\\Microsoft\\"
"ProductVersion"="7.1.7600.0.30514"
"ComponentName"="Windows SDK Intellisense and Reference Assemblies"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.1\WinSDKInterop]
"InstallationFolder"="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\"
"ProductVersion"="7.1.7600.0.30514"
"ComponentName"="Microsoft Windows SDK NetFx Interop"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.1\WinSDKNetFx35Tools]
"InstallationFolder"="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\bin\\"
"ProductVersion"="7.1.7600.0.30514"
"ComponentName"="Microsoft Windows SDK NetFx 3.5 Tools"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.1\WinSDKNetFx35Tools\1033]
"SP"=dword:00000000

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.1\WinSDKNetFx35Tools-x64]
"InstallationFolder"="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\bin\\x64\\"
"ProductVersion"="7.1.7600.0.30514"
"ComponentName"="Microsoft Windows SDK NetFx 3.5 Tools (x64)"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.1\WinSDKSamples]
"InstallationFolder"="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Samples\\"
"ProductVersion"="7.1.7600.0.30514"
"ComponentName"="Windows SDK Samples"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.1\WinSDKTools]
"InstallationFolder"="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\bin\\"
"ProductVersion"="7.1.7600.0.30514"
"ComponentName"="Windows SDK Common Utilities"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.1\WinSDKTools-x64]
"InstallationFolder"="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\bin\\x64\\"
"ProductVersion"="7.1.7600.0.30514"
"ComponentName"="Windows SDK Common Utilities (x64)"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.1\WinSDKWin32Tools]
"InstallationFolder"="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\bin\\"
"ProductVersion"="7.1.7600.0.30514"
"ComponentName"="Windows SDK Utilities for Win32 Development"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.1\WinSDKWin32Tools-x64]
"InstallationFolder"="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\bin\\x64\\"
"ProductVersion"="7.1.7600.0.30514"
"ComponentName"="Windows SDK Utilities for Win32 Development (x64)"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.1A]
"InstallationFolder"="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.1A\\"
"ProductVersion"="7.1.51106"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.1A\XPSupport]
"InstallationFolder"="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.1A\\"
"ProductVersion"="7.1.51106"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v8.0A]
"InstallationFolder"="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v8.0A\\"
"ProductVersion"="8.0.50709"
"ServicingVersion"="8.0.50710"
"ProductName"="Microsoft .NET Framework 4.5 SDK"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v8.0A\WinSDK-NetFx35Tools]
"ProductVersion"="8.0.50727"
"ComponentName"="Microsoft Visual Studio 2012 Multi-targeting Utilities for .NET Framework 3.5"
"InstallationFolder"="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin\\"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v8.0A\WinSDK-NetFx35Tools-x64]
"ProductVersion"="8.0.50727"
"ComponentName"="Microsoft Visual Studio 2012 Multi-targeting Utilities for .NET Framework 3.5 (x64)"
"InstallationFolder"="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin\\x64\\"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v8.0A\WinSDK-NetFx35Tools-x86]
"ProductVersion"="8.0.50727"
"ComponentName"="Microsoft Visual Studio 2012 Multi-targeting Utilities for .NET Framework 3.5"
"InstallationFolder"="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin\\"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v8.0A\WinSDK-NetFx40Tools]
"ProductVersion"="8.0.50709"
"ComponentName"="Microsoft .NET Framework 4.5 SDK"
"InstallationFolder"="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v8.0A\\bin\\NETFX 4.0 Tools\\"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v8.0A\WinSDK-NetFx40Tools-x64]
"ProductVersion"="8.0.50709"
"ComponentName"="Microsoft .NET Framework 4.5 SDK"
"InstallationFolder"="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v8.0A\\bin\\NETFX 4.0 Tools\\x64\\"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v8.0A\WinSDK-NetFx40Tools-x86]
"ProductVersion"="8.0.50709"
"ComponentName"="Microsoft .NET Framework 4.5 SDK"
"InstallationFolder"="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v8.0A\\bin\\NETFX 4.0 Tools\\"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v8.1]
"InstallationFolder"="C:\\Program Files (x86)\\Windows Kits\\8.1\\"
"ProductName"="Microsoft Windows SDK for Windows 8.1"
"ProductVersion"="8.1"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v8.1A]
"InstallationFolder"="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v8.1A\\"
"ProductVersion"="8.1.51641"
"ProductName"="Microsoft .NET Framework 4.5.1 SDK"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v8.1A\WinSDK-NetFx40Tools]
"ProductVersion"="8.1.51641"
"ComponentName"="Microsoft .NET Framework 4.5.1 SDK"
"InstallationFolder"="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v8.1A\\bin\\NETFX 4.5.1 Tools\\"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v8.1A\WinSDK-NetFx40Tools-x64]
"ProductVersion"="8.1.51641"
"ComponentName"="Microsoft .NET Framework 4.5.1 SDK"
"InstallationFolder"="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v8.1A\\bin\\NETFX 4.5.1 Tools\\x64\\"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v8.1A\WinSDK-NetFx40Tools-x86]
"ProductVersion"="8.1.51641"
"ComponentName"="Microsoft .NET Framework 4.5.1 SDK"
"InstallationFolder"="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v8.1A\\bin\\NETFX 4.5.1 Tools\\"

其实在此前,我已经安装了Windows SDK7.1,应该是可以编译的,不知道为什么。。。
当时时间紧迫,没能细究。
希望我现在的注册表配置,能给大家提供参考。。。

cpp用函数实现sizeof操作符的功能

#include "stdafx.h"
#include <stdlib.h>

using namespace std;

template<class ToT>
int getTypeSize(ToT *t,int len=1);

#define GET_TYPE_LEN(TYPE_NAME) getTypeSize(new TYPE_NAME());

struct MM{
	int m1;
	char m2;
	long m3;
	char* m4;
};

int _tmain(int argc, _TCHAR* argv[])
{
	struct MM mm;
	int nLen1 = getTypeSize(&mm);
	int nLen2 = GET_TYPE_LEN(MM); 

	return 0;
}

template<class ToT>
int getTypeSize(ToT *t, int len)
{
	return((char *)(t+1)-(char *)t)*len;
}

这种实现,有几个问题:
1、区分是类型还是变量,暂时没有找到好的办法
2、对于数组,暂时没有好的方法处理
3、为简化处理,要求输入为指针