Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/271.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# CreateProcessAsUser从Windows服务打印时不使用LogonUser令牌_C#_Windows Services_Pinvoke_Createprocessasuser - Fatal编程技术网

C# CreateProcessAsUser从Windows服务打印时不使用LogonUser令牌

C# CreateProcessAsUser从Windows服务打印时不使用LogonUser令牌,c#,windows-services,pinvoke,createprocessasuser,C#,Windows Services,Pinvoke,Createprocessasuser,我正在LocalSystem帐户下构建一个windows服务,它将在某个时间间隔内打印pdf 为此,我使用LogonUser IntPtr currentToken = IntPtr.Zero; const int LOGON32_LOGON_INTERACTIVE = 2; const int LOGON32_PROVIDER_DEFAULT = 0; bool loggedOn = LogonUser(user, domain, password, LOGON32_LOGON_INTERAC

我正在LocalSystem帐户下构建一个windows服务,它将在某个时间间隔内打印pdf

为此,我使用
LogonUser

IntPtr currentToken = IntPtr.Zero;
const int LOGON32_LOGON_INTERACTIVE = 2;
const int LOGON32_PROVIDER_DEFAULT = 0;
bool loggedOn = LogonUser(user, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref currentToken);
并在
CreateProcessAsUser

CreateProcessAsUser(primaryToken, null, command, ref Security1, ref Security2, false, CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT, lpEnvironment, null, ref StartupInfo, out processInfo_);
但这不是它的工作

如果我使用以下代码获取当前用户令牌

public static IntPtr GetCurrentUserToken()
{
    IntPtr currentToken = IntPtr.Zero;
    IntPtr primaryToken = IntPtr.Zero;
    IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;

    int dwSessionId = 0;
    IntPtr hUserToken = IntPtr.Zero;
    IntPtr hTokenDup = IntPtr.Zero;

    IntPtr pSessionInfo = IntPtr.Zero;
    int dwCount = 0;

    WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, ref pSessionInfo, ref dwCount);

    Int32 dataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO));

    Int32 current = (int)pSessionInfo;
    for (int i = 0; i < dwCount; i++)
    {
        WTS_SESSION_INFO si = (WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)current, typeof(WTS_SESSION_INFO));
        if (WTS_CONNECTSTATE_CLASS.WTSActive == si.State)
        {
            dwSessionId = si.SessionID;
            break;
        }

        current += dataSize;
    }

    WTSFreeMemory(pSessionInfo);

    bool bRet = WTSQueryUserToken(dwSessionId, out currentToken);
    if (bRet == false)
    {
        return IntPtr.Zero;
    }

    bRet = DuplicateTokenEx(currentToken, TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenPrimary, out primaryToken);
    if (bRet == false)
    {
        return IntPtr.Zero;
    }

    return primaryToken;
}

但是GetExitCodeProcess返回true。首先,我没有发现任何错误

与上次发布此问题()时一样,您需要了解并确定哪些特定API调用失败,然后调用,这将为您提供有关调用失败原因的更多信息

GetLastError:检索调用线程的上一个错误代码值

其次

可能是
GetCurrentUserToken
中的一个调用(例如
WTSQueryUserToken
中的调用)有权限问题或其他可以修复的问题(尽管我对此表示怀疑)

阅读文档以了解它似乎陈述了以下内容

WTSQueryUserToken:获取由指定的登录用户的主访问令牌 会话ID为

此外,
WTSQueryUserToken
可能正在返回

ERROR_NO_TOKEN
1008
错误\u无\u令牌:令牌查询用于没有用户登录的会话
。这 例如,当会话处于空闲状态或 SessionId为零

第三

在我看来,我认为这种方法在您的情况下永远不会起作用,而且从服务打印实际上并不被正式推荐

请看下面的问题

最后

我能想到的唯一一件事是,在一个用户帐户下运行您的服务,该帐户可以访问打印机,或者通过调用来模拟用户,然后通过Gdi+打印(这将有它自己的问题)

请注意

而通过获取 打印机的设备上下文句柄,然后将该句柄传递给 GDI+图形构造函数,不推荐使用。GDI+ Windows中不支持使用函数和类 服务试图从Windows应用程序中使用这些函数和类 服务可能会产生意外问题,例如服务减少 性能和运行时异常或错误:


简言之,您可以使用现有的解决方案,并且您当前拥有的源代码不太可能工作,在我看来,您很可能会在这个问题上花费大量时间,试图做一些服务真正不打算做的事情(这也超出了当前问题的范围)

我真的认为你需要认真地重新考虑你想做什么,为什么要这样做,并祝你好运

有关GDI打印和服务打印的附加信息


您没有提供有关打印过程的任何信息,但根据您提供的信息,我猜它必须在交互式会话下运行。第一种方法不起作用,因为
LogonUser
提供的令牌与调用进程具有相同的会话id,即0。您的第二种方法在注销后不起作用,因为
WTSQueryUserToken
将按其假设的方式失败。因此,我建议您尝试winlogon解决方案,它可以概括为查找交互式会话的winlogon进程,复制其令牌,并使用该令牌创建您的打印进程。有所有的细节。

公然从链接页面中窃取

通常,调用函数的进程必须具有SE_INCREASE_QUOTA_名称

该帐户具有以下权限: ... SE_增加_配额_名称(禁用) 因此,我很惊讶CreateProcessAsUser能够在本地系统上下文中工作

CreateProcessAsUser不会将指定用户的配置文件加载到HKEY_用户注册表项中。因此,要访问HKEY_CURRENT_用户注册表项中的信息,必须在调用CreateProcessAsUser之前,使用LoadUserProfile函数将用户的配置文件信息加载到HKEY_用户中。确保在新进程退出后调用UnloadUserProfile

CreateProcessAsUser似乎比CreateProcessWithLogonW更挑剔。我将尝试使用LOGON\u with\u PROFILE参数


您可以在代码中的令牌上调用DuplicateTokenEx,这似乎是可行的。您可能希望使用LogonUser令牌尝试此操作。

我正在检查类似于此的上次错误
uint exitCode;如果(!GetExitCodeProcess(processInfo.HPProcess,out exitCode)){int lastError=Marshal.GetLastWin32Error();Logger.LogService(“GetExitCodeProcess Error”+lastError);}
GetExitCode>返回
true
。我没有发现任何错误
ERROR_NO_TOKEN
1008