Powershell - Close Out-GridView after specific time - windows

I want that a Out-GridView closes after a specific time, e.g after 10 seconds.
Not used to the windows powershell.
Any answer helps.

Unfortunately, PowerShell doesn't natively offer finding and closing arbitrary GUI windows, but you can use the Add-Type cmdlet with ad hoc-compiled C# code that in turn uses P/Invoke declarations to access the Windows API.
The following is a working example:
It defines a distinct window title to use for the Out-GridView call so that the window can be (hopefully) unambiguously located by its title later; also the assumption is that only one window by that title exists.
To make this more robust by limiting the window search to the same process, ... would require quite a bit of extra work.
It creates a background job that uses Add-Member to define a static helper class with a method for closing a window by its title, and calls it after a specifiable timeout.
It invokes Out-GridView synchronously (blocking) with -Wait, using the specified window title. If the window is left open for the specified timeout period, the background job will automatically close it.
It removes the background job after the window has closed.
Note: If you don't need the Out-GridView call to be synchronous, you wouldn't necessarily need a background job.
# Define a distinct window title that you expect no other window to have.
$title = 'Close Me'
# Start a background job that closes the window after a specified timeout.
$job = Start-Job {
param($timeout, $title)
# Define a helper class that uses the Windows API to find and close windows.
Add-Type -Namespace same2u.net -Name WinUtil -MemberDefinition #'
// P/Invoke declarations for access to the Windows API.
  [DllImport("user32.dll", SetLastError=true)]
  private static extern IntPtr FindWindow(string lpszClass, string lpszWindow);
[DllImport("user32.dll", SetLastError=true)]
private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
const UInt32 WM_CLOSE = 0x0010;
// Returns the hWnd (window handle) of the first window that matches the
// specified title and, optionally, window class.
// If none is found, IntPtr.Zero is returned, which can you test for with -eq 0
public static IntPtr GetWindowHandle(string title, string className = null) {
// As a courtesy, we interpet '' as null, because passing null from
// PowerShell requires the non-obvious [nullstring]::value.
if (className == "") { className = null; }
return FindWindow(className, title);
}
// Closes the first window that matches the specified title and, optionally,
// window class. Returns true if a windows found and succesfully closed.
public static bool CloseWindow(string title, string className = null) {
bool ok = false;
// As a courtesy, we interpet '' as null, because passing null from
// PowerShell requires the non-obvious [nullstring]::value.
if (className == "") { className = null; }
IntPtr hwnd = FindWindow(className, title);
if (hwnd != IntPtr.Zero) {
SendMessage(hwnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
// !! SendMessage seemingly always returns 0. To determine success,
// !! we simply test if the window still exists.
ok = IntPtr.Zero == FindWindow(className, title);
}
return ok;
}
'#
Start-Sleep $timeout
$null = [same2u.net.WinUtil]::CloseWindow($title)
} -ArgumentList 3, $title
# Open an Out-GridView window synchronously.
# If you leave it open, the background job will close it after 3 seconds.
1..10 | Out-GridView -Title $title -Wait
# Remove the background job; -Force is needed in case the job hasn't finished yet
# (if you've closed the window manually before the timeout).
Remove-Job -Force $job

Related

Get the start and end times of the Focused Window from powershell

I want to get the start time and end time of the Focused Window that is focused through Powershell. The Script used to get the Focused Window is as follows.
Add-Type #"
using System;
using System.Runtime.InteropServices;
public class Tricks {
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
}
"#
$a = [tricks]::GetForegroundWindow()
get-process | ? { $_.mainwindowhandle -eq $a }
Now I want the start time when the window is focused and when the control is lost(End time). Thanks in Advance.

Setting Windows screensaver require password with powershell

I know that I can set screensaver values through the registry, but those apply at login. I gather the correct way is to use the SystemParametersInfo function, which then makes the changes apply immediately.
I am able to get and set the screensaver timeout values using the following:
$signature = #"
[DllImport("user32.dll")]
public static extern bool SystemParametersInfo(int uAction, int uParam, ref int lpvParam, int flags );
"#
$systemParamInfo = Add-Type -memberDefinition $signature -Name ScreenSaver -passThru
Function Get-ScreenSaverTimeout
{
[Int32]$value = 0
$systemParamInfo::SystemParametersInfo(14, 0, [REF]$value, 0)
$($value/60)
}
Function Set-ScreenSaverTimeout
{
Param ([Int32]$value)
$seconds = $value * 60
[Int32]$nullVar = 0
$systemParamInfo::SystemParametersInfo(15, $seconds, [REF]$nullVar, 2)
}
from https://powershellreflections.wordpress.com/2011/08/02/control-your-screensaver-with-powershell/
I am trying to change the flag for "On resume, display logon screen". Getting the value with the following is successful:
function Get-ScreenSaverSecure
{
[Int32]$value = 0
$systemParamInfo::SystemParametersInfo(118, 0, [REF]$value, 0)
$value
}
However, setting the value with:
Function Set-ScreenSaverSecure
{
[Int32]$nullVar = 0
$systemParamInfo::SystemParametersInfo(119, $true, [REF]$nullVar, 2)
}
does not set the flag. From the MSDN link, I think I should be passing SPI_SETSCREENSAVESECURE (which is uiParam 119) a $true or $false, depending on the mode, however neither seem to apply.
Any help is appreciated.
I used function by #Tim AtLee and tailored as follows:
Function Set-OnResumeDisplayLogon
{
Param ([Int32]$value)
[Int32]$nullVar = 0
$systemParamInfo::SystemParametersInfo(119, $value, [REF]$nullVar, 2)
}
then called by:
Set-OnResumeDisplayLogon(0)
to set the 'On resume, display logon' flag as unchecked; or
Set-OnResumeDisplayLogon(1)
to set the 'On resume, display logon' flag as checked

Hide an MFC dialog window

I have written an MFC dialog based application which is launched by some another application. For now, I have not added any code. It is just the default files that I got. The other application can successfully launch my application.
I am trying to hide the window of my application when the other application launches it.
BOOL CMyApp::InitInstance()
{
CMyAppDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
}
else if (nResponse == IDCANCEL)
{
}
return FALSE;
}
I tried to use:
dlg.ShowWindow(SW_HIDE)
but it still does not hide the window.
How can I accomplish this task?
I'd suggest you have another problem someplace.
If you create a totally new, blank MFC app (Visual Studio 2010) then in App::InitInstance, setting SW_HIDE rather than SW_SHOW does cause the resultant window to be hidden.
BOOL CProj1App::InitInstance()
{
// boilerplate code
. . .
// The one and only window has been initialized, so show and update it
m_pMainWnd->ShowWindow(SW_HIDE); // WORKS!
m_pMainWnd->UpdateWindow();
return TRUE;
}
As soon as you call DoModal your dialog is doomed to be shown. There is only one workaround that successfully avoids focus/flicker problems. See my answer here: Hiding an MFC dialog box
Hence, your code should look like this:
BOOL CMyApp::InitInstance()
{
CMyAppDlg dlg;
dlg.SetVisible(FALSE); // Sets m_visible flag to FALSE.
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
}
else if (nResponse == IDCANCEL)
{
}
return FALSE;
}
Solution to the above issue. The InitInstance code should be as follows:
BOOL CMyApp::InitInstance()
{
CWinApp::InitInstance();
AfxEnableControlContainer();
CMyAppDlg dlg;
dlg.Create(IDD_MyAppUI_DIALOG,NULL);
dlg.ShowWindow(SW_HIDE);
dlg.UpdateWindow();
m_pMainWnd = &dlg;
return TRUE;
}
First of all let me address some issues with previous solutions.
chintan s:
Indeed dialog will be killed when function goes out of scope. It would be a valid solution if dialog was declared as a member variable of the app class.
Vikky:
No need to call Windows API, since dialog is derived from CWnd and it inherits ShowWindow member that take only one parameter: show command.
ixe013:
This solution will work, however, before dialog hides, it will flash, since ShowWindow is called before OnInitDialog is called.
Pete:
This won’t work, since, modal dialog starts before m_pMainWnd has any value assigned to it.
The solution is pointed by ixe013.
This is so far the only solution that works but you will have to declare member variable in you dialog class, as described in the article.
You must hide the dialog from the inside.
Overload OnInitDialog
Call CDialogEx::OnInitDialog()
Hide your window and return
Here is the code
BOOL CMyAppDlg::OnInitDialog()
{
BOOL result = CDialogEx::OnInitDialog();
this->ShowWindow(SW_HIDE);
return result; // return TRUE unless you set the focus to a control
}
There is another method with a sentinel value, YMMV.
The showWindow method has 2 variable.
handle of window
nCmdShow(Controls how the window is to be shown)
BOOL WINAPI ShowWindow(
In HWND hWnd,
In int nCmdShow
);
HWND hWnd = GetSafeHwnd();
ShowWindow(hWnd,SW_HIDE);
See HERE

Shell BrowseForFolder preselected path

I have this call:
oShell.BrowseForFolder(Me.hwnd, "Select path:", 0, "C:\dir\")
This opens a standard file browser dialog with "C:\dir\" as root.
My problem is that you can not browse above the root folder. (as specified in doc http://msdn.microsoft.com/en-us/library/bb774065(v=vs.85).aspx)
Any suggestions on oppening this dialog with a selected path and full browsing posibility?
Thanks
The way to do this involves calling the underlying API, SHBrowseForFolder().
Since you want the entire shell namespace to be available you need to pass NULL as pidlRoot. In order to select your desired folder you will need to provide a callback in lpfn. Make this callback respond to BFFM_INITIALIZED by setting the selected folder. This selection is performed by sending the BFFM_SETSELECTION message to the dialog's window handle (passed to the callback function).
No code because I don't have VB6, but hopefully this outline of the method is enough to get you on your way.
Karl E Peterson's excellent website contains a sample which demonstrates the API call SHBrowseForFolder with a callback, as in David Heffernan's answer.
The KeyStuff project
Look at MFolderBrowse.bas, routine BrowseForFolderByPIDL which passes a callback function BrowseCallbackProc.
Try the old CCRP project. It has a nicely done implementation of the Browse dialog. I used it in several of my projects and it has properties to address the issue you are having.
Here a code ready for copy and paste in a C++ class:
// static
int CALLBACK Func::FolderBrowserCallback(HWND h_Dlg, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
if (uMsg == BFFM_INITIALIZED)
{
// Requires Windows XP or higher
SendMessageW(h_Dlg, BFFM_SETEXPANDED, TRUE, lpData);
}
return 0;
}
// returns an empty string u16_PathOut if an error occurrs or if the user cancels the dialog
void Func::GetOpenFolder(HWND h_Owner,
const WCHAR* u16_Title, // IN: Title at the top of dialog
int s32_CsidlRoot, // IN: Root folder for treeview (CSIDL_DRIVES -> My Computer)
const WCHAR* u16_Preselect, // IN: NULL or the folder to be preselected and expanded
WCHAR* u16_PathOut) // OUT: selected path
{
u16_PathOut[0] = 0;
// CoInitialize(NULL);
// InitCommonControls();
ITEMIDLIST* pk_RootPIDL = NULL; // NULL -> Root = Desktop
SHGetSpecialFolderLocation(h_Owner, s32_CsidlRoot, &pk_RootPIDL);
BROWSEINFOW k_Info = {0};
k_Info.hwndOwner = h_Owner;
k_Info.pidlRoot = pk_RootPIDL;
k_Info.lpszTitle = u16_Title;
k_Info.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI;
if (u16_Preselect)
{
k_Info.lpfn = FolderBrowserCallback;
k_Info.lParam = (LPARAM)u16_Preselect;
}
// DO NOT DISABLE Wow64FsRedirection HERE !!
LPITEMIDLIST pk_IDlist = SHBrowseForFolderW(&k_Info);
if (pk_IDlist)
{
SHGetPathFromIDListW(pk_IDlist, u16_PathOut);
CoTaskMemFree(pk_IDlist);
}
CoTaskMemFree(pk_RootPIDL);
}

timed MessageBox in console application

I use MessageBox function in Win32 console application.
Application does not not use MFC, not even event loop.
I need to make a wrapper, MessageBoxTimed(), that exits
(and dialog box disappears) after N seconds, if user did not press any button.
Is there more or less simple way to do this ?
This will not be trivial. Since the MessageBox() function itself is modal, you will likely need to start another thread that waits for the predefined number of seconds, and is interrupt-able if the message box is dismissed manually.
If the timer expires, use the FindWindow() API to find the handle of the message box and then simulate a click of the OK button, or perhaps more appropriately a keypress of the ESC button.
EDIT: Actually, not too bad. This isn't fully tested, may need some additional cleanup, but is enough to get you started.
#include <Windows.h>
class TimedMB
{
public:
TimedMB() : timeout_(0), caption_(0)
{
interrupt_ = CreateEvent(NULL, FALSE, FALSE, NULL);
}
~TimedMB()
{
CloseHandle(interrupt_);
}
static DWORD WINAPI timer(LPVOID param)
{
TimedMB* mb = reinterpret_cast<TimedMB*>(param);
if(WAIT_TIMEOUT == WaitForSingleObject(mb->interrupt_, mb->timeout_))
{
HWND message_box = FindWindow(NULL, mb->caption_);
if(::IsWindow(message_box))
{
PostMessage(message_box, WM_COMMAND, IDCANCEL, 0);
}
}
return 0;
}
void DisplayMessageBox(const char* msg, const char* caption, DWORD timeout)
{
timeout_ = timeout;
caption_ = caption;
CreateThread(NULL, 0, &TimedMB::timer, this, 0, NULL);
::MessageBox(NULL, msg, caption, MB_OKCANCEL);
::SetEvent(interrupt_);
}
private:
HANDLE interrupt_;
DWORD timeout_;
const char* caption_;
};
int main()
{
TimedMB mb;
mb.DisplayMessageBox("Hello There!", "My Message Box", 5000);
}
If you need to dismiss it automatically, I'd avoid using MessageBox at all. Instead, I'd just put together a dialog that closes itself after the specified period of time. If memory serves, you can do this pretty easily by setting a time when you display the pseudo-message box dialog. When the time goes off or the user clicks "ok" (or "close", etc.) you close the window and cancel the timer.
Don't do this. Modal dialogs should be closed by user intervention. Deviating from this pattern is just confusing and non-standard. If you want a message windows that closes itself, then use a balloon window.

Resources