how can i change the event while closing my powershell gui? - powershell

I'm currently working on a powershell gui and i wanted to add a command to the closing event.
While starting the gui, i'm loading a session and i want to close it when leaving.
here is the part of my script:
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
[System.Windows.Forms.Application]::EnableVisualStyle()
$Form = New-Object System.Windows.Forms.Form
$Form.ClientSize = '1300,700'
$Form.Text = "Test close event"
$Form.Add_Closing({
Param($sender,$e)
$result = [System.Windows.Forms.MessageBox]::show(`
"wish to quit?",`
"quit",[System.Windows.Forms.MessageBoxButtons]::YesNoCancel)
If($result -ne [System.Windows.Forms.DialogResult]::Yes)
{
Get-PSSession |Remove-PSSession
$e.Cancel = $true
}
})
$session = New-PSSession -ConfigurationName Microsoft.exchange -URI "server" -Authentication Kerberos
Import-PSSession $session | Out-Null
... Rest of the script ...
$Form.ShowDialog()
The rest work fine but this part seems to pose problem.
If someone has an idea i'm interested.

If I understood correctly, your form on closing displays the "wish to quit?" question successfully, then it successfully executes Get-PSSession | Remove-PSSession. But once all finished you see your Exchange connection is still active.
If that's the case, the following approach should work - use "script:" scope for your $session variable.
code fragments:
$script:session = New-PSSession -ConfigurationName Microsoft.exchange -URI "server" -Authentication Kerberos
Import-PSSession $script:session | Out-Null
Remove-PSSession $script:session
Full code:
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
[System.Windows.Forms.Application]::EnableVisualStyle()
$Form = New-Object System.Windows.Forms.Form
$Form.ClientSize = '1300,700'
$Form.Text = "Test close event"
$Form.Add_Closing({
Param($sender,$e)
$result = [System.Windows.Forms.MessageBox]::show(`
"wish to quit?",`
"quit",[System.Windows.Forms.MessageBoxButtons]::YesNoCancel)
If($result -ne [System.Windows.Forms.DialogResult]::Yes)
{
Remove-PSSession $script:session
$e.Cancel = $true
}
})
$script:session = New-PSSession -ConfigurationName Microsoft.exchange -URI "server" -Authentication Kerberos
Import-PSSession $script:session | Out-Null
... Rest of the script ...
$Form.ShowDialog()
Note Since we are referencing session variable using "script:" prefix, you shall save your code in *.ps1 file and run it as a script, e.g. PS> C:\scripts\myscript.ps1
Reference:
about_Scopes

Related

New-Pssession in runspace does not connect to remote exchange server

I am trying to import Exchange Server session into runspace.addscript({
it is something like below
$PowerShell = [powershell]::Create()
$PowerShell.RunspacePool = $RunspacePool
#$PowerShell.AddCommand({New-PSSession});
#$PowerShell.AddParameter("ConfigurationName", "Microsoft.Exchange");
#$PowerShell.AddParameter("ConnectionUri","http://win2012-2/PowerShell/");
#$PowerShell.AddParameter("Credential", $ExchangeCredential);
#$PowerShell.AddParameter("Authentication", "Kerberos");
$PowerShell.AddScript({
param($FileName,$FilePath,$i_f)
[console]::WriteLine("script")
$User = "localdomain\administrator"
$Pass = "********"
$ExchangeCredential = New-Object -typename System.Management.Automation.PSCredential -argumentlist $User, $Pass
$ExchangeSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://win2012-2/PowerShell/ -Authentication Kerberos -Credential $ExchangeCredential
$Session = Import-PSSession $ExchangeSession -AllowClobber
$state = $Session.SessionState
[console]::WriteLine($state) | FT
But i could not get session information from $Session object or $state object,
how can i import the exchange session to runspace script?
any help would be appreciated
Thank you
[console]::WriteLine("foo") does not work inside a runspace, so you don't see any input. You can get around this by passing your current console's details ($host) to your scriptblock
I know you commented them out, but any parameters you're adding should be defined in the param() of your script block
I only have exchange-online, but this should work pretty similarly for either
# example of getting cred once at start
$UserCredential = Get-Credential
# create the PS session and assign a runspace
$PowerShell = [powershell]::Create()
$PowerShell.Runspace = [runspacefactory]::CreateRunspace()
$PowerShell.Runspace.Open()
# First, the script block
$Scriptblock = {
param($cred,$console)
# use $cred defined as a parameter
$ExchSession = New-PSSession -Credential $cred -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Authentication Basic
Import-PSSession $ExchSession -DisableNameChecking -AllowClobber
# test session and output to console
$m = get-mailbox user#domain.com
$console.UI.WriteLine($m.name)
Remove-PSSession $ExchSession
}
# Then add the script block to your runspace
# add Arguments in order, or add named Parameters
$powershell.AddScript($Scriptblock) | out-null
$powershell.AddArgument($UserCredential) | out-null
$powershell.AddArgument($host) | out-null
# run
$invokeInfo = $PowerShell.BeginInvoke()
# wait for completion, check output...
$PowerShell.Runspace.Dispose()
$PowerShell.Dispose()

How to run Command as a different user with Powershell?

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\

Insert Sharepoint Credentials using Powershell

When trying to open or sometimes close, via powershell, a word document in a sharepoint directory hosted in my company's network, the windows security box popup.
How can I authenticate this ? Here is part of my script:
$docpath = "\\sharepoint.[Domain].com\[...]\mydoc.docx"
$word = New-Object -ComObject Word.Application
$word.Visible = $true
$doc = $word.Documents.Open("$docpath")
{...process...}
$doc.Close([ref]$true)
$word.Quit()
$word = $null
[gc]::collect()
[gc]::WaitForPendingFinalizers()
Here is a visual example of what happens.
I´ve found something that works, but only if if have an admin user. Still would like to know if there is a way to do this without this kind of permission.
Here is the code:
$User = "domain\useradmin"
$Cred = Get-Credential -Credential $User
$srv = "sharepoint.[Domain].com"
Invoke-Command -ComputerName $srv -Credential $Cred -ScriptBlock{
$docpath = "\\sharepoint.[Domain].com\[...]\mydoc.docx"
$word = New-Object -ComObject Word.Application
$word.Visible = $true
$doc = $word.Documents.Open("$docpath")
{...process...}
$doc.Close([ref]$true)
$word.Quit()
$word = $null
}

Enter-Pssession not working

I have to machines in same network one with windows7 and another win windows server 2012.I tried Enter-PSsession on windows7 machine from server2012 machine...
$ComputerName = "windows7-PC"
$username="administrator"
$password="password"
$secstr = New-Object -TypeName System.Security.SecureString
$password.ToCharArray() | ForEach-Object {$secstr.AppendChar($_)}
$cr = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $secstr
$Session = New-PSSession -ComputerName $ComputerName -Credential $cr
Invoke-Command -Session $Session -ScriptBlock { echo '1' }
On doing same,i got an error
New-PSSession : [windows7-PC] Connecting to remote server windows7-PC failed with the following error message : Access is denied.
Invoke-Command : Cannot validate argument on parameter 'Session'. The argument is null or empty. Provide an
argument that is not null or empty, and then try the command again.
using same script i m able to execute 'echo 1' from windows7-pc to server2012-pc but not from server2012-pc to windows7-pc.
You need to add the remote server in trusted domain.
Please follow below article:
https://technet.microsoft.com/en-us/magazine/ff700227.aspx
This will surely help you.

Powershell - Some commands won't run with Invoke-Command

I am trying to send some commands from a server to about 50 clients running Powershell. Most commands work using Invoke-Command. I used the exact same format as my other commands, yet this one won't work. Basically I want to have each client fetch an .xml file from my server to import it later on. I am missing $credentials and other variables from my code sample here but they are setup correctly somewhere else in my script.
Permission wise, TrustedHosts in winrm is set to * and script execution is set to Unrestricted.
clear
$temp = RetrieveStatus
$results = $temp.up #Contains pinged hosts that successfully replied.
$profileName = Read-Host "Enter the profile name(XML file must be present in c:\share\profiles\)"
$File = "c:\profiles\profile.xml"
$webclient = New-Object System.Net.WebClient
$webclient.Proxy = $NULL
$ftp = "ftp://anonymous:anonymous#192.168.2.200/profiles/$profileName"
$uri = New-Object System.Uri($ftp)
$command = {write-host (hostname) $webclient.DownloadFile($uri, $File)}
foreach($result in $results)
{
# download profile from C:\share\profiles
Invoke-Command $result.address -ScriptBlock $command -Credential $credentials
# add profile to wireless networks
# Invoke-Command $result.address -ScriptBlock {write-host (hostname) (netsh wlan add profile filename="c:\profiles\$args[0].xml")} -argumentlist $profileName -Credential $credentials
}
I get the following error:
You cannot call a method on a null-valued expression.
+ CategoryInfo : InvalidOperation: (DownloadFile:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Any idea? The same command works flawlessly on the clients when run locally.
You use $webclient within a scriptblock where $webclient will not be defined on the other end. Why don't you create the web client in the scriptblock e.g.:
$command = {
param($profileName)
$File = "c:\profiles\profile.xml"
$webclient = New-Object System.Net.WebClient
$webclient.Proxy = $NULL
$ftp = "ftp://anonymous:anonymous#192.168.2.200/profiles/$profileName"
$uri = New-Object System.Uri($ftp)
Write-Host (hostname)
$webclient.DownloadFile($uri, $File)}
}
$profileName = Read-Host "Enter the profile name(XML file must be present in c:\share\profiles\)"
Invoke-Command $result.address -ScriptBlock $command -Credential $credentials -Arg $profileName
This will require you to provide some of the variables from the client to the remote machine via the -ArgumentList parameter on Invoke-Command. Those supplied arguments then map to the param() statement in the scriptblock.