在服务程序中想要对注册表HKEY_CURRENT_USER下的内容进行读写,不会返回失败,但是始终无效。原因是:

1.服务运行在系统权限之下,而不是任何一个用户

2.HKEY_CURRENT_USER存储的是当前用户的信息================>导致在服务中读取HKEY_CURRENT_USER实际操作的不是当前登录的用户的数据。

所以如果我要操作HKEY_CURRENT_USER之内的键值,就必须模拟当前用户去读取。

有几种思路可以做到:

1.创建一个用户进程去操作注册表,使用CreateProcessAsUser函数可以做到

2.让当前线程模拟当前登录用户的安全上下文(lets the calling thread impersonate the security context of a logged-on user)。使用ImpersonateLoggedOnUser 函数可以做到。

第一个方法需要用到另外一个程序,感觉比较麻烦。

以下演示第二种方法:

BOOL GetTokenByName(HANDLE &hToken,LPTSTR lpName)
{
if (!lpName)
return FALSE; HANDLE hProcessSnap = NULL;
BOOL bRet = FALSE;
PROCESSENTRY32 pe32 = {}; hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, );
if (hProcessSnap == INVALID_HANDLE_VALUE)
return (FALSE); pe32.dwSize = sizeof(PROCESSENTRY32); if (Process32First(hProcessSnap, &pe32))
{
do
{
if(!_tcscmp(_tcsupr(pe32.szExeFile),_tcsupr(lpName)))
{
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,FALSE,pe32.th32ProcessID);
bRet = OpenProcessToken(hProcess,TOKEN_ALL_ACCESS,&hToken);
CloseHandle (hProcess);
CloseHandle (hProcessSnap);
return (bRet);
}
}
while (Process32Next(hProcessSnap, &pe32));
bRet = FALSE;
}
else
{
bRet = FALSE;
} CloseHandle (hProcessSnap);
return (bRet);
}
//
//获取用户sid
//
bool GetAccountSid(LPTSTR AccountName, PSID *Sid)
{
PSID pSID = NULL;
DWORD cbSid = ;
LPTSTR DomainName = NULL;
DWORD cbDomainName = ;
SID_NAME_USE SIDNameUse;
BOOL bDone = FALSE;
try
{
if(!LookupAccountName(NULL,
AccountName,
pSID,
&cbSid,
DomainName,
&cbDomainName,
&SIDNameUse))
{
pSID = (PSID)malloc(cbSid);
DomainName = (LPTSTR)malloc(cbDomainName * sizeof(TCHAR));
if(!pSID || !DomainName)
{
throw;
}
if(!LookupAccountName(NULL,
AccountName,
pSID,
&cbSid,
DomainName,
&cbDomainName,
&SIDNameUse))
{
throw;
}
bDone = TRUE;
}
}
catch(...)
{
//nothing
}
if(DomainName)
{
free(DomainName);
} if(!bDone && pSID)
{
free(pSID);
}
if(bDone)
{
*Sid = pSID;
}
return bDone;
} // 模拟当前用户环境设置默认打印机
void SimulateCurrentUserSetDefaultPrinter()
{
HANDLE hToken = NULL;
do
{
if (!GetTokenByName(hToken,_T("EXPLORER.EXE")))
{
break;
} // 模拟登录用户的安全上下文
if(FALSE == ImpersonateLoggedOnUser(hToken))
{
break;
} // 获取用户名
TCHAR szUsername[MAX_PATH];
DWORD dwUsernameLen = MAX_PATH;
if(FALSE == GetUserName(szUsername, &dwUsernameLen))
break; // 到这里已经模拟完了,别忘记返回原来的安全上下文
if(FALSE == RevertToSelf())
break; // 获取sid
PSID pSid = NULL;
LPWSTR sid;
GetAccountSid(szUsername, &pSid); //获取得到的是一个结构体
ConvertSidToStringSid(pSid, &sid); //从结构体中得到sid串 // 设置默认打印机信息
//SetDefaultPrinter(PSSD_PRINTER_NAME);
HKEY hKey;
int i=; //操作结果:0==succeed
wchar_t lswRegValue[MAX_PATH];
StringCchPrintf(lswRegValue, MAX_PATH, L"%s,winspool,%s", PSSD_PRINTER_NAME, PSSD_PRINTER_PORT_NAME);
wchar_t lswKeyPath[MAX_PATH] = {};
StringCchPrintf(lswKeyPath, MAX_PATH, L"%s\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows", sid);
if(RegOpenKeyEx(HKEY_USERS, lswKeyPath, , KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
{
if(RegSetValueEx(hKey,L"Device",NULL,REG_SZ, (const LPBYTE)lswRegValue, (wcslen(lswRegValue) + ) * sizeof(wchar_t))!=ERROR_SUCCESS)
{
i=;
}
RegCloseKey(hKey);
}
else
{
i=;
}
if( == i)
{
OutputDebugStringW(L"STST: 设置默认打印机失败");
}
else
{
SendNotifyMessage(HWND_BROADCAST, WM_SETTINGCHANGE, , );
} } while (false);
if(NULL != hToken)
CloseHandle(hToken);
}

如何在Windows服务程序中读写HKEY_CURRENT_USER注册表的更多相关文章

  1. 如何在Windows服务程序中添加U盘插拔的消息

    研究了下这个问题,主要要在一般的windows服务程序中修改两个地方: 一.调用RegisterServiceCtrlHandlerEx VOID WINAPI SvcMain( DWORD dwAr ...

  2. 如何在C#中读写INI文件

    INI文件就是扩展名为"ini"的文件.在Windows系统中,INI文件是很多,最重要的就是"System.ini"."System32.ini&q ...

  3. 如何在 Windows 10 中搭建 Node.js 环境?

    [编者按]本文作者为 Szabolcs Kurdi,主要通过生动的实例介绍如何在 Windows 10 中搭建 Node.js 环境.文章系国内 ITOM 管理平台 OneAPM 编译呈现. 在本文中 ...

  4. 64 位 Windows 平台开发注意要点之注册表重定向

    Window 系统错误代码 ERROR_SUCCESS,本博客中一律使用 NO_ERROR 代替.虽然 ERROR_SUCCESS 与 NO_ERROR 是完全等价的,都代表成功,但是后者却和其他错误 ...

  5. QSettings配置读写-win注册表操作-ini文件读写

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QSettings配置读写-win注册表操作-ini文件读写     本文地址:http:// ...

  6. 使用Windows命令行reg控制注册表键值

    使用Windows命令行reg控制注册表键值 引言 熟悉Windows操作系统的朋友可能都知道,Windows操作系统下的注册表相当于系统的数据库 ,部分软件将自己的配置信息都放在注册表里面,而注册表 ...

  7. SQL Server 2008 安装过程中遇到“性能计数器注册表配置单元一致性”检查失败 问题的解决方法

    操作步骤: 1. 在 Microsoft Windows 2003 或 Windows XP 桌面上,依次单击"开始"."运行",然后在"打开&quo ...

  8. 关于软件开发中兼容win7注册表的解决方案

    关于软件开发中兼容win7注册表的解决方案   编写人:CC阿爸 2014-3-14 l  近来在开发一winform程序时,发现在xp 系统访问注册表一切正常.可偏这个时候,微软又提醒大家.Xp今年 ...

  9. 64位Windows操作系统中的注冊表

    x64系统上有x64.x86两种注冊表,记录下. 64 位Windows系统中的注冊表分为 32 位注冊表项和 64 位注冊表项.很多 32 位注冊表项与其对应的 64 位注冊表项同名. 在64位版本 ...

随机推荐

  1. C primer plus 读书笔记第二章

    这章的标题是C语言概述,内容大概是介绍一些简单的示例程序,来了解和熟悉C语言的一些基本特征. 这是书里的第一段代码,敲敲找找感觉.推荐在linux环境下写代码. PS:倒腾sublime text一下 ...

  2. hduTHE MATRIX PROBLEM(差分约束)

    题目请戳这里 题目大意:给一个n*m的矩阵,求是否存在这样两个序列:a1,a2...an,b1,b2,...,bm,使得矩阵的第i行乘以ai,第j列除以bj后,矩阵的每一个数都在L和U之间. 题目分析 ...

  3. Android - 消息机制与线程通信

    以下资料摘录整理自老罗的Android之旅博客,是对老罗的博客关于Android底层原理的一个抽象的知识概括总结(如有错误欢迎指出)(侵删):http://blog.csdn.net/luosheng ...

  4. Linux随笔

    列表:ls -l(显示详细属性)long -a(显示全部文件包括隐藏文件)all -h(字节转换) -d(显示当前目录本身不显示目录下) -i(显示I节点) df -h 人性化查看磁盘占用率 serv ...

  5. 扩展欧几里德 POJ 1061

    欧几里德的是来求最大公约数的,扩展欧几里德,基于欧几里德实现了一种扩展,是用来在已知a, b求解一组x,y使得ax+by = Gcd(a, b) =d(解一定存在,根据数论中的相关定理,证明是用裴蜀定 ...

  6. 关于 gravity与layout_gravity

    区别 gravity与layout_gravity的区别在于: android:gravity是用来设置该view中内容相对于该view组件的对齐方式 android:layout_gravity是用 ...

  7. (转)使用DataTime这个类来获取当前的时间

    我们可以通过使用DataTime这个类来获取当前的时间.通过调用类中的各种方法我们可以获取不同的时间:如:日期(--).时间(::).日期+时间(-- ::)等. //获取日期+时间 DateTime ...

  8. 秒味课堂Angular js笔记------$scope.$watch和$scope.$apply

    $scope.$watch(watchFn , watchAction , deepWatch) 其中,watchFn是带有angular表达式或函数字符串: watchAction是一个函数或者表达 ...

  9. java沙箱机制原理

    参考文档如下: http://www.2cto.com/kf/201012/79578.html

  10. Struts2 模型驱动及页面回显

    * 要从页面中获取表单元素的值,需要在动作类中声明与页面元素同名的属性.导致动作类中既有javabean又有业务方法.        * 将javabean和业务方法进行分离:        * 将重 ...