Why does powershell console incorrectly size my GUI form? - forms

I want to open a powershell GUI Form of a specific size on a Windows 11 screen of 1920 x 1080 pixels. The system scaling in Settings is set to 125%. This cannot be an unusual configuration.
As a test, I try to open a form that is a quarter of the screen in size, as follows:
Add-Type -AssemblyName System.Windows.Forms
$form = New-Object System.Windows.Forms.Form
$form.width = 960
$form.height = 540
$GuiResponse = $Form.ShowDialog()
The problem is simple - this works perfectly in the Powershell ISE, but I cannot get it to work in the Powershell Console because the window is always significantly larger than it should be - I think because the console is performing some sort of reverse scaling.
I can of course do my own scaling and make the window proportionally smaller so that it is the right size when run from the console - but there's an additional associated issue in that any text written to the window is smudgy as it is being inappropriately scaled (at a guess).
There has been some discussion about this type of issue on Stack Overflow and elsewhere, but nothing I've tried resolves this. Yet it seems such an elementary problem, it surely has a simple solution?

You can make your Windows Form DPI Aware via P/Invoke by calling the SetProcessDPIAware function:
Add-Type -AssemblyName System.Windows.Forms
Add-Type -TypeDefinition '
public class DPIAware {
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern bool SetProcessDPIAware();
}
'
[System.Windows.Forms.Application]::EnableVisualStyles()
[void] [DPIAware]::SetProcessDPIAware()
$form = [System.Windows.Forms.Form]#{
Width = 960
Height = 540
}
$form.ShowDialog()
See Setting the default DPI awareness for a process for more relevant information.
If you would like to call the newer function SetProcessDpiAwarenessContext which is the one recommended in the MS Docs but do note this is compatible starting from Windows 10, version 1607, here is how the implementation would look:
Add-Type -TypeDefinition '
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
public class DPIAware {
public static readonly IntPtr UNAWARE = (IntPtr) (-1);
public static readonly IntPtr SYSTEM_AWARE = (IntPtr) (-2);
public static readonly IntPtr PER_MONITOR_AWARE = (IntPtr) (-3);
public static readonly IntPtr PER_MONITOR_AWARE_V2 = (IntPtr) (-4);
public static readonly IntPtr UNAWARE_GDISCALED = (IntPtr) (-5);
[DllImport("user32.dll", EntryPoint = "SetProcessDpiAwarenessContext", SetLastError = true)]
private static extern bool NativeSetProcessDpiAwarenessContext(IntPtr Value);
public static void SetProcessDpiAwarenessContext(IntPtr Value) {
if (!NativeSetProcessDpiAwarenessContext(Value)) {
throw new Win32Exception();
}
}
}
'
[DPIAware]::SetProcessDpiAwarenessContext([DPIAware]::PER_MONITOR_AWARE_V2)

Related

VTI71.DLL Give error du0x80004005 in c# project

I am try to automate Gupta's Team Developer control as mention in
Centura Gupta Team Developer Automation Possibility
I download 32-bit trial version of Team Developer 7.1
[DllImport("user32.dll")]
static extern IntPtr WindowFromPoint(System.Drawing.Point p);
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern long GetClassName(IntPtr hwnd, StringBuilder lpClassName, long nMaxCount);
const string guptadllpath = #"C:\program files (x86)\gupta\team developer 7.1\VTI71.DLL";
[DllImport(guptadllpath)]
extern static int VisTblFindString(IntPtr hwndTable, int lStartRow, IntPtr hwndColumn, string lpctszSearchFor);
IntPtr _wndFromPoint;
private void MainForm_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
Cursor.Current = Cursors.Default;
Point p = PointToScreen(e.Location);
_wndFromPoint = WindowFromPoint(p);
StringBuilder classText = new StringBuilder(256);
GetClassName(_wndFromPoint, classText, 256);
listBox1.Items.Add("Class: " + classText);
int a = VisTblFindString(_wndFromPoint, 0, IntPtr.Zero, "Pat");
this.Text = a.ToString();
}
}
But give me below error:
System.Runtime.InteropServices.SEHException (0x80004005): External component has thrown an exception.
My sample application is
Please suggest me how to resolve this error. Is it correct way to use Gupta's dll in c# for automate?
Thanks,
Calling VisTblFindString(..) from outside won't work. Even though the function takes a window handle as a parameter this will only work from inside the "grid-application". The reason is that one process cannot peek into the memory of another process (ok you can use GetWindowText(..) but this is not applicable here since in a grid not every cell is a distinct window).
You have to set up some interprocess-communication. Unfortunately in gupta grid there are no built-in functions that support this.
The only way I see is that you have to modify the grid-application (not sure if you control the source code of it). If you have the possibility to modify it then you can implement automation e.g. via Windows messages.
I dont know c# from a bar of soap - but if you are using the dll outside of TeamDeveloper, it could be the way you have imported it , or you haven't registered the dll, or you dont have a license to use it outside of TeamDeveloper , or you should be using the 64bit version. A Trial license may not cut it. But I'm just guessing here.

Correct way to bring window to foreground

I have the code below which is "supposed" to bring an application (in this case, VMware View) to the foreground/activate it.
However, this only seems to work if the window is minimized. If it is maximized or if any other window is already activated while it is maximized, it does not seem to do anything at all.
# Restore VMware View window
$sig = '[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);'
Add-Type -MemberDefinition $sig -Name NativeMethods -Namespace Win32
Get-Process -Name vmware-view
$hwnd = #(Get-Process vmware-view)[0].MainWindowHandle
[Win32.NativeMethods]::ShowWindowAsync($hwnd, 4)
You are passing 4 as the second parameter to ShowWindowAsync, its documents point to the ShowWindows function for a definition of the second parameter. This defines 4 (SW_SHOWNOACTIVATE) as:
Displays a window in its most recent size and position. This value is similar to SW_SHOWNORMAL, except that the window is not activated.
Note the last clause.
I think you want to be using SetForegroundWindow.
This is what worked:
Add-Type #"
using System;
using System.Runtime.InteropServices;
public class SFW {
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
}
"#
$fw = (get-process vmware-view).MainWindowHandle
[SFW]::SetForegroundWindow($fw)
The definition of a nCmdShow of 4 (SW_SHOWNOACTIVATE) is:
Displays a window in its most recent size and position. This value is
similar to SW_SHOWNORMAL, except that the window is not activated.
And AFAIK all other nCmdShow types don't put any Window on top.
I would used SetWindowPos instead:
$User32 = Add-Type -Debug:$False -MemberDefinition '
[DllImport("user32.dll")] public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X,int Y, int cx, int cy, uint uFlags);
' -Name "User32Functions" -namespace User32Functions -PassThru
[Void]$User32::SetWindowPos($hwnd, -1, 0, 0, 0, 0, 0x53)

Change PowerShell execution mode to -NonInteractive within Script?

To avoid interaction or stops in script execution for input in PowerShell has to be run in Non Interactive mode. Such as:
powershell.exe -NonInteractive
I would like to change this execution mode in script 'runtime' without having to restart or use another PowerShell console. Or maybe a way to force the 'non-interaction'.
Is this possible?
Why not just hide the console during runtime, and show the console again when you are done.
Add-Type -Name Window -Namespace Console -MemberDefinition '
[DllImport("Kernel32.dll")]
public static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
'
function Show-Console {
$consolePtr = [Console.Window]::GetConsoleWindow()
#5 show
[Console.Window]::ShowWindow($consolePtr, 5)
}
function Hide-Console {
$consolePtr = [Console.Window]::GetConsoleWindow()
#0 hide
[Console.Window]::ShowWindow($consolePtr, 0)
}

HoloLens Callbacks with Native Library

My goal is to call methods, which are implemented in the Unity Code, from my UWP DLL. (So I can use them in my HoloLens Project)
I tried this with a bigger project but failed. Therefore I wrote a simple example to make it easier to find the mistake and exclude other influences.
But still, I get the same error.
My Working Environment:
64-bit Computer with OS Windows 10
Micsrosoft Visual Studio Community
2015 Version 14.0.25431.01 Update 3
HoloLens Emulator 10.0.14393.0
Unity 5.5.0f3 Personal (64 bit)
Creating the UWP DLL:
To approach this I created a C++ DLL(Windows Universal) in Visual Studio 2015 as followed:
New Project > Visual C++ > Windows > Universal > DLL(Universal Windows)
After the project was auto generated I added my code.
So the code looks like this:
Native Library Code:
SimpleProjectDLL.cpp:
#include "pch.h"
#define DLL_EXPORT __declspec(dllexport)
typedef void(*CB_V)();
typedef void(*CB_V_VI)(const char * a, int b);
CB_V_VI cb_native_log;
CB_V cb_call;
void log()
{
// this method makes problems !
cb_native_log("Call for callback", 1);
}
extern "C" {
DLL_EXPORT void initInterfaceCallbacks(
CB_V_VI native_log,
CB_V call
) {
cb_native_log = native_log;
cb_call = call;
}
DLL_EXPORT void callSmth()
{
cb_call();
}
DLL_EXPORT int getSomeInt()
{
return 42;
}
DLL_EXPORT void initCallback()
{
log();
}
}
SimpleProjectDLL.h is prepearing the delegates:
SimpleProjectDLL.h:
#pragma once
#include <cstdint>
#define DLL_EXPORT __declspec(dllexport)
extern "C"
{
typedef void(*CB_V)();
typedef void(*CB_V_VI)(const char * a, int b);
}
I did not make any changes to the auto generated files dllmain.cpp, pch.cpp, pch.h or targetver.h.
Finally I build the project for "Release" mode and architecture "x86" to generate the DLL-file.
Location of the DLL-file is now: project-root-folder/Release/SimpleProject/SimpleProjectDLL.dll.
---------------------
Next step I created a new Unity Project added the HoloLens-Toolkit and made sure that the new project is running fine on the emulator.
Unity Project Code:
After that I added the SimpleProjectDLL.dll in the Asset-Folder and implemented the following code:
First of all we need to create the connection between the delegates.
Cpp.cs prepears the Delegates:
Cpp.cs
using UnityEngine;
using System;
using System.Runtime.InteropServices;
namespace Cpp
{
delegate void DelegateV();
delegate void DelegateVVi(IntPtr a, int b);
}
SimpleInterfaceCpp.cs initializes the connection:
SimpleInterfaceCpp.cs
using Cpp;
using System.Runtime.InteropServices;
using UnityEngine;
public static class SimpleInterfaceCpp
{
public static void Init()
{
initInterfaceCallbacks(
SimpleInterface.NativeLog,
SimpleInterface.Call
);
}
[DllImport(SimpleInterface.DLL)]
private static extern void initInterfaceCallbacks(
DelegateVVi native_log,
DelegateV call
);
}
Main:
MainController.cs
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
public class MainController : MonoBehaviour
{
void Start ()
{
SimpleInterfaceCpp.Init();
SimpleInterface.TestCalls();
}
}
SimpleInterface.cs is calling the methodes:
SimpleInterface.cs
using System;
using UnityEngine;
using System.Runtime.InteropServices;
using AOT;
using IntPtr = System.IntPtr;
using Cpp;
using StringReturn = System.IntPtr;
public class SimpleInterface
{
public const string DLL = "SimpleProjectDLL";
public static void TestCalls()
{
// This works fine
int number = getSomeInt();
Debug.Log("getSomeInt: " + number);
// This also works fine and outputs "--- A callback ---"
callSmth();
// This call gives the output "call_log: native log" but crashes afterwards !
initCallback();
}
[MonoPInvokeCallback(typeof(DelegateVVi))]
public static void NativeLog(IntPtr logMessage,
int logLevel)
{
string result = StringFromCReturn(logMessage);
UnityEngine.Debug.Log(result); // outputs "call_log: native log"
}
[MonoPInvokeCallback(typeof(DelegateV))]
public static void Call()
{
UnityEngine.Debug.Log("--- A callback---");
}
[DllImport(DLL)]
private static extern void initCallback();
[DllImport(DLL)]
private static extern void callSmth();
[DllImport(DLL)]
private static extern int getSomeInt();
public static string StringFromCReturn(StringReturn someReturnVal)
{
return Marshal.PtrToStringAnsi(someReturnVal);
}
}
Now if I create a SLN, open the project in Visual Studio and start it with the "HoloLens Emulator" I get the following Output:
getSomeInt: 42
(Filename: C:/buildslave/unity/build/artifacts/generated/Metro/runtime/DebugBindings.gen.cpp Line: 51)
--- A callback---
(Filename: C:/buildslave/unity/build/artifacts/generated/Metro/runtime/DebugBindings.gen.cpp Line: 51)
call_log: native log
(Filename: C:/buildslave/unity/build/artifacts/generated/Metro/runtime/DebugBindings.gen.cpp Line: 51)
The program '[1932] SimpleProject.exe' has exited with code -1073740791 (0xc0000409).
After that the App just closes.
So my Question is, does anyone know what the problem could be?
Is this the right way to use callbacks in a HoloLens Project?
Or does someone know how to find an error description for the code "-1073740791 (0xc0000409)" ?
Additional Information:
I also tried it on a real HoloLens device, same issue, so the problem does not lays at the emulator.
The error is STATUS_STACK_BUFFER_OVERRUN. The call destroyed callstack.
You have different declarations of callbacks in SimpleProjectDLL.cpp and SimpleProjectDLL.h. Cpp file uses "CPP" call conversation, header uses "C" call conversation.
You should change SimpleProjectDLL.cpp by removing
typedef void(*CB_V)();
typedef void(*CB_V_VI)(const char * a, int b);
and adding
#include "SimpleProjectDLL.h"

Powershell: AsyncCallback Events using Hidlibrary

I need some help implementing asynchronous events in Powershell.
As a testbed for a larger HID project I want to use Powershell to read the data from a usb panic button that I got off amazon. The perfect solution would implement the data callback as an event that could then be registered using Register-ObjectEvent.
My current approach is to use the Hidlibrary library. I am having difficulty invoking both the Read() or ReadReport() methods. They do not appear to be typical asynccallbacks and the standard solution of using New-ScriptBlockCallback does not work.
What I have so far that works and allows me to pull a readhandle.
Add-Type -Path .\Projects\UsbPanicButton\HidLibrary.dll
$device = [HidLibrary.HidDevices]::GetDevice('\\?\hid#vid_1130&pid_0202&mi_00#7&29add023&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}')
$device.OpenDevice()
This does not work. (Cannot find an overload)
$device.ReadReport((New-ScriptBlockCallback {Write-host "HI"}))
How can I convert the ReadReport method into an event that can be registered?
The ReadReport method signature:
public delegate void ReadReportCallback(HidReport report);
Isn't a fit for New-ScriptBlockCallback. It works with methods taking an AsyncCallback parameter. IF you know the callback is called on the creating thread during the ReadReport method call you can use:
$device.ReadReport({param($hidReport) $hidReport.ReadStatus })
If it is called back on a different thread, try this modified version of the New-ScriptBlockCallback function:
function New-ScriptBlockCallback {
param(
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[scriptblock]$Callback
)
if (-not ("CallbackEventBridge" -as [type])) {
Add-Type #"
using System;
using HidLibrary;
public sealed class CallbackEventBridge
{
public event HidDevice.ReadReportCallback CallbackComplete = delegate { };
private CallbackEventBridge() {}
private void CallbackInternal(HidReport report)
{
CallbackComplete(report);
}
public HidDevice.ReadReportCallback Callback
{
get { return new HidDevice.ReadReportCallback(CallbackInternal); }
}
public static CallbackEventBridge Create()
{
return new CallbackEventBridge();
}
}
"#
}
$bridge = [callbackeventbridge]::create()
Register-ObjectEvent -input $bridge -EventName callbackcomplete -action $callback -messagedata $args > $null
$bridge.callback
}