因此,我尝试运行PowerShell脚本作为一个窗口服务,我已经尝试了不同的解决方案,但我有一个问题,PowerShell脚本文件不应该提供给管理员,我不能利用第三方库或类似的。它是风险暴露运行脚本本身,而不是暴露.exe文件,给管理员。我尝试过这个解决方案:https://learn.microsoft.com/en-us/archive/msdn-magazine/2016/may/windows-powershell-writing-windows-services-in-powershell
我现在正在尝试使用这个(https://www.janhendrikpeters.de/2021/01/15/developing-a-windows-service-in-powershell/)解决方案,请参见代码。
通过$OnStart变量将我的PowerShell脚本传递给脚本和服务代码可以工作,但PowerShell脚本需要在服务器上可用。本质上,我希望我的PS代码包含在已编译的exe文件中。因此,我尝试在.NET部分之前制作一个“$OnStart”代码块,将其转换为字符串,并让.NET代码启动此代码。然而,这不起作用,因为我在我的PowerShell代码中使用了“引号,是的,我不能将“更改为”,因为我的脚本中的某些函数需要双引号。我还没有尝试过的解决方案是在脚本开始时创建一个文件,并将我的PowerShell脚本写入该文件,使用Addscript函数与此文件的路径,运行脚本,并且在脚本已经开始删除文件之后。
这是一个可行的选择吗?
或者,是否有办法将包含“”的PowerShell代码脚本块传递到“AddScript”函数中?
param
(
[string]
$ServiceName = 'InfraSvc',
[string]
$OutPath = $pwd.Path,
[string]
$OnStart,
[string]
$OnStop,
[switch]
$Register
)
$binPath = (Join-Path -Path $OutPath -ChildPath "$ServiceName.exe")
if (Test-Path -Path $binPath)
{
Remove-Item -Path $binPath
}
Add-Type -TypeDefinition @"
using System;
using System.ServiceProcess;
using System.Management.Automation;
public static class HostProgram
{
#region Nested classes to support running as service
public const string ServiceName = "$ServiceName";
public class Service: ServiceBase
{
public Service()
{
ServiceName = HostProgram.ServiceName;
}
protected override void OnStart(string[] args)
{
HostProgram.Start(args);
}
protected override void OnStop()
{
HostProgram.Stop();
}
}
#endregion
static void Main(string[] args)
{
if (!Environment.UserInteractive)
// running as service
using (var service = new Service())
ServiceBase.Run(service);
else
{
// running as console app
Start(args);
Console.WriteLine("Press any key to stop...");
Console.ReadKey(true);
Stop();
}
}
private static void Start(string[] args)
{
// service startup code here
string onStart = @"$OnStart";
if (string.IsNullOrWhiteSpace(onStart)) return;
using (var psh = PowerShell.Create())
{
psh.AddScript((System.IO.File.ReadAllText(onStart)));
psh.Invoke();
}
}
private static void Stop()
{
// service startup code here
string onStop = @"$OnStop";
if (string.IsNullOrWhiteSpace(onStop)) return;
using (var psh = PowerShell.Create())
{
psh.AddScript((System.IO.File.ReadAllText(onStop)));
psh.Invoke();
}
}
}
"@ -OutputAssembly $binPath -ReferencedAssemblies System.ServiceProcess, System.Management.Automation
if ($Register.IsPresent)
{
New-Service -Name $ServiceName -BinaryPathName $binPath -StartupType Automatic
}
1条答案
按热度按时间t98cgbkg1#
我的主要问题是在powershell中编写一个windows服务,将其制作成一个.exe文件,以便在安装后“隐藏”代码和配置,并从Services. msc运行它。
我设法解决了这些问题,但我不会说这是一个美丽的解决方案。每一个问题都是在同一个脚本中解决的。
1.使用iExpress将脚本打包到“.exe”文件中
1.在.net中制作一个非常基本的windows服务,用于启动和停止打包的脚本。
用于将脚本打包到SED文件中的Powershell代码:
因为我在“Program files”文件夹中安装了该服务,所以我必须将路径转换为8.3文件名才能使iExpress运行它。因此,$Text变量中用于生成iExpress打包powershellscript所需的. SED文件的所有变量都被转换。这是通过将“Program files”替换为“PROGRA~1”来完成的。代码示例:
打包的powershell代码的路径将在Windows服务代码中使用,“$PackedExePath”. Windows服务代码用于启动和停止打包的powershell文件:
可以在同一个脚本中执行此操作,但是您需要检查服务是否已经安装,以避免在每次启动服务时创建一个新的脚本包和一个新的windows服务。因此,上面显示的所有代码都包含在此if语句中:
最好是在.Net中创建一个windows服务,但是如果你除了powershell没有其他选择,并且你的powershell代码需要打包,这是我能想到的最好的免费方法,我知道有一些工具可以打包你的powershell脚本,但是我负担不起。
值得一提的是,iExpress包含一些漏洞,但在此情况下不会造成任何风险。您可以阅读更多有关iExpress here中漏洞的信息。