.NET CF:
[DllImport("coredll.Dll")] private static extern int GetLastError(); [DllImport("coredll.Dll")] private static extern int ReleaseMutex(IntPtr hMutex); [DllImport("coredll.Dll")] private static extern IntPtr CreateMutex(SECURITY_ATTRIBUTES lpMutexAttributes,
bool bInitialOwner,
string lpName); [StructLayout( LayoutKind.Sequential)] public class SECURITY_ATTRIBUTES { public int nLength; public int lpSecurityDescriptor; public int bInheritHandle; } const int ERROR_ALREADY_EXISTS = 0183;
static void Main() { #region Api_Call CreateMutex; IntPtr hMutex; hMutex=CreateMutex(null,false,"程序名"); if (GetLastError()!=ERROR_ALREADY_EXISTS) { Application.Run(new Frmmenu()); } else { MessageBox.Show("本程序只允许同时运行一个"); ReleaseMutex(hMutex); } #endregion }
EVC:
HANDLE hMutex=::CreateMutex(NULL,TRUE,L"LiCR"); if(hMutex!=NULL) { if(GetLastError()==ERROR_ALREADY_EXISTS) {
AfxMessageBox( "已经有一个程序运行." );
ReleaseMutex(hMutex);
return FALSE;
}
}
大部分网站就只提供到这一步,但是在实际操作过程中,有时还是会打开多个实例,下面提供一个方式,再次单击时,打开第一个实例,经实际测试,通过
[DllImport("coredll.dll", EntryPoint = "CreateMutex", SetLastError = true)]
public static extern IntPtr CreateMutex(IntPtr lpMutexAttributes, bool bInitiaOwner, string lpName);
[DllImport("coredll.dll", SetLastError = true)]
public static extern int ReleaseMutex(IntPtr hMutex);
[DllImport("coredll.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("coredll.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("coredll.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
public const int ERROR_ALREADY_EXISTS = 183;
public const int SW_SHOW = 5;public static LoginForm MainWindow;
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[MTAThread]
static void Main()
{
IntPtr hMutex = CreateMutex(IntPtr.Zero, false, @"GprsPatrolNtV2");if (Marshal.GetLastWin32Error() == ERROR_ALREADY_EXISTS)
{
IntPtr mainFrm = FindWindow(null, GlobalSetting.ApplicationTitle);
ShowWindow(mainFrm, SW_SHOW);
SetForegroundWindow(mainFrm);
Application.Exit();
}
else
{
MainWindow = new LoginForm();
Application.Run(MainWindow);ReleaseMutex(hMutex);
}
}
所谓Windows后台服务,即后台自动运行的程序,一般随操作系统启动而启动,在我的电脑 服务后应用程序 服务里面能看到当前电脑的服务.一般而言,程序上用VC、C++写Windows服务,但是我对这些语言不是很熟,一般编程用C#较多,所以就用C#语言写了一个Windows服务.
其实需求是这样的,做那个报价系统的时候加入了发短信的功能,订单处理完即将发货的时候要发送短信都客户手机上,公司内部员工处理订单超时要自动发短信,群发产品促销信息到客户手机上等,还有定时发送短信的需求,所以最后面决定把发短信的模块独立出来,以后还有什么功能方便一起调用,而最终选择了采用Windows后台服务.
其实Windows服务并不好做到通用,它并不能在用户的界面显示一些什么信息等,它只是在后台默默的处理一些事情,起着辅助的作用.那如何实现发送段信通用调用的接口呢?它们之间的信息又是如何来交互呢?数据库!对,就是它存储数据信息的.而数据库都能很方便的访问操作.把发送短信的后台服务定时去访问一个数据库,而另外任何要发送短信的地方也访问数据库,并插入一条要发送的短信到表里面,稍后Windows后台服务访问该表将此短信发送出去.这可能是一个比较蠢的方法,但实现起来较简单.
首先,由于它是要安装的,所以它运行的时候就需要一个安装类Installer将服务安装到计算机,新建一个后台服务安装类继承自Installer,安装初始化的时候是以容器进行安装的,所以还要建立ServiceProcessInstaller和ServiceInstaller服务信息组件添加到容器安装,在Installer类增加如下代码:
private System.ServiceProcess.ServiceProcessInstaller spInstaller;
private System.ServiceProcess.ServiceInstaller sInstaller;
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
// 创建ServiceProcessInstaller对象和ServiceInstaller对象
this.spInstaller = new System.ServiceProcess.ServiceProcessInstaller();
this.sInstaller = new System.ServiceProcess.ServiceInstaller();
// 设定ServiceProcessInstaller对象的帐号、用户名和密码等信息
this.spInstaller.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
this.spInstaller.Username = null;
this.spInstaller.Password = null;
// 设定服务名称
this.sInstaller.ServiceName = "SendMessage";
sInstaller.DisplayName = "发送短信服务";
sInstaller.Description = "一个定时发送短信的服务";
// 设定服务的启动方式
this.sInstaller.StartType = System.ServiceProcess.ServiceStartMode.Automatic;
this.Installers.AddRange(new System.Configuration.Install.Installer[] { this.spInstaller, this.sInstaller });
}
再添加一个服务类继承自ServiceBase,我们可以重写基类的OnStart、OnPause、OnStop、OnContinue等方法来实现我们需要的功能并设置指定一些属性.由于是定事发送短信的服务,自然少不了Windows记时器,在OnStart事件里我们写入服务日志,并初始化记时器.
private static readonly string CurrentPath = Application.StartupPath + "\\";
protected override void OnStart(string[] args)
{
string path = CurrentPath + "Log\\start-stop.log";
FileStream fs = new FileStream(path, FileMode.Append, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine("The Service is Starting On " + DateTime.Now.ToString());
sw.Flush();
sw.Close();
fs.Close();
time = new System.Timers.Timer(1000 * Convert.ToInt32(GetSettings("TimeSpan")));
time.Enabled = true;
time.Elapsed += this.TimeOut;
time.Start();
}
实例化记时器类启动后,将在指定时间间隔触发Elapsed指定事件,如上GetSettings为读取我App.config文件里一个配置节点(值为30)的方法,所以上面将会每隔30秒调用TimeOut方法.而改方法就是我们发短信的具体操作.代码如下:
{
try
{
if (GetSettings("Enabled").ToLower() == "true")
{
SqlConnection con = new SqlConnection(GetSettings("ConnString"));
SqlCommand cmd = new SqlCommand("select [sysid],[admin_inner_code],[user_inner_code],[phone],[message],[sendtime] from [tbl_note_outbox]", con);
con.Open();
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
string phone = rdr["phone"].ToString();
string message = rdr["message"].ToString();
string sendtime = rdr["sendtime"].ToString();
System.Text.Encoding encoder = System.Text.Encoding.GetEncoding("GB2312");
string url = string.Format("http://211.155.23.205/isapi.dll?SendSms&AgentID={0}&PassWord={1}&phone={2}&msg={3}&sendtime={4}", GetSettings("AgentID"), GetSettings("PassWord"), phone,System.Web.HttpUtility.UrlEncode( message,encoder), sendtime);
System.Net.WebClient wClient = new System.Net.WebClient();
string msg = System.Text.Encoding.Default.GetString(wClient.DownloadData(url));
wClient.Dispose();
//删除已经发送成功的,并保存发送记录
if (msg == "发送成功")
{
DateTime dtsend = sendtime == "0" ? DateTime.Now : DateTime.ParseExact(sendtime, "yyyyMMddHHmmss", null);
string sql = string.Format("delete from [tbl_note_outbox] where [sysid]={0} INSERT INTO [tbl_note_log] ([admin_inner_code],[user_inner_code],[status],[phone],[message],[sendtime]) VALUES('{1}','{2}','{3}','{4}','{5}','{6}')", rdr["sysid"], rdr["admin_inner_code"], rdr["user_inner_code"], msg, phone, message, dtsend);
SqlConnection conn = new SqlConnection(GetSettings("ConnString"));
SqlCommand delete = new SqlCommand(sql, conn);
conn.Open();
delete.ExecuteNonQuery();
conn.Close();
delete.Dispose();
}
}
rdr.Close();
con.Close();
cmd.Dispose();
}
}
catch (Exception ex)
{
string errorPath = CurrentPath + "Log\\error.log";
if (!File.Exists(errorPath))
{
FileStream create = File.Create(errorPath);
create.Close();
}
FileStream fs = new FileStream(errorPath, FileMode.Append, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine("Exception: " +ex.Message+" --"+ DateTime.Now.ToString());
sw.Flush();
sw.Close();
fs.Close();
}
}
上面我们使用try、catch访问数据库,并记录错误异常信息. 发送短信是使用发送一个Web请求发送出去的,要注意请求url字符串的编码类型,要与请求页面编码一致,不然会出现乱码.上面我们请求的是智网通集团短信(网址:http://www.09168.net/)的Web接口,通过访问他的网站来实现发短信,当然还要传递一些用户名、密码、手机号码和要发送的短信息等参数.他的收费平均大概为7分/条的样子,其实我原本不想用发送Web请求的这样方式来发送短信的,它本身提供了调用它发送短信的DLL,而且还有vc、delphi调用的Demo,但是没有用C#调用的例子,我刚开始试着用非托管动态链接库他提供的DLL,不知方法调用那里出错了一直都没能成功发送出短信,所以后来就用了他的Web方式接口了.他页面直接返回发送短信的状态信息.返回发送成功则短信发送成功,成功后我再将此条信息从要发送短信表里删除并保存在发送记录表里面,以备日后方便查询.其实登陆他的官网进入后台也能方便的查询,如下图.

发送短信服务的代码基本上搞定了,就看怎么在服务器上安装部署了.C#写的Windows后台服务不能直接安装,需要借助.NET Framework里面的InstallUtil.exe安装工具安装,我们可以做成一个执行CMD命令的文件BAT文件来安装启动它,命令如下:

安装完成以后,我们可以在我的电脑管理服务里面看到才安装上的后台服务

经测试,采用定时访问数据库发送短信的服务并不是很耗资源,刚启动的时候只占用内存为7、8M左右,经过在服务器上连续运行几天不关闭占用的内存也只升到15M左右,运行比较稳定,这里提供一个短信二次开发接口说明,有兴趣的朋友可以去下载看下
介绍
微软的.net framework 2.0相对于1.x来说增加了对FTP的支持。以前为了符合我的需求,我不等不使用第三方类库来实现FTP功能,但是为了可靠,还是使用.net framework的类比较好。我的这段代码没有做成可重复使用的类库的形式,但它却是比较容易理解的并能满足你的需求。它可以实现上传,下载,删除等任意功能。在这篇文章的后面将给大家出示.net 2.0下实现ftp的简单代码,使用的语言是c#。或许是因为这是.net新增的类,又或许是第三方类库已经能很好的实现你的需求,.net 2.0的这部分类库并没有得到足够的关注。
背景
作为我的工作的一部分,我已经使用了ftp模块,但是我只能在.net 1.1中去使用它,所以我不能深入的研究.net 2.0下ftp的实现。但是我相信,.ne 2.0下对ftp的支持是非常好的。
代码
不要忘记引入命名空间
using System.Net;
using System.IO;
下面的几个步骤包括了使用FtpWebRequest类实现ftp功能的一般过程
1、创建一个FtpWebRequest对象,指向ftp服务器的uri
2、设置ftp的执行方法(上传,下载等)
3、给FtpWebRequest对象设置属性(是否支持ssl,是否使用二进制传输等)
4、设置登录验证(用户名,密码)
5、执行请求
6、接收相应流(如果需要的话)
7、如果没有打开的流,则关闭ftp请求
开发任何ftp应用程序都需要一个相关的ftp服务器及它的配置信息。FtpWebRequest暴露了一些属性来设置这些信息。
接下来的代码示例了上传功能
首先设置一个uri地址,包括路径和文件名。这个uri被使用在FtpWebRequest实例中。
然后根据ftp请求设置FtpWebRequest对象的属性
其中一些重要的属性如下:
·Credentials - 指定登录ftp服务器的用户名和密码。
·KeepAlive - 指定连接是应该关闭还是在请求完成之后关闭,默认为true
·UseBinary - 指定文件传输的类型。有两种文件传输模式,一种是Binary,另一种是ASCII。两种方法在传输时,字节的第8位是不同的。ASCII使用第8位作为错误控制,而Binary的8位都是有意义的。所以当你使用ASCII传输时要小心一些。简单的说,如果能用记事本读和写的文件用ASCII传输就是安全的,而其他的则必须使用Binary模式。当然使用Binary模式发送ASCII文件也是非常好的。
·UsePassive - 指定使用主动模式还是被动模式。早先所有客户端都使用主动模式,而且工作的很好,而现在因为客户端防火墙的存在,将会关闭一些端口,这样主动模式将会失败。在这种情况下就要使用被动模式,但是一些端口也可能被服务器的防火墙封掉。不过因为ftp服务器需要它的ftp服务连接到一定数量的客户端,所以他们总是支持被动模式的。这就是我们为什么要使用被动模式的原意,为了确保数据可以正确的传输,使用被动模式要明显优于主动模式。(译者注:主动(PORT)模式建立数据传输通道是由服务器端发起的,服务器使用20端口连接客户端的某一个大于1024的端口;在被动(PASV)模式中,数据传输的通道的建立是由FTP客户端发起的,他使用一个大于1024的端口连接服务器的1024以上的某一个端口)
·ContentLength - 设置这个属性对于ftp服务器是有用的,但是客户端不使用它,因为FtpWebRequest忽略这个属性,所以在这种情况下,该属性是无效的。但是如果我们设置了这个属性,ftp服务器将会提前预知文件的大小(在upload时会有这种情况)
·Method - 指定当前请求是什么命令(upload,download,filelist等)。这个值定义在结构体WebRequestMethods.Ftp中。
| private void Upload(string filename) { FileInfo fileInf = new FileInfo(filename); string uri = "ftp://" + ftpServerIP + "/" + fileInf.Name; FtpWebRequest reqFTP; // 根据uri创建FtpWebRequest对象 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "/" + fileInf.Name)); // ftp用户名和密码 reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); // 默认为true,连接不会被关闭 // 在一个命令之后被执行 reqFTP.KeepAlive = false; // 指定执行什么命令 reqFTP.Method = WebRequestMethods.Ftp.UploadFile; // 指定数据传输类型 reqFTP.UseBinary = true; // 上传文件时通知服务器文件的大小 reqFTP.ContentLength = fileInf.Length; // 缓冲大小设置为2kb int buffLength = 2048; byte[] buff = new byte[buffLength]; int contentLen; // 打开一个文件流 (System.IO.FileStream) 去读上传的文件 FileStream fs = fileInf.OpenRead(); try { // 把上传的文件写入流 Stream strm = reqFTP.GetRequestStream(); // 每次读文件流的2kb contentLen = fs.Read(buff, 0, buffLength); // 流内容没有结束 while (contentLen != 0) { // 把内容从file stream 写入 upload stream strm.Write(buff, 0, contentLen); contentLen = fs.Read(buff, 0, buffLength); } // 关闭两个流 strm.Close(); fs.Close(); } catch (Exception ex) { MessageBox.Show(ex.Message, "Upload Error"); } } |
以上代码简单的示例了ftp的上传功能。创建一个指向某ftp服务器的FtpWebRequest对象,然后设置其不同的属性Credentials,KeepAlive,Method,UseBinary,ContentLength。
打开本地机器上的文件,把其内容写入ftp请求流。缓冲的大小为2kb,无论上传大文件还是小文件,这都是一个合适的大小。
| private void Download(string filePath, string fileName) { FtpWebRequest reqFTP; try { FileStream outputStream = new FileStream(filePath + "\\" + fileName, FileMode.Create); reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "/" + fileName)); reqFTP.Method = WebRequestMethods.Ftp.DownloadFile; reqFTP.UseBinary = true; reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse(); Stream ftpStream = response.GetResponseStream(); long cl = response.ContentLength; int bufferSize = 2048; int readCount; byte[] buffer = new byte[bufferSize]; readCount = ftpStream.Read(buffer, 0, bufferSize); while (readCount > 0) { outputStream.Write(buffer, 0, readCount); readCount = ftpStream.Read(buffer, 0, bufferSize); } ftpStream.Close(); outputStream.Close(); response.Close(); } catch (Exception ex) { MessageBox.Show(ex.Message); } } |
上面的代码实现了从ftp服务器上下载文件的功能。这不同于之前所提到的上传功能,下载需要一个响应流,它包含着下载文件的内容。这个下载的文件是在FtpWebRequest对象中的uri指定的。在得到所请求的文件后,通过FtpWebRequest对象的 GetResponse()方法下载文件。它将把文件作为一个流下载到你的客户端的机器上。
注意:我们可以设置文件在我们本地机器上的存放路径和名称。
| public string[] GetFileList() { string[] downloadFiles; StringBuilder result = new StringBuilder(); FtpWebRequest reqFTP; try { reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "/")); reqFTP.UseBinary = true; reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); reqFTP.Method = WebRequestMethods.Ftp.ListDirectory; WebResponse response = reqFTP.GetResponse(); StreamReader reader = new StreamReader(response.GetResponseStream()); string line = reader.ReadLine(); while (line != null) { result.Append(line); result.Append("\n"); line = reader.ReadLine(); } // to remove the trailing '\n' result.Remove(result.ToString().LastIndexOf('\n'), 1); reader.Close(); response.Close(); return result.ToString().Split('\n'); } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message); downloadFiles = null; return downloadFiles; } } |
上面的代码示例了如何从ftp服务器上获得文件列表。uri指向ftp服务器的地址。我们使用StreamReader对象来存储一个流,文件名称列表通过“\r\n”分隔开,也就是说每一个文件名称都占一行。你可以使用StreamReader对象的ReadToEnd() 方法来得到文件列表。上面的代码中我们用一个StringBuilder对象来保存文件名称,然后把结果通过分隔符分开后作为一个数组返回。我确定只是一个比较好的方法。
其他的实现如Rename,Delete,GetFileSize,FileListDetails,MakeDir等与上面的几段代码类似,就不多说了。
注意:实现重命名的功能时,要把新的名字设置给FtpWebRequest对象的RenameTo属性。连接指定目录的时候,需要在FtpWebRequest对象所使用的uri中指明。
需要注意的地方
你在编码时需要注意以下几点:
·除非EnableSsl属性被设置成true,否作所有数据,包括你的用户名和密码都将明文发给服务器,任何监视网络的人都可以获取到你连接服务器的验证信息。如果你连接的ftp服务器提供了SSL,你就应当把EnableSsl属性设置为true。
·如果你没有访问ftp服务器的权限,将会抛出SecurityException错误
·发送请求到ftp服务器需要调用GetResponse方法。当请求的操作完成后,一个FtpWebResponse对象将返回。这个 FtpWebResponse对象提供了操作的状态和已经从ftp服务器上下载的数据。FtpWebResponse对象的StatusCode属性提供了ftp服务器返回的最后的状态代码。FtpWebResponse对象的StatusDescription属性为这个状态代码的描述。
VS2008下,在一个项目里做好了一个ajaxpro的效果。
做好测试成功后,我搬到正式的项目中去,但是却一直不成功,总说未定义(命名空间)。检查来检查去,都不知道那出问题。
解决办法:
在web.config文件里添加如下语句:
<httpHandlers>
<add verb="*" path="*.ashx" type="AjaxPro.AjaxHandlerFactory,AjaxPro.2"/>
</httpHandlers>
问题解决!
QT4.3.3版本在VS2005集成开发环境下面的安装与配置
1 编译QT
1)下载QT的源代码文件包(注意:必须是.zip后缀的,.exe后缀的包是用mingw做编译器的源代码文件)。
2)如果是.zip后缀的源码包,将QT源代码解压到硬盘,例如:D:\Qt\4.3.3\;如果是.exe后缀的安装包,双击开始安装,(安装时需要指定mingW的路径,没有的话,应该要点击下载到本地并安装,缺少的话不知道会不会有问题)
2 下载并安装允许QT用vc编译的补丁
1)从网站 sourceforge.net下载acs-4.3.0-patch2.zip 。
2)将其解压到QT源代码的目录下。
(似乎从4.3.2版本开始,就不需要这个补丁了)
Qt 4.3.2 Windows OpenSource版下载:
http://www.qtcn.org/download/qt-win-opensource-src-4.3.2.zip
ftp://ftp.trolltech.com/qt/source/qt-win-opensource-src-4.3.2.zip
3 打开命令行工具,并把路径切换到QT源代码的目录下。
打开开始菜单,所有程序->Microsoft Visual Studio 2005->Visual Studio Tool,然后选择Visual Studio 2005 Command Prompt(VS2005的命令提示符),确保环境设置正确。
方法是看看nmake.exe是否在路径中:
D:\Qt\4.3.0> nmake /?
Microsoft (R) Program Maintenance Utility Version 6.00.8168.0
Copyright (C) Microsoft Corp1988-1998. All rights reserved.
Usage: NMAKE @commandfile
NMAKE [options] [/f makefile] [/x stderrfile] [macrodefs] [targets]
Options:……
如果环境变量不正确,会提示“'nmake' 不是内部或外部命令,也不是可运行的程序或批处理文件。”这时需要将路进切换到..\Common7\Tools,运行vsvars32.bat。
5 安装QT
如果环境变量设置正确,在VS2005命令提示符下,切换路径到QT安装目录:
D:
cd D:\Qt\4.3.0
configure –debug-and-release(这个作用是编译出 debug版本和release版本的qt的库,更多选项 可以用configure –help)
开始的时候会提问是否接受GPLlicence,输入y。然后就是漫长的等待了。根据提示,要求输入nmake。又是漫长的等待~
(只输入nmake 的话,就会把包括examples等的都给编译,那会很大很大…… 我们可以先输入nmake sub-src编译,其它的留待以后再编译)
6 设置环境变量
QMAKESPEC = win32-msvc2005
QTDIR = D:\Qt\4.3.4
path = %QTDIR%\bin
这样,如果要修改QT的路径,只要改QTDIR的值就可以了。
至此,QT环境就安装好了。
7 测试使用QT
编辑一个Qt测试程序测试是否安装成功了。在一个空文件夹中,建立一个文件 main.cpp 输入以下内容
保存后,打开VS2005命令提示符,将路径切换到例子所在的文件夹,
qmake -project
qmake
nmake
没有输入错误的话,就会发现,已经自动生成了debug目录,并且,生成了debug版本的程序。运行一下,就可以看到结果了。
nmake release 就可以生成release版本的程序。
qmake有很多的用处,点击查看详细的解释。
如果要在VS2005下面中编译,先用命令行 qmake -project 生成pro文件
再用命令行 qmake –t vcapp 生成VS2005的工程文件 *.vcproj
然后打开VS2005,打开生成的*.vcproj文件,编译后,则在对应的debug目录下面生成相对应的可执行文件。
8 使用Visual Studio的插件:Qt Visual Studio Integration v1.2.2 for.VS.2003.2005.exe
首先从网上面下载该插件,在安装时要求输入用户名和序列号,可以输入任意用户明,然后采用以下的序列号:
FGJ7UGX-WQPWJ6X-F4M-UG6ZQC-2G8N2G-6AYP3G-864F
FGJ58F-HQGNCCM-F4M-BVY8ELX-8KG9WT-NU5JAQ-6C21
FGBBY3M-WYYUFN9-F4M-GWEVVS9-WTKP39X-UKJUUDM-EE0D
FGM9UXX-PJ8CRVX-F4M-UQDJFQ9-PXHXTQ-BZF46Y9-694B
安装完毕后,打开vs2005,即发现菜单中多了个QT选项,新建项目时,可以选择QT projects。
如果有问题的话,可以打开S2005,选择"Tools" -> "Options" -> "Qt" -> "Builds", 查看是否配置成功。里面应该有QT的名字和安装路径,如果没有的话,进行手动设置。
Qt Visual Studio Integration v1.2.2 for.VS.2003.2005.exe的下载网址为:http://www618.fixdown.com/Qt.Visual.Studio.Integration.exe
8 测试使用
新建一个QT工程,方法为选择"Qt projects" -> "Qt Application"类型,输入工程名字,单击OK,一直Next,最后Finish.
