Slow Windows shell performance using _hotkeys folder shortcuts for volume control - windows

I'm trying to create a native, global, focus-independent hotkey control for incrementing/decrementing/mute-toggling system volume on Windows, specifically W10, though I expect whatever solution we find will likely work back through 7 and 8/8.1 as well.
I have found this - How can I mute/unmute my sound from PowerShell - and it works a treat, from within a PowerShell window. Ok, but I need this Type to be persistent and global then?
I then created three files, -.ps1, +.ps1, and 0.ps1, which include the entire type definition from the linked post, and then a one liner each, as follows:
[Audio]::Volume = [Audio]::Volume - .2
[Audio]::Volume = [Audio]::Volume + .2
[Audio]::Mute = [Audio]::Mute -bxor 1
Technically, all that works, but running each one pops open a PS window for 50 milliseconds or so. That's ugly, but maybe unavoidable.
Then I found this, - How to run a PowerShell script without displaying a window? - to use PSRun.exe. Turns out that in no case could I get that to successfully execute any of these scripts. I used shortcuts (.lnk) with arguments and .cmd files, and only got compilation errors.
So I tried this - https://www.faqforge.com/windows/how-to-execute-powershell-scripts-without-pop-up-window/ - using a VBS helper to hide the window. That works too, but I'd rather not use VBS if possible.
I then created a folder, %homedrive%\Users\\AppData\Roaming\Microsoft\Windows\Start Menu_hotkeys, and put one shortcut each to the .ps1 files, and assigned Alt-F6, Alt-F7, and Alt-F8 to the shortcuts.
When I run one of the shortcuts by GUI clicking, it takes about 100 milliseconds for either the .vbs or the .ps1 directly. However, when running either shortcut via hotkey, it takes more than a second!
I imagine there might be two (or more) solutions:
Can I increase the performance of a Windows shell hotkey that runs a shortcut to a script file? I realize that call stack looks silly long for something that seems like it should be so simple of a task.
OR
Can I create a persistent PowerShell window and run scripts into it by use of a global, focus-independent hotkey?
I'd even entertain building a TSR that does nothing but silently awaits hotkeys for volume control, but that seems less "nice" than working this out with PowerShell.
And before you ask, it's not a performance issue from this hardware, I'm running W10x64 on an i7-7700K with 16GB of RAM and a 128GB M.2. Running 40 Firefox tabs and 25 applications gets me to about 20% CPU use and 40% RAM use.
Feel free to slap me around if this question already has a solid, functional answer and my Google-Fu just didn't find it. My searches turned up things from across the last 5 years, but nothing conclusive or properly functional.

Related

A blue window pops up randomly while using my laptop, it says windows power shell, should I suspect someone hacked into my laptop?

While I'm using my computer a blue window will pop up for a second then go away. The label said windows power shell, I've tried looking at the event viewer but I could not identify anything there since I'm a new user. What could be causing this?
Running windows 10
Sometimes installed programs open up command prompts to run services/init tasks, so its not completely unusual.
I've never seen it happen with powershell however.
it could be innocent and just a program you have installed running init behavior, but it could also be malicious.
the first thing to try is checking what programs are set to startup automatically. if there is a load of bloat, you could try turning off the unnecessary ones and see if it still happens.
but realistically the only real way forward is to get a good quality antivirus, and run a full system scan over your pc to double check. it wont give you 100% certainly as things could possibly get passed it, but realistically if it passes you should be fine

Continue batch script only after program has booted

I have a batch script (yes I know batch is awful, no I don't care) that checks my VM's on the local machine to the ones stored on my USB, if they're out of date, it updates them, then boots them. I use multiple machines at uni, so this makes it easier to ensure the VM I'm working on are always the latest.
When I open them like this;
PATH "%PROGRAMFILES%\VMware\VMware Workstation\"
START vmware.exe -x "%USERPROFILE%\Desktop\VMs\VM1\VM1.vmx"
START vmware.exe -x "%USERPROFILE%\Desktop\VMs\VM2\VM2.vmx"
START vmware.exe -x "%USERPROFILE%\Desktop\VMs\VM3\VM3.vmx"
It causes the VM's to open in separate windows, rather than tabs of the same window for easy switching.
The workaround I came up with is to boot the VMware program first, then when I open the .VMXs, they all open as tabs in the same window.
The problem is that the VMware program sometimes takes a long time to open. Similar to Photoshop's loading splashscreen, but instead with no visual indicator, VMware opens up to 20 seconds after the icon has been clicked, or it has been summoned with a script.
So finally, here is my question.
Is there a way to make a batch that waits for the program to open before continuing? I know by omitting START I can stop the batch until the program closes, but obviously this is useless for my purposes.
If all else fails, I may just have to include a 30 second timeout and hope it's enough.
I don't think there's any reliable way to do this.
If you have a program that you need to open and then wait for a certain state to change in the program before doing something else, that state could be set by any arbitrary operation running on any thread spawned by the application. There would be no way to know when the application had set that state unless you were able to somehow communicate with the program to query or be notified of its state.
Theoretically if you knew enough about what the program was doing internally you could monitor the thread count or file system accesses or something to determine roughly when it had changed to the desired state, but just using a timer would be much much simpler.

Supporting two shells in windows

I'd like to write my own (very simple) explorer.exe alternative that I could actively switch between without having to restart my computer.
Is it possible to run two shells simultaneosly (or to write a program that temporarily disables the current shell)?
If not, is it possible to stop explorer without it restarting itself, and have my shell start itself instead?
Edit
More info: I'd like to write a simple productivity tool for myself. I want to set up a very simple task manager that prevents me from starting/opening/using anything but a whitelisted set of applications I list ahead of time. Locking me into that set of apps for whatever time period I've set. If there's another (better) way to prevent people from shutting down my app, switching from my app (with alt-tab, etc) I'm all ears.
Note: I'm fine with the app/shell/whatever being escapable by restarting my computer. I just want to make it massively inconvenient to switch to being distracted, and I wanted to learn a bit more about the Windows API.
See this question for details about writing a shell.
No, there can only be one real shell process (SetShellWindowEx only works when there is no other shell process) WH_SHELL can be used by other processes and it might be enough for your needs (Maybe in combination with IShellExecuteHook)
When explorer.exe is started and it detects a different shell it will not display the taskbar, just a file browser window. Explorer also looks at the shell value in the registry IIRC. You might also want to look into the shift to exit trick.

Present a default window layout on startup in Windows 7

I have a Win7 PC in use as part of an experiment control system. The experiment in question uses 4 windows simultaneously, and I would like to find away to open, position and size these 4 windows with a script.
The script would run at start up, so that the newly booted PC presents the user with the four windows as default.
Obviously I can use a batch file in the startup folder to open windows and run applications, but is there a way to specify the layout of these windows?
Many thanks
Si
Assuming that you have access to a scripting language that supports making calls to Windows API functions it shouldn't be too hard. Otherwise I'd suggest writing a small executable in some language (at least any of C++, C# or VB.Net would all work fine) and have that do it.
You could use FindWindow, as described here, to find the windows and MoveWindow, as described here, to move them around.
I use an AutoHotkey script to set up all my environment (around 7 windows in 3 different virtual screens), works pretty well. You can set the location of windows etc.
I can use a batch file to open the apps, then run WiLMA to relocate them

What's the best way to stop multiple instances of a Windows app being launched?

Many Windows apps (like Skype or MSN for instance) don't let you start multiple instances, rather trying to run it a 2nd time just leaves the existing version running.
Is this typically done in some simple way - the start-menu shortcut is a 'wrapper' app around the main app - or is there some registry magic you can do to delegate the problem to Windows itself?
Specifically dealing with Win32 here (unmanaged C++) but happy to hear more general solutions as long as they are workable on Windows XP or later.
EDIT: this seems the best duplicate.
Named Mutex or similar OS-specfic named object. If it exists - app is running.
Lock file somewhere (in temporary directory, etc - create it on program start, remove on program end). Linux software frequently operates this way (some programs store PID in lockfile), but it isn't safe - if you suddenly lose power (electricity cut off), it is possible that lock file won't be deleted.
And you can always enum all running processes and try to find yourself.
There could be more ways to do it, but those are the first ones I could think of.
As far as i remember, there exist system-wide Mutexes. Set Mutex on first launch, if on launch already set, immediately exit.
Use CreateMutex() call an prepend the name with "Global\" should to the trick.
I just check to see if the process is already running: if it's not start the application, if it's already running bring the window to foreground. The check is done in the Main method.
I get the process name with System.Diagnostics.Process.GetCurrentProcess().ProcessName and check if it's already running System.Diagnostics.Process.GetProcessesByName(). If there are more than 1 processes focus the first of them and then exit.

Resources