Can anyone please tell me how to click on "ok" or "cancel" on a popup window using powershell?
I am trying to automate a website using powershell, but I am new to powershell. I have to click on OK button in a popup box to proceed. I know VBscript, in that I can use
set obj0 = createobject("wscript.shell")
count = 0
do while count = 0
if obj0.appactivate "Popupboxname" then
----perform required action---
count = 1
else
wscript.sleep(2000)
end if
loop
Can anyone tell me how to do the same in powershell? If i can somehow access the popup window, atleast i can use sendkeys command to send the enter key. Please let me know how to handle the popup window. Thanks in advance.
With Powershell v2 you can use PInvoke to access the normal Win32 API, thus giving you access to FindWindow and SetForegroundWindow. Then use SendKeys to send a Enter key.
Something like this to register the methods:
$pinvokes = #'
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr FindWindow(string className, string windowName);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
'#
Add-Type -AssemblyName System.Windows.Forms
Add-Type -MemberDefinition $pinvokes -Name NativeMethods -Namespace MyUtils
Now you can find the window you need:
$hwnd = [MyUtils.NativeMethods]::FindWindow(null, "Popupboxname")
Give it focus:
[MyUtils.NativeMethods]::SetForegroundWindow($hwnd)
And send the Enter key:
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
Sources/inspiration:
power shell : how to send middle mouse click?
http://poshcode.org/1837
http://www.tek-tips.com/viewthread.cfm?qid=1563429
Try something like this:
$wshell = New-Object -ComObject wscript.shell;
$wshell.AppActivate('Vector RP1210 API Setup')
Sleep 1
$wshell.SendKeys('%C')
$wshell.AppActivate('Vector RP1210 API')
Sleep 1
$wshell.SendKeys('{ENTER}')
You might want to investige the WASP snapin from CodePlex:
http://wasp.codeplex.com/wikipage?title=Some%20Usage%20Examples&referringTitle=Home
Related
I'm using the unmanaged Windows API RegLoadKey within PowerShell to mount registry hives offline.
That works fine, and outside of PowerShell everything works as expected - once mounted I can browse to them in regedit.exe, and manipulate them and so on.
However, if I use Get-ChildItem I can then no longer dismount the hive. RegUnloadKey returns a value of 5 which is "Access Denied". This does NOT happen if I simply don't touch the registry key from within PowerShell
The code is very very simply, I can replicate it as such:
Add-Type -Name LoadHive -NameSpace RegistryHelper -MemberDefinition #"
[DllImport("advapi32.dll", SetLastError = true)]
public static extern Int32 RegLoadKey(UInt32 hKey, String lpSubKey, String lpFile);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern Int32 RegUnLoadKey(UInt32 hKey, string lpSubKey);
"#
$hiveMountPoint = 2147483651 (This is the built-in constant for HKEY_USERS)
$hiveMountName = "TEMP-HIVE"
$hivePath = [Filepath to offline hive]
[RegistryHelper.LoadHive]::RegLoadKey($hiveMountPoint, $hiveMountName, $hivePath)
$hiveKeys = Get-ChildItem "REGISTRY::HKEY_USERS\TEMP-HIVE"
[RegistryHelper.LoadHive]::RegUnLoadKey($hiveMountPoint, $hiveMountName)
I'm using RegUnLoadKey to dismount. Can anybody shed some light on why Get-ChildItem is locking me out here?
Get-ChildItem is agnostic to the underlying provider (FileSystem, Registry ...). So even if you use Interop to load the hive, Powershell is not aware of that and the Registry Provider will return RegistryKey objects. These objects contains a Handle property that probably prevent you to close the hive gracefully. You should call Close method on all keys stored in $hiveKeys before unloading the hive to close all handles.
When I boot up my computer I open several file explorers and sort them around the screen to help speed up my workflow. It's not time consuming, only tedious, and I'd like a small program to do it for me. I know how to open an explorer, but I don't see any positional arguments.
Is there a way to spawn a file explorer at a set of screen coordinates, or move it programatically after it opens? Preferably with python 3+, but batch will work as well.
That was simultaneously easier and harder than I thought it was going to be. Everything is commented, let me know if you have any more questions. This is a PowerShell/batch hybrid script (so save it as a .bat file) because PowerShell is disabled on systems by default or something.
<# :
:: Based on https://gist.github.com/coldnebo/1148334
:: Converted to a batch/powershell hybrid via http://www.dostips.com/forum/viewtopic.php?p=37780#p37780
:: Array comparison from http://stackoverflow.com/a/6368667/4158862
#echo off
setlocal
set "POWERSHELL_BAT_ARGS=%*"
if defined POWERSHELL_BAT_ARGS set "POWERSHELL_BAT_ARGS=%POWERSHELL_BAT_ARGS:"=\"%"
endlocal & powershell -NoLogo -NoProfile -Command "$_ = $input; Invoke-Expression $( '$input = $_; $_ = \"\"; $args = #( &{ $args } %POWERSHELL_BAT_ARGS% );' + [String]::Join( [char]10, $( Get-Content \"%~f0\" ) ) )"
goto :EOF
#>
# Create an instance of the Win32 API object to handle and manipulate windows
Add-Type #"
using System;
using System.Runtime.InteropServices;
public class Win32 {
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
}
"#
# Get a list of existing Explorer Windows
$previous_array = #()
$shell_object = New-Object -COM 'Shell.Application'
foreach($old_window in $shell_object.Windows())
{
$previous_array += $old_window.HWND
}
# Open four more Explorer Windows in the current directory
explorer
explorer
explorer
explorer
# Pause for 1 second so that the windows have time to finish opening
sleep 1
# Get the list of new Explorer Windows
$new_array = #()
foreach($new_window in $shell_object.Windows())
{
$new_array += $new_window.HWND
}
# Compare the two arrays and only process the new windows
$only_new = Compare-Object -ReferenceObject $previous_array -DifferenceObject $new_array -PassThru
# MoveWindow takes HWND value, X-position on screen, Y-position on screen, window width, and window height
# I've just hard-coded the values, adjust them to suit your needs
[Win32]::MoveWindow($only_new[0],0,0,960,540,$true)
[Win32]::MoveWindow($only_new[1],960,0,960,540,$true)
[Win32]::MoveWindow($only_new[2],0,540,960,540,$true)
[Win32]::MoveWindow($only_new[3],960,540,960,540,$true)
I have some vbs code that will automatically change my windows theme via cmd as well as close it after the operation completes. The personalization window opens, Windows changes the theme, and then the personalization window closes. The problem is, sometimes the window doesn't close after changing the theme and I'm wondering why. Also, is there a one-liner code in cmd (or vbs that can execute through cmd) that just closes the personalization window? Thanks in advance for your help! My code used is as follows:
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run "rundll32.exe %SystemRoot%\system32\shell32.dll,Control_RunDLL %SystemRoot%\system32\desk.cpl desk,#Themes /Action:OpenTheme /file:""C:\Windows\Resources\Ease of Access Themes\basic.theme"""
Wscript.Sleep 1600
WshShell.AppActivate("Desktop Properties")
WshShell.Sendkeys "%FC"
WshShell.Sendkeys "{F4}"
Your Run call is being done asynchonously so your script will continue without waiting for Run to complete. This is fine, and it's what you need in your situation. But if it takes longer than 1600ms to launch the Desktop Properties dialog then AppActivate and your SendKeys commands are being sent to a nonexistent window. Have you tried increasing the sleep time to see if it works?
You can also test the availability of the window in a loop. AppActivate returns True if the window is found and False otherwise. For example, here's a snippet that tries for 10 seconds to see if the window appears (checking each second)...
For i = 1 To 10
WScript.Sleep 1000
If WshShell.AppActivate("Desktop Properties") Then
WshShell.Sendkeys "%FC"
WshShell.Sendkeys "{F4}"
Exit For
End If
Next
' If i > 10, it failed to find the window.
After trying a similar solution, I came up with the following powershell:
Function Get-WindowHandle($title,$class="") {
$code = #'
[System.Runtime.InteropServices.DllImport("User32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
'#
Add-Type -MemberDefinition $code -Namespace MyWinAPI -Name GetWindowHandle
return [MyWinAPI.GetWindowHandle]::FindWindow($class, $title)
}
Function Close-WindowHandle($windowHandle) {
$code = #'
[System.Runtime.InteropServices.DllImport("User32.dll")]
public static extern bool PostMessage(IntPtr hWnd, int flags, int idk, int idk2);
'#
Add-Type -MemberDefinition $code -Namespace MyWinAPI -Name CloseWindowHandle
#https://msdn.microsoft.com/en-us/library/windows/desktop/ms632617(v=vs.85).aspx
$WM_CLOSE = 0x0010
return [MyWinAPI.CloseWindowHandle]::PostMessage($windowHandle, $WM_CLOSE, 0, 0)
}
Close-WindowHandle $(Get-WindowHandle 'Personalization' 'CabinetWClass')
I'm having a problem calling Winspool.drv "OpenPrinter" when I run my program in standard user acccount. But when I ran my program in Administrator account. It can properly execute API call.
I am trying to call OpenPrinter using this API
[DllImport("WinSpool.drv", SetLastError = true)]
static extern unsafe bool OpenPrinter (string pPrinterName, int* phPrinter, void* pDefault);
and implementing it using this code
static unsafe int CSOpenPrinter(string printerName)
{
bool bResult;
int hPrinter;
PRINTER_DEFAULTS pd = new PRINTER_DEFAULTS();
//int rawsize = Marshal.SizeOf(pd);
//IntPtr pdPtr = Marshal.AllocHGlobal(rawsize);
//pd.pDatatype = null;
//pd.pDevMode = null;
pd.DesiredAccess = PRINTER_ALL_ACCESS;
bResult = OpenPrinter(printerName, &hPrinter, &pd);
System.Diagnostics.Debug.WriteLine("bResult: " + bResult);
if (!bResult)
{
throw new ApplicationException("Cannot open printer '" +
printerName + "' " +
Marshal.GetLastWin32Error());
}
return hPrinter;
}
Ok again, that code works perfectly when I try to make my program "Run As Administrator". How do I make my application run as a Administrator without right clicking on the application and selecting "Run As Administrator"?
I believe this is a UAC problem, but can you give me an Idea how to solve this? Is adding app.manifest will help? Can you give me an exampple?
Best to all
What are you trying to do with the printer? Your code is asking for full access and so requires admin access.
If you just want to use the printer, request PRINTER_ACCESS_USE access instead.
If it is actually an admin process, then add an appropriate manifest to the executable to tell windows that it needs admin access.
Add manifest file to your project. Like here
I need to activate Windows start menu on mouse location.
I know I can send CTRL + ESC or Win keys to the specific window, and move the window afterwards, but it still shows menu on original location for a short period of time (unless I install hook, and that is overkill for the task).
I recall there is some way to do this, using some dll call or sending some message to the shell or something.
Ty
Do you get the same behaviour if you "press" the button more programmatically?
// Find the Start button
HANDLE hScreenDC = GetDC(0);
DWORD height = GetDeviceCaps(hScreenDC, VERTRES);
ReleaseDC(0, hScreenDC);
hTaskBarWnd = FindWindow("Shell_TrayWnd", 0);
hStartButtonWnd = GetWindow(hTaskBarWnd, GW_CHILD);
// Now simulate a press on the Start button
SendMessage(hButtonWnd, WM_LBUTTONDOWN,
MK_LBUTTON, LOWORD(5) + HIWORD(height - 20));
Otherwise you might explore the "Shell_TrayWnd" window using WinSpy++ or by using a similar utility, perhaps the Start menu is a child window of the tray window.
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindow (string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern bool ShowWindow (IntPtr hWnd, ShowWindowCommand nCmdShow);
int ShowCmd = 5;
int HideCmd = 0;
ShowWindow(FindWindow("DV2ControlHost", "Start menu"), ShowCmd);
Should do the trick in windows 7 at least. Use "HideCmd" instead of "ShowCmd" to hide again.