简体   繁体   English

从计划任务启动时,如何使进程监听WinEvents?

[英]How can I get my process listening for WinEvents when started from a Scheduled Task?

I have a ClickOnce application built in C#. 我有一个用C#内置的ClickOnce应用程序。 As you know, ClickOnce applications, by design, cannot run with administrative privileges. 如您所知,按设计,ClickOnce应用程序无法以管理特权运行。 However, if you need to perform functions that require elevated privileges, what you can do is package another arbitrary EXE along with your ClickOnce application, and have your application call out to that separate EXE as needed. 但是,如果您需要执行需要提升特权的功能,则可以做的是将另一个任意EXE与ClickOnce应用程序一起打包,并根据需要让应用程序调用该单独的EXE。

The trouble, of course, is that each time you call out the separate application, it triggers a UAC prompt asking the user if they really want to run with elevated privileges. 当然,问题在于,每次您调用单独的应用程序时,都会触发UAC提示,询问用户是否确实要使用提升的特权运行。 This particular application is in a very closed environment, and I can ensure that I always want the elevated privileges part to run. 这个特定的应用程序处于非常封闭的环境中,我可以确保我始终希望运行特权提升部分。 However, when presented to average users, sometimes that UAC prompt can seem scary. 但是,将其呈现给普通用户时,有时该UAC提示似乎令人恐惧。

So to mitigate this, I built my EXE in a way that it only fires once, then continues running in the background and listens for WinEvents . 因此,为了减轻这种情况,我以仅触发一次的方式构建了EXE,然后继续在后台运行并侦听WinEvents My main process then triggers various WinEvents as needed, which I put in the range between AIA_START ( 0xA000 ) and AIA_END ( 0xAFFF ), since those are community reserved events. 然后,我的主进程会根据需要触发各种WinEvent,并将它们放在AIA_START( 0xA000 )和AIA_END( 0xAFFF )之间,因为它们是社区保留的事件。

Still with me? 还在我这儿? So far, what I've described has worked perfectly. 到目前为止,我所描述的已经非常完美。 However it still requires the user to press Yes to a UAC prompt once every time you start the app. 但是,它仍然需要用户在每次启动应用程序时按一次“是”到UAC提示符。 And I realized I could do better. 我意识到我可以做得更好。

By creating a Windows Scheduled Task which fires my secondary EXE, I would then only need to click Yes on the UAC prompt, ever -- upon installation. 通过创建触发我的辅助EXE的Windows计划任务,安装后,我只需要在UAC提示符下单击“是”即可。 Afterwards, I would simply be able to trigger the Scheduled Task to in turn launch the EXE with elevated privileges. 之后,我将仅能够触发“计划任务”,从而以提升的特权启动EXE。 And this seemed to be working too. 而且这似乎也起作用。 I can verify that my EXE is launching with administrative rights, and I've effectively bypassed the UAC prompt every time, which is great. 我可以验证我的EXE是否以管理权限启动,并且每次都有效地绕过了UAC提示,这很棒。

However , now that I'm launching the EXE from a Scheduled Task rather than starting it directly, it appears it is no longer to listening the WinEvents I'm triggering in my ClickOnce application. 但是 ,既然我是从计划任务中启动EXE而不是直接启动它,则似乎不再需要监听在ClickOnce应用程序中触发的WinEvents。 Or, if it is listening (which I presume it is), there's something getting in the way of that communication. 或者,如果正在侦听(我想是),那么交流中会遇到障碍。 I'm not really sure what is obstructing things, as it appears both processes are still running under the same user account in Windows. 我不太确定是什么阻碍了事情,因为看起来两个进程仍在Windows中的同一用户帐户下运行。

Does anyone know why my secondary process no longer seems to respond to WinEvents when started via a Scheduled Task? 有谁知道为什么我的辅助进程通过计划任务启动后似乎不再响应WinEvents? And how do I solve this? 我该如何解决呢? I realize I could use a different line of communication (listen on a TCP port, poll continuously on a shared file, etc.), but since I already have the code written to send and listen for WinEvents, I would much prefer to continue using that. 我意识到我可以使用不同的通信线路(在TCP端口上监听,在共享文件上连续轮询等),但是由于我已经编写了发送和侦听WinEvents的代码,因此我更希望继续使用那。

And if you're curious, here's a brief overview of the code I'm using to listen for WinEvents: 如果您好奇的话,下面是我用来监听WinEvents的代码的简要概述:

public delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);

[DllImport("user32.dll")]
private static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);

private void App_OnStartup(object sender, StartupEventArgs e)
{
    var handler = new WinEventDelegate(MyHandlerMethod);
    SetWinEventHook(0xA000, 0xAFFF, IntPtr.Zero, handler, 0, 0, 0x0002);
}

private void MyHandlerMethod(IntPtr hook, uint evt, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
    // handle the incoming WinEvents here
}

As requested, here's what I'm doing to create the Scheduled Task. 根据要求,这是我要创建计划任务的工作。 I have to create it using an XML file so that I can set the DisallowStartIfOnBatteries property to false. 我必须使用XML文件创建它,以便可以将DisallowStartIfOnBatteries属性设置为false。 So using the following XML file... 因此,使用以下XML文件...

<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <RegistrationInfo>
    <Date>2015-03-20T11:10:15</Date>
    <Author>myuser</Author>
  </RegistrationInfo>
  <Triggers>
    <TimeTrigger>
      <StartBoundary>2014-01-01T00:00:00</StartBoundary>
      <Enabled>true</Enabled>
    </TimeTrigger>
  </Triggers>
  <Principals>
    <Principal id="Author">
      <UserId>myuser</UserId>
      <LogonType>Password</LogonType>
      <RunLevel>HighestAvailable</RunLevel>
    </Principal>
  </Principals>
  <Settings>
    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
    <AllowHardTerminate>true</AllowHardTerminate>
    <StartWhenAvailable>false</StartWhenAvailable>
    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
    <IdleSettings>
      <StopOnIdleEnd>true</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>false</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <WakeToRun>false</WakeToRun>
    <ExecutionTimeLimit>P3D</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>C:\MySecondaryApp.exe</Command>
    </Exec>
  </Actions>
</Task>

...I call schtasks.exe /Create /TN MySecondaryApp /XML task.xml /RU myuser /RP mypassword to create the task. ...我调用schtasks.exe /Create /TN MySecondaryApp /XML task.xml /RU myuser /RP mypassword创建任务。 This operation does require the user to press Yes to the UAC prompt, but obviously the create is a one-time operation, meaning I can do it myself during the installation. 此操作确实需要用户在UAC提示符下按“是”,但是显然创建是一次操作,这意味着我可以在安装过程中自行完成。 From then on, all I have to do is call schtasks.exe /Run /TN MySecondaryApp to start the process. 从那时起,我要做的就是调用schtasks.exe /Run /TN MySecondaryApp启动该过程。 Because the "Run with Highest Privileges" property is already set on the task, this bypasses the need for any more UAC prompts. 因为已经在任务上设置了“以最高特权运行”属性,所以这无需任何其他UAC提示。

And like I said, I've already verified that this works. 就像我说的那样,我已经验证了这可行。 What doesn't seem to work is the WinEvents listener when running this way. 以这种方式运行时,WinEvents侦听器似乎不起作用。 I just came across another SO question which said something about processes running in different sessions won't work win WinEvents, which doesn't leave me feeling too hopeful about this. 我只是碰到另一个SO问题 ,它说在不同的会话中运行的进程在WinEvents中是行不通的,这不会使我对此抱有太大希望。

In your principle object, use the following element: 在您的主要对象中,使用以下元素:

 <LogonType>InteractiveToken</LogonType>

Adding this XML tag changes the scheduled task to "Run only when user is logged on" option, which correlates to the full GUI mode where you will see your windows messages again. 添加此XML标记会将计划的任务更改为“仅在用户登录时运行”选项,这与完整的GUI模式相关,在该模式下您将再次看到Windows消息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何找到启动我的进程的计划任务的instanceid / correlation ID - how can i find the instanceid/correlation ID of the scheduled Task that started my process 我如何知道 Kestrel 何时开始收听? - How can I know when Kestrel has started listening? 如何从进程开始和结束之间的时间获取数据? - How can i get the data from the time between a process started and ended? 如何高效处理定时任务? - How can I process scheduled tasks effeciently? 如何在当前进程启动时获取DateTime? - How to get the DateTime when the current process started? 当由一组信用卡下的计划任务启动的进程在不同的一组Cred下运行另一个程序时,Windows是否有限制 - does windows have a limitation when a process started by a scheduled task under one set of creds runs another program under a different set of Creds 当我的应用退出时,如何防止由Process.Start()启动的进程退出? - How to prevent a process started by Process.Start() from exiting when my app exits? 如何识别进程是手动启动还是从任务计划程序启动? - How to identify the process is started manually or from Task Scheduler? 如何将我的 c# 程序作为计划任务运行 - How do I run my c# program as a scheduled task 我可以编写一个C#程序 - 当作为计划任务运行时 - 检测任务计划程序何时尝试停止它 - can I write a C# program that - when run as a scheduled task - detects when Task Scheduler tries to stop it
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM