在网络服务帐户下发布到 WMI 时出现权限问题
我将 WMI 发布添加到基于 .net Framework 3.5 的 Windows 服务,该服务在“网络服务”帐户下运行。
根据我在 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 或代码中的 code-gen 目标目录吗?我不想在部署服务时摆弄文件系统权限...
更新:我认为这是一个“功能”,旧的 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] 具有默认权限/安全设置,并且无需使用反射来修改框架内部/私有成员。 “开箱即用”但干净的解决方案受到欢迎。如果允许的话,将开设第二个相关的赏金-Q 作为另一个 550pt 的占位符。
赏金更新:我打算通过第二个手把手问题将这个问题的赏金加倍,该问题将作为赏金占位符:
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... 路径中的权限错误,导致惨败。接下来,我将该服务重新编译为 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
......越来越近......
I'm adding WMI publishing to a .net framework 3.5 based windows service that is running under the 'network service' account.
According to a document I came across on MSDN, the 'network service' account should by default have WMI publishing permissions. ("By default, the following users and groups are allowed to publish data and events: ... Network Service, ...")
However, when the service calls Instrumentation.Publish(myStatusClassInstance), it throws a 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'.
..so it looks like System.Management.Instrumentation tries to generate code on the fly, and when running under network service it targets a directory where network service has no permissions.
What is the best fix/workaround for this? Can I override the code-gen target dir in app.config or in code? I don't want to have to fiddle around with file system permissions when deploying the service...
Update: I think this is a 'feature' where older FX code clashes with newer security settings in Win7. Internally the WMI managed classes retrieves the WMI installation directory from registry, and uses that as the output path for generated code. Unfortunately a lot of users are not allowed to (or supposed to) write stuff under %SystemRoot%... ...I filed a connect bug (#530392) to see if MSFT can bring any clarity and/or provide a fix or workaround.
Update 2: I'm guessing that for normal user accounts this is not an issue, because UAC virtualization will kick in and store the files elsewhere. However, apparently the 'network service' account is not covered by UAC virtualization..(?)
Update 3: Added 550pt bounty. Simple constraints: .net framework 3.5 based windows service, running as network service, need to be able to publish data through WMI using System.Management.Instrumentation on Win7 and Win2008[RTM & R2] with default permissions/security settings and without resorting to modifying framework internal/private members using reflection. 'Out-of-the-box' but clean solutions welcome. Will open a second related bounty-Q as a placeholder for another 550pt if SO allows.
Bounty update: I intend to double the bounty for this Q through a second hand-in-hand question that will serve as a bounty placeholder:
https://stackoverflow.com/questions/2208341/bounty-placeholder ( <-- Apparently this was not allowed, so the bounty placeholder question got closed by the SO etiquette police.)
Update 4: This gets better and better. I noticed that installutil was writing the missing files to c:\windows\syswow64...etc..., so I realized that I was using the 32-bit version of installutil to install the service, but the service was running as a 64-bit process. The obvious side effect was that code generated when installutil was running ended up under syswow64 (the 32-bit system directory), while the service was looking for it under the 64-bit system directory (system32). (<-- off topic, but I really like how MSFT managed to switch around the names there... :) ).
So I tried installing the service with the 64-bit version of installutil. That failed miserably with permission errors in the %sysroot%\wbem\framework...etc... path. Next I recompiled the service as x86 and registered it again using the 32-bit version of installutil. That resulted in an entirely new exception:
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
...getting closer...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为问题不在于发布数据,而在于第一次在 WMI 中注册该类型。
如果您检查 reflector 中的
System.Management.Instrumentation
代码a> 或其他反汇编程序,您会看到当要发布的程序集尚未注册时,代码将尝试注册程序集并将程序集信息保存在 WBEM 下专门命名的子目录中安装文件夹。我怀疑,如果您首先以管理员身份运行代码来发布 WMI 数据,它将注册程序集,然后网络服务帐户将具有执行正常发布的权限。
I believe the problem is not with publishing data, but with registering that type in WMI for the first time.
If you examine the
System.Management.Instrumentation
code in reflector, or some other disassembler, you'll see that wen the assembly that is about to publish hasn't been registered, then the code will try to register the assembly and save the assembly info in a specially named sub directory under the WBEM installation folder.I suspect that if you run code to publish the WMI data as an administrator first, it would register the assembly and then the Network Service account would have the permissions to do the normal publishing.
您是否使用 installutil 检查了您的程序集?这应该会为您提供安装问题的日志。 (但由于您无法将其作为网络服务帐户运行,因此它可能不会显示您遇到的问题。)
此外,您确定此服务必须在网络服务帐户下运行吗?
由于特权帐户运行Windows服务存在漏洞风险,微软对这些特殊服务帐户做了一些限制,这些限制在Vista和Win7中得到了加强。自 Vista 以来,Microsoft 限制了在此帐户下运行的服务数量,以支持权限较低的服务(请参阅 本文)。网络服务帐户(又名“NT AUTHORITY\NETWORK SERVICE”)可以访问网络(充当本地计算机帐户 PCNAME$),但它在本地计算机上的权限有所减少(与本地系统帐户不同)。
您是否检查过您的程序集正在使用的分支的 WMI 安全权限?运行 wmimgmt.msc 并深入了解。 ..当我快速检查一些随机分支时,我可以看到网络服务帐户没有写入权限。
最后,我建议使用 Sysinternals 的 ProcMon,这将允许您过滤到该进程并查看文件或注册表设置中是否存在任何“拒绝访问”错误。多年来,这个工具为我解决了许多问题。
Have you inspected your assembly with the installutil? That should give you a log of the installation issues. (But since you can't run it as the Network Service account, it might not show the problem you're having.)
Also, are you sure this service must be run under the Network Service account?
Because of the vulnerability risk in running Windows services in privileged accounts, Microsoft has made these special service accounts with some limitations, which were strengthened in Vista and Win7. Since Vista, Microsoft has limited the number of services running under this account in favor of less-privileged ones (see this article). The Network Service account (aka "NT AUTHORITY\NETWORK SERVICE") can access the network (acting as the local machine account PCNAME$), but it has reduced rights on the local machine (unlike the Local System account).
Have you checked the WMI security permissions for the branch your assembly is using? Run wmimgmt.msc and dig in... When I did a quick check of some random branches, I could see that the Network Service account did not have write rights.
Lastly, I would suggest using Sysinternals' ProcMon, which would allow you to filter to just that process and see if there are any Access Denied errors in file or registry settings. This tool has solved many problems for me over the years.
不确定是您提出的还是其他人提出的,但请看一下:
http://connect.microsoft.com/VisualStudio/feedback/details/530392/wmi-publishing-fails- on-permission-error-please-provide-a-way-to-override-codepath-in-system-management-instrumentation-schemanaming-in-app-config-web-config
这可能会帮助您理解更好地解决问题的根本原因
Not sure if you raised it or someone else but please have a look:
http://connect.microsoft.com/VisualStudio/feedback/details/530392/wmi-publishing-fails-on-permission-error-please-provide-a-way-to-override-codepath-in-system-management-instrumentation-schemanaming-in-app-config-web-config
This may help you to understand the root cause of the issue better