I want to run a powershell script when i close the lid on a laptop with windows 10, if there isn't an external monitor attached to te pc, it goes sleep. The script works well if i lauch it manually, but i cannot find inside task scheduler an activation event like 'closing the lid'.
This is the powershell script:
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
if ( #(Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorBasicDisplayParams | where-object { $_.Active }).Length -eq 1 )
{
#put laptop to sleep if there are no external monitor connected
$PowerState = [System.Windows.Forms.PowerState]::Suspend;
$Force = $true;
$DisableWake = $false;
[System.Windows.Forms.Application]::SetSuspendState($PowerState, $Force, $DisableWake);
}
Related
This is my script:
$name = function Get-Name {
$env:computername
}
Get-Name
$time = function Get-SystemUptime {
$operatingSystem = Get-WmiObject Win32_OperatingSystem
"$((Get-Date) - ([Management.ManagementDateTimeConverter]::ToDateTime($operatingSystem.LastBootUpTime)))"
}
Get-SystemUptime
$string = Get-SystemUptime
$separator = "\."
$string.Split($separator, 2)
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
Add-Type -AssemblyName PresentationFramework
Add-Type –AssemblyName System.Windows.Forms
$days = $string.Split(".")[0]
if ([convert]::ToInt32($days, 10) -ge 1) {
$MsgboxTxt = "TXT $($days) TXT"
$MsgboxTitle = '!!! TXT !!!'
[System.Windows.Forms.MessageBox]::Show($MsgboxTxt, $MsgboxTitle, [Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Stop, [System.Windows.Forms.MessageBoxDefaultButton]::Button1, [System.Windows.Forms.MessageBoxOptions]::DefaultDesktopOnly)
}
I start it with this command on remote computer by my company program who runs it with batch (CMD) administration rights:
Powershell.exe -ExecutionPolicy RemoteSigned -File uptime.ps1
When I run in on local computer by copy file and run it from CMD in local priveliges it's OK. Everything working fine.
I think my company program (LOGSystem) runs it on administration user, not logged user.
Is there a option to run it on logged users using CMD command or else?
I'm trying to setup Powershell ISE to manage few VMs hosted under Hyper-V and using Powershell Direct.
What I'm trying to do is:
collect in one script all relevant "settings" under variables whose name starts with an appropriate prefix, for example "vms";
at the end of this script open a PowerShellTab for each VM to manage (if not already opened);
copy in the runspace of this new Tab all the relevant settings variables (I think this is necessary for the next step);
start a remote PSSession with the VM (if not already started) and copy or update the settings variables also in this remote PSSession;
enter interactively this PSSession to be able to launch my commands (F8) after selecting portions of sample/template scripts.
My script is this one.
$vms = 'VMName1','VMName2'
$vmsCredentials = #{
VMName1 = [pscredential]::new('User1', (ConvertTo-SecureString 'pw1' -AsPlainText -force))
VMName2 = [pscredential]::new('User2', (ConvertTo-SecureString 'pw2' -AsPlainText -force))
}
$vmsInfo1 = 'blah,blah,blah'
$vmsInfo2 = #{}
$vmsInfo3 = #(1,2,3)
$tabPrevious = $psISE.CurrentPowerShellTab
$vms |% {
Write-Information $_
$tab = $psISE.PowerShellTabs |? DisplayName -eq $_
if ($tab -eq $null)
{
# opens new PS ISE Tab
$tab = $psISE.PowerShellTabs.Add()
$psISE.PowerShellTabs.SetSelectedPowerShellTab($tabPrevious)
$tab.DisplayName = $_
$tab.ExpandedScript = $true
$tab.Files.Clear()
# open all files in new tab
$tabPrevious.Files |% FullPath |? { Test-Path $_ } |% {
[void]$tab.Files.Add($_)
}
}
else
{
# exit remote interactive session, if any
if ($tab.Prompt -match "^\[$_\]: ") {
while (!$tab.CanInvoke) { sleep -Milliseconds 100 }
$tab.Invoke('exit')
}
}
# export/update variables to tab
while (!$tab.CanInvoke) { sleep -Milliseconds 100 }
$rs = ($tab.InvokeSynchronous({ $ExecutionContext.Host.Runspace }, $false))[0]
if ($null -ne $rs) {
Get-Variable "vms*" |% { $rs.SessionStateProxy.SetVariable($_.Name, $_.Value) }
}
# start a new remote PSSession for the tab, if not already done
while (!$tab.CanInvoke) { sleep -Milliseconds 100 }
$tab.Invoke("if (`$null -eq `$pchPSSession) { `$pchPSSession = New-PSSession -VMName '$_' -Credential `$vmsCredentials['$_'] }")
# export/update variables to the remote PSSession and enter interactively
while (!$tab.CanInvoke) { sleep -Milliseconds 100 }
$tab.Invoke("Invoke-Command `$pchPSSession { `$args |% { Set-Variable `$_.Name `$_.Value } } -ArgumentList (Get-Variable 'vms*'); Enter-PSSession -Session `$pchPSSession")
# uncomment this line and no error occurs
#[void]$psISE.PowerShellTabs.Remove($tab)
}
Unfortunately this script works well:
the very first time I run the script in a fresh ISE,
or when only one new Tab need to be opened,
or if I close immediately the just added Tab (uncomment last line),
or under Debugger
otherwise the two last PowerShellTab.Invoke fails (Null Reference).
Any idea to solve this error?
Any way to do it better?
I need to be able to stop my script when the user clicks cancel on a certain popup box. Part of the script goes as follows:
$OS = (Get-WmiObject -class Win32_OperatingSystem).caption
if ($OS -ne "Microsoft Windows 10 *"){
$wshell = New-Object -ComObject Wscript.Shell
$wshell.Popup("This computer is currently running $OS. To continue with the
script click OK, otherwise click Cancel.",0,"Windows 10
Notification",0x1)
}
That is where the user has to decide to terminate the script progress or continue. And I need to be able to continue the script when the user clicks OK, but stop the script from continuing when he clicks Cancel.
you can capture the popup answer in a variable and use an if-statement to stop the script with Break. Try using this:
$OS = (Get-WmiObject -class Win32_OperatingSystem).caption
if ($OS -ne "Microsoft Windows 10 *"){
$wshell = New-Object -ComObject Wscript.Shell
$answer = $wshell.Popup("This computer is currently running $OS. To continue with the
script click OK, otherwise click Cancel.",0,"Windows 10
Notification",0x1)
if($answer -eq 2){Break}
}
$answer shows as 1 for OK and 2 for Cancel
I prefer using Windows Forms and updated the script accordingly. You can find more examples here.
I also changed the if condition because you where checking if the variable $OS was exactly "Microsoft Windows 10 *"; to check if it begins with the string use -notlike instead of -ne.
$OS = (Get-WmiObject -class Win32_OperatingSystem).caption
if ($OS -notlike "Microsoft Windows 10 *") {
$PopupTitle = "Windows 10 Notification"
$PopupMessage = "This computer is currently running $OS. To continue with the script click OK, otherwise click Cancel."
$PopupOptions = "OkCancel"
$PopupAnswer = [System.Windows.Forms.MessageBox]::Show($PopupMessage,$PopupTitle,$PopupOptions,[System.Windows.Forms.MessageBoxIcon]::Exclamation)
if ($PopupAnswer -eq "Cancel") {
Break
}
}
The variable at the top of the script defines several commands/variables for New-PSDrive, as well as connection and installation.
After this, a function is created to open a text file and extract information out of it. I know this part works because I use it in 2 other scripts.
Lastly, The script executes the commands in the first variable.
The script will show as running successfully, but checking the remote computer reveals that nothing happened.
Prior to doing any of this activity, the remote computer has a script run against it that:
enables PSRemoting (setting firewall rules and starting WinRM), and
bypasses execution policies.
After those steps, the script below is run to install a piece of software.
$eAudIT2014V2Install = {
$eAudIT2014V2password = ConvertTo-SecureString "PasswordHere" -AsPlainText -Force
$eAudIT2014V2cred = New-Object System.Management.Automation.PSCredential('domain\user', $eAudIT2014V2password)
$eAudIT2014V2drive = New-PSDrive -Name eAudIT2014V2 -PSProvider FileSystem -Root "\\Server\Share" -Credential $eAudIT2014V2cred
$eAudIT2014V2job = Start-Job {"eAudIT2014V2:\Setup.cmd"}
Wait-Job $eAudIT2014V2job
Receive-Job $eAudIT2014V2job
}
Function Get-OpenFile($initialDirectory) {
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") |
Out-Null
$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$OpenFileDialog.InitialDirectory = $initialDirectory
$OpenFileDialog.ShowDialog()
$OpenFileDialog.Filename
$OpenFileDialog.ShowHelp = $true
}
$InputFile = Get-OpenFile
if ($InputFile -eq "Cancel") {
Write-Host "Canceled By User"
exit
} else {
$Computers = #(Get-Content -Path $InputFile)
}
foreach ($computer in $computers) {
Write-Host "Installing eAudIT 2014V2 on Selected Computers"
Invoke-Command $eAudIT2014V2Install
}
I'm noticing that if I tell this script to run something basic like notepad.exe, a dllhost process starts on the machine, but notepad never does. What am I doing wrong?
The answer is pretty simple here. All of your script is for naught if you don't tell the Invoke-Command cmdlet what computer you want to execute the code on. As it is you are simply iterating a loop and invoking that command X number of times on the local machine. You need to change that second to the last line to specify the machine to execute the code on:
Invoke-Command $eAudIT2014V2Install -ComputerName $computer
I need to generate some load on about 100 Windows 2012 R2 servers. The idea I have is to use PowerShell remoting to kick off my script the generate the CPU load. I am also trying to control the load by checking the current load and if it is over X% don't spawn a new job. It's not the most elegant script, but the script works if I execute it locally. When I run it remotely things go wrong.
it seems as if the foreach loop does nothing. So I just have an idle process
it will start about 15 jobs with no issues then the rest all report as having failed.
I have tried various methods of calling the function. I have modified the function so that it contains a server variable but still not getting the desired result. I have replaced Start-Job with Invoke-Command. PSRemoting is working I can do basic tasks on the remote servers.
Any guidance would be appreciated
Below is my code
function Invoke-CPUStress
{
[CmdletBinding()]
param (
$duration
)
$start = (get-date).AddMinutes(1)
$end = $start.AddMinutes($duration)
while ((Get-Date) -lt $start)
{
sleep -Seconds 10
}
while ((get-date) -lt $end)
{
$Load = (Get-WmiObject Win32_Processor | Measure-Object -Property LoadPercentage -Average).Average
If ($Load -lt 60)
{
Start-Job -ScriptBlock {
$result = 1;
foreach ($number in 1..2147483647)
{
$result = $result * $number
sleep -Milliseconds 1
}
}
}
}
Get-Job | Stop-Job
Get-Job | Remove-Job
}
Invoke-CPUStress -duration 5