Windows 7 在Windows 7欢迎屏幕上运行进程

Windows 7 在Windows 7欢迎屏幕上运行进程,windows-7,login-script,Windows 7,Login Script,下面是独家新闻: 不久前,我编写了一个小型C#应用程序,显示主机名、ip地址、映像日期、解冻状态(我们使用DeepFreeze)、当前域和当前日期/时间,以显示在Windows 7实验室机器的欢迎屏幕上。这是为了取代我们以前的信息块,它在启动时是静态设置的,实际上是将文本嵌入到背景中,使用一些更具动态性和功能性的东西。该应用程序使用计时器每秒更新ip地址、deepfreeze状态和时钟,并检查用户是否已登录并在检测到此类情况时自杀 如果我们只是通过我们的启动脚本(通过组策略设置)运行它,它将保持

下面是独家新闻:

不久前,我编写了一个小型C#应用程序,显示主机名、ip地址、映像日期、解冻状态(我们使用DeepFreeze)、当前域和当前日期/时间,以显示在Windows 7实验室机器的欢迎屏幕上。这是为了取代我们以前的信息块,它在启动时是静态设置的,实际上是将文本嵌入到背景中,使用一些更具动态性和功能性的东西。该应用程序使用计时器每秒更新ip地址、deepfreeze状态和时钟,并检查用户是否已登录并在检测到此类情况时自杀

如果我们只是通过我们的启动脚本(通过组策略设置)运行它,它将保持脚本打开,并且机器永远不会进入登录提示。如果我们在一个单独的shell/进程下使用start或cmd命令来启动它,它将一直运行到启动脚本完成,此时Windows似乎会清理脚本的所有子进程。目前,我们可以使用
psexec-s-d-i-x
来启动它,这样可以在启动脚本完成后保持它,但速度可能非常慢,增加启动时间5秒到1分钟以上

我们已经尝试过使用另一个C#应用程序来启动流程,通过process类,使用带有各种启动标志的WMI调用(Win32#u process和Win32#u ProcessStartup),等等,但最终都会导致相同的脚本完成和信息块进程被终止。我尝试将应用程序改写为一项服务,但服务从未设计为与桌面交互,更不用说登录窗口了,在正确的环境下运行似乎从未真正起作用


那么问题是:有没有人有一个好的方法来实现这一点?启动一个任务,使其独立于启动脚本,并在欢迎屏幕上运行?

我认为您可以这样做,但它非常复杂。交互应用程序通常不允许在欢迎屏幕上运行。在较高级别上,您需要:

  • 创建自动启动的windows服务
  • 使用windows服务在当前会话和桌面上创建另一个进程(使用Win32方法
    WTSGetActiveConsoleSessionId
    OpenInputDesktop
我编写了一个应用程序,可以与登录屏幕进行某种程度的交互,但它不显示任何UI。这可能是可以做到的,但它可能涉及更多

注意:我发现我无法从Windows服务中从
OpenInputDesktop
获取结果。我不得不在另一个进程中调用,并通知服务在正确的桌面上重新启动进程

我希望这至少能让你开始。祝你好运

这是一个“你真的需要一个很好的理由这样做”的问题。Microsoft极力阻止在启动屏幕上运行的应用程序-Windows中与登录屏幕交互的每一段代码都经过非常仔细的代码审查,因为登录屏幕上运行的代码中的错误会带来可怕的安全后果-如果你稍微出错,您将允许恶意软件进入计算机


为什么要在登录屏幕上运行程序?也许有一种记录在案的方法没有那么危险。

这可以通过很多Win32 API调用来实现。我已经设法在Winlogon桌面上安装了一个带有GUI的程序(在有人问之前,它不是交互式GUI)。基本上,您需要以系统的形式运行加载程序进程,然后它将生成新进程。由于您很可能希望在启动时运行此进程,因此可以使用任务调度器作为系统运行加载程序,也可以使用服务执行相同的操作。我目前正在使用一项服务,但我尝试使用任务调度器,它工作得很好

小结:

  • 获取Winlogon.exe进程(作为进程)
  • 使用进程的.handle使用OpenProcessToken获取winlogon的令牌
  • 创建一个新令牌并将winlogon令牌复制到该令牌
  • 提升令牌的权限
  • 使用CreateProcessAsUser创建进程,确保将lpDesktop设置为“Winsta0\Winlogon”,并使用您创建的令牌
  • 代码示例:

    //获取winlogon进程
    进程winLogon=null;
    foreach(Process.getprocesss()中的进程p){
    if(p.ProcessName.Contains(“winlogon”)){
    winLogon=p;
    打破
    }
    }
    //获取winlogon的令牌
    IntPtr userToken=IntPtr.Zero;
    if(!OpenProcessToken(winLogon.Handle,TOKEN|QUERY | TOKEN|IMPERSONATE | TOKEN|u replicate,out userToken)){
    日志(“错误:OpenProcessToken返回false-”+Marshal.GetLastWin32Error());
    }
    //创建一个新令牌
    IntPtr newToken=IntPtr.Zero;
    SECURITY_ATTRIBUTES tokenAttributes=新的SECURITY_ATTRIBUTES();
    tokenAttributes.nLength=Marshal.SizeOf(tokenAttributes);
    SECURITY_ATTRIBUTES threadAttributes=新的SECURITY_ATTRIBUTES();
    threadAttributes.nLength=Marshal.SizeOf(threadAttributes);
    //将winlogon令牌复制到新令牌
    如果(!DuplicateTokenEx(userToken,0x10000000,ref-tokenAttributes,SECURITY\u-IMPERSONATION\u-LEVEL.SecurityImpersonation,
    TOKEN_TYPE.TokenImpersonation,out newToken)){
    日志(“错误:DuplicateTokenEx返回false-”+Marshal.GetLastWin32Error());
    }
    TOKEN_PRIVILEGES tokPrivs=新的TOKEN_PRIVILEGES();
    tokPrivs.PrivilegeCount=1;
    LUID seDebugNameValue=新LUID();
    if(!LookupPrivilegeValue(null,SE_DEBUG_NAME,out seDebugNameValue)){
    日志(“错误:LookupPrivilegeValue返回false-”+Marshal.GetLastWin3