WINDOWS服务启动应用程序看不到界面

sodisla 2016-05-17 07:43:01
如题,网上搜索了很久,都说是允许桌面交互的就可以了,为什么无论是手动设置、代码设置、服务器重启依旧看不到界面,网上那些方法难道都是复制粘贴没有实际应用测试吗?
...全文
2731 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
关中山水郎 2019-04-16
  • 打赏
  • 举报
回复
Windows服务一般在Session0里,EXE应用一般在Session1里,Win7及以后的系统将服务与应用程序进行了Session隔离,不允许其进行UI交互,可以考虑穿透Session隔离来启动,这个我之前也遇到过,已经解决了,看我的博客里有详细的解决方案。
关中山水郎 2019-04-16
  • 打赏
  • 举报
回复
C#穿透session隔离———Windows服务启动UI交互程序https://www.cnblogs.com/CityOfThousandFires/p/10375242.html
我叫胖头鱼 2019-04-16
  • 打赏
  • 举报
回复
我也有同样的困惑,有恢复推荐是“可以让服务以其他用户来运行exe,就可以显示出来界面”,但具体怎么以其他用户运行我也不了解
  • 打赏
  • 举报
回复
引用 楼主 sodisla 的回复:
如题,网上搜索了很久,都说是允许桌面交互的就可以了,为什么无论是手动设置、代码设置、服务器重启依旧看不到界面,网上那些方法难道都是复制粘贴没有实际应用测试吗?
你看到都是针对 window 7/Vista 之前的“老黄历”的文章吧?!或者是某些网站恶意抄袭的文章。
Harbin Kakashi 2019-03-16
  • 打赏
  • 举报
回复
你好 请问最后是如何解决的
desperaso 2018-12-13
  • 打赏
  • 举报
回复
https://www.cnblogs.com/qiaoke/p/6654449.html
里面有下载
desperaso 2018-12-13
  • 打赏
  • 举报
回复
我常用的,服务调用交互,没问题

public class Interop
{
public static void CreateProcess(string app, string path)
{
bool result;
IntPtr hToken = WindowsIdentity.GetCurrent().Token;
IntPtr hDupedToken = IntPtr.Zero;
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
sa.Length = Marshal.SizeOf(sa);
STARTUPINFO si = new STARTUPINFO();
si.cb = Marshal.SizeOf(si);
int dwSessionID = WTSGetActiveConsoleSessionId();
result = WTSQueryUserToken(dwSessionID, out hToken);
result = DuplicateTokenEx(
hToken,
GENERIC_ALL_ACCESS,
ref sa,
(int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
(int)TOKEN_TYPE.TokenPrimary,
ref hDupedToken
);
IntPtr lpEnvironment = IntPtr.Zero;
result = CreateEnvironmentBlock(out lpEnvironment, hDupedToken, false);
result = CreateProcessAsUser(
hDupedToken,
app,
String.Empty,
ref sa, ref sa,
false, 0, IntPtr.Zero,
null, ref si, ref pi);
if (pi.hProcess != IntPtr.Zero)
CloseHandle(pi.hProcess);
if (pi.hThread != IntPtr.Zero)
CloseHandle(pi.hThread);
if (hDupedToken != IntPtr.Zero)
CloseHandle(hDupedToken);
}
[StructLayout(LayoutKind.Sequential)]
public struct STARTUPINFO
{
public Int32 cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public Int32 dwProcessID;
public Int32 dwThreadID;
}
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public Int32 Length;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
}
public enum SECURITY_IMPERSONATION_LEVEL
{
SecurityAnonymous,
SecurityIdentification,
SecurityImpersonation,
SecurityDelegation
}
public enum TOKEN_TYPE
{
TokenPrimary = 1,
TokenImpersonation
}
public const int GENERIC_ALL_ACCESS = 0x10000000;
[DllImport(""kernel32.dll"", SetLastError = true,
CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern bool CloseHandle(IntPtr handle);
[DllImport(""advapi32.dll"", SetLastError = true,
CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern bool CreateProcessAsUser(
IntPtr hToken,
string lpApplicationName,
string lpCommandLine,
ref SECURITY_ATTRIBUTES lpProcessAttributes,
ref SECURITY_ATTRIBUTES lpThreadAttributes,
bool bInheritHandle,
Int32 dwCreationFlags,
IntPtr lpEnvrionment,
string lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
ref PROCESS_INFORMATION lpProcessInformation);
[DllImport(""advapi32.dll"", SetLastError = true)]
public static extern bool DuplicateTokenEx(
IntPtr hExistingToken,
Int32 dwDesiredAccess,
ref SECURITY_ATTRIBUTES lpThreadAttributes,
Int32 ImpersonationLevel,
Int32 dwTokenType,
ref IntPtr phNewToken);
[DllImport(""wtsapi32.dll"", SetLastError = true)]
public static extern bool WTSQueryUserToken(
Int32 sessionId,
out IntPtr Token);
[DllImport(""userenv.dll"", SetLastError = true)]
static extern bool CreateEnvironmentBlock(
out IntPtr lpEnvironment,
IntPtr hToken,
bool bInherit);
public static IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;
public static void ShowMessageBox(string message, string title)
{
int resp = 0;
WTSSendMessage(
WTS_CURRENT_SERVER_HANDLE,
WTSGetActiveConsoleSessionId(),
title, title.Length,
message, message.Length,
0, 0, out resp, false);
}
[DllImport(""kernel32.dll"", SetLastError = true)]
public static extern int WTSGetActiveConsoleSessionId();
[DllImport(""wtsapi32.dll"", SetLastError = true)]
public static extern bool WTSSendMessage(
IntPtr hServer,
int SessionId,
String pTitle,
int TitleLength,
String pMessage,
int MessageLength,
int Style,
int Timeout,
out int pResponse,
bool bWait);
}


public static void Start()里调用
{
Interop.CreateProcess(@"""+ exe文件 + @""", @""C:\Windows\System32\"");
}

如果是开机启动的服务,加上延时打开
  • 打赏
  • 举报
回复
顺便说一下,我们的服务程序虽然是使用 .net 4.6.1 甚至是 4.7 的目标平台的,但是是要求支持 windows7 的(集群中有些服务器是使用 windows7操作系统)。 而 .net 框架中有些新东西不支持 windows7,那就是鸡肋。
  • 打赏
  • 举报
回复
windows service 程序"看到桌面界面"并不是重点,重点是你要调用的一些功能可能只能找到用户态下的一些工具程序,那么这个时候就只好在服务器硬件上跑桌面程序了。这个时候你设计开发桌面程序,既要也能按照大的服务系统的标准来设计,例如可以自动下载最新程序版本甚至自动重启业务服务进程,例如需要自动发微信报警,这都是不是传统的桌面要有的功能,但是对服务很重要。
  • 打赏
  • 举报
回复
我给你说一下我们的服务的做法: 比如说我们的服务,是集群的,并且要求能调用 Office 组件来处理用户自定义的 Excel 模板中的统计公式、导出 PDF、公文排版等等。并且是高并发的,一个集团里边不同分公司的人经常可能几百人在1天同时要处理同一类工作。 这类功能往往要进行一个相对长一点时间的文档处理过程(不是简单地增删改查),并且有可能不稳定而造成进程崩溃,并且其实也有可能需要分布式地使用许多 CPU 才能处理突发的大量请求。 我们的服务 .exe 程序可以是注册为 windows service,也可以是控制台程序执行。两种形式都可以运行。同时这个服务第一次运行时仅仅是一个”守护进程“,仅仅有几行代码而已,这几行代码的任务是负责拉起这个 .exe 程序的另外一个进程,而这个新的进程才负责真正业务操作。比如说,打开”进程管理器“可以看到这个 .exe 启动了同名的两个进程。这样当守护进程发现被守护进程宕机了,就会自动拉起另外一个被守护进程。 那么实际上只要远程登录到服务器,然后手动启动一个控制台程序,它就会自动拉起另外一个控制台程序。然后我们选择”锁定“而不是”注销“来退出远程桌面,就能保证总有一个用户态的程序在服务器上运行。同时也不怕用户态的 Office 组件偶尔崩溃造成服务宕机。
  • 打赏
  • 举报
回复
服务不可展示前台界面,请使用进程间交互功能用前台应用调用服务操作。
xuzuning 2018-12-07
  • 打赏
  • 举报
回复
服务本身就是在后台运行的,让他去启动一个前台应用,似乎没啥道理
再说服务器都摆放在机房里,被他启动的前台应用由谁去操作呢?
  • 打赏
  • 举报
回复
引用 楼主 sodisla 的回复:
如题,网上搜索了很久,都说是允许桌面交互的就可以了,为什么无论是手动设置、代码设置、服务器重启依旧看不到界面,网上那些方法难道都是复制粘贴没有实际应用测试吗?
你搜索的,是不是都是过去很多年前针对 windows7 以下的帖子?! 自从 windows7 以后,这个设置不管用了。windows7和 windows server2008r2 以后服务器端默认就不会用用户态执行了。
feitianxiaozi 2018-12-07
  • 打赏
  • 举报
回复
DWORD __stdcall INTER_GetExplorerToken(OUT PHANDLE phExplorerToken)
{

DWORD dwStatus = ERROR_FILE_NOT_FOUND;
BOOL bRet = FALSE;
HANDLE hProcess = NULL;
HANDLE hProcessSnap = NULL;
WCHAR szExplorerPath[MAX_PATH] = { 0 };
WCHAR FileName[MAX_PATH] = { 0 };
PROCESSENTRY32 pe32 = { 0 };
//__try
{
GetWindowsDirectory(szExplorerPath, MAX_PATH);
//StrCatW(szExplorerPath, L"\\explorer.exe");
//StrNCatW(szExplorerPath, L"\\explorer.exe", MAX_PATH);
StringCchCat(szExplorerPath, MAX_PATH, L"\\explorer.exe");
string expStr = QwBase::ws2s(szExplorerPath);
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{

dwStatus = GetLastError();
return dwStatus;
//__leave;
}
pe32.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hProcessSnap, &pe32))
{
dwStatus = GetLastError();
return dwStatus;
}
BOOL bres = FALSE;
do {
hProcess = OpenProcess(
PROCESS_ALL_ACCESS,
FALSE,
pe32.th32ProcessID);
if (NULL != hProcess)
{
DWORD(__stdcall *GMFNE)(HANDLE hProcess,
HMODULE hModule,
LPTSTR lpFilename,
DWORD nSize);
HMODULE hPsapi = LoadLibrary(L"PSAPI");
if (!hPsapi)
{
dwStatus = GetLastError();
break;
}
GMFNE = (DWORD(__stdcall *) (HANDLE, HMODULE, LPTSTR, DWORD))GetProcAddress(hPsapi, "GetModuleFileNameExW");
if (GMFNE(hProcess, NULL, FileName, MAX_PATH))
{
string tmp = QwBase::ws2s(FileName);
if (!_stricmp(expStr.c_str(), tmp.c_str()))
{
HANDLE hToken;
if (OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken))
{
*phExplorerToken = hToken;
dwStatus = 0;
}
break;
}
}
CloseHandle(hProcess);
hProcess = NULL;
}
bres = Process32Next(hProcessSnap, &pe32);
} while (bres);
}
//__finally
{
if (NULL != hProcess)
{
CloseHandle(hProcess);
}
if (NULL != hProcessSnap)
{
CloseHandle(hProcessSnap);
}
}

return dwStatus;

}

直接上代码
江南小鱼 2016-05-17
  • 打赏
  • 举报
回复
XP系统,windows服务器可以启动桌面应用程序 WIN7别想了,微软封死这个口子了,windows服务能启动桌面应用程序,但是在windows服务所在用户是看不到界面的
sodisla 2016-05-17
  • 打赏
  • 举报
回复
引用 1 楼 rocmemory 的回复:
看看任务管理器里,是不是用“SYSTEM”用户启动的
是SYSTEM用户,但是我将服务指定用户为administrator效果还是一样的。
为轮子而生 2016-05-17
  • 打赏
  • 举报
回复
看看任务管理器里,是不是用“SYSTEM”用户启动的

111,130

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧