6

我想显示长时间运行的批次的气球通知。

我知道您可以显示弹出窗口(并且一些解决方案非常有想象力),但也有这个选项会很有趣。

有没有办法从批处理文件中显示气球通知?请至少从 Windows 7 开始,但也欢迎 XP。

我想至少需要一个托盘图标,但坦率地说,我不能走得更远。也许与rundll32.exe?我知道这不是从命令行执行任何操作的推荐方法

此知识库文章中记录了 rundll32.exe 调用的函数所需的函数签名。 这并没有阻止人们使用 rundll32 调用并非设计为由 rundll32 调用的随机函数,例如 user32 LockWorkStationuser32 ExitWindowsEx

但我发现Yaniv Pessach的这个RunAnyDll 实用程序似乎可以正确调用 .dll。不幸的是,我没有找到测试它的有效链接(不,它不在 Internet 档案中)。我写信给作者要他一份。让我们来看看。

(我什至不知道它是否有用,但它是一个有趣的实用程序。也许它可以使这个弹出问题的答案Run起作用。我认为框和命令行执行之间的区别与调用约定有关Raymond Chen 帖子中的内容。)

另一个无法找到的测试实用程序是已弃用的事件触发器,但我再次不确定它是否有帮助。

编辑以澄清:

npocmaka和greg zakharov答案都非常有趣。npocmaka的那个更接近我的要求,因为它会产生一个气球通知。greg zakharov使用了不同的技术,但其结果非常相似(在这种情况下,文本出现在鼠标指针位置)。我已经在 XP 中对它们进行了测试,并且都可以工作(安装了 .NET)。两者都有超时,我不知道如何在用户点击之前保留通知(以防万一用户不在但你想看到它)。

理想情况下,我的问题是关于得到这样的东西。

@echo off

echo Some long part job that goes well.

call :balloon "Report about above tasks" [optional parameters about icon, title, timeout, etc.]

echo More tasks but one fails
if errorlevel 1 call :balloon "Error this and that" [optional parameters]

echo This is the end of the tasks
goto :eof

:balloon

    echo If you don't want to make a temporary file
    echo then you must make one-liner calls to PowerShell, wscript or whatever.

exit /b

因此,作为混合脚本,我看到的缺点是在任何批处理中插入它一定非常困难。.exe如果要在批处理中重复使用多次,则为每个气球生成一个似乎不切实际,因此,最后,正如greg zakharov所说,只生成一个接受参数并重复使用它的 .exe 会更加健壮和灵活(就像notifu)。最后,我认为使用进行:balloon单行 powershell 调用的子例程是你能得到的最好的(在 XP 中几乎是原生的,因为你需要下载但你也需要 .net)。

4

4 回答 4

9

使用 PowerShell 单线

无需创建文件,无论执行策略是什么,它都可以工作。感谢Mark Dodsons我们展示了使用 PS 实现此目的的方法,并感谢 npocmaka提供图标列表。

另存为,例如,balloon.bat(当然,您可以将其作为子程序插入任何批处理中)。

@echo off

if "%~1"=="" call :printhelp  & exit /b 1
setlocal

if "%~2"=="" (set Icon=Information) else (set Icon=%2)
powershell -Command "[void] [System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); $objNotifyIcon=New-Object System.Windows.Forms.NotifyIcon; $objNotifyIcon.BalloonTipText='%~1'; $objNotifyIcon.Icon=[system.drawing.systemicons]::%Icon%; $objNotifyIcon.BalloonTipTitle='%~3'; $objNotifyIcon.BalloonTipIcon='None'; $objNotifyIcon.Visible=$True; $objNotifyIcon.ShowBalloonTip(5000);"

endlocal
goto :eof

:printhelp
echo USAGE: %~n0 Text [Icon [Title]]
echo Icon can be: Application, Asterisk, Error, Exclamation, Hand, Information, Question, Shield, Warning or WinLogo
exit /b

如果没有第二个参数,则默认为Information.

我想你可以使用mshtavbscript 或 javascript,但我直到现在都没有成功。

于 2018-06-28T09:33:21.107 回答
7

.bat这是一个带有硬编码值的 jscript.net/bat polyglot 脚本(必须另存为.NET 自 Windows Vista 以来默认安装在每台 Windows 机器上,因此它比 powershell 更向后兼容):

@if (@X)==(@Y) @end /* JScript comment
@echo off

setlocal
del /q /f %~n0.exe >nul 2>&1
for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d  /o:-n "%SystemRoot%\Microsoft.NET\Framework\*jsc.exe"') do (
   set "jsc=%%v"
)

if not exist "%~n0.exe" (
    "%jsc%" /nologo /out:"%~n0.exe" "%~dpsfnx0"
)

if exist "%~n0.exe" ( 
    "%~n0.exe" %* 
)


endlocal & exit /b %errorlevel%

end of jscript comment*/

import System;
import System.Windows;
import System.Windows.Forms;
import System.Drawing;
import System.Drawing.SystemIcons;

var notification;
try {
    notification = new System.Windows.Forms.NotifyIcon();


} catch (err){

}

notification.Icon = System.Drawing.SystemIcons.Hand; // Could be Application,Asterisk,Error,Exclamation,Hand,Information,Question,Shield,Warning,WinLogo
notification.BalloonTipText = "Message!!";
notification.Visible = true;
// optional - BalloonTipIcon = System.Windows.Forms.ToolTipIcon.Info;
// optional - BalloonTipTitle = "My Title",




// Display for 2 seconds.
notification.ShowBalloonTip(2000);
System.Threading.Thread.Sleep(2100);

notification.Dispose();

它将编译一个将被调用的小型可执行文件。如果您不想创建临时可执行文件,可以检查此处使用的 msbuild 技术(尽管这仅适用于 Windows 10)。我也可以创建一个参数化版本。

编辑: 这是一个带有命令行选项的工具:

call systemTrayNotification.bat   -tooltip warning -time 3000 -title "Woow" -text "Boom" -icon question
于 2018-06-19T14:40:03.953 回答
4

方法 1: LC.exe CMDLet
这个小 CMDlet(您可以从批处理文件中调用的便携式 .exe 文件)可以比较两个文件,并导出 txt 文档中第一个文件唯一的old.txt行和第二个文件唯一的行txt 命名new.txt的上下文是lc File1.txt File2.txt
这里是文件:1drv.ms/u/s!AlRLV33Rdz2CgrgeqSerXbeXyVhRYQ
方法 2: 批处理文件中的 Powershell 脚本

:notification
::Synax is call :notification [Title] [Body] [Icon]
echo notification: %1 %2 %3

echo [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") > notfy.ps1
echo $objNotifyIcon = New-Object System.Windows.Forms.NotifyIcon  >> notfy.ps1
echo $objNotifyIcon.Icon = "ico%3.ico" >> notfy.ps1
echo $objNotifyIcon.BalloonTipIcon = "None"  >> notfy.ps1
echo $objNotifyIcon.BalloonTipText = %2  >> notfy.ps1
echo $objNotifyIcon.BalloonTipTitle = %1 >> notfy.ps1
echo $objNotifyIcon.Visible = $True  >> notfy.ps1
echo $objNotifyIcon.ShowBalloonTip(10000) >> notfy.ps1

Powershell "& ""%cd%\notfy.ps1"""
del /f /q "notfy.ps1"
exit /b

只需将其添加到您的批处理文件并使用call :notification "Title" "Body" "Icon File"

注意调用它:此方法需要将 Powershell 执行策略设置为无限制(不是默认设置)。你可以用这个来测试:

powershell Get-ExecutionPolicy >pgep.t
Find "Unrestricted" "pgep.t" >nul
if %errorlevel%==0 goto setuphere
del /f /q pgep.t
:setuphere
::Start a Batch File as admin with the command [Powershell Set-ExecutionPolicy $POLICY -Force] in it. (remove the brackets).
于 2018-06-21T13:40:37.317 回答
3

有很多 hacky 方法可以实现既定目标。其中之一由npocmaka描述。请密切注意,PowerShell 也可以使用相同的方法(可以在此处找到如何组合 PowerShell 脚本的示例)。另一个可以生心的怪物(这个可以兼容WinXP)可以是CMD加WSH。

0</* :
@echo off
  setlocal
    echo Some batch code here...
    cscript /nologo /e:jscript "%~f0" "Warning!"
    pause
    echo Another batch code...
    cscript /nologo /e:jscript "%~f0" "All done!"
    pause
  endlocal
exit /b*/0;
(function(msg) {
   with (new ActiveXObject('Internet.HHCtrl')) {
      TextPopup(msg, 'Lucida Console, 23', 1, 1, 1, 1);
      WScript.Sleep(1500);
   }
}(
   WScript.Arguments.length !== 1 ?
   WScript.Quit(1) : WScript.Arguments.Unnamed(0)
));

请注意,我不强烈建议使用混合动力车和其他海默拉。我敢肯定,做你所问的最好方法是编写特殊的命令行工具。

于 2018-06-19T17:26:10.133 回答