Kill a program started as an admin without any extra input - autohotkey

I use OBS as a replay buffer on my machine. For that purpose it is always started when I log on. OBS also is started as an admin because the recording is choppy otherwise.
This setup generally works, the only problem is that OBS prevents my PC from going into sleep while the replay buffer is active. For this purpose I wanted to create a new shortcut that kills OBS and then sends my PC to sleep.
I created the following script, which is started with admin rights with the same task scheduler task that starts OBS.
RWin & Y::
Run, *RunAs cmd.exe taskkill /f /t /im "obs64.exe"
DllCall("PowrProf\SetSuspendState", "int", 0, "int", 1, "int", 0)
Return
However when I press RWin and Y OBS survives. I've tried a few solutions so far (that I sadly deleted and thus can't show), but they all either didn't kill OBS or required a seperate input (like confiriming that the script may change my computer).
Is there any way to reliably kill a programm that desperatly doesn't want to be killed?

If you run the AHK script as administrator the result should be successful.
if not A_IsAdmin{
Run *RunAs "%A_ScriptFullPath%"
ExitApp
}
LWin & Y::
Process, Close, obs64.exe
DllCall("PowrProf\SetSuspendState", "int", 0, "int", 1, "int", 0)
return

Related

Powershell script with response and no window?

I want to run a command in PowerShell and use the response in AutoHotkey. I have found a lot of information on how to run a PowerShell script, but none saying how I can use the response from it in AutoHotkey.
I have tried this:
MsgBox % ComObjCreate("WScript.Shell").Exec("powershell.exe -ExecutionPolicy Bypass -WindowStyle Hidden -noProfile -nologo dir").StdOut.ReadAll()
But this still flashes a window for a very brief time. I loop this command for every 25ms, so letting a window blink that often is not a valid solution.
Edit:
Ended up with this as the simplest solution:
cmd = powershell.exe -command "(Get-Process -Id " %pid% ").Threads[1].WaitReason"
shell := setup()
Loop {
string := shell.exec(cmd).stdout.readall()
...}
setup() {
detecthiddenwindows on
run %comspec% /k ,, hide useerrorlevel, pid
winwait ahk_pid %pid%,, 10
DllCall("AttachConsole", "uint", pid)
con := DllCall("CreateFile"
, "str", "CONOUT$", "uint", 0xC0000000, "uint", 7, "uint", 0, "uint", 3, "uint", 0, "uint", 0)
oshell := comobjcreate("wscript.shell")
return oshell
}
Note: Using AHK (AutoHotkey) with an external PowerShell process is ill-suited to a task that must run every 25ms, as you've discovered yourself - there's too much processing overhead.
If getting a directory listing is all that is needed, you can do that with built-in AHK features, using the Loop command for files - see this answer.
The solution below generally demonstrates how to run a console program:
hidden (no flashing windows)
synchronously (wait for it exit)
with its output captured
from AHK.
You can't use ComObjCreate("WScript.Shell").Exec() to run a console application hidden.
Conversely, while you can use RunWait to run hidden, you cannot use it to capture (console) output.
The workaround is to:
Use RunWait.
Add an output redirection to a (temporary) file to your console-program invocation.
Read that file's content with FileRead afterwards (and delete the temp. file).
; Get a temporary file path
tempFile := A_Temp "\" DllCall("GetCurrentProcessId") ".txt" ; "
; Run the console program hidden, redirecting its output to
; the temp. file (with a program other than powershell.exe or cmd.exe,
; prepend %ComSpec% /c; use 2> to redirect error output), and wait for it to exit.
RunWait, powershell.exe -ExecutionPolicy Bypass -WindowStyle Hidden -noProfile dir > %tempFile%,, Hide
; Read the temp file into a variable and then delete it.
FileRead, content, %tempFile%
FileDelete, %tempFile%
; Display the result.
MsgBox % content

What's the difference between Run command and commands in cmd?

I have the following script:
^!c::
Run stop
Return
Stop is configured to run a program via environment variables.
So if I open up cmd and type “stop” and hit enter the program opens as intended, even if I push winkey + R it does the same thing. However if I use the script with ctrl+alt+c. I do not get the same result.
Why is the script doing something different?
How can I change my script to behave the same way as if it was typed into cmd or winkey + R?
Simple:
run, %comspec% /c stop
Or if this doesn't work you could just start a cmd window and send it directly
run, %comspec% /k
WinWait, %comspec%
WinActivate
Send stop{Enter}
/c tells the console window to close after execution, /k lets it stay open
or you could use an COM object and even get the output.
objShell := ComObjCreate("WScript.Shell")
objExec := objShell.Exec(ComSpec " /c stop")
strStdOut := ""
while, !objExec.StdOut.AtEndOfStream
{
strStdOut := objExec.StdOut.ReadAll()
}
Update:
Without the run command at all:
SetTitleMatchMode, 2
send #r
WinWait, TITLE_OF_THE_RUN_WINDOW
WinActivate
send cmd{Enter}
WinWait, cmd.exe
WinActivate
WinGetTitle, title
Send stop{Enter}
WinWait, %title%,,, stop
WinClose,
TITLE_OF_THE_RUN_WINDOW replace this with the title of the window, which opens on Win+r. A windows cmd window has the command in its title while it gets executed. So we save the title of the command window, and wait for it to drop the command ("stop") and close it then.
UPDATE: Cmd window close added to solution 4

Spawn Child process in XP with Perl

I would like to spawn a child process in XP; for example:
system "start", "cmd.exe", "perl", "child.pl", "arg1";
When I run this, it tells me that "start doesn't exist." (Start works in Win 7).
When I run:
system "cmd.exe", "perl", "child.pl", "arg1";
The child process occurs in the same console as the parent process and upon completion the console session ends--so, I believe that the child simply takes over and the parent dies.
Normally, when I run these commands in Win 7, a new console appears and everything works fine.
When I type:
"start"
into the XP console, a new console appears--why can it find it then, but not when I call it from within a Perl script???
I've tried Win::Process and Win::Job to no avail: it still just kills the parent and starts the child, the whole tree dying upon completion.
Banging my head against this. Does anyone have a sure fire way to create an independent child process in XP (and not with fork).
Start is a built-in in cmd.exe, try system('cmd.exe /c "start perl child.pl arg1"').

Autohotkey script - taskkill.exe error on Windows shutdown

I am using lot of portable application locally on my laptop and if i leave some of them opened when i shutdown Windows it doesn't close them properly and some applications don't save their settings. I am trying to use taskkill option in a autohotkey script which will be executed on windows shutdown and will close properly opened portable application.
I am using this script:
#SingleInstance, force
#Persistent
DllCall("kernel32.dll\SetProcessShutdownParameters", UInt, 0x4FF, UInt, 0)
OnExit , closepgs
return
closepgs:
If (A_ExitReason="Shutdown" or A_ExitReason="Logoff")
{
Run, taskkill.exe /F /IM uTorrent.exe
}
ExitApp`
But when i shutdown Windows i receive this taskkill.exe error:
"Application failed to initialize properly (0xc0000142). Click on OK to terminate the application"
If i use the taskkill code outside the script like this it works fine:
^!Home::
Run, taskkill.exe /F /IM uTorrent.exe
But if i use it inside the script i receive taskkill.exe error.
Any idea why this error happening?
I have Windows XP Pro SP3.
Use Process, Close instead of taskkill.exe:
Process, Close, uTorrent.exe
It seems that as of Windows Vista and later, processes aren't allowed to spawn new processes during the shutdown phase. The only source a quick web search yielded was this one.
On a different note, using native functionality instead of calling programs is almost always preferable. Especially when using AHK, I recommend always looking for a built-in function to start with.

VBScript hangs when launching batch file with WShell.Script Run

During an install of PostgreSQL 9.1.2 on my Windows 7 64-bit Home Premium box, the installation hung. After a long furious search I discovered the problem was that an installer VB Script was hung waiting for a batch file to complete in a hidden window.
I isolated the problem to the following line of code:
Dim objShell
Set objShell = WScript.CreateObject("WScript.Shell")
objShell.Run "hello.bat", 1, True
(where 1 sets WindowStyle to Visible and True waits for completion). The Run call had launched the command prompt but was not executing the batch file. Thus, it would never complete.
I solved the problem by launching cmd.exe instead of the batch file directly, according to numerous online sources:
objShell.Run "%COMSPEC% /c hello.bat", 1, True
Since the fix is buried in the PostgreSQL installer (and I've submitted a bug report), I can only work around the problem unless the installer is modified.
But my main questions are:
Why does the first call hang?
Why use %COMSPEC% instead of calling the batch directly?
In regards to #2, could this be because executing a .bat directly makes an assumption that the default action associated with a .bat file is to execute it? I've in the past (on other machines) changed this default action to 'Edit'. And if I'd done that, I would have hung the PostgreSQL installer as well! (I imagine)
The batch file executes normally on other machines. So there is something weird on this one laptop. So in regards to #1, I need to figure out why this one laptop is different. I should note that there are some weird behaviors with batch files on this machine (one which I just noticed):
The context menu actions contain only "Open" and are missing "Edit", "Run", "Run As"
Double-clicking a batch file opens a command prompt but does not execute the batch file
I just noticed #2 while writing this. Clearly the default action for .bat is messed up. Yesterday I nearly bricked my computer removing Context Menu Handlers from my registry as recommended by several sites trying to restore my "Edit", "Run", etc. entries.
Any advice on questions 1 and 2 would be appreciated.
Thanks,
Eric
The problem was an HKCU override on .bat which created an association to cmd.exe, as noted on this wonderful post. Additional help was found here.
My registry looked like this:
HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.bat
\OpenWithList
(Default) REG_SZ (value not set)
a REG_SZ NOTEPAD.EXE
MRUList REG_SZ a
\OpenWithProgids
(Default) REG_SZ (value not set)
batfile REG_NONE (zero-length binary value)
\UserChoice
(Default) REG_SZ (value not set)
Progid REG_SZ (Applications\cmd.exe)
Removing the entire .bat entry fixed everything. All context menu items were restored properly (Open, Edit, Print, Run as Administrator, and Troubleshoot Compatability) and double clicking on the batch file executed the batch.
The .bat key re-generated automatically sometime after I deleted it and double-clicked my test batch file. This automatically generated entry was:
HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.bat
\OpenWithList
(Default) REG_SZ (value not set)
\OpenWithProgids
(Default) REG_SZ (value not set)
batfile REG_NONE (zero-length binary value)
Ultimately it was the \UserChoice key that was causing my problem. So I'm all cleared up now. My test scripts run properly and I re-installed PostgreSQL from scratch and the install went smoothly.
E
The 1st call launches a window that remains open until something tells it to close. Prsumably hello.bat terminates with an EXIT command, which would of course close the window, and your installation can then continue on its way.
But hello.bat fails to run on your one machine, so of course the window never closes, and your installation hangs.
The 2nd call through %COMSPEC% is opening a window and running CMD.EXE with the /C "command" option. The specifiation for the /C option states that CMD.EXE will terminate once the "command" completes (or fails). Your "command" is "hello.bat". Closure of the window is no longer dependent on an EXIT command in the hello.bat file. The window will close even if hello.bat fails to run.