我说一下我的思想:先写一个关机程序,这个程序一直访问网络上的一个文件,这个文件是我们事先准备好的,里面有命令字符串,程序读取这个文件的内容,如果发现是关机命令,就执行关机命令,这样就可以通过一个网络文件来向远程计算机发命令了。想要通过手机来往网络文件里写命令,最好不过的是采用网页的形式了,只要在网站服务器上事先写好一个网页,该网页可以往配置文件里写命令,这样就好了。网页可以采用JSP、PHP、asp.net等书写,当然要取决于你的网站服务器了。这样通过手机访问相关网页,相关网页往配置文件里写入关机命令,再由运行在远程主机上的程序读取,最后实现关机。废话不说了,上代码。
//这是关机函数
void CShutdownApp::ShutDown()
{
OSVERSIONINFO OsVersionInfo; //包含操作系统版本信息的数据结构
OsVersionInfo.dwOSVersionInfoSize= sizeof(OSVERSIONINFO);
GetVersionEx(&OsVersionInfo); //获取操作系统版本信息
if(OsVersionInfo.dwPlatformId!= VER_PLATFORM_WIN32_WINDOWS) // 对于Windows NT系统
{
HANDLE hToken; // 指向 access token的指针。
TOKEN_PRIVILEGES tkp; //保存用户权限列表的数据结构。
// Get a token for this process. 得到一个进程的access token,并将它放入到hToken中。
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
AfxMessageBox("OpenProcessToken");
// Get the LUID for the shutdown privilege. 得到关机权限的LUID,并且放入到TOKEN_PRIVILEGES结构体的第一个列表项中。
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
&tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1; // one privilege to set 将关机权限对应的LUID的对应属性改为可用 SE_PRIVILEGE_ENABLED;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Get the shutdown privilege for this process. 调整进程的access token,使它具有shutdown权限的可用属性。
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
(PTOKEN_PRIVILEGES)NULL, 0);
// Cannot test the return value of AdjustTokenPrivileges.
if (GetLastError() != ERROR_SUCCESS)
AfxMessageBox("AdjustTokenPrivileges");
// Shut down the system and force all applications to close.
if (!ExitWindowsEx(EWX_SHUTDOWN |EWX_POWEROFF, 0))
//EWX_REBOOT,EWX_LOGOFF (uFlags)
//EWX_FORCE,EWX_FORCEIFHUNG (Value)
AfxMessageBox("ExitWindowsEx");
}
else
{
//Windows98,调用ExitWindowsEx()函数重新启动计算机
ExitWindowsEx(EWX_SHUTDOWN |EWX_POWEROFF,0); //可以改变第一个参数,实现注销用户、
//关机、关闭电源等操作
}
}
//这是读取网络文件的函数
void CShutdownDlg::ShutDownByRemote()
{
char url[256] = "http://www.renyugang.cn/s/shutdown.ini";
HINTERNET hNet = ::InternetOpen("1986", //当HTTP协议使用时,这个参数随意赋值
PRE_CONFIG_INTERNET_ACCESS, //访问类型指示Win32网络函数使用登记信息去发现一个服务器。
NULL,
INTERNET_INVALID_PORT_NUMBER, //使用INTERNET_INVALID_PORT_NUMBER相当于提供却省的端口数。
0 //标志去指示使用返回句句柄的将来的Internet函数将"不"为回调函数发送状态信息
) ;
HINTERNET hUrlFile = ::InternetOpenUrl(hNet, //从InternetOpen返回的句柄
(char *)url, //需要打开的URL
NULL, //用来向服务器传送额外的信息,一般为NULL
0, //用来向服务器传送额外的信息,一般为 0
INTERNET_FLAG_RELOAD, //InternetOpenUrl行为的标志
0) ; //信息将不会被送到状态回调函数
char buffer[1024] ;
memset(buffer,0,1024);
DWORD dwBytesRead = 0;
BOOL bRead = ::InternetReadFile(hUrlFile, //InternetOpenUrl返回的句柄
buffer, //保留数据的缓冲区
sizeof(buffer),
&dwBytesRead); //指向包含读入缓冲区字节数的变量的指针;
//如果返回值是TRUE,而且这里指向0,则文件已经读到了文件的末尾。
::InternetCloseHandle(hUrlFile);
::InternetCloseHandle(hNet) ;
if (strcmp(buffer,"<?command shutdown ?>")==0)
{
this->SetWindowText("接收到远程指令,系统即将关机!");
SetDlgItemText(IDC_STATIC_NOWTIME,"接收到远程指令,系统即将关机!");
KillTimer(1);
shutdown();
}
}
//网页代码也上了吧 PHP的
//notify.php
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>远程控制端</title>
</head>
<body>
<center>
<a href="notify.php">通知远程主机关机</a><br/>
<a href="deleteini.php">删除shutdown.ini</a>
<?php
if(copy("../shutdown.ini","shutdown.ini")==true)
{
echo "<br/>notify target host successfully";
}
?>
</center>
</body>
</html>
为了全面起见,你还要提供删除配置文件的代码。不然那个程序一运行就会关机啊。