powershell send keys with $ not working correct here is the code
when i put the password with $ it types back as variable
$enter_password = Read-Host "Enter Your Password" -AsSecureString
$password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($enter_password))
$wshell = New-Object -ComObject wscript.shell;
Sleep 3
$wshell.SendKeys($password)
[System.Windows.Forms.SendKeys]::SendWait("$password")
exemple
password 1q2w3e$R%T^Y
i get 1q2w3e$R
how can i fix that?
Try to escape special characters:
$enter_password = Read-Host "Enter Your Password" -AsSecureString
$password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($enter_password))
$wshell = New-Object -ComObject wscript.shell;
$wshell.Run("notepad")
$wshell.AppActivate("notepad")
Sleep 3
$password = $password.Replace('%', '{%}').Replace('^','{^}')
$wshell.SendKeys("$password")
write-host $password
In case the input has brackets, clean up the text using the following
$cleanString = ""
$string.toCharArray() | foreach {
if ($_ -in $string){
$cleanString = $cleanString + "{" + $_ + "}"
}
else{
$cleanString = $cleanString + $_
}
}
If any character is a keyword, escape it with brackets
Related
I used to use a tiny utility called ScriptMan, it would sit in the system tray, and with two clicks it would copy the contents of my selected RTF to the clipboard. I haven't found an equivalent that works on Windows 10 and doesn't monitor the clipboard constantly, so I've tried to write my own in PowerShell. It's worked - almost...
After spending a bit of (way too much of!!) my afternoon/evening on StackOverflow and several other places, I've come up with the following script:
function RTF_to_Clipboard {
$ScriptName = $this.Tag
Write-Host "ScriptName = $ScriptName"
$LabelOutput.Text = "Button $ScriptName clicked"
$ScriptFilePath = "$ScriptsFolder$ScriptName"
Write-Host "$ScriptFilePath = $ScriptFilePath"
#https://stackoverflow.com/questions/65543792/how-to-write-contents-of-an-rtf-file-to- windows-clipboard-with-one-liner
Add-Type -AssemblyName System.Windows.Forms
$rtf = Get-Content -Path $ScriptFilePath
$IsRTF = ($rtf | Select-String '\{\\rtf1' -Quiet)
Write-Host "File $ScriptFilePath" (&{If($IsRTF) {"is"} Else {"IS NOT"}}) "an RTF file."
#[Windows.Forms.Clipboard]::SetText($rtf, [System.Windows.Forms.TextDataFormat]::Rtf)
#[Windows.Forms.Clipboard]::SetDataObject($rtf, $true)
[Windows.Forms.Clipboard]::SetText($rtf, [System.Windows.Forms.TextDataFormat]::Text)
Write-Host $rtf
}
This function is launched by a GUI:
# https://theitbros.com/powershell-gui-for-scripts/
$ScriptsFolder = 'C:\Users\me\OneDrive\Documents\IT\scripts\'
$Scripts = #(
'script 1 - multiline text.rtf',
'script 2 - single line text.rtf',
'script 3 - multiline RTF.rtf'
)
Add-Type -assembly System.Windows.Forms
#Now create the screen form (window) to contain elements:
$main_form = New-Object System.Windows.Forms.Form
#Set the title and size of the window:
$main_form.Text ='Copy Scripts to Clipboard'
$main_form.Width = 600
$main_form.Height = 400
#If the elements on the form are out of window bounds, use the AutoSize property to make the form automatically stretch.
$main_form.AutoSize = $true
#Create button and label for each item in the $Scripts array
$loopcount = 0
foreach($Command in $Scripts)
#for ($loopcount=0; $loopcount -lt $Scripts.count; $loopcount++)
{
$YPos = 25 * $loopcount + 5
$loopcount++
# $Command = $Scripts[$loopcount]
#Now put the button on the form:
Echo "Create button $loopcount for function $Command"
$Button = New-Object System.Windows.Forms.Button
$Button.Location = New-Object System.Drawing.Size(0,$YPos)
$Button.Size = New-Object System.Drawing.Size(60,23)
$Button.Text = "Load"
$Button.Tag = $Command
$Button.Add_Click({
$LabelOutput.Text = "$Command clicked"
Write-Host "$Command clicked"
RTF_to_Clipboard
# RTF_to_Clipboard -ScriptName $Command
})
$main_form.Controls.Add($Button)
#Create a label element on the form:
$Label = New-Object System.Windows.Forms.Label
$Label.Text = $Command
$Label.Location = New-Object System.Drawing.Point(70,$YPos)
$Label.AutoSize = $true
$main_form.Controls.Add($Label)
}
$LabelOutput = New-Object System.Windows.Forms.Label
$LabelOutput.Text = "No command selected yet"
$LabelOutput.Location = New-Object System.Drawing.Point(0,150)
$LabelOutput.AutoSize = $true
$main_form.Controls.Add($LabelOutput)
#Now you can display the form on the screen.
$main_form.ShowDialog()
The form buttons appear to be working, but not copying the text/RTF to the clipboard.
As you can guess from the script names, I have 3 test scripts:
Multi-line plain text
Single-line plain text
Rich Text Format
You can see also from the # remming lines out that I've tried a few methods that others have said they used:
[Windows.Forms.Clipboard]::SetText($rtf, [System.Windows.Forms.TextDataFormat]::Rtf)
This method pastes the plain text into MS word, but doesn't paste anything into NotePad++ or PuTTY (where I need them. The RTF is correct in MS Word (tables preserved), but throws a bunch of errors about "This is not a valid style name."
[Windows.Forms.Clipboard]::SetDataObject($rtf, $true)
The second method copies the single-line text to the clipboard no worries, and it pastes OK in NotePad++, PuTTY and MS Word. The multi-line text and RTF buttons appear to put nothing on the clipboard.
[Windows.Forms.Clipboard]::SetText($rtf, [System.Windows.Forms.TextDataFormat]::Text)
With the last method, the single-line scripts work fine, but the multi-line script all ends up on one line. RTF files get their raw data converted to text - i.e.: a tonne of RTF formating code displayed as plain text; again, all on one line:
{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch0\stshfloch31506\stshfhich31506\stshfbi31506\deflang2057\deflangfe2057\themelang2057\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi
\froman\fcharset0\fprq2{*\panose 02020603050405020304}Times New
Roman;}{\f0\fbidi \froman\fcharset0\fprq2{*\panose
02020603050405020304}Times New Roman;} {\f37\fbidi
\fswiss\fcharset0\fprq2{*\panose
020f0502020204030204}Calibri;}{\f38\fbidi
\fswiss\fcharset0\fprq2{*\panose
00000000000000000000}Tahoma;}{\flomajor\f31500\fbidi
\froman\fcharset0\fprq2{*\panose 02020603050405020304}Times New
Roman;} etc., etc., etc., etc., etc., etc., etc., etc., etc.....
When there is nothing pasting from the clipboard, the PowerShell console is still showing the text value of the files when I call Write-Host $rtf, so I know that $rtf = Get-Content -Path $ScriptFilePath worked each time.
Has anyone got any pointers as to how to get the multi-line text copied correctly to the clipboard at least?
I should mention that some of my multi-line scripts (the files that I'm trying to copy to the clipboard) are bash scripts, not sure if their content is breaking the PowerShell clipboard, e.g.:
alias pingAll="while true; do datenow=$(date -D "hh:mm:ss"|cut
-c12-19);echo -ne $datenow; echo -ne " -> VPN: "; if ping -q -c 1 -w 5 $VPN_Server_IP>/dev/null; then echo -ne "Up "; else echo -ne " Down"; fi; echo -ne " -> Server A: "; if ping -q -c 1 -w 5
$ServerA_IP>/dev/null; then echo -ne "Up "; else echo -ne "
Down"; fi; echo -ne " -> Server B: "; if ping -q -c 1 -w 5
$ServerB_IP>/dev/null ; then echo -ne "Up "; else echo -ne "
Down"; fi; echo ; sleep 5; done"
Version = ";grep "<version" /etc/stationInfo.xml |cut -f2 -d">"|cut
-f1 -d"<"; echo -ne "Firmware Revision = ";grep "<revision" /etc/stationInfo.xml |cut -f2 -d">"|cut -f1 -d"<"; echo -ne "Firmware
Grade = ";grep "<grade" /etc/stationInfo.xml |cut -f2 -d">"|cut -f1
-d"<"; echo -ne "Firmware Date = ";grep "<date" /etc/stationInfo.xml |cut -f2 -d">"|cut -f1 -d"<"'alias fwver='echo -ne "Firmware
I also tried Set-Clipboard -Path "c:\temp\script.rtf", but it pastes nothing into NotePad++, and pastes the text or RTF into MS word as an embedded object that needs to be opened to edit, not as inline text.
Any clues how to get this working?
Thanks for your help!
Cheers.
Here's the solution that I'm running now, works just as I want it (would be nice to hide the PowerShell output window, but not a problem).
I've removed the array of script paths, and have my script scan the script folder and grab every *.txt and *.rtf in the script folder instead. To add a new script, you just need to copy it to the script folder, no changes to this script required.
As I had too many scripts to fit on one screen, I now start a new column of buttons when half of them are displayed.
If a script contains "#", its label is set to red font, to make my email addresses stand out so I can grab them quickly. (Yes, I use this for even short things I need to type regularly. :) )
# Scott Critchley
# 16/02/2022
# With help from https://stackoverflow.com/questions/71149309/powershell-copy-rtf-to-cliboard-multiple-line-text-not-working?noredirect=1#comment125769903_71149309
# and https://stackoverflow.com/questions/65543792/how-to-write-contents-of-an-rtf-file-to-windows-clipboard-with-one-liner
# Detect if we're running in the ISE or not, so can exit the shell when done, but not when in ISE
# https://www.sapien.com/forums/viewtopic.php?t=14149#:~:text=Another%20way%20to%20determine%20what,'Windows%20PowerShell%20ISE%20Host'.
[bool]$ISE = 0
switch ($Host.Name){
ConsoleHost { }
PrimalScriptHostImplementation { }
'Windows PowerShell ISE Host' {
Write-Host 'Running in Windows PowerShell ISE Host'
$ISE = 1
}
}
#https://community.spiceworks.com/topic/1710213-hide-a-powershell-console-window-when-running-a-script?page=1#entry-5990631
$Script:showWindowAsync = Add-Type -MemberDefinition #"
[DllImport("user32.dll")]
public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
"# -Name "Win32ShowWindowAsync" -Namespace Win32Functions -PassThru
Function Show-Powershell()
{
$null = $showWindowAsync::ShowWindowAsync((Get-Process -Id $pid).MainWindowHandle, 10)
}
Function Hide-Powershell()
{
$null = $showWindowAsync::ShowWindowAsync((Get-Process -Id $pid).MainWindowHandle, 2)
}
function RTF_to_Clipboard {
# param (
# [string]$ScriptName
# )
$ScriptName = $this.Tag
Write-Host "ScriptName = $ScriptName"
$LabelOutput.Text = "Button: $ScriptName clicked"
$ScriptFilePath = "$ScriptsFolder$ScriptName"
Write-Host "ScriptFilePath = $ScriptFilePath"
#https://stackoverflow.com/questions/65543792/how-to-write-contents-of-an-rtf-file-to-windows-clipboard-with-one-liner
Add-Type -AssemblyName System.Windows.Forms
$rtf = Get-Content -Path $ScriptFilePath -Raw
$IsRTF = ($rtf | Select-String '\{\\rtf1' -Quiet)
Write-Host "File $ScriptFilePath" (&{If($IsRTF) {"is"} Else {"IS NOT"}}) "an RTF file."
if ( $IsRTF )
{
[Windows.Forms.Clipboard]::SetText($rtf, [System.Windows.Forms.TextDataFormat]::Rtf)
}
else
{
[Windows.Forms.Clipboard]::SetDataObject($rtf, $true)
}
}
# https://theitbros.com/powershell-gui-for-scripts/
$ScriptsFolder = 'C:\Users\me\OneDrive\Documents\IT\scripts\'
Add-Type -assembly System.Windows.Forms
#Now create the screen form (window) to contain elements:
$main_form = New-Object System.Windows.Forms.Form
#Set the title and size of the window:
$main_form.Text ='Copy Scripts to Clipboard'
$main_form.Width = 60
$main_form.Height = 40
#If the elements on the form are out of window bounds, use the AutoSize property to make the form automatically stretch.
$main_form.AutoSize = $true
#Create button and label for each item in the $Scripts array
$loopcount = 0
$XPos = 0
$YPosCount = 0
# All files in folder from #https://www.winhelponline.com/blog/how-to-change-shortcut-lnk-targets-in-bulk-using-script/
# As implemented in Update Shortcuts.ps1
$ScriptCount = (gci $ScriptsFolder\* -Include *.txt, *.rtf |Measure-Object ).Count
Write-Host "Total Script Count = $ScriptCount"
gci $ScriptsFolder\* -File -Include *.txt, *.rtf | foreach {
$Command = $_.Name
$YPos = 25 * $YPosCount + 5
$YPosCount++
$loopcount++
if ($loopcount -eq ([math]::floor($ScriptCount/2))){
Write-Host "XPos = $XPos"
$XPos = 370
$YPosCount = 0
$YPosMax = $YPos
}
#Now put the button on the form:
Echo "Create button $loopcount for function $Command at $XPos,$YPos"
$Button = New-Object System.Windows.Forms.Button
$Button.Location = New-Object System.Drawing.Size($XPos,$YPos)
$Button.Size = New-Object System.Drawing.Size(60,23)
$Button.Text = "Load"
$Button.Tag = $Command
$Button.Add_Click({
$LabelOutput.Text = "$Command clicked"
Write-Host "$Command clicked"
RTF_to_Clipboard
})
$main_form.Controls.Add($Button)
#Create a label element on the form:
$Label = New-Object System.Windows.Forms.Label
$Label.Text = $Command.Substring(0,$Command.Length - 4)
$LabelXPos = $XPos + 70
$Label.Location = New-Object System.Drawing.Point($LabelXPos,$YPos)
$Label.AutoSize = $true
if ($Command -like '*#*') {
$Label.ForeColor = 'Red'
$Label.BorderStyle = 'Fixed3D'
}
$main_form.Controls.Add($Label)
}
$YPos = $YPosMax + 5
$LabelOutput = New-Object System.Windows.Forms.Label
$LabelOutput.Text = "No command selected yet"
$LabelOutput.Location = New-Object System.Drawing.Point(0,$YPos)
$LabelOutput.AutoSize = $true
$main_form.Controls.Add($LabelOutput)
if($ISE)
{
Show-Powershell
}
else
{
Hide-Powershell
}
#Now you can display the form on the screen.
$main_form.ShowDialog()
if(-Not $ISE)
{[Environment]::Exit(1)}
I have a problem with an app that I am creating: this app can configure from a remote device a server/PC through IP, Username, Password. There is a script I made in PowerShell that can add User with password in server (New-LocalUser), but when I'll execute it, it gives me this error
Cannot bind parameter 'Password'. Cannot convert the "System.Security.SecureString" value of type "System.String" to
type "System.Security.SecureString".
The password is saved in a temporary file and convert into secure string in PS script, so I don't understand why it doesn't work
Here the script
$path = (Get-Location).ToString() + "\..\..\script\PS\lib.ps1"
Import-Module -Name $path
$json = (Get-Location).ToString() + "\..\..\misc\json\user.json"
$userinfo = Get-Content $json | ConvertFrom-Json
$uj = (Get-Location).ToString() + "\..\..\misc\json\userToAdd.json"
$commands = Get-Content $uj | ConvertFrom-Json
$passtype = $commands.passwordType
$pass = $commands.password
if($commands.isEnable -eq "False"){
$arg = '-Disabled '
}
if($commands.password -eq "")
{
$arg = $arg + $commands.passwordType + '-NoPassword '
}else{
$npass = $pass | ConvertTo-SecureString -AsPlainText -Force
$arg = $arg + $commands.passwordType + '-Password '
}
if($commands.Description -eq ""){
$desc = " "
}else{
$desc = " -Description " + $commands.Description + " "
}
$cmd = "New-LocalUser -Name " + $commands.Name + $desc + $arg + $npass
$cmd
$ScriptBlock = [scriptblock]::Create($cmd)
ExcuteRemoteCommand -serverAddress $userinfo.ip -ServerUsername $userinfo.user -ServerPassword $userinfo.password -code $ScriptBlock
if($commands.logon -eq "True"){
$cmd = "net user " + ($commands.Name).ToString() + " /logonpasswordchg:yes"
$cmd
$ScriptBlock = [scriptblock]::Create($cmd)
ExcuteRemoteCommand -serverAddress $userinfo.ip -ServerUsername $userinfo.user -ServerPassword $userinfo.password -code $ScriptBlock
}else{
$cmd = "net user " + ($commands.Name).ToString() + " /logonpasswordchg:no"
$cmd
$ScriptBlock = [scriptblock]::Create($cmd)
ExcuteRemoteCommand -serverAddress $userinfo.ip -ServerUsername $userinfo.user -ServerPassword $userinfo.password -code $ScriptBlock
}
Read-Host
Exit
I finally find a solution for my problem. I used the command NET, so here the che command line that I used
NET USER $user $pass /ADD
For the other parameters, I'll pass after it creates the user
$pass is NOT a secure string!
there!!
Here is my goal, I'm trying accomplish with Powershell script.
I have administrative user that need to be able extract csv file from password protected zip file and send this csv file by email.
Given directory has many zip files named by username (e.g. dana.zip) and protected with the same password (123456). The administrative user (who know the password for zip files) needs to run powershell script which asking for input desired user name and then do it's staff - extract file to the same directory and send it by email.
So far I find and adopt for above needs following powershell scripts.
Unzip Password protected file:
$7ZipPath = '"C:\Program Files\7-Zip\7z.exe"'
$User = Read-Host -Prompt 'Please Input Desired User Name'
write-host ""
write-host " --------------------------------------------------------------------------------- " -foregroundcolor DarkCyan
write-host ""
write-host " Desired file will be extracted to W:\ADMINISTRATION folder " -foregroundcolor Cyan
write-host ""
write-host " --------------------------------------------------------------------------------- " -foregroundcolor DarkCyan
write-host ""
$zipFile = '"W:\ADMINISTRATION\$User.zip"'
$zipFilePassword = "123456"
$command = "& $7ZipPath e -oW:\ADMINISTRATION -y -tzip -p$zipFilePassword $zipFile"
iex $command
This script doing it's job, but I'm trying to avoid usage of password as plain text in the script. Since this script will be run under same administrative user account I've tried to use encrypted password file in the script.
First, I've run following command to create encrypted password file:
"123456" | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString | Out-File "W:\Admin\ZipPassword.txt"
Afterwards I've adopt my script to use encrypted password file:
$7ZipPath = '"C:\Program Files\7-Zip\7z.exe"'
$User = Read-Host -Prompt 'Please Input Desired User Name'
write-host ""
write-host " --------------------------------------------------------------------------------- " -foregroundcolor DarkCyan
write-host ""
write-host " Desired file will be extracted to W:\\ADMINISTRATION folder " -foregroundcolor Cyan
write-host ""
write-host " --------------------------------------------------------------------------------- " -foregroundcolor DarkCyan
write-host ""
$zipFile = '"W:\ADMINISTRATION\$User.zip"'
$cred = Get-Content "W:\Admin\ZipPassword.txt" | ConvertTo-SecureString
$zipFilePassword = new-object -typename System.Management.Automation.PSCredential -argumentlist ($cred)
$command = "& $7ZipPath e -oW:\ADMINISTRATION -y -tzip -p$zipFilePassword $zipFile"
iex $command
When running this script I'm getting following error:
If it possible to make this script use encrypted password file it will me very beneficial...
The second script - sending extracted file by email.
First, I've created encrypted password file (in this script it 's working perfectly):
"myPassword" | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString | Out-File "W:\Admin\EmailPassword.txt"
And here is the script itself:
$User = "me.me#gmail.com"
$File = "W:\Admin\EmailPassword.txt"
$cred=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, (Get-Content $File | ConvertTo-SecureString)
$EmailTo = "me.me#gmail.com"
$EmailFrom = "me.me#gmail.com"
$Subject = "Some text here"
$Body = "Some text here"
$SMTPServer = "smtp.gmail.com"
$filenameAndPath = "W:\ADMINISTRATION\dana.csv"
$SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom,$EmailTo,$Subject,$Body)
$Attachment = New-Object System.Net.Mail.Attachment($filenameAndPath)
$SMTPMessage.Attachments.Add($attachment)
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential($cred.UserName, $cred.Password);
$SMTPClient.Send($SMTPMessage)
write-host "Mail Sent Successfully !!" -foregroundcolor Green
This script working as expected... The only problem is that administrative user need edit it each time and put proper filename (dana.csv, david.csc... etc). Of course I can use user input method in this script as well, but I want to combine both scripts into the single one... So far I tried this one:
$7ZipPath = '"C:\Program Files\7-Zip\7z.exe"'
$User = Read-Host -Prompt 'Please Input Desired User Name'
write-host ""
write-host " --------------------------------------------------------------------------------- " -foregroundcolor DarkCyan
write-host ""
write-host " Desired file will be extracted to W:\\ADMINISTRATION folder " -foregroundcolor Cyan
write-host ""
write-host " --------------------------------------------------------------------------------- " -foregroundcolor DarkCyan
write-host ""
$zipFile = '"W:\ADMINISTRATION\$User.zip"'
$zipFilePassword = "123456"
$command = "& $7ZipPath e -oW:\ADMINISTRATION -y -tzip -p$zipFilePassword $zipFile"
iex $command
$User = "me.me#gmail.com"
$File = "W:\Admin\EmailPassword.txt"
$cred=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, (Get-Content $File | ConvertTo-SecureString)
$EmailTo = "me.me#gmail.com"
$EmailFrom = "me.me#gmail.com"
$Subject = "Some text here"
$Body = "Some text here"
$SMTPServer = "smtp.gmail.com"
$filenameAndPath = "W:\ADMINISTRATION\$User.csv"
$SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom,$EmailTo,$Subject,$Body)
$Attachment = New-Object System.Net.Mail.Attachment($filenameAndPath)
$SMTPMessage.Attachments.Add($attachment)
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential($cred.UserName, $cred.Password);
$SMTPClient.Send($SMTPMessage)
write-host "Mail Sent Successfully !!" -foregroundcolor Green
But it's failed to attach file to email. I think I have problem here (wrong syntax):
$filenameAndPath = "W:\ADMINISTRATION\$User.csv"
So, if someone can help me to fix following issues, it will be much appreciated:
In the first portion of script, use encrypted password file instead of plain text
In the second portion, adopt user input from the first part of the script ($User) to be used as file name (for instance, if user input was "dana" , $User.csv will be equal to dana.csv)
Remove *.csv file after mail was sent.
Thank you in advance,
Igor.
I've fixed all the issues after "googling" them, So I can share my experience...
In the first portion of script, use encrypted password file instead of plain text
Like TheIncorrigible1 mentioned in his answer on my question:
You cannot completely avoid having a reversible password in your
script while using an external command like 7z unless it also supports
encrypted passwords being passed to it. SecurePassword is a
Windows-specific construct.
It looks like 7zip not supporting Windows-specific encrypted password, so I need convert it back to plain text before using it.
I've found how to do it in those sites:
https://blogs.msdn.microsoft.com/timid/2009/09/10/powershell-one-liner-decrypt-securestring/#comment-6495
and
http://www.travisgan.com/2015/06/powershell-password-encryption.html
So this peace of code helped me out fixing encrypted password issue:
$Password = Get-Content 'W:\Administration\EncryptedPasswords\ZipPassword.txt'| ConvertTo-SecureString
$Marshal = [System.Runtime.InteropServices.Marshal]
$Bstr = $Marshal::SecureStringToBSTR($Password)
$ZipPassword = $Marshal::PtrToStringAuto($Bstr)
$Marshal::ZeroFreeBSTR($Bstr)
In the second portion, adopt user input from the first part of the script ($User) to be used as file name (for instance, if user input
was "dana" , $User.csv will be equal to dana.csv)
This was my mistake,- I've used the same variable $User in the first and second portions of script, so $User variable from second portion of script override existing one... Therefore file wasn't attached to email. After changing variable in the first portion of script, issue goes away:
$Username = Read-Host -Prompt 'Please Input Desired User Name'....
$zipFile = "W:\ADMINISTRATION\$UserName.zip"...
$filenameAndPath = "W:\ADMINISTRATION\$UserName.csv"
Remove *.csv file after mail was sent.
I've accomplished this goal using separate PowerShell script:
Get-ChildItem W:\Administration\*.csv | Where { ! $_.PSIsContainer } | remove-item
write-host " ---------------------------------------------- " -foregroundcolor DarkCyan
write-host ""
write-host " All Operations Completed Successfully !!" -foregroundcolor Green
write-host ""
write-host " ---------------------------------------------- " -foregroundcolor DarkCyan
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"
Below is the code to an internal tool I was put in charge of setting up. It basically references a spreadsheet based on a known value and uses some of that information for sorting purposes and uses other information to populate the automated email. I've had several versions of it working but it seems that for whatever reason it acts like one of the variables isn't populated or is no longer accepting a string as a valid data type. I'm rather new to stack exchange so if there is any formatting or anything I could do to clear up what seems to be the issue, I'll be happy to oblige.
echo off #hiding my stuff
$Setup = Test-Path "$env:APPDATA\ExcelLocation.txt"
Function Get-FileName($initialDirectory)
{
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$OpenFileDialog.initialDirectory = $initialDirectory
$OpenFileDialog.filter = "XLSX (*.xlsx)| *.xlsx"
$OpenFileDialog.ShowDialog() | Out-Null
$OpenFileDialog.filename
}
if($Setup -eq $False){
Write-Host "Please participate in 1st time setup!"
$FilePath = Get-FileName "$env:USERPROFILE\Downloads\"
$FilePath | Out-File "$env:APPDATA\ExcelLocation.txt"
$Setup -eq $True
}
$FilePath = Get-Content -Path "$env:APPDATA\ExcelLocation.txt"
Write-Host $FilePath
$DealerCodeLookup = Read-Host -Prompt 'Please put in the Dealer code.'
#Specify the path of the excel file
#$FilePath = "C:\Users\LAB\Downloads\2017 02 Custom Cellular Hierarchy.xlsx"
#Specify the Sheet name
$SheetName = "Sheet1"
# Create an Object Excel.Application using Com interface
$objExcel = New-Object -ComObject Excel.Application
# Disable the 'visible' property so the document won't open in excel
$objExcel.Visible = $false
# Open the Excel file and save it in $WorkBook
$Workbook = $objExcel.Workbooks.Open($FilePath, 2, $True)
# Load the WorkSheet 'BuildSpecs'
$WorkSheet = $WorkBook.sheets.item($SheetName)
#$WorkBook.sheet | Select-Object -Property Name
$Row = 1
$Column = 5
$Found = $False
while (($WorkSheet.Cells.Item($Row, $Column).Value() -ne $Null) -and ($Found -eq $False)) {
#^-- looping though the excel list, updating the row. Stop if Cell is Empty or Value is Found
If (($WorkSheet.Cells.Item($Row, $Column).Value()).ToUpper() -eq $DealerCodeLookup.ToUpper()) {
#^-- Cell value equals $Arg
$locale = $WorkSheet.Cells.Item($Row, $Column+1).Value()
$State =$WorkSheet.Cells.Item($Row, $Column+10).Value()
$Adrs = $WorkSheet.Cells.Item($Row, $Column+7).Value(),$WorkSheet.Cells.Item($Row, $Column+9).Value(),
$WorkSheet.Cells.Item($Row, $Column+10).Value(),$WorkSheet.Cells.Item($Row, $Column+11).Value()
$Found = $True
}
$Row += 1 #Continue to the next row
}
Write-Host $State
$LastRow = $WorkSheet.UsedRange.rows.count + 1
if($Row = $LastRow -and $Found -eq $False){
Write-Host "What you put in is not a valid dealer code!"
$objExcel.quit()
exit
}
$objExcel.quit()
#$DealerCode = Read-Host -Prompt 'Please put in the Dealer code.' #stores the dealer code
$DealerName = 'CUSTOM CELLULAR' #Default dealer name (we are custom cellular)
#$Locale = Read-Host -Prompt 'Please put in the Location name.' #This stores the human location name
#$Address = Read-Host -Prompt 'Please put in the Location Address.' #This stores their address and the thing we use to determine the email address that is sent.
$SoftTokenAmount = Read-Host -Prompt 'Please put in the amount of tokens needed.' #This stores the amount of tokens needed
$Reason = Read-Host -Prompt 'Why do you have to order these tokens??' #This stores the reason for our request
#$SoutheastArea = '* MO *','* KS *','* IL *','* WI *','* MN *','* IA *','* IN *','* NE *' <--possible more efficient usage of the determining loop
#Below is the if statement that determes the Region(SoutheastArea,CenteralArea,WesternArea)
#This specific loop is for the SoutheastArea
if($State -like '*MO*' -or ($State -like '*KS*') -or ($State -like '*IL*') - or ($State -like '*WI*') -or ($State -like '*MN*') -or ($State -like '*IA*')-or ($State -like '*IN*') -or ($State -like '*NE*'))
{
$To = "shalasere1#gmail.com"
}
#This loop is for the CentralArea
Elseif($State -like '*TN*' -or ($State -like '*GA*'))
{
$To = "shalasere2#gmail.com"
}
#This loop is for the WesternArea
Elseif($State -like '*CO*' -or ($State -like '*UT*'))
{
$To = "shalasere3#gmail.com"
}
$From = "tokenrequest#ccinational.com" #Default from email, mine.
#$Cc = "YourBoss#YourDomain.com" #Optional CC'd users to said email (possibly yours.)
$Subject = "Token Request" #The subject of the email
#Below is the default contents of the email including the variables entered above.
$Body = "
New/Replacement Token Request:
Dealer Name: $DealerName
Dealer Code: $DealerCodeLookup
Location: $locale
(office name)
Address: $Adrs
Dealer Email:
Amount of Soft Tokens Needed: $SoftTokenAmount
Reason for Request: $Reason"
#This final chuck is the actual sending an email smtp information for gmail
$SMTPServer = "smtp.office.com"
$SMTPPort = "587"
$secpasswd = ConvertTo-SecureString "publicpass" -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential ("TokenRequest#whereiwork.com", $secpasswd)
Send-MailMessage -From $From -to $To -Subject $Subject `
-Body $Body -SmtpServer $SMTPServer -dno onSuccess, onFailure -port $SMTPPort -UseSsl `
-Credential $mycreds
#= New-Object System.Management.Automation.PSCredential ("TokenRequest#whereiwork.com", $secpasswd)
#(new-object System.Net.NetworkCredential("scott","","ccin****.com"))
#(Get-Credential) #<- this line prompts for the outlook login of the default email (mine.) User is jacob#r**** and password is 8888!
Send-MailMessage : A positional parameter cannot be found that accepts argument '='.
At G:\Token Request v2.0.ps1:144 char:1
+ Send-MailMessage -From $From -to $To -Subject $Subject `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Send-MailMessage], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.SendMailMessage
Seems that it was required to have a single ' around the from subject to be passed correctly.