Bạn có thể có thể thực thi mã làm việc của mình, nhưng sử dụng mã thông báo người dùng phiên hiện đang hoạt động (nhưng không có phiên hoạt động thì điều này không hoạt động)
Để đơn giản, mã này sẽ không được biên dịch: trước tiên bạn phải điều chỉnh và thêm một số P / Gọi .
Bạn phải tìm id phiên hoạt động. Đối với phiên mở cục bộ, sử dụng:
[DllImport("wtsapi32.dll", SetLastError = true)]
public static extern int WTSEnumerateSessions(
IntPtr hServer,
int Reserved,
int Version,
ref IntPtr ppSessionInfo,
ref int pCount);
Sau đó tìm kiếm id phiên mở:
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;
}
Nếu không tìm thấy, tìm kiếm một phiên thứ bảy với:
[DllImport("kernel32.dll")]
public static extern uint WTSGetActiveConsoleSessionId();
Với điều đó nhận được mã thông báo
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);
}
}
Với điều đó, bạn có thể thực thi một exe từ dịch vụ Hệ thống cục bộ, trên phiên người dùng đã mở.
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);
}
}
Bây giờ hãy xem nếu bạn có thể điều chỉnh mã của mình thành 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);
}
}
Hy vọng mã này sẽ phục vụ cho bạn hoặc người khác!