在网络服务帐户下发布到WMI时的权限问题

时间:2010-02-03 07:54:24

标签: windows-7 permissions wmi uac

我正在将WMI发布添加到基于.net framework 3.5的Windows服务,该服务在“网络服务”帐户下运行。

根据document I came across on MSDN,“网络服务”帐户默认情况下应具有WMI发布权限。 (“默认情况下,允许以下用户和群组发布数据和事件:... 网络服务,... ”)

但是,当服务调用Instrumentation.Publish(myStatusClassInstance)时,它会抛出DirectoryNotFoundException;

System.IO.DirectoryNotFoundException was unhandled
Message: Could not find a part of the path 'C:\Windows\system32\WBEM\Framework\root\MyWMINamespace\MyService_SN__Version_1.0.3686.26280.cs'.

..所以它看起来像System.Management.Instrumentation试图动态生成代码,并且当在网络服务下运行时,它的目标是网络服务没有权限的目录。

对此最好的解决方法/解决方法是什么?我可以在app.config或代码中覆盖代码生成目标目录吗?在部署服务时我不想乱用文件系统权限......

更新:我认为这是一个“功能”,旧版FX代码与Win7中较新的安全设置发生冲突。在内部,WMI托管类从注册表中检索WMI安装目录,并将其用作生成代码的输出路径。不幸的是,许多用户不允许(或者应该)在%SystemRoot%下写东西......我提交了一个连接错误(#530392)以查看MSFT是否可以带来任何清晰度和/或提供修复或解决方法。

更新2:我猜测对于普通用户帐户来说这不是问题,因为UAC虚拟化会启动并将文件存储在其他位置。但是,UAC虚拟化显然没有涵盖“网络服务”帐户。(?)

更新3:新增550pt赏金。简单约束:基于.net framework 3.5的Windows服务,作为网络服务运行,需要能够使用Win7和Win2008上的System.Management.Instrumentation通过WMI发布数据[RTM& R2]具有默认权限/安全设置,无需使用反射修改框架内部/私有成员。 “开箱即用”,但欢迎干净的解决方案。如果SO允许,将打开第二个相关的赏金Q作为另一个550pt的占位符。

Bounty更新:我打算通过第二个手持问题将此Q的赏金加倍,该问题将作为赏金占位符:
https://stackoverflow.com/questions/2208341/bounty-placeholder(< - 显然这是不允许的,因此SO礼仪警察关闭了赏金占位符问题。)

更新4:这越来越好了。我注意到installutil正在将丢失的文件写入c:\ windows \ syswow64 ...等等......所以我意识到我使用的是32位版本的installutil来安装服务,但该服务是作为一个服务运行的64位进程。显而易见的副作用是,在installutil运行时生成的代码最终在syswow64(32位系统目录)下生成,而服务在64位系统目录(system32)下查找它。 (< - 关于主题,但我真的很喜欢MSFT如何设法切换那里的名字...... :)。

所以我尝试使用64位版本的installutil安装该服务。在%sysroot%\ wbem \ framework ... etc ... path中,权限错误失败了。接下来,我将服务重新编译为x86,并使用32位版本的installutil再次注册它。这导致了一个全新的例外:

System.Exception: The code generated for the instrumented assembly failed to compile.
   at System.Management.Instrumentation.InstrumentedAssembly..ctor(Assembly assembly, SchemaNaming naming)
   at System.Management.Instrumentation.Instrumentation.Initialize(Assembly assembly)
   at System.Management.Instrumentation.Instrumentation.GetInstrumentedAssembly(Assembly assembly)
   at System.Management.Instrumentation.Instrumentation.GetPublishFunction(Type type)
   at System.Management.Instrumentation.Instrumentation.Publish(Object instanceData)
   at SomeService.InstanceClass.PublishApp(String name) in e:\work\clientname\SomeService\SomeService\WMIProvider.cs:line 44
   at SomeService.SomeServiceService..ctor() in e:\work\clientname\SomeService\SomeService\SomeServiceService.cs:line 26
   at SomeService.Program.Main() in e:\work\clientname\SomeService\SomeService\Program.cs:line 17

......越来越近......

3 个答案:

答案 0 :(得分:2)

我认为问题不在于发布数据,而是第一次在WMI中使用注册类型。

如果您检查reflector或其他反汇编程序中的System.Management.Instrumentation代码,您会看到即将发布的程序集尚未注册,那么代码将尝试注册程序集并将程序集信息保存在WBEM安装文件夹下的特别命名的子目录中。

我怀疑如果您首先以管理员身份运行代码来发布WMI数据,它会注册程序集,然后网络服务帐户将拥有执行正常发布的权限。

答案 1 :(得分:2)

您是否使用installutil检查过您的程序集?这应该会给你一个安装问题的日志。 (但由于您无法将其作为网络服务帐户运行,因此可能无法显示您遇到的问题。)

此外,您确定此服务必须在网络服务帐户下运行吗?

由于在特权帐户中运行Windows服务存在漏洞风险,因此Microsoft已将这些特殊服务帐户设置为一些限制,这些限制在Vista和Win7中得到了加强。自Vista以来,微软已经限制了在此帐户下运行的服务数量,而不是特权较低的服务(请参阅this article)。网络服务帐户(又名“NT AUTHORITY \ NETWORK SERVICE”)可以访问网络(充当本地计算机帐户PCNAME $),但它减少了本地计算机的权限(与本地系统帐户不同)。

您是否检查了程序集正在使用的分支的WMI安全权限?运行wmimgmt.msc并挖掘...当我快速检查一些随机分支时,我可以看到网络服务帐户没有写权限。

最后,我建议使用Sysinternals' ProcMon,这样您就可以过滤到该过程,并查看文件或注册表设置中是否存在任何“拒绝访问”错误。多年来,这个工具为我解决了许多问题。

答案 2 :(得分:1)