我有一個Windows服務應用程序。 目前所有的管理任務都是通過配置編輯完成的。如何爲Windows服務添加命令行界面
我想添加某種命令行界面 - 我希望它通過powershell來完成。
我不知道我應該從哪裏開始 - 我如何在這種情況下創建應用程序接口。 PowerShell應該如何與服務進行通信?在這種情況下也需要遠程功能。
(在功能也有可能是其它管理工具 - 使用GUI或通過瀏覽器。)
我有一個Windows服務應用程序。 目前所有的管理任務都是通過配置編輯完成的。如何爲Windows服務添加命令行界面
我想添加某種命令行界面 - 我希望它通過powershell來完成。
我不知道我應該從哪裏開始 - 我如何在這種情況下創建應用程序接口。 PowerShell應該如何與服務進行通信?在這種情況下也需要遠程功能。
(在功能也有可能是其它管理工具 - 使用GUI或通過瀏覽器。)
擴大一點就LB的短上下的一句話:具有優越的服務與用戶的桌面進行交互是不最好的想法,因爲這樣做可能會開啓特權提升的路線。例如Shatter attacks就是這樣工作的。
一個更好的方式來處理與用戶的交互將是對本地主機的特權的監聽器(如127.0.0.1:5555
),將顯示通過該端口提交的郵件,並有特權服務連接到監聽器將消息發送到用戶。
下面的代碼片段 - 而留下了很多改進餘地 - 應該給你這樣的聽衆會怎麼看起來像一個總體思路:
$addr = "127.0.0.1"
$port = 5555
[byte[]]$byte = @(0)
$enc = [System.Text.Encoding]::ASCII
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$socket = New-Object System.Net.Sockets.TcpListener([System.Net.IPAddress]::Parse($addr), $port)
$socket.Start()
while ($true) {
$client = $socket.AcceptTcpClient()
$stream = $client.GetStream()
[byte[]]$input = @()
while (($i = $stream.Read($byte, 0, 1)) -ne 0) { $input += $byte }
$client.Close()
[System.Windows.Forms.MessageBox]::Show($enc.GetString($input), "Title")
}
Windows服務最初看起來是這樣的:
using System.ServiceProcess;
internal partial class MyService : ServiceBase
{
static void Main()
{
ServiceBase[] ServicesToRun = new ServiceBase[] { new MyService() };
ServiceBase.Run(ServicesToRun);
}
}
我所做的就是修改Main()
,這樣我可以用它既能推出的服務,並處理命令行的東西,像這樣:
using System;
using System.Runtime.InteropServices;
using System.ServiceProcess;
internal partial class MyService : ServiceBase
{
const int ATTACH_PARENT_PROCESS = -1;
[DllImport("kernel32.dll")]
static extern bool AttachConsole(int dwProcessId);
[DllImport("kernel32.dll")]
static extern bool FreeConsole();
static void Main()
{
if (Environment.UserInteractive) {
try {
// Redirect console output to the parent process.
AttachConsole(ATTACH_PARENT_PROCESS);
// Process command line arguments here...
} catch {
// Handle exceptions here...
} finally {
// Detach from the console.
FreeConsole();
}
} else {
ServiceBase[] ServicesToRun = new ServiceBase[] { new MyService() };
ServiceBase.Run(ServicesToRun);
}
}
}
構建可執行文件時,我會正常註冊到操作系統(actually, I use a -install command-line option to do that)。當服務啓動時,UserInteractive
標誌爲false,所以服務開始照常。但是,從命令提示符處,UserInteractive
標誌是true,因此命令行處理會接管。
所有你需要在這一點上是有你的可執行文件的命令行實例通過某種IPC與可執行的服務實例通信 - 插座,管道,共享內存,WCF等
[HttpListener ](http://msdn.microsoft.com/en-us/library/system.net.httplistener.aspx)? –
簡單而直接 - 不知道爲什麼 - 但我沒有想過這個。 –