Detect when Win10 is headless and run BAT file - automation

I want to launch "D:\Programmi\usbmmidd(virtual-screen)\$-SCREEN-ADD.bat" when there are no physical or virtual screens.
I've tried with AutoHotKey, since I already can trigger run $-SCREEN-ADD.BAT with a hotkey.
This is what I have. (I don't need the automation to use AHK, it's just what I'm most familiar with.)
OnMessage(0x219, "MsgMonitor")
MsgMonitor(wParam, lParam, msg)
{
SysGet, MonitorCount, MonitorCount
if (MonitorCount<1) {
run "D:\Programmi\usbmmidd(virtual-screen)\$-SCREEN-ADD.bat"
}
}

WORKING SOLUTION:
; ►►►►►►►►►►►►►► 𝐊𝐄𝐄𝐏 𝐎𝐍 𝐓𝐎𝐏 ◄◄◄◄◄◄◄◄◄◄◄◄◄◄◄
OnMessage(0x219, "MsgMonitor")
MsgMonitor(wParam, lParam, msg)
{
SysGet, MonCount, MonitorCount ;► num of screens
SysGet, W1, 78 ;► width of all the screens
SysGet, H1, 79 ;► height of all the screens
if (MonCount=1 and W1=640 and H1=480) {
run "D:\Programmi\usbmmidd(virtual-screen)\$-SCREEN-ADD.bat"
}
}
; ►►►►►►►►►►►►►► 𝐊𝐄𝐄𝐏 𝐎𝐍 𝐓𝐎𝐏 ◄◄◄◄◄◄◄◄◄◄◄◄◄◄◄
; PUT HERE YOUR OTHER SCRIPTS IF NEEDED
DESCRIPTION: the script runs with any change in hardware. It adds a virtual screen (by running $-SCREEN-ADD.bat) whenever it detects only 1 screen with a resolution of 640x480, which is what Windows thinks it has when it has no physical or virtual monitors connected.
NOTE: this script has to be in the top of the file, which is the auto-execute portion. More info on the script in this thread on the AutoHotKey forum.

Related

At which address is qemu expecting to find the image?

I'm working with the qemu riscv32 emulator. I have managed to boot a simple hello-world image I have got from github, however I haven't managed to boot my own image. I suspect this is because I built my image without a linker script, therefore it is being loaded at the wrong address. I'm trying to understand how the qemu boot sequence works to fix this.
This is the linker script I'm using
OUTPUT_ARCH( "riscv" )
OUTPUT_FORMAT("elf32-littleriscv")
ENTRY( _start )
SECTIONS
{
/* text: test code section */
. = 0x20400000;
.text : { *(.text) }
/* gnu_build_id: readonly build identifier */
.gnu_build_id : { *(.note.gnu.build-id) }
/* rodata: readonly data segment */
.rodata : { *(.rodata) }
/* data: Initialized data segment */
. = 0x80000000;
.data : { *(.data) }
.sdata : { *(.sdata) }
.debug : { *(.debug) }
. += 0x1000;
stack_top = .;
/* End of uninitalized data segement */
_end = .;
}
And this is the qemu command I'm executing:
qemu-system-riscv32 -nographic -machine sifive_e -bios none -kernel hello
# with -s -S when debugging
The source code is not very relevant, it is just a small assembly file that writes "hello".
My main question is:
How can I know at which address is qemu expecting to find the image?
Other questions I would like to answer:
With gdb, I have noticed that qemu starts executing at address 0x1004 (before me doing anything). I was expecting it to be 0x0. Why is this?
I have read hat qemu can use U-boot. Does it use it, or any other bootloader, by default?
If so, is there any way to load an image at address 0x0 without any sort of bootloader intervening? (I ask this for debugging purposes, because the first time you try a new arch. possibly yo want to keep everything as simple as possible)
Does the kernel option just load the provided image, or does it something more? (like loading a Linux kernel and execute the provided image on top of it)
I'm using the sifive_e emulator, therefore I have gone to the SiFive E series datasheet (like this one ) to check the memory map, and find the starting address. This is what I have found:
Those address are very different from those specified in the linker script above. It seems I'm looking at the wrong place, where can I found the SiFive E boot address?
EDIT
With regards to the last question about the memory map, I found the answer. It is explained here (5.16) and here (chapter 6)

UMDF PnP Driver creates no trace logs

Im trying to create trace log messages for this Idd Sample Driver. I am following this document.
I add WPP_INIT_TRACING(pDriverObject, pRegistryPath) to the DriverEntry, and WPP_CLEANUP(pDriverObject)to the EvtCleanupCallback.
_Use_decl_annotations_
void DriverContextCleanup(WDFOBJECT DriverObject)
{
UNREFERENCED_PARAMETER(DriverObject);
DoTraceMessage(MYDRIVER_ALL_INFO, "Tracing Fini Success");
WPP_CLEANUP(WdfDriverWdmGetDriverObject(DriverObject));
}
_Use_decl_annotations_
extern "C" NTSTATUS DriverEntry(
PDRIVER_OBJECT pDriverObject,
PUNICODE_STRING pRegistryPath
)
{
WDF_DRIVER_CONFIG Config;
NTSTATUS Status;
WDF_OBJECT_ATTRIBUTES Attributes;
WDF_OBJECT_ATTRIBUTES_INIT(&Attributes);
Attributes.EvtCleanupCallback = DriverContextCleanup;
WDF_DRIVER_CONFIG_INIT(&Config,
IddSampleDeviceAdd
);
WPP_INIT_TRACING(pDriverObject, pRegistryPath);
DoTraceMessage(MYDRIVER_ALL_INFO, "Tracing Init . . .");
Status = WdfDriverCreate(pDriverObject, pRegistryPath, &Attributes, &Config, WDF_NO_HANDLE);
if (!NT_SUCCESS(Status))
{
DoTraceMessage(MYDRIVER_ALL_INFO, "Tracing Init Failed");
WPP_CLEANUP(pDriverObject);
return Status;
}
DoTraceMessage(MYDRIVER_ALL_INFO, "Tracing Init Success");
return Status;
}
I add some DoTraceMessage() calls with a flag of MYDRIVER_ALL_INFO to the DriverEntry and DeviceEntry.
NTSTATUS IddSampleDeviceD0Entry(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState)
{
UNREFERENCED_PARAMETER(PreviousState);
// This function is called by WDF to start the device in the fully-on power state.
DoTraceMessage(MYDRIVER_ALL_INFO, "Tracing Device Entry");
auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(Device);
pContext->pContext->InitAdapter();
return STATUS_SUCCESS;
}
I make sure WPP Tracing is set to YES in the properties of the project.
The project builds, I go into TraceView and open the IddSampleDriver.PDB file, I set the level to verbose, and check all of the flags. I verified that it has the trace stuff it needs. Since if I open the IddSampleApp.PDB file, it fails.
I install the driver after enabling TestSigning and installing with pnputil -a ./x64/Debug/IddSampleDriver/IddSampleDriver.inf, run the sample app, the driver spins up 3 virtual monitors in the Display Settings. I then exit the app, and the monitors disappear. Everything seems to be functional. The problem is there is no traces in TraceView.
I have tried using tracelog, following this. Still nothing.
I have tried using logman, following this. Still nothing.
I am at my wits end. I spent all last week on this, Trying every possible avenue to get my trace messages to appear.
Either I followed every one of these instructions with no success. Either I somehow messed up every single one of them, or I am missing something else that I need to do in order to view these traces.
Additional Info:
Trace.h was left untouched
Targeting x64, Debug. Running on build machine. Win10.
CTL file I used:
b254994f-46e6-4718-80a0-0a3aa50d6ce4 MyDriver1TraceGuid
Basic process I used (tracelog as example):
tracepdb -f .\x64\Debug\IddSampleDriver.pdb
tracelog -start TestTraceIDD -guid .\guid.ctl -f testTrace.etl -flag 0xff
pnputil -a .\x64\Debug\IddSampleDriver\IddSampleDriver.inf #install driver
.\x64\Debug\IddSampleApp.exe #create software device and attach driver to it
<exit app>
tracelog -stop TestTraceIDD
tracefmt.exe .\testTrace.etl -p . -o test.out```
pnputil -d oem20.inf -f #uninstall driver
Solved my problem. I wasnt actually installing my driver, since it was still installed from the first time I installed it, so it was always using that driver instead of my new one with WPP enabled. I was installing and uninstalling the driver with pnputil.
I was doing pnputil -d oem20.inf -f for example to uninstall the driver. This is BAD. I have learned now that force deleting a driver does nothing. The reason I was force deleting was because it wouldnt delete when i still had a device, even though i would exit the sample app.
So what you have to do in order to properly delete the driver is enumerate the devices with pnputil, remove the ones that use your driver, then delete the driver. This allows a proper fresh driver installation.

Why don't all the shell processes in my promises (start blocks) run? (Is this a bug?)

I want to run multiple shell processes, but when I try to run more than 63, they hang. When I reduce max_threads in the thread pool to n, it hangs after running the nth shell command.
As you can see in the code below, the problem is not in start blocks per se, but in start blocks that contain the shell command:
#!/bin/env perl6
my $*SCHEDULER = ThreadPoolScheduler.new( max_threads => 2 );
my #processes;
# The Promises generated by this loop work as expected when awaited
for #*ARGS -> $item {
#processes.append(
start { say "Planning on processing $item" }
);
}
# The nth Promise generated by the following loop hangs when awaited (where n = max_thread)
for #*ARGS -> $item {
#processes.append(
start { shell "echo 'processing $item'" }
);
}
await(#processes);
Running ./process_items foo bar baz gives the following output, hanging after processing bar, which is just after the nth (here 2nd) thread has run using shell:
Planning on processing foo
Planning on processing bar
Planning on processing baz
processing foo
processing bar
What am I doing wrong? Or is this a bug?
Perl 6 distributions tested on CentOS 7:
Rakudo Star 2018.06
Rakudo Star 2018.10
Rakudo Star 2019.03-RC2
Rakudo Star 2019.03
With Rakudo Star 2019.03-RC2, use v6.c versus use v6.d did not make any difference.
The shell and run subs use Proc, which is implemented in terms of Proc::Async. This uses the thread pool internally. By filling up the pool with blocking calls to shell, the thread pool becomes exhausted, and so cannot process events, resulting in the hang.
It would be far better to use Proc::Async directly for this task. The approach with using shell and a load of real threads won't scale well; every OS thread has memory overhead, GC overhead, and so forth. Since spawning a bunch of child processes is not CPU-bound, this is rather wasteful; in reality, just one or two real threads are needed. So, in this case, perhaps the implementation pushing back on you when doing something inefficient isn't the worst thing.
I notice that one of the reasons for using shell and the thread pool is to try and limit the number of concurrent processes. But this isn't a very reliable way to do it; just because the current thread pool implementation sets a default maximum of 64 threads does not mean it always will do so.
Here's an example of a parallel test runner that runs up to 4 processes at once, collects their output, and envelopes it. It's a little more than you perhaps need, but it nicely illustrates the shape of the overall solution:
my $degree = 4;
my #tests = dir('t').grep(/\.t$/);
react {
sub run-one {
my $test = #tests.shift // return;
my $proc = Proc::Async.new('perl6', '-Ilib', $test);
my #output = "FILE: $test";
whenever $proc.stdout.lines {
push #output, "OUT: $_";
}
whenever $proc.stderr.lines {
push #output, "ERR: $_";
}
my $finished = $proc.start;
whenever $finished {
push #output, "EXIT: {.exitcode}";
say #output.join("\n");
run-one();
}
}
run-one for 1..$degree;
}
The key thing here is the call to run-one when a process ends, which means that you always replace an exited process with a new one, maintaining - so long as there are things to do - up to 4 processes running at a time. The react block naturally ends when all processes have completed, due to the fact that the number of events subscribed to drops to zero.

unable to use f_read() and f_lseek() in Fatfs

I'm trying to connect to a 2GB sd card class 6 with stm32f091cctx MCU via SPI. Using fatFs library ver. R0.13a I'm able to mount the drive and open the file with f_mount and f_open functions. But when it comes to reading from file, it just freezes somewhere in f_read function. Also when I try to change the position of pointer with f_lseek, again it freezes. f_lseek works only when I write it as: f_lseek(&MyFile, 0).
This part of my code is as below:
if(FATFS_LinkDriver(&SD_Driver, SDPath) == 0)
{
f_mount(&SDFatFs, (TCHAR const*)SDPath, 1);
f_open(&MyFile, "SAMPLE1.WAV", FA_READ);
f_lseek(&MyFile, 200);
f_read(&MyFile, rtext, 1000, (UINT*)&bytesread);
}
You are probably run out of heap size and go to HardFault exception.
You can increase HEAP size from CubeMX -> Project Setting or directly from **_startup.s file.
PS: Print something in HardFault_Handler and Error_Handler function to see when something goes wrong.

ERROR_INVALID_PRINTER_NAME returned by OpenPrinter() in Windows 8 when executed under "SYSTEM" account

My application deletes virtual printer when user uninstalls the application.
Application's installation and Uninstallation can be done using user interaction(wizard) or by setting group policy in Windows server 2003(domain admin sets the policy in server and the domain user in client PC need to update the group policy and restart the Client PC for installation or uninstallation of the application).
The follwing code in the application deletes printer and printer driver when uninstalling the application.
void CPrinterDriver::DeletePrinterIfExists()
{
// Delete old printer driver if existing
ControlSpoolService(TRUE);
HANDLE hPrinter = NULL;
PRINTER_DEFAULTS pDefaults = { NULL, NULL, PRINTER_ALL_ACCESS };
// Ignore error codes
OpenPrinter(m_driverInfo.pName, &hPrinter, &pDefaults);
if (hPrinter)
{
// deleting jobs
SetPrinter(hPrinter, 0, NULL, PRINTER_CONTROL_PURGE);
// Delete printer
DeletePrinter(hPrinter);
// Get printer driver name and delete it
DWORD dwNeeded = 0;
GetPrinter(hPrinter, 2, NULL, 0, &dwNeeded);
if (dwNeeded)
{
PRINTER_INFO_2 *pi2 = (PRINTER_INFO_2 *)GlobalAlloc(GPTR, sizeof(PRINTER_INFO_2)*dwNeeded);
if (pi2)
{
GetPrinter(hPrinter, 2, (LPBYTE)pi2, dwNeeded, &dwNeeded);
DeletePrinterDriver(NULL, NULL, pi2->pDriverName);
GlobalFree(pi2);
}
}
ClosePrinter(hPrinter);
}
}
The above code works well in Windows 7 in both cases(user interactive installation and using group policy) of uninstallation. In Windows 8, it works well using user interactive installation and uninstallation.
But in Windows 8 the above OpenPrinter() is returing ERROR_INVALID_PRINTER_NAME.
We found that the OpenPrinter() is called using the "SYSTEM" account.
Kindly help.
We found that during system startup, group policy is trying to uninstall the printer before the available printers list in the PC is populated (list is populated under the below registry key.If the list is not populated the below key does not exists).
"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Printers"
Hence we added delay of 2 minutes(not less than 2 mins) before calling openPrinter().
After the delay the registry key exists and the OpenPrinter() succeeded.
Thus we are able to uninstall the printer.
Note: Microsoft claims that Windows 8 boot time is reduced to 7 secs for certain supported hardware. But inserting delay of 2 mins degrades the boot performance of the Windows 8 PC.
For more details regarding the improvement in the boot time of Windwos 8 OS please refer the below link.
http://blogs.msdn.com/b/b8/archive/2012/05/22/designing-for-pcs-that-boot-faster-than-ever-before.aspx
Hence delay of 2 mins can be terated as a workaround.
Need to check the behaviour in the Windows 8 OS release after 10/26.
If you suffer from the issue where:
the registry key for the shared (network) printer is missing and
the API gives you the invalid printer name error
Then you can try opening the printer by its full UNC path.
So when opening MYPRINTER does not work, then open it as \\MYSERVER\MYPRINTER .
Of course this still assumes that you can already print to this printer normally from other applications!