I am trying to play sound as long as the GUI is open, but as I am not familiar with powershell I need help..
Right now I have this:
$sound = New-Object System.Media.SoundPlayer
$sound.SoundLocation="c:\WINDOWS\Media\ringout.wav"
$Form.ShowDialog()
$sound.PlayLooping()
$flag=$false
1..10 | foreach {
if ($_ -gt 5) {
$flag=$true
}
else {
sleep -s 1
}
if($flag) {
$sound.Stop()
}
}
Of course it's playing after I close this GUI, If I will put $Form.ShowDialog() at the end it will be play before GUI will show...
GUI is closed by button, simple $Form.Close()
Edit ($Form declaration) :
$Form = New-Object System.Windows.Forms.Form
$Form.Text = "ALERT"
$Form.StartPosition = "CenterScreen"
$Form.Topmost = $True
$Form.BackColor = "White"
$Form.AutoSize = $True
$Form.AutoSizeMode = "GrowAndShrink"
$Form.ControlBox = $false
I tried also with if and while loop but without success. Any ideas?
First things first. There is an important difference between Form.Show() and $Form.ShowDialog(). While Show() will return immediately, the latter one waits upon Dialog completion. So, if you start the music before ShowDialog() and stop it after that line, I don't know, why it shouldn't work.
For your needs, you might like events. Use the Forms Load event to execute some logic while the form loads, and its Closing event to add some logic when the form closes:
$Form = New-Object System.Windows.Forms.Form -Property #{
Text = "ALERT"
StartPosition = "CenterScreen"
Topmost = $True
BackColor = "White"
AutoSize = $True
AutoSizeMode = "GrowAndShrink"
ControlBox = $false
}
$sound = New-Object System.Media.SoundPlayer -Property #{SoundLocation = "c:\WINDOWS\Media\ringout.wav"}
$Form.Add_Load({
$sound.PlayLooping()
})
$Form.Add_Closing({
$sound.Stop()
})
$Form.Show()
One might think for readability and reusability the following works better:
[scriptblock]$startMusic = {
$sound.PlayLooping()
}
[scriptblock]$stopMusic = {
$sound.Stop()
}
$Form.Add_Load($startMusic)
$Form.Add_Closing($stopMusic)
This would easily allow us to reuse those methods (e.g. for other dialogs and actions)
Related
I want to read JSON from a website. Before I get the data in JSON format I need to login to create a session. The second URL must be opened in the same session.
My code:
$ie = New-Object -ComObject "InternetExplorer.Application"
$requestUri = "LOGIN_URL"
$ie.Visible = $true
$ie.Navigate($requestUri)
$requestUri = "JSON_URL"
$ie.Navigate($requestUri)
while ($ie.Busy) { Start-Sleep -Milliseconds 100 }
I tried to get the content with something like $ie.Document.Body but that doesn't work.
I found the solutio, the following will return json:
$ie.Document.documentelement.innertext
I am trying to script a little application that would make possible to copy AD user's security groups and paste them to another one's profile.
I am good with this part but I want to make it a little bit more difficult by implementing some input boxes that would search for the AD user, errors out in case it does not exit in my AD and prompt once again until user has been found.
ipmo activedirectory
Add-type -assemblyName Microsoft.VisualBasic
Add-Type -AssemblyName System.Windows.Forms
$userref = [Microsoft.VisualBasic.Interaction]::Inputbox("Enter username
", "Prime User")
$usertar = [Microsoft.VisualBasic.Interaction]::Inputbox("Enter username",
"Target")
$userref, $usertar | foreach {
if ([bool](Get-ADUser -Filter {samaccountname -eq $_}) -ne $true) {
[System.Windows.Forms.MessageBox]::Show("This user does not exist!")
}
else {Write-Host "User Ok"}
}
Since you need to validate the existance of two AD users before the rest of your code can run, you are basically asking the same thing twice using inputboxes.
In that case I would suggest adding a small custom function to do that.
Something like this perhaps:
Import-Module ActiveDirectory
Add-type -AssemblyName Microsoft.VisualBasic
Add-Type -AssemblyName System.Windows.Forms
function Get-UserFromInputbox ([string]$Title) {
do {
$account = [Microsoft.VisualBasic.Interaction]::Inputbox("Enter user accountname", $Title)
# On Cancel the InputBox function simply returns an empty string.
# in that case, just return $null so the calling code can handle it
if ([string]::IsNullOrEmpty($account)) { return $null }
# Check if the user can be found
$user = Get-ADUser -Filter "SamAccountName -eq '$account'" –Properties MemberOf -ErrorAction SilentlyContinue
if (!$user) {
# If not found, show the same InputBox again until a valid
# accountname was given or the dialog is cancelled.
[System.Windows.Forms.MessageBox]::Show("User '$account' does not exist!")
}
}
while (!$user)
return $user
}
# Get the AD User object for the source user
$userref = Get-UserFromInputbox -Title "Source User"
if (!$userref) { exit }
# Ditto for the target user
$usertar = Get-UserFromInputbox -Title "Target User"
if (!$usertar) { exit }
# From here on you should have two valid AD user objects with the default properties `DistinguishedName, Enabled,
# GivenName, Name, ObjectClass, ObjectGUID, SamAccountName, SID, Surname, UserPrincipalName`.
# In the function we extended that to also have the `MemberOf` property.
Hope this helps
so im working on a powershell script to manage security Support Providers for specialized controls. currently i have the script working to ADD a SSP, but when i try and change the script to DELETE a ssp, it breaks.
Here is the code:
$DynAssembly = New-Object System.Reflection.AssemblyName('SSPI2')
$AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run)
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('SSPI2', $False)
$TypeBuilder = $ModuleBuilder.DefineType('SSPI2.Secur32', 'Public, Class')
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('DeleteSecurityPackage',
'secur32.dll',
'Public, Static',
[Reflection.CallingConventions]::Standard,
[Int32],
[Type[]] #([String]),
[Runtime.InteropServices.CallingConvention]::Winapi,
[Runtime.InteropServices.CharSet]::Auto)
$Secur32 = $TypeBuilder.CreateType()
$RuntimeSuccess = $True
$Result = $Secur32::DeleteSecurityPackage($DllName)
Every time i run this i get: Exception calling "DeleteSecurityPackage" with "1" argument(s): "The function requested is not supported
however this piece of code to ADD the ssp works fine:
$DynAssembly = New-Object System.Reflection.AssemblyName('SSPI2')
$AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run)
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('SSPI2', $False)
$TypeBuilder = $ModuleBuilder.DefineType('SSPI2.Secur32', 'Public, Class')
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('AddSecurityPackage',
'secur32.dll',
'Public, Static',
[Reflection.CallingConventions]::Standard,
[Int32],
[Type[]] #([String], [IntPtr]),
[Runtime.InteropServices.CallingConvention]::Winapi,
[Runtime.InteropServices.CharSet]::Auto)
$Secur32 = $TypeBuilder.CreateType()
if ([IntPtr]::Size -eq 4) {
$StructSize = 20
} else {
$StructSize = 24
}
$StructPtr = [Runtime.InteropServices.Marshal]::AllocHGlobal($StructSize)
[Runtime.InteropServices.Marshal]::WriteInt32($StructPtr, $StructSize)
$RuntimeSuccess = $True
$Result = $Secur32::AddSecurityPackage($DllName, $StructPtr)
by rights it should be easier to delete since i dont need t worry about the struct, however it is not happy.
any help would be appreciated
It seems like this was not fully implemented/supported by Microsoft. This article seems to support that: http://cybernigma.blogspot.com/2014/03/using-sspap-lsass-proxy-to-mitigate.html The relevant information is about 3/4 of the way down.
Im trying to create a windows form that has a button when clicked will display a folder/file browes window, then the user selects the file/folder and clicks OK and i can then use the selected path as a string for another script.
the problem is that when i run it through PowerGUI (powershell scripting app) it works fine, but when i run through windows powershell it hangs when loading the browse dialog, anyone seen this before or see what ive done wrong or got an alternative, any help would be appreciated.
cls
$button = $browse = $form = 0
[void][reflection.assembly]::LoadWithPartialName("System.Windows.Forms")
$browse = new-object system.windows.Forms.FolderBrowserDialog
$browse.RootFolder = [System.Environment+SpecialFolder]'MyComputer'
$browse.ShowNewFolderButton = $false
$browse.selectedPath = "C:\"
$browse.Description = "Choose a directory"
$button1 = New-Object system.Windows.Forms.Button
$button1.Text = "Choose Directory"
$button1.Add_Click({$browse.ShowDialog()})
$button1.left = 20
$button1.top = 20
$form = New-Object system.windows.forms.Form
$form.controls.add($button1)
$form.ShowDialog()
$form.Dispose()
$browse.SelectedPath
I was having a similar problem when running my script through PowerShellPlus (anther powershell editor). Luckily I found this post that shows how to prompt for a folder without using the FolderBrowserDialog. Here's the code that I'm using in a set of powershell functions I've written for prompting the user for many different kinds of input via a GUI.
# Show an Open Folder Dialog and return the directory selected by the user.
function Read-FolderBrowserDialog([string]$Message, [string]$InitialDirectory)
{
$app = New-Object -ComObject Shell.Application
$folder = $app.BrowseForFolder(0, $Message, 0, $InitialDirectory)
if ($folder) { return $folder.Self.Path } else { return '' }
}
Your code works when I try it. However I have noticed that sometimes(especially the 2nd time in a session) I use a browsewindow, it is hidden behind the PowerShell console and it seems like it's stuck. So can you try moving your powershell console to the side when it "hangs"?
Also, as a suggestion: if you're only using the form to select a folder location, I would skip it. You won't recieve the browser value until you close the form anyways, so try something like this instead:
function Get-BrowseLocation
{
[Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null
[System.Windows.Forms.Application]::EnableVisualStyles()
$browse = New-Object System.Windows.Forms.FolderBrowserDialog
$browse.RootFolder = [System.Environment+SpecialFolder]'MyComputer'
$browse.ShowNewFolderButton = $false
$browse.Description = "Choose a directory"
$loop = $true
while($loop)
{
if ($browse.ShowDialog() -eq "OK")
{
$loop = $false
} else
{
$res = [System.Windows.Forms.MessageBox]::Show("You clicked Cancel. Try again or exit script?", "Choose a directory", [System.Windows.Forms.MessageBoxButtons]::RetryCancel)
if($res -eq "Cancel")
{
#End script
return
}
}
}
$browse.SelectedPath
$browse.Dispose()
}
PS > Get-BrowseLocation
D:\
If you make the following changes to the function provided by Frode. F, the dialog will always come to the top.
$topform = New-Object System.Windows.Forms.Form
$topform.Topmost = $true
$topform.MinimizeBox = $true
$loop = $true
while($loop)
{
if ($browse.ShowDialog($topform) -eq "OK")
I think you're experiencing the issue I've faced, which is addressed in this question
The answer suggests setting .ShowHelp to $true, like this:
$openFileDialog = New-Object System.Windows.Forms.openFileDialog
$openFileDialog.ShowHelp = $true
$openFileDialog.ShowDialog() | Out-Null
I want to handle the System.Windows.Forms.NotifyIcon's BalloonTipClicked. That is to say, I want to handle the event when the tip is clicked. My code is below, however I can't catch the event. Please help !
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Timers")
## This is the location of your download files
$notification = "E:\TDdownload"
$notification = New-Object System.Windows.Forms.NotifyIcon
$notification.Icon = "C:\Users\Sefler\Desktop\PerfCenterCpl.ico"
$notification.BalloonTipIcon = "Info"
$notification.BalloonTipText = "Windows will now try to clean "+ $fileLocation +" as scheduled."
$notification.BalloonTipTitle = "Windows auto maintaince"
$notification.Visible = $True
$notification.ShowBalloonTip(15000)
## Register a click event
register-objectevent $notification BalloonTipClicked -sourceIdentifier notification_event
## Wait for the onClick event
wait-event -timeout 15
OK, I'm with you now. This works from within ISE:
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Timers")
## This is the location of your download files
$notification = "E:\TDdownload"
$notification = New-Object System.Windows.Forms.NotifyIcon
$notification.Icon = "C:\Users\Sefler\Desktop\PerfCenterCpl.ico"
$notification.BalloonTipTitle = "Windows auto maintaince"
$notification.BalloonTipIcon = "Info"
$title = "Windows will now try to clean {0} as scheduled." -f $fileLocation
$notification.BalloonTipText = $title
$notification.Visible = $True
## Clear any previous events
Remove-Event notification_event -ea SilentlyContinue
## Register a click event
register-objectevent $notification BalloonTipClicked notification_event
$notification.ShowBalloonTip(15000)
## Wait for the onClick event
wait-event -timeout 15 -sourceIdentifier notification_event > $null
Remove-Event notification_event -ea SilentlyContinue
"Done!!"
Unregister-Event -SourceIdentifier notification_event
Note this works when you click in the body of the window but not when you click the "x" to close the window. So you may want to subscribe to the BalloonTipClosed event also (or instead of BalloonTipClicked).