[VOID] [reflection.assembly]::loadwithpartialname("System.Windows.Forms ");[reflection.assembly]::loadwithpartialname ("System.Drawing")
$notify = new-object system.windows.forms.notifyicon
$notify.icon = [System.Drawing.SystemIcons]::Information
$notify.visible = $true
$notify.showballoontip(10,"Operation Complete","All updates have been installed.",[system.windows.forms.tooltipicon]::None)
Is it possible to run this powershell script to display a popup balloon notification from a batch file with parameters to change the title and message?
This works:
#echo off
setlocal EnableDelayedExpansion
PowerShell.exe ^
[VOID] [reflection.assembly]::loadwithpartialname(\"System.Windows.Forms\"); ^
[reflection.assembly]::loadwithpartialname(\"System.Drawing\"); ^
$notify = new-object system.windows.forms.notifyicon; ^
$notify.icon = [System.Drawing.SystemIcons]::Information; ^
$notify.visible = $true; ^
$notify.showballoontip(10,\"Operation Complete\",\"All updates have been installed.\",[system.windows.forms.tooltipicon]::None)
In order to change any parameter just use the usual %replacement% value in the PS lines. Remember that these lines will be evaluated as a long Batch line, and then executed as a PowerShell command. For the same reason, all quotes must be preceded by back-slash.
You could do
#ECHO OFF
PowerShell.exe
[VOID] [reflection.assembly]::loadwithpartialname("System.Windows.Forms ");[reflection.assembly]::loadwithpartialname ("System.Drawing")
$notify = new-object system.windows.forms.notifyicon
$notify.icon = [System.Drawing.SystemIcons]::Information
$notify.visible = $true
$notify.showballoontip(10,"Operation Complete","All updates have been installed.",[system.windows.forms.tooltipicon]::None)
Look at http://www.howtogeek.com/204088/how-to-use-a-batch-file-to-make-powershell-scripts-easier-to-run/
Related
I have written a dice roller script. I have one with a single die and one with two dice. they both work in powershell, and the single die version works after converting to .exe using ps2exe. but the two die version runs as an exe but I get the following error "You cannot call a method on a null-valued expression"
Below is the 2 die script that gives the error after converting.
<#
.NAME
Random Dice Roller
#>
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
$Display1 = 1,2,3,4,5,6 | Get-Random
$Display2 = 1,2,3,4,5,6 | Get-Random
$LabelImage = [system.drawing.image]::FromFile("f:\psscripts\Die1.png")
$Form = New-Object system.Windows.Forms.Form
$Form.ClientSize = New-Object System.Drawing.Point(400,300)
$Form.text = "Roll The Dice"
$Form.TopMost = $false
$Form.location = New-Object System.Drawing.Point(1,1)
$Form.StartPosition = "CenterScreen"
$Die1 = New-Object system.Windows.Forms.Label
$Die1.Text = "$Display1"
$Die1.AutoSize = $false
$Die1.width = 200
$Die1.height = 200
$Die1.location = New-Object System.Drawing.Point(1,1)
$Die1.Font = New-Object System.Drawing.Font('Microsoft Sans Serif',150,[System.Drawing.FontStyle]([System.Drawing.FontStyle]::Bold))
$Die1.ForeColor = [System.Drawing.ColorTranslator]::FromHtml("#000000")
$Die1.BackgroundImage = $LabelImage
$Die2 = New-Object system.Windows.Forms.Label
$Die2.Text = "$Display2"
$Die2.AutoSize = $false
$Die2.width = 200
$Die2.height = 200
$Die2.location = New-Object System.Drawing.Point(200,1)
$Die2.Font = New-Object System.Drawing.Font('Microsoft Sans Serif',150,[System.Drawing.FontStyle]([System.Drawing.FontStyle]::Bold))
$Die2.ForeColor = [System.Drawing.ColorTranslator]::FromHtml("#000000")
$Die2.BackgroundImage = $LabelImage
$Button1 = New-Object System.Windows.Forms.Button
$Button1.Location = New-Object System.Drawing.Size(175,220)
$Button1.Size = New-Object System.Drawing.Size(80,50)
$Button1.Text = "Roll Me"
$Button1.Add_Click({Roll})
$Form.controls.AddRange(#($Die1,$Die2,$Button1))
$Die.Add_Click({ Roll })
#region Logic
function Roll{
$Form.Close()
$Form.Dispose()
.\Dice.exe}
#endregion
[void]$Form.ShowDialog()
There are two possible causes here:
Note that there is no safety in wrapping you PowerShell script in an .exe file. In fact the PowerShell script is extracted in a temporary folder and executed from there which might be the cause of your issue (e.g. the relative .\Dice.exe location)
It is unwise to do a $Form.Dispose() from within a form function/event
Remove that from the function and put it outside the form, e.g.:
[void]$Form.ShowDialog(); $Form.Dispose()
(Or do not use the Dispose method at all as PowerShell will usually already takes care of that if you [void] the $From.)
What is your motive for creating an EXE?
An alternative might be to create a CMD file with a Batch bootstrap instead. Create a CMD file with the following code and include your script after this.
<# :
#ECHO OFF
SET f0=%~f0
PowerShell -NoProfile -ExecutionPolicy RemoteSigned -Command ".([scriptblock]::Create((get-content -raw $Env:f0)))"
PAUSE
GOTO :EOF
<#~#>
# Insert PowerShell script after this line.
I'm trying to make a script that changes the HostnameAlias for a given dns record.
But only certain users have access to editing these records, for example ADMIN can edit it but CURRENTUSER cannot.
Currently I have this piece of code:
param(
[ValidateNotNull()]
[System.Management.Automation.PSCredential]
$Credential = $(Get-Credential)
)
$Command = "Set-DnsServerResourceRecord -NewInputObject $($NewObject) -OldInputObject $($OldObject) -ZoneName $($ZoneName)"
Start-Process -FilePath PowerShell -NoNewWindow -Credential $Credential -ArgumentList $Command
But i just keep getting Start-Process : This command cannot be run due to the error: The user name or password is incorrect even though I am absolutely sure they are indeed correct.
What am I doing wrong here.
Ps, I have looked at all the related questions, none seem to answer my question.
You can call System.Management.Automation.PSCredential object to specify any credentials you want and run with it in any process
$User = 'yourdomain\youruser'
$Password = 'yourpassword'
$Secure_Password = ConvertTo-SecureString $Password -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PSCredential($User, $Secure_Password)
$Command = "Set-DnsServerResourceRecord -NewInputObject $($NewObject) -OldInputObject $($OldObject) -ZoneName $($ZoneName)"
Start-Process -FilePath PowerShell -NoNewWindow -Credential $Credential -ArgumentList $Command
You can use this:
#Get User credential
$Credential = Get-Credential Domain\UserNameYouWant
#Use System.Diagnostics to start the process as User
$ProcessInfo = New-Object System.Diagnostics.ProcessStartInfo
#With FileName we're basically telling powershell to run another powershell process
$ProcessInfo.FileName = "powershell.exe"
#CreateNoWindow helps avoiding a second window to appear whilst the process runs
$ProcessInfo.CreateNoWindow = $true
#Note the line below contains the Working Directory where the script will start from
$ProcessInfo.WorkingDirectory = $env:windir
$ProcessInfo.RedirectStandardError = $true
$ProcessInfo.RedirectStandardOutput = $true
$ProcessInfo.UseShellExecute = $false
#The line below is basically the command you want to run and it's passed as text, as an argument
$ProcessInfo.Arguments = "The command you want"
#The next 3 lines are the credential for User as you can see, we can't just pass $Credential
$ProcessInfo.Username = $Credential.GetNetworkCredential().username
$ProcessInfo.Domain = $Credential.GetNetworkCredential().Domain
$ProcessInfo.Password = $Credential.Password
#Finally start the process and wait for it to finish
$Process = New-Object System.Diagnostics.Process
$Process.StartInfo = $ProcessInfo
$Process.Start() | Out-Null
$Process.WaitForExit()
#Grab the output
$GetProcessResult = $Process.StandardOutput.ReadToEnd()
# Print the Job results
$GetProcessResult
Just a mistake on my part, forgot to specify domain before username when entering credentials.
Can solve it like this Get-Credential Domain\
I am trying to create a batch file that will create a file that will send an email through powershell. It does many things, but email is just a snippet of it. Here is what I have so far:
REM Creates batch file with contents of the powershell script
echo "I need to add the below powershell script" > email.bat
echo "into email.bat with all the quotes included">> email.bat
echo "like what I'm doing now with appending text">> email.bat
REM powershell script to send email.
$smtp = new-object Net.Mail.SmtpClient("smtp.gmail.com")
if( $Env:SmtpUseCredentials -eq "true" ) {
$credentials = new-object Net.NetworkCredential("username","password")
$smtp.Credentials = $credentials
}
$objMailMessage = New-Object System.Net.Mail.MailMessage
$objMailMessage.From = "myemail#gmail.com"
$objMailMessage.To.Add("whereImsendingto#gmail.com")
$objMailMessage.Subject = "Logs for today"
$objMailMessage.Body = "(the logs)"
$smtp.send($objMailMessage)
In batch, I have the way to append text to another file down if what I'm adding does not have quotes, but I need to add text that includes quotes to the file.
Why don't you simply echo whithout quotes and escape possible chars <>|& with a caret ^ and double percent signs?
In a (code block) you've to also escape closing parentheses ^)
#Echo off
( Echo:$smtp = new-object Net.Mail.SmtpClient("smtp.gmail.com"^)
Echo:
Echo:if( $Env:SmtpUseCredentials -eq "true" ^) {
Echo: $credentials = new-object Net.NetworkCredential("username","password"^)
Echo: $smtp.Credentials = $credentials
Echo:}
Echo:$objMailMessage = New-Object System.Net.Mail.MailMessage
Echo:$objMailMessage.From = "myemail#gmail.com"
Echo:$objMailMessage.To.Add("whereImsendingto#gmail.com"^)
Echo:$objMailMessage.Subject = "Logs for today"
Echo:$objMailMessage.Body = "(the logs^)"
Echo:
Echo:$smtp.send($objMailMessage^)
) > "SomeFile.ps1"
PFB the code. I have tried to capture the output directly, but no luck. Then I tried to put the output into a log file and later capture the text from log file. That also didn't work. could you please tell me what is wrong in this.
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
$Form = New-Object System.Windows.Forms.Form
$Form.width = 600
$Form.height = 600
$Form.Text = "Form Title"
$Form.startposition = "centerscreen"
$Form.FormBorderStyle= [System.Windows.Forms.FormBorderStyle]::Fixed3D
Function ShowProcess(){
$Textbox1 = New-Object System.Windows.Forms.RichTextBox
#$text = Get-Process | Out-String
$Textbox1.Size = New-Object System.Drawing.Size(550, 400)
$Textbox1.Multiline = $true
$Textbox1.Font ="Lucida Console"
$Textbox1.WordWrap = $false
Start-Transcript -Path C:\Mywork\log.txt
&C:\Mywork\Script\test.bat
Stop-Transcript
$Textbox1.Text = Get-Content C:\Mywork\log.txt
$Form.Controls.Add($Textbox1)
}
$button1 = New-Object System.Windows.Forms.Button
$button1.Location = New-Object System.Drawing.Point(350, 450)
$button1.Size = New-Object System.Drawing.Size(120, 100)
$button1.Text = "Press"
$button1.FlatAppearance.BorderSize=0
$Form.Controls.Add($button1)
$button1.Add_Click({ShowProcess})
$Form.ShowDialog()
Below is the content of test.bat:
PS C:\Users\sghosh> Get-Content C:\Mywork\Script\test.bat
tree
pause
Remove pause from your batch file. It prompts the user for confirmation, but since you're running the script non-interactively from your PowerShell code it causes the batch script to hang. Thus no batch output ever gets to the form.
Change test.bat to this:
#echo off
tree
and change these lines in your PowerShell script
Start-Transcript -Path C:\Mywork\log.txt
&C:\Mywork\Script\test.bat
Stop-Transcript
$Textbox1.Text = Get-Content C:\Mywork\log.txt
to this:
$Textbox1.Text = & C:\Mywork\Script\test.bat *>&1 | Out-String
I'm new to Powershell and I am struggling with creating a script that'll return the file(s) chosen to the batch script I'm writing.
It's suppose to, when launched, open up a file browser where you can select multiple files and when the user confirms the selection, returns the file paths to the batch script.
This is what's in the batch file.
call :createPSscript
powershell -noprofile -noninteractive -executionpolicy unrestricted -Command "%~dp0FileSelector.ps1" >status
del FileSelector.ps1 >nul 2>&1
set /p status=<status
set /p queue=<queue
del status >nul 2>&1
echo %queue%
echo %status%
pause
:createPSscript
echo Add-Type -AssemblyName System.Windows.Forms>FileSelector.ps1
echo $openFileDialog = New-Object System.Windows.Forms.OpenFileDialog>>FileSelector.ps1
echo $openFileDialog.Title = "Select APK(s) to work with.">>FileSelector.ps1
echo $openFileDialog.InitialDirectory = [Environment]::GetFolderPath("Desktop")>>FileSelector.ps1
echo $openFileDialog.Filter = "Android App Package (*.apk)|*.apk|All files (*.*)|*.*">>FileSelector.ps1
echo $openFileDialog.MultiSelect = $true>>FileSelector.ps1
echo $openFileDialog.ShowHelp = $true>>FileSelector.ps1
echo $openFileDialog.AutoUpgradeEnabled = $true>>FileSelector.ps1
echo $openFileDialog.ShowDialog() > $null>>FileSelector.ps1
echo $stream = [System.IO.StreamWriter] "%~dp0queue">>FileSelector.ps1
echo 1 ^| %% $stream.WriteLine^($openFileDialog.Filenames^)>>FileSelector.ps1
echo $stream.close^(^)>>FileSelector.ps1
exit /b
And in the powershell script that the batch outputs to.
Add-Type -AssemblyName System.Windows.Forms
$openFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$openFileDialog.Title = "Select APK(s) to work with."
$openFileDialog.InitialDirectory = [Environment]::GetFolderPath("Desktop")
$openFileDialog.Filter = "Android App Package (*.apk)|*.apk|All files (*.*)|*.*"
$openFileDialog.MultiSelect = $true
$openFileDialog.ShowHelp = $true
$openFileDialog.AutoUpgradeEnabled = $true
$openFileDialog.ShowDialog()
$stream = [System.IO.StreamWriter] "C:\Users\<redacted>\<redacted>\queue"
1 | % $stream.WriteLine($openFileDialog.Filenames)
$stream.close()
It works perfectly fine when I use $openFileDialog.Filename instead of $openFileDialog.Filename
%Status% returns if the user canceled or not and %queue% should return the list of files.
Did I do the syntax correctly?
Annnnnnd I'm an idiot. Turns out just by invoking $openFileDialog.Filenames, it'll return the selected files to the output.