为新手准备的应用程序提升:提升并写入注册表的逐步指南





5.00/5 (8投票s)
我们将使您的应用程序能够写入HKEY_LOCAL_MACHINE中的条目,并在必要时提升您的应用程序权限。
引言
我们将使用http://msdn.microsoft.com/en-us/library/bb530410.aspx#vistauac_topic6c中列出的COM方法,使您的应用程序能够写入HKEY_LOCAL_MACHINE中的条目,并在必要时提升您的应用程序权限。
我们将创建一个具有两种方法的新COM对象:WriteString
和WriteLong
,并在写入本地计算机条目时使用该COM对象。然后,我们将创建一个控制台应用程序来演示其用法。这非常简单,我们将在5分钟内完成所有操作。所以,让我们开始吧。
背景
如果您在阅读完本主题:http://msdn.microsoft.com/en-us/library/bb530410.aspx#vistauac_topic6b后,确定您的应用程序是混合应用程序,那么本文适合您。
使用代码
注册服务器后,您的应用程序可以使用CElevatedRegistryWritter
类随时提升权限并在注册表中写入。
CElevatedRegistryWritter writter(GetConsoleWindow());
if(writter.WriteString(_T("Software\\Microsoft"),
_T("Message"), _T("Hello World")) &&
writter.WriteLong(_T("Software\\Microsoft"),
_T("MyValue"), 100))
{
print("All done!");
}
阶段1:创建注册表COM对象
- 创建一个新的ATL项目(我将其命名为Elevator)。
- 在ATL项目向导对话框中选择可执行文件(EXE)作为服务器类型。
- 向您的Elevator项目添加一个新类。
- 在添加类对话框中选择ATL简单对象,然后按添加。
- 在ATL简单对象向导对话框中将您的类命名为“LocalMachineWriter”,然后按完成。
- 向接口
ILocalMachineWritter
添加一个新方法。 - 将您的新方法命名为
WriteString
,并添加三个in
参数:path
、var
和value
,它们都是BSTR
,然后按完成。 - 对
WriteLong
方法重复步骤6和7(value
参数必须为LONG
)。 - 修改
CLocalMachineWritter::WriteString
和CLocalMachineWritter::WriteLong
的代码如下所示 - 现在,我们必须启用我们的COM对象以提升权限,向注册表中添加两个条目。
- 现在,编译COM对象。
- 最后,我们必须注册我们的COM对象才能让其他应用程序使用它。打开一个提升权限的Cmd(按住Ctrl+Shift键执行CMD.exe),转到Debug或Release目录,并使用/RegServer参数执行服务器进行注册
我们完成了!
我们创建了一个COM对象,可以写入本地计算机。现在,我们必须创建客户端代码以使用提升的权限运行我们的COM对象。
- 创建一个新的Win32控制台应用程序。将其命名为Client,然后按OK。
- 在Win32应用程序向导对话框中选择控制台应用程序,然后按完成。
- 修改StdAfx.h文件以包含Windows.h和comutil.h。
- 将Elevator_i.c和Elevator_i.h从您的Elevator项目目录复制到您全新的客户端应用程序目录(这些文件是必要的,因为它们声明了接口和接口和对象的GUID)。
- 向您的客户端应用程序添加一个新类
- 在添加类对话框中选择C++类
- 将您的新类命名为
CElevatedRegistryWritter
,然后在泛型C++类向导对话框中按完成。 - 用这个替换ElevatedRegistryWritter.h
- 最后,更新您的
main()
函数,首先初始化COM,然后使用我们的类。
STDMETHODIMP CLocalMachineWriter::WriteString(BSTR path, BSTR var, BSTR value)
{
HKEY hk = NULL;
if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0,
KEY_READ | KEY_WRITE, &hk))
return E_FAIL;
bool nReturn = E_FAIL;
if(ERROR_SUCCESS == RegSetValueEx( hk, var, 0, REG_SZ,
(const BYTE*)value, (1 + (DWORD)_tcslen(value)) * sizeof(TCHAR) ))
nReturn = S_OK;
RegCloseKey(hk);
return nReturn;
}
STDMETHODIMP CLocalMachineWriter::WriteLong(BSTR path, BSTR var, LONG value)
{
HKEY hk = NULL;
if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE,
path, 0, KEY_READ | KEY_WRITE, &hk))
return E_FAIL;
bool nReturn = E_FAIL;
if(ERROR_SUCCESS == RegSetValueEx( hk, var, 0, REG_DWORD,
(const BYTE*)&value, sizeof(LONG)))
nReturn = S_OK;
RegCloseKey(hk);
return nReturn;
}
打开LocalMachineWriter.rgs并添加粗体行
HKCR
{
Elevator.LocalMachineWriter.1 = s 'LocalMachineWriter Class'
{
CLSID = s '{E89BECE0-84AC-4EE0-BC26-835C269C166F}'
}
Elevator.LocalMachineWriter = s 'LocalMachineWriter Class'
{
CLSID = s '{E89BECE0-84AC-4EE0-BC26-835C269C166F}'
CurVer = s 'Elevator.LocalMachineWriter.1'
}
NoRemove CLSID
{
ForceRemove {E89BECE0-84AC-4EE0-BC26-835C269C166F} =
s 'LocalMachineWriter Class'
{
ProgID = s 'Elevator.LocalMachineWriter.1'
VersionIndependentProgID = s 'Elevator.LocalMachineWriter'
ForceRemove 'Programmable'
LocalServer32 = s '%MODULE%'
'TypeLib' = s '{A38F2A11-AF97-4903-9DF3-F757291C9358}'
val LocalizedString = s '@%MODULE%,-100'
ForceRemove Elevation = s ''
{
val Enabled = d '1'
}
}
}
}
有关.rgs文件的更多信息,请参阅此链接:http://msdn.microsoft.com/en-us/library/k32htktc.aspx。有关为什么添加这些条目的信息,请参阅此链接:http://msdn.microsoft.com/en-us/library/ms679687.aspx。
#include <windows.h>
#include <comutil.h>
#ifdef _DEBUG
#pragma comment(lib, "comsuppwd.lib")
#else
#pragma comment(lib, "comsuppw.lib")
#endif
我们包含了ComUtil.h和库comsuppw,因为我们将使用_bstr_t
类(http://msdn.microsoft.com/en-us/library/zthfhkd6(VS.71).aspx)。
#pragma once
#include "Elevator_i.h"
/// <summary>
/// Wrapper class to load the LocalMachineWritter object
/// with elevated credentials.
/// </summary>
/// <creation date="08/04/2009" by="Jose Angel"/>
class CElevatedRegistryWritter
{
HWND wndParent;
ILocalMachineWriter* object;
#pragma region Constructors and destructor
public:
/// <summary>
/// Constructor of the class
/// </summary>
/// <param name="wndParent">
/// Handle to a window.
/// Use <c>GetConsoleWindow</c>
/// or <c>AfxGetMainWnd</c> for instance
/// </param>
CElevatedRegistryWritter(HWND wndParent);
/// <summary>
/// Destructor. It will unload the Com object if necessary.
/// </summary>
~CElevatedRegistryWritter();
#pragma endregion
#pragma region Public methods
/// <summary>
/// This method ininialize the Com object
/// if necessary and write a string in the registry.
/// </summary>
/// <param name="path">Path of the key to write.</param>
/// <param name="var">Name of the key to write.</param>
/// <param name="value">Value to write.</param>
/// <returns>True if success.</returns>
bool WriteString(LPCTSTR path, LPCTSTR var, LPCTSTR value);
/// <summary>
/// This method ininialize the Com object
/// if necessary and write a long in the registry.
/// </summary>
/// <param name="path">Path of the key to write.</param>
/// <param name="var">Name of the key to write.</param>
/// <param name="value">Value to write.</param>
/// <returns>True if success.</returns>
bool WriteLong(LPCTSTR path, LPCTSTR var, LONG value);
#pragma endregion
#pragma region Implementation
private:
/// <summary>
/// Utility method to create the object as an administrator.
/// </summary>
HRESULT CoCreateInstanceAsAdmin(HWND hwnd, REFCLSID rclsid,
REFIID riid, __out void ** ppv);
#pragma endregion
};
并用这个替换ElevatedRegistryWritter.cpp
#include "StdAfx.h"
#include "ElevatedRegistryWritter.h"
#include "Elevator_i.c"
CElevatedRegistryWritter::CElevatedRegistryWritter(HWND _wndParent)
: object(NULL)
, wndParent(_wndParent)
{
}
CElevatedRegistryWritter::~CElevatedRegistryWritter(void)
{
if(NULL != object)
object->Release();
}
bool CElevatedRegistryWritter::WriteString(LPCTSTR path, LPCTSTR var, LPCTSTR value)
{
if( NULL == object && FAILED(CoCreateInstanceAsAdmin(wndParent,
CLSID_LocalMachineWriter, IID_ILocalMachineWriter, (void**)&object)))
return false;
SUCCEEDED(object->WriteString(_bstr_t(path), _bstr_t(var), _bstr_t(value)));
}
bool CElevatedRegistryWritter::WriteLong(LPCTSTR path, LPCTSTR var, LONG value)
{
if( NULL == object && FAILED(CoCreateInstanceAsAdmin(wndParent,
CLSID_LocalMachineWriter, IID_ILocalMachineWriter, (void**)&object)))
return false;
SUCCEEDED(object->WriteLong(_bstr_t(path), _bstr_t(var), value));
}
HRESULT CElevatedRegistryWritter::CoCreateInstanceAsAdmin(HWND hwnd,
REFCLSID rclsid, REFIID riid, __out void ** ppv)
{
BIND_OPTS3 bo;
WCHAR wszCLSID[50];
WCHAR wszMonikerName[300];
StringFromGUID2(rclsid, wszCLSID, sizeof(wszCLSID)/sizeof(wszCLSID[0]));
_stprintf_s(wszMonikerName, L"Elevation:Administrator!new:%s", wszCLSID);
memset(&bo, 0, sizeof(bo));
bo.cbStruct = sizeof(bo);
bo.hwnd = hwnd;
bo.dwClassContext = CLSCTX_LOCAL_SERVER;
return CoGetObject(wszMonikerName, &bo, riid, ppv);
}
#include "stdafx.h"
#include "ElevatedRegistryWritter.h"
int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
MessageBox(NULL, _T("Accept to elevate"),
_T("Testing elevation"), MB_OK);
CElevatedRegistryWritter writter(GetConsoleWindow());
if(writter.WriteString(_T("Software\\Microsoft"),
_T("Message"), _T("Hello World")) &&
writter.WriteLong(_T("Software\\Microsoft"),
_T("MyValue"), 100))
{}
CoUninitialize();
return 0;
}