Jump to content
Belini

Impedir que um programa seja fechado.

Recommended Posts

Estou precisando de algum comando/função que impeça o encerramento de um programa para que ele só seja encerrado por sí mesmo ou seja corretamente, o windows restringe o encerramento de vários programas escenciais dele e estes não conseguimos fechar pelo gerenciador, ProcessClose() e com nenhum outro método, tem como fazer isto com um script também?

Share this post


Link to post
Share on other sites

Belini, não sei te dizer exatamente o que fazer, mas tenho um palpite e você pode tentar pesquisar a respeito.

Talvez se você iniciar o processo com o usuário SYSTEM, vc obtenha o resultado que precisa... Se não me engano há um caminho para executar um processo como SYSTEM, porém o processo tem que ser executado na inicialização, antes do usuário ser autenticado no windows.... Eu lembro quando eu precisei fazer algo parecido em um pc que eu não sabia a senha de login, então substitui o executável das opções de acessibilidade pelo executável do cmd, daí quando aparecia a tela de logon, eu apertava shift 5x, aparecia o prompt e então eu executava o explorer ou criava uma credencial para acessar a máquina.. Enfim... Nesse caso o CMD era executado pelo System e acho que outro usuário não podia encerrar o programa..
Então imagino que você possa criar um programa que inicialize antes do logon e esse programa, aberto como system, seja sua ponte para rodar outro programa.. Hierarquicamente, qualquer programa que você abrir através dele, será aberto pelo usuário que executou ele, independente do usuário autenticado...

 

Bom, esse é meu palpite, só testando pra saber...

Share this post


Link to post
Share on other sites

Eu consegui algo parecido com isso:

* cria uma conta de usuário para esse programa ser executado.

Porém, se você precisar de interação, só por TCP-IP (acredito que PIPES também funcione).

 

Embora no fórum americano existe uma UDF bem legal do Guiness, para manter um aplicativo sempre se "auto-executando", mas as vezes tem como burlar e fechar.

 

Rodar o aplicativo como um serviço com a ajuda do nssm.exe funciona muito bem também, isso até evita que você tenha a complicação de escrever o script como serviço nativamente (funciona, mas é complicado).

Pensando bem, acho que até é melhor do que a primeira resposta.

Nisso é possível manter o aplicativo sempre se executando. Você fecha, ele se abre de novo...

 

Obs: trabalhar com o nssm.exe é bem facinho, se precisar de ajuda, grita, acho que até tenho uma UDF pra ele.

Edited by Luigi

Share this post


Link to post
Share on other sites

@antony-ag e @Luigi só reabrir o programa caso ele seja encerrado não resolve o problema pois o que eu preciso mesmo é que ele não seja fechado em momento algum pois se fechar e reabrir o que estiver sendo executado na hora será perdido, @Luigi se puder posta a UDF que falou para que eu possa fazer ums testes aqui.

Share this post


Link to post
Share on other sites

@Belini, isso realmente se parece com um aplicativo que eu fiz algum tempo atrás.

Eu fiz uma pesquisa por um bom tempo, e o melhor resultado que encontrei foi a primeira resposta, mas vou detalhar um pouco mais.

 

1. criar uma conta específica para executar esse aplicativo

2. esse deve rodar como um serviço (um serviço do nssm.exe já basta), como ele vai ser executado em uma conta específica não tem como alguém paralizá-lo, a não ser que se entre na conta e pare o serviço

3. rodar um script de AutoIt como serviço, se for pelo nssm.exe é fácil, se for pelas UDFs do fórum, é um pouco (bem) mais complicado, mas também funciona

4. existem categorias de serviço que são "UNSTOPABLE" (acho que é isso), mas não cheguei nesse ponto, pois o 3 item resolveu a minha vida

5. um serviço não possui interface gráfica, a forma mais eficaz que eu consegui interagir com o serviço, foi por TCP/IP na localhost, demorou um pouco pra pegar o jeito, mas funcionou bem

6. eu interagia com o serviço por um aplicativo-cliente, quando o usuário encerrava o aplicativo-cliente, o serviço se encarregava de iniciar o aplicativo-cliente novamente

7. existem outras formas de IPC (Inter Process Comunication, como: mail slot, pipes, etc) mas o servidor e o cliente necessitam ser executados na mesma conta.

8. no caso de cliente e servidor em contas diferentes, eu acho que a melhor forma é TCP (127.0.0.1) (se existe outra forma, gostaria de saber)

 

Bem, trabalhar com o NSSM.exe é fácil, no próprio site do desenvolvedor tem uma boa documentação.

Mas eu precisava de algo que permitisse o próprio AutoIt criar, iniciar, parar e remover serviços, então fiz essa UDF.

 

O que o AutoIt_Service vai fazer? Nada.

É apenas um script AutoIt compilado rodando como serviço para fins de exemplo.

 

Como ver se o serviço está rodando? services.msc e procure por AutoIt_Service

 

Se eu puder ser útil em algo mais, diga.

 

Comandos:

; instalar serviço

nssm_set("AutoIt_Service", "C:\nssm\AutoIt_Service.exe")

ConsoleWrite("nssm_install-> " & nssm_install() & @LF)

 

; paralizar um serviço

nssm_set("AutoIt_Service", "C:\nssm\AutoIt_Service.exe")

nssm_stop()

 

; remover serviço

nssm_set("AutoIt_Service", "C:\nssm\AutoIt_Service.exe")

nssm_stop()

nssm_delete()

 

; iniciar um serviço

nssm_set("AutoIt_Service", "C:\nssm\AutoIt_Service.exe")

nssm_start()

 

Antes de rodar a UDF, crie um diretório na unidade "C:\nssm"

 

Lá descompacte o nssm.exe de 32 bits baixado do site acima.

 

Compile o serviço como e nomei-o para "AutoIt_Service"

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Compression=4
#AutoIt3Wrapper_UseUpx=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
While Sleep(250)
WEnd

NSSM UDF

#include-once
#include <File.au3>
#include <Crypt.au3>
#include <AutoItConstants.au3>
#include <WinAPIDiag.au3>
#include <Array.au3>
#include <Process.au3>
#RequireAdmin

If Not IsDeclared("hCrypt") Then $hCrypt = _Crypt_Startup()
If Not $hCrypt Then $hCrypt = _Crypt_Startup()

OnAutoItExitRegister("__nssm_exit")

Global $sNssm_ServicePath, $sNssm_ServiceExe
Global Const $NSSM = nssm_exe()
Global $sNssm_ServiceName = "AutoIt_Service"
Global $cmd = 'nssm install ' & $sNssm_ServiceName & ' ' & $sNssm_ServicePath & $sNssm_ServiceExe & ''

#cs
; instalar serviço
nssm_set("AutoIt_Service", "C:\nssm\AutoIt_Service.exe")
ConsoleWrite("nssm_install-> " & nssm_install() & @LF)

; paralizar um serviço
nssm_set("AutoIt_Service", "C:\nssm\AutoIt_Service.exe")
nssm_stop()

; remover serviço
nssm_set("AutoIt_Service", "C:\nssm\AutoIt_Service.exe")
nssm_stop()
nssm_delete()

; iniciar um serviço
nssm_set("AutoIt_Service", "C:\nssm\AutoIt_Service.exe")
ConsoleWrite("  nssm_start-> " & nssm_start() & @LF)
#ce

Func nssm_unset()
	$sNssm_ServiceName = ""
	$sNssm_ServicePath = ""
	$sNssm_ServiceExe = ""
EndFunc   ;==>nssm_unset

Func nssm_set($sServiceName = "", $sServicePath = "")
	If Not $sServiceName Then Return SetError(1, 0, 0)
	$sNssm_ServiceName = $sServiceName
	If $sServicePath Then
		Local $sDrive, $sDir, $sFileName, $sExtension
		$sServicePath = StringReplace($sServicePath, "/", "\")
		While StringInStr($sServicePath, "\\")
			$sServicePath = StringReplace($sServicePath, "\\", "\")
		WEnd
		If Not FileExists($sServicePath) Then Return SetError(2, 0, 0)
		_PathSplit($sServicePath, $sDrive, $sDir, $sFileName, $sExtension)
		$sNssm_ServicePath = $sDrive & $sDir
		$sNssm_ServiceExe = $sFileName & $sExtension
	EndIf
EndFunc   ;==>nssm_set

Func nssm_delete()
	Local $status = nssm_query()
	If @error Then

	Else
		Switch $status
			Case "SERVICE_RUNNING"
				nssm_stop()
		EndSwitch
	EndIf

	Local $cmd = __nssm_pre_execute($NSSM & ' remove "' & $sNssm_ServiceName & '" confirm')
	Switch $cmd
		Case 'stop[Service "' & $sNssm_ServiceName & '" removed successfully!]'
			Return 1
		Case "Can't open service!"
			Return SetError(1, 0, 0)
	EndSwitch

EndFunc   ;==>nssm_delete

Func nssm_set_user_pass($user, $pass)
EndFunc

Func nssm_install()
	If Not $sNssm_ServicePath Or Not $sNssm_ServiceExe Then Return SetError(1, 0, 0)
	Local $cmd = __nssm_pre_execute($NSSM & ' install ' & $sNssm_ServiceName & ' "' & $sNssm_ServicePath & $sNssm_ServiceExe & '"')
	Switch $cmd
		Case 'Service "' & $sNssm_ServiceName & '" installed successfully!'
			Return 1
		Case 'stop[Error creating service!]'
			Return SetError(1, 0, 0)
		Case Else
			Return SetError(2, 0, 0)
	EndSwitch
EndFunc   ;==>nssm_install

Func __nssm_pre_execute($sInput = "")
	If Not $sInput Then Return SetError(1, 0, 0)
	Local $iPID = Run($sInput, @ScriptDir, @SW_HIDE, $STDERR_MERGED)
	Local $sOutput = ""
	While 1
		$sOutput &= StdoutRead($iPID, False, True)
		If @error Then ExitLoop
	WEnd
	$sOutput = (StringSplit(nssm_remove_cr(BinaryToString($sOutput, 2)), @LF, 2))[0]
	ConsoleWrite("__nssm_pre_execute[ " & $sOutput & " ]" & @LF)
	Return $sOutput
EndFunc   ;==>__nssm_pre_execute

Func nssm_start()
	Local $cmd = __nssm_pre_execute($NSSM & ' start ' & $sNssm_ServiceName & ' "')
	Switch $cmd
		Case $sNssm_ServiceName & ": START: " & _WinAPI_GetErrorMessage(1056)
			Return 1
		Case $sNssm_ServiceName & ": START: " & _WinAPI_GetErrorMessage(0)
			Return 1
		Case "Can't open service!"
			Return SetError(1, 0, 0)
		Case Else
			Return SetError(2, 0, 0)
	EndSwitch
EndFunc   ;==>nssm_start

Func nssm_stop()
	Local $cmd = __nssm_pre_execute('nssm stop "' & $sNssm_ServiceName & '"')
	Switch $cmd
		Case $sNssm_ServiceName & ": STOP: " & _WinAPI_GetErrorMessage(0)
			ConsoleWrite("foi paralizado" & @LF)
		Case "SERVICE_RUNNING"
			ConsoleWrite("está parado" & @LF)
	EndSwitch
EndFunc   ;==>nssm_stop

Func nssm_query()
	Local $cmd = __nssm_pre_execute('nssm status "' & $sNssm_ServiceName & '"')
	Switch $cmd
		Case "Can't open service!"
			Return SetError(1, 0, 0)
		Case "SERVICE_STOPPED"
			Return 1
		Case "SERVICE_RUNNING"
			Return 2
		Case Else
			Return SetError(2, 0, 0)
	EndSwitch
EndFunc   ;==>nssm_query

Func nssm_remove_cr($input)
	$input = StringReplace($input, @CRLF, @LF)
	Return StringReplace($input, @CR, @LF)
EndFunc   ;==>nssm_remove_cr

Func nssm_catch()

EndFunc   ;==>nssm_catch

Func nssm_exe($sInput = @ScriptDir)
	Local $iSearch = 0
	Local $aHash[2][2] = [ _
			["X86", "0xD9EC6F3A3B2AC7CD5EEF07BD86E3EFBC"], _
			["X64", "0xBECEAE2FDC4F7729A93E94AC2CCD78CC"] _
			]

	Local $arr = _FileListToArrayRec($sInput, "nssm*.exe", 1, 1, 0, 2)

	If IsArray($arr) And $arr[0] > 1 Then
		Local $aNew[UBound($arr, 1) - 1][3]
		For $ii = 1 To UBound($arr, 1) - 1
			$aNew[$ii - 1][0] = $arr[$ii]
			$aNew[$ii - 1][1] = __nssm_get_hash($arr[$ii])
		Next
		$iSearch = _ArraySearch($aNew, $aHash[_ArraySearch($aHash, @OSArch, 0, Default, 0, 0, 0, 0, False)][1], 0, UBound($aNew, 1) - 1, 2, 0, 0, 1, False)
		If @error Then
			MsgBox(0, "@error", "No NSSM.exe available")
			Exit
		Else
			Return $aNew[$iSearch][0]
		EndIf
	Else
		MsgBox(0, "@error", "No NSSM.exe available")
		Exit
	EndIf
EndFunc   ;==>nssm_exe

Func __nssm_get_hash($sInput = "")
	If Not $sInput Or Not FileExists($sInput) Then Return SetError(1, 0, 0)
	Return _Crypt_HashFile($sInput, $CALG_MD5)
EndFunc   ;==>__nssm_get_hash


Func __nssm_exit()
	If IsDeclared("hCrypt") And $hCrypt Then _Crypt_Shutdown()
EndFunc   ;==>__nssm_exit

Share this post


Link to post
Share on other sites

@Luigi não consegui fazer o teste ainda pois esta UDF pede vários includes que eu não tenho, vc tem aí os includes necessários para executar a UDF?

 

Por enquanto falta:

#include <AutoItConstants.au3>
#include <WinAPIDiag.au3>
#include "APIDiagConstants.au3"
#include "StringConstants.au3"
#include "WinAPI.au3"
#include "WinAPIFiles.au3"
#include "WinAPIInternals.au3"
#include "WinAPIProc.au3"
#include "WinAPIShellEx.au3"
#include "WinAPITheme.au3"
Edited by Belini

Share this post


Link to post
Share on other sites

@Luigi tá complicado mesmo testar esta UDF pois quando coloco os includes que estão sendo pedidos passa a faltar outros que estão relacionados nos includes que coloquei antes ou seja está igual a uma bola de neve!

Share this post


Link to post
Share on other sites

Só tem um detalhe ao executar um programa na conta SYSTEM: Não temos acesso ao desktop do usuário atual!

 

JS

  • Like 1

Share this post


Link to post
Share on other sites

Consegui executar na conta SYSTEM usando o psexec.exe só não sei ao certo se esta impedindo que o processo seja fechado ou se está reabrindo assim que ele fecha!

 

http://ss64.com/nt/psexec.html

https://technet.microsoft.com/en-us/sysinternals/bb897553.aspx

psexec.exe -i -s -d -accepteula "C:\testando.exe"
  • Like 1

Share this post


Link to post
Share on other sites

Não deu certo desta maneira também pois o psexec.exe só mantém o programa aberto se os 2 estiverem na raiz da unidade caso o programa que foi aberto esteja numa pasta mesmo constando no gerenciador como SYSTEM continua podendo ser fechado!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


×