繁体   English   中英

Powershell 转 EXE 工具建议

[英]Powershell to EXE tool Advice

所以这就是交易。 由于许多......让我们说不是 PowerShell 聪明的人将使用我刚刚完成的非常复杂的应用程序,我需要能够将它打包到一个 exe 包装器中。

这不应该那么难

我能够成功地使用PS2EXE ,除了 AD 的某种原因,它抛出了一大堆我无法摆脱的 AD 文本。 在感到沮丧并继续前进之前,试图解决这个问题几天。

然后,我发现了PowerGUI 我完全不能说我喜欢它。 然而,它的编译器正是我想要的! 除了 Exchange 2010 管理单元通过此应用程序与.NET 4.5不兼容这一事实。

我想非常清楚地表明,我的脚本在多台不同的计算机上都能完美运行,但是一旦我使用这些工具中的任何一个,一切都会中断

一个 exe 是我能想到的最好的东西来简化界面,并防止技术上的智力障碍破坏一切,或者每一个小错误都跑向我,因为他们以某种方式进入了代码并输入了一些东西并保存了它,现在没有任何效果,这是世界末日,他们不知道发生了什么

如果你们知道任何工具可以将其打包成一个 exe,或者对如何提供帮助有任何其他想法,我将非常感谢你们能给我的任何东西。

你过去从来没有让我失望过!

从我的角度来看,如果你真的想要一个 EXE 文件,你应该编写一个 .NET 应用程序,嵌入 PowerShell CmdLets 并不难。

为了避免最终用户修改您的代码,我知道两种解决方案:

首先:在用户计算机上将执行策略设置为AllSigned并签署您部署的脚本。 您可以设法使用我们自己的证书(根本不贵)或公共证书(更贵)。 此解决方案的缺点之一是它不会阻止用户查看代码。 另一个大缺点是 PKI 和符号代码基础设施浪费了很多时间。

第二:对于非交互式脚本(小心这是一种临时工作):

  1. 创建一个新的用户帐户
  2. 只允许访问新帐户的脚本文件。
  3. 在 Windows 调度程序中设置一个任务,以在该特定帐户下使用 PowerShell 运行该脚本文件。 计划任务的权限允许对用户进行读取和执行访问。 然后将任务设置为“禁用”。
  4. 每当需要运行脚本文件时,都由用户手动启动相应的任务。

使用此解决方案还可以让您远程执行脚本。

当我遇到类似的部署问题时 - 1) 用户不知道 powershell 2) 我不想让他们必须了解诸如执行策略之类的东西,3) 如何启动 PS,4) 等等。我把它打包成一个批次文件。 我还想确保有经验的 PS 用户仍然具有 PS 的功能,因此批处理文件确定它是否在 PS 下运行,并在适用时在当前 PS 会话中运行。 我从不担心用户会弄乱脚本 - 如果它“正常工作”,他们会很高兴。 所以不管用户喜欢 Explorer、CMD.EXE 还是 PS,他们都被容纳了。

我编写的批处理文件首先运行了一些powershell 代码,以确定批处理文件的进程是否是powershell 进程的孙子进程。 如果是,则正在从 PS 调用批处理文件。 执行策略也会被检查,如果它足够宽松,那么 Wscript.SendKeys 用于向 PS 发送击键,以使脚本在当前 PS 会话中运行。 如果不是,则它使用 -ExecutionPolicy 参数启动一个新的 PS 会话,并将脚本作为命令行参数 (-Command) 传递。

这段 powershell 代码使用返回码与 .CMD 文件进行通信。 对不起,它很神秘,但命令行参数的长度是有限的。 这是代码:

set scr=       $mp=[diagnostics.process]::getcurrentprocess().id
set scr=%scr%; $pp=([wmi]\"win32_process.handle='$mp'\").parentprocessid
set scr=%scr%; $gp=([wmi]\"win32_process.handle='$pp'\").parentprocessid
set scr=%scr%; $ep=[int][microsoft.powershell.executionpolicy](get-executionpolicy)
set scr=%scr%; try {$pnp=1-[int](([wmi]\"win32_process.handle='$gp'\").Name -eq \"powershell.exe\")
set scr=%scr%; } catch {$pnp=1}
set scr=%scr%; $ev = (8 * $pnp + $ep) -band 0xB; %wo% pp: $pp gp: $gp ev: $ev; if ($ev -le 1) {
set scr=%scr%    %wo% Launching within existing powershell session...`n;
set scr=%scr%    $w=new-object -com wscript.shell;$null=$w.appactivate($gp);

set scr=%scr%;   $w.sendkeys(\"^&{{}`$st =cat "%me%";`$sc=`$st -join [char]10 -split 'rem PS script';
set scr=%scr%     `$script:myArgs = `\" %*`\";`$sb=[scriptblock]::create{(} `$sc[3]{)};. `$sb{}}~\")
set scr=%scr%; }
set scr=%scr%; exit $ev
powershell -noprofile -Command %scr%

%wo% 是允许调试这个“检查脚本”。 如果调试在 %wo% 设置为write-host 否则,它被设置为定义一个“空”函数,然后调用空函数。 null 不执行任何操作,因此不会输出作为函数参数的消息。

请注意调用 SendKeys 时的转义。 ^ 是 CMD.EXE 转义字符,SendKeys 有自己的转义机制,PS 也是如此。

如果从 PS 运行,由于 SendKeys,您最终会进入 PS 会话。 否则批处理文件会这样做:

set scr=       ren function:prompt prompto
set scr=%scr%; function prompt{ 'myApp: '+(prompto)}
set scr=%scr%; $st= (cat %me%) -join \"`n\";
set scr=%scr%; $sx=($st -split 'rem PS script')
set scr=%scr%; $sc=$sx[3]
set scr=%scr%; %wo% myArgs: $myArgs script length: $sc.length 
set scr=%scr%; ^&{$script:myArgs=\"%*\"; iex $sc}

title MyApp
rem Change the number of lines on the console if currently set to 25
for /f "tokens=2" %%i in ('mode con^|findstr Lines:') do if %%i LEQ 25 (mode con lines=50&color 5F)
powershell -noexit -noprofile -command "%scr%"

这个“辅助脚本”也不能太长。 因此,辅助脚本读取原始 .CMD 文件,然后使用字符串“rem PS script”将其拆分。 该字符串将在此帮助程序脚本以及批处理文件中(将批处理文件语句与 PS 语句分开)。 在我的情况下,字符串也在批处理文件注释中,所以这就是使用索引 3 的原因。

您的 PS 脚本可以定义函数或模块。 你的 PS 脚本还可以输出一些介绍性信息,向用户解释如何开始、如何获得帮助或任何你想要的。

您的 PS 脚本不仅可以使用 PS 命令行,还可以创建自己的交互式环境(例如使用 Read-Host)。 但是我不想这样做,因为它会阻止有经验的 PS 用户使用他们的 PS 知识。 例如,如果您的脚本需要用户名/密码,则经验丰富的 PS 用户可以使用 get-credential 创建一个凭据以发送到您的脚本。

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM