在服务程序中想要对注册表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. Unity3D之MeleeWeaponTrail武器轨迹插件的使用

    MeleeWeaponTrail是Unity Asset Store中的一个免费插件.主要是用于显示武器的轨迹. 首先,找到武器绑定的骨骼.并在骨骼以下加入轨迹显示的起点和终点. 接着,给该骨骼加入M ...

  2. lamp安装指南(转)

    主要软件包, 1. httpd-2.2.6.tar.gz 2. mysql-5.0.45-linux-i686-glibc23.tar.gz ( 这个版本是已编译好的压缩包,解压后稍做配置即可使用 ) ...

  3. linux系统中中断已连接的用户

    1.用w命令查看当前系统登录的用户 [root@rhel7 ~]# w :: up :, users, load average: 0.00, 0.01, 0.05 USER TTY FROM LOG ...

  4. tail和head命令

    [root@rhel7 ~]# cat rusky --cat命令查看文件内容 line1 line2 line3 line4 line5 line6 line7 line8 line9 line10 ...

  5. CentOS 7 修改hostname

    centOS 7 里面修改hostname的方式有所改变,修改/etc/hosts和/etc/sysconfig/network两个文件已经不能生效.使用的新命令是 : hostnamectl set ...

  6. 画画 保存为图片 MaskFilter 边缘效果

    使用 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> publ ...

  7. javascript小数四舍五入

    javascript小数四舍五入 1. function get(){    var s = 22.127456 + "";    var str = s.substring(0, ...

  8. CSS元素分类及区别

    元素是文档结构的基础,在CSS中,每个元素生成了一个包含了元素内容的框(box,也译为“盒子”).但是不同的元素显示的方式会有所不同,例如<div>和<span>就不同,而&l ...

  9. ViewState探索

    什么是 view state? View State是客户端状态管理重要机制之一.当页面PostBack(向服务器发送或获得数据)时,它能存储页面的值.ASP.NET把View State属性作为页面 ...

  10. Windows Server 2003 SP2 R2 企业版/标准版/32与64位 CD-KEY

    微软发布Windows Server 2003 R2版的目的是希望透过它填补Windows Server 2003 SP1和Longhorn Server之间的产品发布时间间隔.所以Windows S ...