おそらく作業コードを実行できますが、現在アクティブなセッションユーザートークンを使用します(ただし、アクティブセッションがない場合、これは機能しません)
簡潔にするために、このコードはコンパイルされません。最初にP / Invokeを調整して追加する必要があります。
アクティブなセッションIDを見つける必要があります。ローカルで開かれたセッションの場合、これを使用します:
[DllImport("wtsapi32.dll", SetLastError = true)]
public static extern int WTSEnumerateSessions(
IntPtr hServer,
int Reserved,
int Version,
ref IntPtr ppSessionInfo,
ref int pCount);
次に、開いているセッションIDを検索します。
var typeSessionInfo = typeof(WTSApi32.WTSSessionInfo);
var sizeSessionInfo = Marshal.SizeOf(typeSessionInfo);
var current = handleSessionInfo;
for (var i = 0; i < sessionCount; i++)
{
var sessionInfo = (WTSApi32.WTSSessionInfo)Marshal.PtrToStructure(current, typeSessionInfo);
current += sizeSessionInfo;
if (sessionInfo.State == WTSApi32.WTSConnectStateClass.WTSActive)
return sessionInfo.SessionID;
}
見つからない場合は、次でrdpセッションを検索します。
[DllImport("kernel32.dll")]
public static extern uint WTSGetActiveConsoleSessionId();
それでトークンを取得
private static IntPtr GetUserImpersonatedToken(uint activeSessionId)
{
if (!WTSApi32.WTSQueryUserToken(activeSessionId, out var handleImpersonationToken))
Win32Helper.RaiseInvalidOperation("WTSQueryUserToken");
try
{
return DuplicateToken(handleImpersonationToken, AdvApi32.TokenType.TokenPrimary);
}
finally
{
Kernel32.CloseHandle(handleImpersonationToken);
}
}
これにより、開いたユーザーセッションでローカルシステムサービスからexeを実行できます。
public static void ExecuteAsUserFromService(string appExeFullPath, uint activeSessionId, bool isVisible = false, string cmdLine = null, string workDir = null)
{
var tokenUser = GetUserImpersonatedToken(activeSessionId);
try
{
if (!AdvApi32.SetTokenInformation(tokenUser, AdvApi32.TokenInformationClass.TokenSessionId, ref activeSessionId, sizeof(UInt32)))
Win32Helper.RaiseInvalidOperation("SetTokenInformation");
ExecuteAsUser(tokenUser, appExeFullPath, isVisible, cmdLine, workDir);
}
finally
{
Kernel32.CloseHandle(tokenUser);
}
}
次に、コードを適合できるかどうかを確認します CreateProcessAsUSer(...)
private static void ExecuteAsUser(IntPtr token, string appExeFullPath, bool isVisible, string cmdLine, string workDir)
{
PrepareExecute(appExeFullPath, isVisible, ref workDir, out var creationFlags, out var startInfo, out var procInfo);
try
{
startInfo.lpDesktop = "WinSta0\\Default";
var processAttributes = new AdvApi32.SecurityAttributes
{
lpSecurityDescriptor = IntPtr.Zero
};
var threadAttributes = new AdvApi32.SecurityAttributes
{
lpSecurityDescriptor = IntPtr.Zero
};
if (!AdvApi32.CreateProcessAsUser(token,
appExeFullPath, // Application Name
cmdLine, // Command Line
ref processAttributes,
ref threadAttributes,
true,
creationFlags,
IntPtr.Zero,
workDir, // Working directory
ref startInfo,
out procInfo))
{
throw Win32Helper.RaiseInvalidOperation("CreateProcessAsUser");
}
}
finally
{
Kernel32.CloseHandle(procInfo.hThread);
Kernel32.CloseHandle(procInfo.hProcess);
}
}
このコードがあなたや他の誰かに役立つことを願っています!