我正在尝试创建一个在服务器上检测到新版本时会“自我更新”的脚本。最初的想法是,当检测到新版本时,下载文件,然后启动一个DOS批处理文件,只用新的文件覆盖原始的exe文件。我想,我可以使用sytem(启动update.bat)然后立即退出0; .bat文件等待几秒钟,然后尝试删除旧的exe。这个失败了,我猜是因为即使使用系统(启动...),新的“进程”实际上是同一个进程,这是正确的吗?有没有办法从Windows中的perl启动一个全新的进程,这将允许我删除.exe?或者有更好的方法吗?
谢谢, Eric Seifert
答案 0 :(得分:2)
请参阅Windows Restart Manager上的文档,这是Windows Vista中引入的API,用于管理重新启动的应用程序以及更新。
答案 1 :(得分:1)
有没有听说过java WebStart? PAR等效,PAR :: WebStart 基本上,您配置它,然后从受信任的网站下载实时代码
所以你的.exe只是PAR :: WebStart的前端,真实的程序从你的网站上下载
答案 2 :(得分:1)
我知道这是一个古老的问题,但我想我会把解决方案放在这里,因为我正在研究同样的事情。您的批处理是我的方式,但我所做的微小改动是使用exec()
而不是system()
,因为前者(根据this)“...执行系统命令并且永不返回“,这似乎释放了正在运行的进程。当使用Strawberry Perl运行解释的Perl文件时,以及使用PAR::Packer
运行已编译的程序时,这似乎都有效。
我创建了test.pl
,最终编译为test.exe
,如下所示:
#!/usr/bin/perl
use 5.10.0;
use strict;
use warnings;
my $batch_file = <<"BATCH";
rem ### IT IS SAFE TO DELETE THIS FILE ###
\@echo off
ping 127.0.0.1 -n 2 -w 1000 > nul
echo Copying over update file...
copy testfile.exe test.exe
BATCH
open my $fh, '>', 'update.bat';
print $fh $batch_file;
close $fh;
exec( 'update.bat' );
testfile.exe
是test.exe
的待机“升级”版本,只是为了确保我可以在test.exe
运行时覆盖它,我可以。 ping
是一种暂停2秒的方法,以确保在尝试覆盖文件之前进程有机会退出。
奇怪的是,创建的批处理文件update.bat
无法自行删除,即使批处理文件通常可以自行删除。如果我创建一个批处理文件:
start /b "" cmd /c del %0
它会自行删除而不会出现任何错误。但是,如果我在update.bat
中包含该代码段,则会抱怨The process cannot access the file because it is being used by another process.
我不确定原因。由于这在我的应用中并不是特别重要,我没有追求这一点。我只是留下update.bat
,并在下次更新时将其覆盖。但是我在文件中注明,如果有人在以后查看它,可以安全删除。