Trying to make it where powershell minimizes all windows, refreshes the desktop, then brings it back up. Thing is.. the desktop doesn't refresh after the windows minimize.
$shell = New-Object -ComObject "Shell.Application"
$shell.minimizeall()
start-sleep 1
$shell.sendkeys('{F5}')
start-sleep 1
$shell.undominimizeall()
exit
You can use this:
$shell = New-Object -ComObject Shell.Application
$shell.minimizeall()
start-sleep 1
$wsh = New-Object -ComObject Wscript.Shell
$wsh.sendkeys('{F5}')
start-sleep 1
$shell.undominimizeall()
exit
Related
I wrote a script that works fine:
# Use Internet Explorer
$ie = New-Object -ComObject 'internetExplorer.Application'
$ie.Visible= $true # Make it visible
# Set Credentials
$username="name.surname#mail.com"
$password="password"
#Navigate to URL
$ie.Navigate("https://service.post.ch/zopa/dlc/app/?service=dlc-web&inMobileApp=false&inIframe=false&lang=fr#!/main")
While ($ie.Busy -eq $true) {Start-Sleep -Seconds 3;}
# Login
$usernamefield = $ie.document.getElementByID('isiwebuserid')
$usernamefield.value = "$username"
$passwordfield = $ie.document.getElementByID('isiwebpasswd')
$passwordfield.value = "$password"
$Link = $ie.document.getElementByID('actionLogin')
$Link.click()
Start-Sleep -seconds 5
# Find file to download
$link = $ie.Document.getElementsByTagName('A') | where-object {$_.innerText -like 'post_adressdaten*'}
$link.click()
Start-Sleep -seconds 3
# Press "Alt + s" on the download dialog
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.SendKeys]::SendWait("%s")
Start-Sleep -seconds 3
# Quit Internet Explorer
$ie.Quit()
But if I change $ie.Visible= $true to $ie.Visible= $false the script doesn't work.
Why?
Because of these two lines:
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.SendKeys]::SendWait("%s")
In these two lines I'm working on the download dialog box of Internet Explorer and if the browser works in background the the script cannot click on it.
How can I send the input in background or in alternative how to keep Internet Explorer always on top?
As your own answer implies, in order to be able to send keystrokes to an application with [System.Windows.Forms.SendKeys]::SendWait(), it must have a window that is (a) visible and (b) has the (input) focus.
A simpler and faster alternative to the technique shown in your answer - where you use ad-hoc compilation of C# code that wraps WinAPI functions via P/Invoke declarations, via Add-Type - is the following:
# Create an Internet Explorer instance and make it visible.
$ie = New-Object -ComObject 'internetExplorer.Application'; $ie.Visible= $true
# Activate it (give it the focus), via its PID (process ID).
(New-Object -ComObject WScript.Shell).AppActivate(
(Get-Process iexplore | Where-Object MainWindowHandle -eq $ie.hWnd).Id
)
Taking a step back:
GUI scripting (automating a task by simulating user input to a GUI) is inherently unreliable; for instance, the user may click away from the window that is expected to have the focus.
While there is no built in solution, it sounds like Selenium offers robust programmatic browser control.
The third-party Selenium PowerShell module is a PowerShell-friendly wrapper for it (available via the PowerShell Gallery and therefore with Install-Module Selenium), but I don't know if it still works (the project is looking for maintainers as of this writing).
The closest thing I have found is this and it's ugly as hell:
# Start Internet Explorer on top
Add-Type -TypeDefinition #"
using System;
using System.Runtime.InteropServices;
public class Win32SetWindow {
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
}
"#
$ie = new-object -comobject InternetExplorer.Application;
$ie.visible = $true;
[Win32SetWindow]::SetForegroundWindow($ie.HWND) # <-- Internet Explorer window on top
# Set Credentials
$username="name.surname#mail.com"
$password="password"
#Navigate to URL
$ie.Navigate("https://service.post.ch/zopa/dlc/app/?service=dlc-web&inMobileApp=false&inIframe=false&lang=fr#!/main")
While ($ie.Busy -eq $true) {Start-Sleep -Seconds 3;}
# Login
$usernamefield = $ie.document.getElementByID('isiwebuserid')
$usernamefield.value = "$username"
$passwordfield = $ie.document.getElementByID('isiwebpasswd')
$passwordfield.value = "$password"
$Link = $ie.document.getElementByID('actionLogin')
$Link.click()
Start-Sleep -seconds 5
# Find file to download
$link = $ie.Document.getElementsByTagName('A') | where-object {$_.innerText -like 'post_adressdaten*'}
$link.click()
Start-Sleep -seconds 3
# Press "Alt + s" on the download dialog
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.SendKeys]::SendWait("%n{TAB}{ENTER}") # or use SendWait("%s")
Start-Sleep -seconds 3
# Quit Internet Explorer
$ie.Quit()
I want to add and remove user from the lokal Administrator group. Problem is that even I elevate rights in first place It still Access Denies me when I try to add them.
In a similar code It works this way... only thing I changed it that I created a GUI for it.
Here is the code:
$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)
$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
if (!$myWindowsPrincipal.IsInRole($adminRole)){
start-process "powershell" -Verb "runas" -ArgumentList "-File",$MyInvocation.MyCommand.Definition
}
[VOID] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[Void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$objForm = New-Object System.Windows.Forms.Form
$objForm.BackgroundImageLayout = 0
$objForm.BackgroundImage =[System.Drawing.Image]::FromFile('xx')
$objForm.StartPosition = "CenterScreen"
$objForm.Icon="xx"
$objForm.Size = New-Object System.Drawing.Size(400,200)
$objForm.Text = "Lokal Admin Adder v.01"
$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(75,30)
$objLabel.Size = New-Object System.Drawing.Size(240,20)
$objLabel.Text = "Nutzernamen eingeben(m_mustermann)"
$objForm.Controls.Add($objLabel)
$objLabel2 = New-Object System.Windows.Forms.Label
$objLabel2.Location = New-Object System.Drawing.Size(280,140)
$objLabel2.Size = New-Object System.Drawing.Size(300,20)
$objLabel2.Text = "by Lucas Klarner"
$objForm.Controls.Add($objLabel2)
$objTextBox = New-Object System.Windows.Forms.TextBox
$objTextBox.Location = New-Object System.Drawing.Size(85,50)
$objTextBox.Size = New-Object System.Drawing.Size(200,20)
$objForm.Controls.Add($objTextBox)
$FinishButton = New-Object System.Windows.Forms.Button
$FinishButton.Location = New-Object System.Drawing.Size (20,80)
$FinishButton.Size = New-Object System.Drawing.Size (150,20)
$FinishButton.Text = "Nutzer hinzufügen"
$FinishButton.Name = "Nutzer hinzufügen"
$FinishButton.Add_Click({
$Usr = $objTextBox.Text; Add-LocalGroupMember -Group Administratoren -Member $Usr })
$objForm.Controls.Add($FinishButton)
$DeleteButton = New-Object System.Windows.Forms.Button
$DeleteButton.Location = New-Object System.Drawing.Size (210,80)
$DeleteButton.Size = New-Object System.Drawing.Size (150,20)
$DeleteButton.Text = "Nutzer entfernen"
$DeleteButton.Name = "Nutzer entfernen"
$DeleteButton.DialogResult = "OK"
$DeleteButton.Add_Click({
$Usr = $objTextBox.Text;Remove-LocalGroupMember -Group Administratoren -Member $Usr -Verbose })
$objForm.Controls.Add($DeleteButton)
[void] $objForm.ShowDialog()
Thanks a lot!!
FIXED:
Somehow my elevation code was not running correctly and I made a new one out of some internet posts:
if (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
$CommandLine = "-File `"" + $MyInvocation.MyCommand.Path + "`" " + $MyInvocation.UnboundArguments
Start-Process -FilePath PowerShell.exe -Verb Runas -ArgumentList $CommandLine
Exit
}
}
Here's how it works:
The first line checks to see if the script is already running in an elevated environment. This would occur if PowerShell is running as Administrator or UAC is disabled. If it is, the script will continue to run normally in that process.
The second line checks to see if the Windows operating system build number is 6000 (Windows Vista) or greater. Earlier builds did not support Run As elevation.
The third line retrieves the command line used to run the original script, including any arguments.
Finally, the fourth line starts a new elevated PowerShell process where the script runs again. Once the script terminates, the elevated PowerShell window closes.
https://blog.expta.com/2017/03/how-to-self-elevate-powershell-script.html
Suppress PowerShell output messages new outlook application object is created?
$outlook = New-Object -ComObject outlook.application
$outlookItem = $outlook.CreateItem("olMailItem")
I already tried using these approaches. They did not work:
$outlook = New-Object -ComObject outlook.application > $Null
$outlook = New-Object -ComObject outlook.application |Out-Null
($outlook = New-Object -ComObject outlook.application) |Out-Null
These are the output message that I don't want them on the screen:
Application : Microsoft.Office.Interop.Outlook.ApplicationClass
Class : 5
...
...
#boxdog, thanks for pointing it out.
After many break points, I noticed the output is produced by Attachments.Add() method. It is resolved using >$null.
$outlookItem.Attachments.Add("fileName.txt") > $null
This is the script which I created:
add-type -AssemblyName System.Windows.Forms
$ie = New-Object -ComObject "InternetExplorer.Application"
$ie.Navigate("http://www.microsoft.com")
$ie.Navigate2("http://www.google.com" , 2048)
$ie.Navigate2("http://www.outlook.com" , 2048)
$ie.Navigate2("https://studer-ksg.intranet.koerber.de/de/nc/fritz-studer-ag.html" , 2048)
$ie.Visible = $true
start-sleep -Milliseconds 4000
[System.Windows.Forms.SendKeys]::SendWait('{F11}')
do
{
start-sleep -Milliseconds 4000
[System.Windows.Forms.SendKeys]::SendWait('^{TAB}')
start-sleep -Milliseconds 100
[System.Windows.Forms.SendKeys]::SendWait("{F5}")
}
While ($i -ne 0)
It opens an IE window with 4 tabs in fullscreen and switches between them. When I start the script, the window opens but nothing happens until I click in it. How can I make this automatically so you only have to run the script and everything goes by itself?
You need to bring the IE Window to the front so it has focus before the SendKeys will work:
Add-Type -AssemblyName System.Windows.Forms
Add-Type -Assembly "Microsoft.VisualBasic"
$ie = New-Object -ComObject "InternetExplorer.Application"
$ie.Navigate("http://www.microsoft.com")
$ie.Navigate2("http://www.google.com" , 2048)
$ie.Navigate2("http://www.outlook.com" , 2048)
$ie.Visible = $true
$IEProcess = Get-Process | Where { $_.MainWindowHandle -eq $ie.HWND }
[Microsoft.VisualBasic.Interaction]::AppActivate($IEProcess.Id)
Start-Sleep -Milliseconds 4000
[System.Windows.Forms.SendKeys]::SendWait('{F11}')
do
{
Start-Sleep -Milliseconds 4000
[System.Windows.Forms.SendKeys]::SendWait('^{TAB}')
Start-Sleep -Milliseconds 100
[System.Windows.Forms.SendKeys]::SendWait("{F5}")
}
While ($i -ne 0)
Pardon me if this is too simple a question, but I'm not finding anything in the help files or online so far regarding doing this. I'm opening up a new browser window to test the login/logout feature of a web based application, but I want to open the IE window in maximized mode. I could set the size as:
$ie.height = 1024
$ie.width - 768
But is there a keyword or anything that I can use to just open it up maximized automatically or would I need to query the screen size first and then fill in the values from that query?
/matt
(new-object -com wscript.shell).run("url",3)
Solved the Problem of starting IE maximized with following:
Function maxIE
{
param($ie)
$asm = [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$screen = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds
$ie.Width = $screen.width
$ie.Height =$screen.height
$ie.Top = 0
$ie.Left = 0
}
cls
$ie = new-object -com "InternetExplorer.Application"
$ie.visible = $true
maxIE $ie
while ($ie.busy) {sleep -milliseconds 50}
$ie.navigate("http://www.google.com")
I couldn't get any specific answer to work, but did get a combination to work. The order in which these are called is important else it doesn't work.
Full Example:
$ie = New-Object -Com "InternetExplorer.Application"
$urls = #("http://www.google.com","http://www.yahoo.com")
$ie.Visible = $true
CLS
write-output "Loading pages now..."
#Maximize IE window
$asm = [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$screen = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds
$ie.height = $screen.height
#Open webpages
foreach ($link in $urls) {
$ie.Navigate2($link, 0x1000)
}
#close first blank tab
$sa = New-Object -ComObject Shell.Application
$tab = $sa.windows() | Where {$_.Name -match 'Internet Explorer' -and $_.LocationName -eq ''}
$tab.quit()
If you have the PowerShell Community Extensions 1.2 (PSCX) installed on PowerShell 2.0, I have verified that this works:
Pscx\Start-Process IExplore.exe; Start-Sleep 3; $hwnd = Get-ForegroundWindow
$sig = #'
[DllImport("user32.dll")]
public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
'#
Add-Type -MemberDefinition $sig -name NativeMethods -namespace Win32
[Win32.NativeMethods]::ShowWindowAsync($hwnd, 3)
It is a little dicey because it is using a wait (start-sleep) of 3 secs to wait for IE to open and then it uses a PSCX cmdlet to get the window handle of the foreground window. If you only have one instance of IExplore running then you can use this to get that handle:
#(Get-Process IExplore)[0].MainWindowHandle
PowerShell 2.0 is required for the Add-Type support that allows us to call down to the Win32 API.
BTW from a quick Bing search it seems that getting IE to start maximized is a pretty common problem. For instance, with Start-Process you can specify -WindowStyle Maximized but IE doesn't honor that.
Just incase anyone else needs help I ended up just calling up iexplore maximized and then connected to it. You need to sleep because it calls too fast to connect. I'm sure there is a better way but I couldn't figure it out.
start iexplore -WindowStyle maximized
Start-Sleep -seconds 1
$ie = (New-Object -COM "Shell.Application").Windows() | ? { $_.Name -eq "Internet Explorer" }
$ie.navigate("URL")
#We will use the Win32 API function ShowWindowAsync, and spawn an IE Window Maximized.
#Parameters can be used for ShowWindowAsync
$Hide = 0
$Normal = 1
$Minimized = 2
$Maximized = 3
$ShowNoActivateRecentPosition = 4
$Show = 5
$MinimizeActivateNext = 6
$MinimizeNoActivate = 7
$ShowNoActivate = 8
$Restore = 9
$ShowDefault = 10
$ForceMinimize = 11
#Specify an interwebs address :)
$URL="http://www.google.com/"
#Create internetexplorer.application object
$IE=new-object -com internetexplorer.application
#Set some parameters for the internetexplorer.application object
$IE.TheaterMode = $False
$IE.AddressBar = $True
$IE.StatusBar = $False
$IE.MenuBar = $True
$IE.FullScreen = $False
$IE.visible = $True
#Navigate to the URL
$IE.navigate2($URL)
#the C#-style signature of an API function
$code = '[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);'
#add signature as new type to PowerShell (for this session)
$type = Add-Type -MemberDefinition $code -Name myAPI -PassThru
#Magic:
$type::ShowWindowAsync($IE.HWND[0], $Maximized)