65.9K
CodeProject 正在变化。 阅读更多。
Home

创建 ATL COM DLL 并通过 PHP 调用它

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.62/5 (5投票s)

2008年10月27日

CPOL

5分钟阅读

viewsIcon

43559

downloadIcon

474

演示如何创建简单的ATL COM DLL并通过PHP调用它。

引言

有时您可能需要从PHP获得对底层操作系统的更大访问权限。本文演示了一种实现上述目的的技术的基本步骤,即创建ATL COM DLL、注册它,最后通过运行Apache Web服务器的Windows环境中的PHP来调用它。

要求

要求列出了用于创建和测试演示版的软件,除非特别说明,否则不一定排除相同软件的其他版本。

  1. Windows XP 专业版
  2. Apache 2.0.54 Web服务器
  3. PHP 5.2.6.(在早期版本中,会触发oleaut32.dll中的访问冲突)
  4. Visual Studio .NET Professional

创建ATL COM DLL

在接下来的步骤中,我们将创建一个具有一个类和两个成员方法的ATL COM DLL,一个用于检索当前正在使用的物理内存的近似百分比,第二个用于重新启动主机计算机。

  1. 启动Visual Studio .NET
  2. 启动“新建项目”
  3. 选择“Visual C++ 项目”
  4. 选择“ATL 项目”
  5. 点击“确定”
  6. 将项目命名为“ATLDemo”
  7. 点击“确定”
  8. 由于默认选项是“动态链接库(DLL)”,请点击“完成”

Visual Studio .NET现在将生成项目,我们已准备好继续。

  1. 右键单击项目名称
  2. 转到“添加”选项
  3. 选择“添加类…”
  4. Add a new class to the project

  5. 选择“ATL简单对象”
  6. 点击“打开”
  7. 为短名称输入“MyClass”
  8. Enter class information

  9. 点击“完成”,我们将接受所有默认选项

我们的新类现已添加,您可能会注意到系统也为我们生成了一个接口类,在本例中名为IMyClass。下一步,我们将按照以下步骤添加我们的两个成员方法:

  1. 右键单击名为“IMyClass”的接口类
  2. Class interface

  3. 转到“添加”
  4. 选择“添加方法”
  5. 为方法名称输入GetMemoryLoad
  6. 在“参数属性”部分下选中“in”复选框
  7. 为参数类型选择VARIANT*
  8. 将参数命名为“vtMemoryLoad
  9. Add new method to the interface

  10. 点击“添加”
  11. 点击“完成”

新成员方法现已添加,下一步我们将为其添加代码

STDMETHODIMP CMyClass::GetMemoryLoad(VARIANT* vtMemoryLoad)
{
	// Create an instance of the MEMORYSTATUSEX structure
	MEMORYSTATUSEX memstatex;

	// Specify the length of the structure
	memstatex.dwLength = sizeof(memstatex);

	// Call the GlobalMemoryStatusEx function and pass to it
	//  a reference to our MEMORYSTATUSEX instance
	::GlobalMemoryStatusEx(&memstatex);

	// Set the ulVal (unsigned long value) of the VARIANT parameter
	//  passed by reference to the function with the dwMemoryLoad
	//   value of the MEMORYSTATUEX instance which specifies the
	//    approximate percentage of the physical memory currently
	//     in use.
	vtMemoryLoad->ulVal = memstatex.dwMemoryLoad;

	return S_OK;
}

我们将重复步骤1-9,以便将第二个函数作为此演示的一部分添加。

  1. 右键单击名为“IMyClass”的接口类
  2. 转到“添加”
  3. 选择“添加方法”
  4. 为方法名称输入RestartHost
  5. 在“参数属性”部分下选中“in”复选框
  6. 为参数类型选择VARIANT*
  7. 将参数命名为“vtLastError
  8. 点击“添加”
  9. 点击“完成”

将以下代码添加到新函数中

STDMETHODIMP CMyClass::RestartHost(VARIANT* vtLastError)
{
	HANDLE hToken;
	TOKEN_PRIVILEGES tkp;

	// In order to be able to restart the local computer we need the 
	//  SE_SHUTDOWN_NAME privilege, in the following steps we will
	//   retrieve the privileges of the current process and enable
	//    the SE_SHUTDOWN_NAME privilege
	if(::OpenProcessToken(GetCurrentProcess(), 
	      TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { 

		::LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
		
		tkp.PrivilegeCount = 1;    
		tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

		::AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0); 

		// If the adjusting of the privilege succeeded
		if(::GetLastError() == ERROR_SUCCESS) {

			// Initiate the system restart, note the fourth argument will
			//  force the shutdown of all applications, when testing please
			//   ensure that you have no unsaved data as it might be lost.
			//    The fifth argument will restart the computer.
			::InitiateSystemShutdown(NULL, _T("ATL COM DLL/PHP Demo"), 0, TRUE, TRUE);
		}
	}

	// Set the ulVal (unsigned long value) of the VARIANT parameter
	//  to the value returned by GetLastError as this might be useful in
	//   troubleshooting.
	vtLastError->ulVal = ::GetLastError();

	return S_OK;
}

下一步,我们将编译DLL。默认情况下,项目将保持Debug模式,在成功编译并进行彻底测试后,我们可以在部署DLL之前将其切换到Release模式。为了进行此演示,我们将立即这样做。

  1. 在菜单上点击“项目”
  2. 点击“ATLDemo属性”
  3. 将“配置:”选项更改为“Release”
  4. 点击“确定”
  5. 在菜单上点击“生成”
  6. 点击“重新生成解决方案”

这标志着创建我们的示例ATL COM DLL的过程结束。

注册ATL COM DLL

现在我们已经创建了ATL COM DLL,下一步是注册它,以便通过COM接口供其他应用程序使用。

  1. 通过浏览到项目的“Release”目录来定位DLL,或者通过名称搜索DLL,在本例中为“ATLDemo.dll”。
  2. 将DLL移动到其最终目的地,在本例中,我们将DLL放入“C:\WINDOWS\system32”目录。
  3. 通过命令行调用REGSVR32实用程序来注册DLL。
    1. 点击“开始”
    2. 点击“运行”
    3. 输入“CMD”
    4. 在命令提示符下,输入:REGSVR32 "C:\WINDOWS\system32\ATLDemo.dll"
    5. 您应该会看到一个消息框,告知您注册已成功。

这标志着注册我们的示例ATL COM DLL并使其可供COM感知应用程序使用的过程结束。

通过PHP调用ATL COM DLL

在本节中,我们将编写一个PHP页面来调用我们新创建的ATL COM DLL并使用它。请注意,此时,我们假定您在Windows环境中运行Apache Web服务器。在此演示中,Apache Web服务器作为可执行文件在一个具有完全管理员权限的帐户下运行。安全设置可能会造成障碍,具体取决于您的Web服务器配置,例如,如果您将Apache Web服务器作为服务在一个权限不足的帐户下运行,则要创建COM对象,您需要调整该帐户的权限。运行IIS而不是Apache也是如此;然而,由于这是一篇简单的概念文章,因此不对安全设置进行详细讨论。

Windows版PHP在其核心功能中提供了调用COM对象的能力。有关详细信息,请参阅http://us.php.net/com

我们的第一步是识别类的ProgID,以便能够实例化该类的实例;最简单的方法是通过访问注册表并了解其值。

  1. 点击“开始”
  2. 点击“运行”
  3. 输入REGEDIT
  4. 点击“确定”
  5. HKEY_CLASSES_ROOT下,找到DLL的名称。
  6. 已找到并确定值为ATLDemo.MyClass

接下来,我们将编写PHP代码,该代码将创建类的实例,立即显示可用物理内存的近似百分比,并提供重新启动主机计算机的功能。

<?php

    // Create an instance of our COM object
    $obj = new COM("ATLDemo.MyClass");
    
    // Create an instance of the VARIANT structure,
    //  initial value 0,
    //   VT_UI4 (data type, see VARIANT data structure for details)
    $vtMemoryLoad = new VARIANT(0, VT_UI4);
    
    // Retrieve the current memory load
    $obj->GetMemoryLoad($vtMemoryLoad);
    
    print '<p>Physical memory in use : '.$vtMemoryLoad.'%</p>';
    
    // If the "Restart Host" button was pressed
    if($_POST['btnRestart']) {
    
        // VARIANT to restore the value returned by the GetLastError() function
        $vtLastError = new VARIANT(0, VT_UI4);
        
        // Initiate host restart
        $obj->RestartHost($vtLastError);

        print '<p>Initiated host restart...</p>';
        print '<p>Last Error Code: '.$vtLastError.'</p>';
    }
?>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="POST">
 <input type="submit" value="Restart Host" 
           name="btnRestart" id="btnRestart" />
</form>
  1. 将文件另存为“index.php”,放在新的Web服务器目录中。
  2. 通过浏览器运行它。
  3. 注意内存使用值,后续的页面访问将根据使用情况改变输出。
  4. 点击“重启主机”按钮来重启计算机(注意:请在测试前保存任何待处理的工作)。
  5. Add new method to the interface

结论

非常感谢您阅读本文。我希望本文或其中至少某些方面可能对您有所帮助。建设性的批评是受到赞赏的,并将予以考虑。

© . All rights reserved.