Empty recycle bin with Powershell V2 - powershell

Is there a way to empty the recycle bin using Powershell 2.0.
I do not want to update Powershell.

You could clear recycle bin via com object. Like so:
$Shell= New-Object -ComObject Shell.Application
$Bin = $Shell.NameSpace(10)
foreach ($Item in #($Bin.Items())){Remove-item $Item.Path -Force}

You could also directly call SHEmptyRecycleBin Win32 function:
$definition = #'
[DllImport("Shell32.dll", CharSet = CharSet.Unicode)]
public static extern uint SHEmptyRecycleBin(IntPtr hwnd, string pszRootPath, uint dwFlags);
'#
$winApi = Add-Type -MemberDefinition $definition -Name WinAPI -Namespace Extern -PassThru
$winApi::SHEmptyRecycleBin(0, $null, 7)
All recycle bins are deleted, no confirmation message is shown, no progress bar, no sound.

Related

Alternative to time delay while installing exe through PowerShell?

I have a software exe which I am trying to install via PowerShell. It's working fine. I am using SendKeys to navigate through the installation GUI. I have given delay between two SendKeys commands, because software takes some time between two steps, but that installation time varies from computer to computer.
My question is how can I bypass this time delay dependency in SendKeys? I have tried AppActivate but its of no use for me. Is there any alternative to delay?
Sure.
I've converted Nitesh's C# function to a Powershell script
$signature_user32_GetForegroundWindow = #"
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
"#
$signature_user32_GetWindowText = #"
[DllImport("user32.dll")]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
"#
$foo = `
Add-Type -MemberDefinition $signature_user32_GetForegroundWindow `
-Name 'user32_GetForegroundWindow' `
-Namespace 'Win32' `
-PassThru
$bar = `
Add-Type -MemberDefinition $signature_user32_GetWindowText `
-Name 'user32_GetWindowText' `
-Namespace 'Win32' `
-Using System.Text `
-PassThru
[int]$nChars = 256
[System.IntPtr] $handle = New-object 'System.IntPtr'
[System.Text.StringBuilder] $Buff = New-Object 'System.Text.StringBuilder' `
-ArgumentList $nChars
$handle = $foo::GetForegroundWindow()
$title_character_count = $bar::GetWindowText($handle, $Buff, $nChars)
If ($title_character_count -gt 0) { Write-Output $Buff.ToString() }
There is a lot going on here. Lemme explain a little of what I did.
I've created two method signatures (the bit in the here-string); one for each function we're calling.
I use those signatures to create corresponding types. Again, one for each method.
For the GetWindowType (which passes the title back in a string and needs a reference to System.Text), I pass in the System.Text namespace in the -Using parameter.
Behind the scenes, PowerShell adds references to the System and System.Runtime.InteropServices so no need to worry about those.
I create my string size ($nChars), window pointer ($handle), and window title buffer ($Buff)
I call the functions through the type-pointer: $foo... and $bar...
Here is what I get when I run all this...
Whenever I have to call the Windows API (which isn't really my thing), I reference the following two articles:
PowerShell P/Invoke Walkthrough
Use PowerShell to Interact with the Windows API: Part 1
I hope this helps!

Is there a way to minimize all windows except one?

I need to Take a screenshot with a script when a process has an error.
is there a way to minimize all windows, except the window of the process that got the error?
I know the way to minimize all:
$shell = new-object -com shell.application
$shell.MinimizeAll()
But is there a way to minimize everything except one window?
Thanks!
use API Windows
$Win32ShowWindowAsync = Add-Type –memberDefinition #”
[DllImport("user32.dll")]
public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
“# -name “Win32ShowWindowAsync” -namespace Win32Functions –passThru
$titletowindow="TODO.csv - Bloc-notes"
get-process |
where mainwindowhandle -ne 0 |
%{if ($_.MainWindowTitle -eq $titletowindow) { $Win32ShowWindowAsync::ShowWindowAsync($_.MainWindowHandle, 3) | Out-Null} else { $Win32ShowWindowAsync::ShowWindowAsync($_.MainWindowHandle, 6) | Out-Null} }

Powershell to run PostMessage Windows API function failing

I need to write a script to install Java runtime of a specific version, add to the system path variable then go on to run the Java program. I want to do this all in one go without having to restart the target computer.
I found this so question and thought I could try to change to my needs.
SendMessage is causing script to hang
So I tried with PostMessage as per the answer. Obviously I needed to change the message.
So I tried code like this:
echo Start of experiment
$NewPath = (Get-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Session Manager\Environment" -Name Path).Path
$NewPath = "%JAVA_BIN%;" + $NewPath
$RegKey ="HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
Set-ItemProperty -Path $RegKey -Name Path -Value $NewPath
echo Updated Path environment variable
# Next bit which isn't working
$HWND_BROADCAST = 0xffff
$WM_SETTINGCHANGE = 0x001A
$ENVIRON = "Environment"
#Store the C# signature of the PostMessage function.
$signature = #"
[DllImport("user32.dll")]
public static extern int PostMessage(int hWnd, int hMsg, int wParam, int lParam);
"#
#Add the SendMessage function as a static method of a class
$PostMessage = Add-Type -MemberDefinition $signature -Name "Win32PostMessage" -Namespace Win32Functions -PassThru
#Invoke the PostMessage Function
$PostMessage::PostMessage($HWND_BROADCAST, $WM_SETTINGCHANGE, 0, $ENVIRON)
echo end of experiment
This is my output:
Start
of
experiment
Cannot convert argument "3", with value: "Environment", for "PostMessage" to type "System.Int32": "Cannot convert value "Environment" to type "System.Int32".
Error: "Input string was not in a correct format.""
At C:\share\tvm_drivers\PED\setenv.ps1:43 char:26
+ $PostMessage::PostMessage <<<< ($HWND_BROADCAST, $WM_SETTINGCHANGE, 0, $ENVIRON)
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument
end
of
experiment
I am running this on Windows 7.
Can anyone help?
For a bit of background, if you reboot the target PC after setting the path env variable, then the setting works. But if you don't reboot, it is necessary to send a broadcast message as above to tell any other Window, including the command prompt, about the change. That is why I need the message.
This is the powershell that successfully updates all the open windows about the env change.
# Notifies other processes that the global environment block has changed.
# This lets other processes see changes to ENV: without having to reboot
# or logoff/logon. A non-zero result from SendMessageTimeout indicates success.
if (-not ("win32.nativemethods" -as [type])) {
# import sendmessagetimeout from win32
add-type -Namespace Win32 -Name NativeMethods -MemberDefinition #"
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(
IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam,
uint fuFlags, uint uTimeout, out UIntPtr lpdwResult);
"#
}
$HWND_BROADCAST = [intptr]0xffff;
$WM_SETTINGCHANGE = 0x1a;
$result = [uintptr]::zero
# notify all windows of environment block change
[win32.nativemethods]::SendMessageTimeout($HWND_BROADCAST, $WM_SETTINGCHANGE,
[uintptr]::Zero, "Environment", 2, 5000, [ref]$result);

Maximizing Lync Window Using Powershell?

I've created a script that will automatically initiate a video call with a user of my choice.
When ran, the script leaves the video call docked, with the lync video call window flashing.
How would I be able to get this window to maximize and go to full screen when the script is ran?
Thank you so much for your help.
Below is my code
$assemblyPath = “C:\Program Files (x86)\Microsoft Office 2013\LyncSDK\Assemblies\Desktop\Microsoft.Lync.Model.DLL”
Import-Module $assemblyPath
$LyncClient = [Microsoft.Lync.Model.LyncClient]::GetClient()
$StartVideoCallMethod = {
$Conversation = $this.ConversationManager.AddConversation();
$contact = $LyncClient.ContactManager.GetContactByUri("useremailhere")
[void]$Conversation.AddParticipant($contact);
[void]$Conversation.Modalities['AudioVideo'].BeginConnect({}, 0);
};
Add-Member -InputObject $LyncClient -MemberType ScriptMethod -Name StartVideoCall -Value $StartVideoCallMethod -Force;
# Initiate the video call
$Conversation = $LyncClient.StartVideoCall();
I don't have Lync, but something like this should work. I'm using the process name (or what I'm guessing it is) to get the MainWindowHandle for the Lync window, then sending that a command to maximize (cmd=3, see here for the full list of values: https://msdn.microsoft.com/en-us/library/windows/desktop/ms633548%28v=vs.85%29.aspx).
This code may break if more than one process matches by name, but it should get you started; if you can get the PID or some other, better unique identifier, use that. Just mess around with the output of Get-Process and you should see a number of options, and remember you can always use a Where clause to filter the output. Or of course if there's some way to get the MainWindowHandle directly from $LyncClient, even better.
$w = Get-Process -Name "Lync"
$Win32ShowWindowAsync = Add-Type –memberDefinition `
'[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);' `
-name “Win32ShowWindowAsync” -namespace Win32Functions –passThru
$Win32ShowWindowAsync::ShowWindowAsync($w.MainWindowHandle,3) | Out-Null
Here the code that I have so far.
Still needs some tweaks to perfect it but it does the job.
Tweaks would be specifying which window to maximize as it will sometimes maximize the lync contacts window.
Code
$assemblyPath = “C:\Program Files (x86)\Microsoft Office 2013\LyncSDK\Assemblies\Desktop\Microsoft.Lync.Model.DLL”
Import-Module $assemblyPath
$exePath = "C:\Program Files\Microsoft Office 15\root\office15\lync.exe"
if(!(get-process | ?{$_.path -eq $exePath})){
Start-Process -FilePath $exePath -WindowStyle Maximized
Start-Sleep -s 10
}
$LyncClient = [Microsoft.Lync.Model.LyncClient]::GetClient()
$StartVideoCallMethod = {
$Conversation = $this.ConversationManager.AddConversation();
$contact = $LyncClient.ContactManager.GetContactByUri("ernesto.gomila#quirchfoods.com")
[void]$Conversation.AddParticipant($contact);
[void]$Conversation.Modalities['AudioVideo'].BeginConnect({}, 0);
};
Add-Member -InputObject $LyncClient -MemberType ScriptMethod -Name StartVideoCall -Value $StartVideoCallMethod -Force;
# Initiate the video call
$Conversation = $LyncClient.StartVideoCall();
#Maximize window
$w = Get-Process -Name "lync"
$Win32ShowWindowAsync = Add-Type –memberDefinition #"
[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
"# -name “Win32ShowWindowAsync” -namespace Win32Functions –passThru
Start-Sleep -s 2
$Win32ShowWindowAsync::ShowWindowAsync($w.MainWindowHandle,3) | Out-Null

Get PID of COM server

I create a com object in powershell like so:
$application = new-object -ComObject "word.application"
Is there a way to get the PID (or some other unique identifier) of the launched MS Word instance?
I want to check if the program is blocked e.g. by modal dialogs asking for passwords, and I can't do it from whithin PowerShell.
Ok, I found out how to do it, we need to call the Windows API. The trick is to get the HWND, which is exposed in Excel and Powerpoint, but not in Word. The only way to get it is to change the name of the application window to something unique and find it using "FindWindow". Then, we can get the PID using the "GetWindowThreadProcessId" function:
Add-Type -TypeDefinition #"
using System;
using System.Runtime.InteropServices;
public static class Win32Api
{
[System.Runtime.InteropServices.DllImportAttribute( "User32.dll", EntryPoint = "GetWindowThreadProcessId" )]
public static extern int GetWindowThreadProcessId ( [System.Runtime.InteropServices.InAttribute()] System.IntPtr hWnd, out int lpdwProcessId );
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
}
"#
$application = new-object -ComObject "word.application"
# word does not expose its HWND, so get it this way
$caption = [guid]::NewGuid()
$application.Caption = $caption
$HWND = [Win32Api]::FindWindow( "OpusApp", $caption )
# print pid
$myPid = [IntPtr]::Zero
[Win32Api]::GetWindowThreadProcessId( $HWND, [ref] $myPid );
"PID=" + $myPid | write-host
you may be able to use
get-process -InputObject <Process[]>