簡體   English   中英

從計划任務啟動時,如何使進程監聽WinEvents?

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

我有一個用C#內置的ClickOnce應用程序。 如您所知,按設計,ClickOnce應用程序無法以管理特權運行。 但是,如果您需要執行需要提升特權的功能,則可以做的是將另一個任意EXE與ClickOnce應用程序一起打包,並根據需要讓應用程序調用該單獨的EXE。

當然,問題在於,每次您調用單獨的應用程序時,都會觸發UAC提示,詢問用戶是否確實要使用提升的特權運行。 這個特定的應用程序處於非常封閉的環境中,我可以確保我始終希望運行特權提升部分。 但是,將其呈現給普通用戶時,有時該UAC提示似乎令人恐懼。

因此,為了減輕這種情況,我以僅觸發一次的方式構建了EXE,然后繼續在后台運行並偵聽WinEvents 然后,我的主進程會根據需要觸發各種WinEvent,並將它們放在AIA_START( 0xA000 )和AIA_END( 0xAFFF )之間,因為它們是社區保留的事件。

還在我這兒? 到目前為止,我所描述的已經非常完美。 但是,它仍然需要用戶在每次啟動應用程序時按一次“是”到UAC提示符。 我意識到我可以做得更好。

通過創建觸發我的輔助EXE的Windows計划任務,安裝后,我只需要在UAC提示符下單擊“是”即可。 之后,我將僅能夠觸發“計划任務”,從而以提升的特權啟動EXE。 而且這似乎也起作用。 我可以驗證我的EXE是否以管理權限啟動,並且每次都有效地繞過了UAC提示,這很棒。

但是 ,既然我是從計划任務中啟動EXE而不是直接啟動它,則似乎不再需要監聽在ClickOnce應用程序中觸發的WinEvents。 或者,如果正在偵聽(我想是),那么交流中會遇到障礙。 我不太確定是什么阻礙了事情,因為看起來兩個進程仍在Windows中的同一用戶帳戶下運行。

有誰知道為什么我的輔助進程通過計划任務啟動后似乎不再響應WinEvents? 我該如何解決呢? 我意識到我可以使用不同的通信線路(在TCP端口上監聽,在共享文件上連續輪詢等),但是由於我已經編寫了發送和偵聽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
}

根據要求,這是我要創建計划任務的工作。 我必須使用XML文件創建它,以便可以將DisallowStartIfOnBatteries屬性設置為false。 因此,使用以下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>

...我調用schtasks.exe /Create /TN MySecondaryApp /XML task.xml /RU myuser /RP mypassword創建任務。 此操作確實需要用戶在UAC提示符下按“是”,但是顯然創建是一次操作,這意味着我可以在安裝過程中自行完成。 從那時起,我要做的就是調用schtasks.exe /Run /TN MySecondaryApp啟動該過程。 因為已經在任務上設置了“以最高特權運行”屬性,所以這無需任何其他UAC提示。

就像我說的那樣,我已經驗證了這可行。 以這種方式運行時,WinEvents偵聽器似乎不起作用。 我只是碰到另一個SO問題 ,它說在不同的會話中運行的進程在WinEvents中是行不通的,這不會使我對此抱有太大希望。

在您的主要對象中,使用以下元素:

 <LogonType>InteractiveToken</LogonType>

添加此XML標記會將計划的任務更改為“僅在用戶登錄時運行”選項,這與完整的GUI模式相關,在該模式下您將再次看到Windows消息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM