共享点:从计时器作业+ SHAREPOINT \系统权限执行stsadm
我遇到一种不寻常的情况,我需要一个SharePoint计时器作业才能既具有本地管理员Windows特权又具有" SHAREPOINT \ System" SharePoint特权。
我可以通过简单地将计时器服务配置为使用本地管理员成员的帐户来获得Windows特权。我知道这不是一个好的解决方案,因为它为SharePoint计时器服务提供了应有的更多权限。但是它至少允许我的SharePoint计时器作业运行stsadm
。
在本地管理员下运行计时器服务的另一个问题是,该用户不一定具有" SHAREPOINT \ System" SharePoint特权,我也需要执行此SharePoint作业。事实证明,在这种情况下,SPSecurity.RunWithElevatedPrivileges
不起作用。 Reflector显示" RunWithElevatedPrivileges"会检查当前进程是否为" owstimer"(运行SharePoint作业的服务进程),并且不执行任何提升操作(这种情况是合理的,我想这是因为计时器服务应该在以下条件下运行)具有" SHAREPOINT \ System" SharePoint特权的" NT AUTHORITY \ NetworkService" Windows帐户,因此无需提升计时器作业的特权)。
此处唯一可行的解决方案似乎是在其常规NetworkService Windows帐户下运行计时器服务,并通过将管理员凭据存储在某处并将其通过StarInfo的用户名传递给System.Diagnostics.Process.Run()来以本地管理员身份运行stsadm。 ,域和密码。
似乎现在一切都应该可以正常工作,但是这是我目前仍然遇到的另一个问题。 Stsamd失败,并显示以下错误弹出窗口(!)(在这种情况下,Winternals filemon显示stsadm正在管理员管理下运行):
应用程序无法正确初始化(0x0c0000142)。
单击确定终止应用程序。
事件查看器除弹出窗口外均不注册。
本地管理员用户是我的帐户,当我以该帐户交互式运行stsadm
时,一切正常。当我将计时器服务配置为在此帐户下运行时,它也可以正常工作。
任何建议表示赞赏:)
解决方案
回答
我不在工作,所以这不是我的首要任务,但是:如果我们获得对站点的引用,是否可以尝试使用SYSTEM-UserToken创建一个新的SPSite?
SPUserToken sut = thisSite.RootWeb.AllUsers["SHAREPOINT\SYSTEM"].UserToken; using (SPSite syssite = new SPSite(thisSite.Url,sut) { // Do what you have to do }
回答
如果其他应用程序以这种方式运行(即从具有明确凭据的计时器作业运行),则失败的方式与"应用程序无法正确初始化"相同。我只是编写了一个简单的应用程序,该应用程序将另一个可执行文件的路径及其参数设置为parameres,并且从该计时器作业运行时,它以相同的方式失败。
internal class ExternalProcess { public static void run(String executablePath, String workingDirectory, String programArguments, String domain, String userName, String password, out Int32 exitCode, out String output) { Process process = new Process(); process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardError = true; process.StartInfo.RedirectStandardOutput = true; StringBuilder outputString = new StringBuilder(); Object synchObj = new object(); DataReceivedEventHandler outputAppender = delegate(Object sender, DataReceivedEventArgs args) { lock (synchObj) { outputString.AppendLine(args.Data); } }; process.OutputDataReceived += outputAppender; process.ErrorDataReceived += outputAppender; process.StartInfo.FileName = @"C:\AppRunner.exe"; process.StartInfo.WorkingDirectory = workingDirectory; process.StartInfo.Arguments = @"""" + executablePath + @""" " + programArguments; process.StartInfo.UserName = userName; process.StartInfo.Domain = domain; SecureString passwordString = new SecureString(); foreach (Char c in password) { passwordString.AppendChar(c); } process.StartInfo.Password = passwordString; process.Start(); process.BeginOutputReadLine(); process.BeginErrorReadLine(); process.WaitForExit(); exitCode = process.ExitCode; output = outputString.ToString(); } }
AppRunner与上述片段基本相同,但是没有用户名和密码