共享点:从计时器作业SHAREPOINT \\\\系统权限执行stsadm

共享点:从计时器作业SHAREPOINT \\\\系统权限执行stsadm

Sharepoint: executing stsadm from a timer job + SHAREPOINT\System rights

我有一种不寻常的情况,我需要一个SharePoint计时器作业才能既具有本地管理员Windows特权又具有SHAREPOINT\\System SharePoint特权。

我可以通过简单地将计时器服务配置为使用作为本地管理员成员的帐户来获得Windows特权。我知道这不是一个好的解决方案,因为它为SharePoint计时器服务提供了应有的更多权限。但这至少允许我的SharePoint计时器作业运行stsadm

在本地管理员下运行计时器服务的另一个问题是该用户不一定具有SHAREPOINT\\System SharePoint特权,我也需要此SharePoint作业。事实证明SPSecurity.RunWithElevatedPrivileges在这种情况下不起作用。 Reflector显示RunWithElevatedPrivileges会检查当前进程是否为owstimer(运行SharePoint作业的服务进程)并且不执行任何提升操作(这种情况是合理的,我想这是计时器服务应该在以下情况下运行) NT AUTHORITY\
etworkService
Windows帐户,该帐户具有SHAREPOINT\\System SharePoint特权,因此不需要提升计时器作业的特权。

这里唯一可能的解决方案似乎是在其常规NetworkService Windows帐户下运行计时器服务,并通过将管理员凭据存储在某处并将其传递给System.Diagnostics.Process.Run()槽,以本地管理员身份运行stsadm。 StarInfo的用户名,域和密码。

看来现在一切都可以正常工作,但是这是我目前遇到的另一个问题。 Stsamd失败,并显示以下错误弹出窗口(!)(在这种情况下,Winternals filemon显示stsadm在管理员下运行):

The application failed to initialize properly (0x0c0000142).
Click OK to terminate the application.

事件查看器只注册弹出窗口。

本地管理员用户是我的帐户,当我以该帐户交互式运行stsadm时,一切正常。当我将计时器服务配置为在此帐户下运行时,它也可以正常工作。

任何建议都值得赞赏:)


我不是在工作,所以这不是我的首要任务,但是:如果获得对站点的引用,是否可以尝试使用SYSTEM-UserToken创建一个新的SPSite?

1
2
3
4
5
6
SPUserToken sut = thisSite.RootWeb.AllUsers["SHAREPOINT\\SYSTEM"].UserToken;

using (SPSite syssite = new SPSite(thisSite.Url,sut)
{
    // Do what you have to do
}

SharePoint Timer作业使用SharePoint Firm Admin凭据运行,因为该信息进入SharePoint Config数据库。因此,应用程序池将没有访问权限。

为了在开发环境中测试计时器作业,我们可以暂时将应用程序池帐户更改为用于管理中心的应用程序池帐户。


如果其他应用程序以这种方式运行(例如,通过具有明确凭据的计时器作业),则失败的方式与"应用程序无法正确初始化"相同。我只是编写了一个简单的应用程序,该应用程序将另一个可执行文件的路径及其参数作为parameres进行了处理,并且从该计时器作业运行时,它以相同的方式失败。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
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与上述片段基本相同,但没有用户名和密码


推荐阅读