I am making a web panel to manage my hyper-v.
I want to manage IP locally with my panel, but windows basic hyper-v powershell option doesn't have assign IP function.
How can I assign an IP to Hyper-V VM with Host's Powershell?
Solved with using this script:
Function Set-VMNetworkConfiguration {
[CmdletBinding()]
Param (
[Parameter(Mandatory=$true,
Position=1,
ParameterSetName='DHCP',
ValueFromPipeline=$true)]
[Parameter(Mandatory=$true,
Position=0,
ParameterSetName='Static',
ValueFromPipeline=$true)]
[Microsoft.HyperV.PowerShell.VMNetworkAdapter]$NetworkAdapter,
[Parameter(Mandatory=$true,
Position=1,
ParameterSetName='Static')]
[String[]]$IPAddress=#(),
[Parameter(Mandatory=$false,
Position=2,
ParameterSetName='Static')]
[String[]]$Subnet=#(),
[Parameter(Mandatory=$false,
Position=3,
ParameterSetName='Static')]
[String[]]$DefaultGateway = #(),
[Parameter(Mandatory=$false,
Position=4,
ParameterSetName='Static')]
[String[]]$DNSServer = #(),
[Parameter(Mandatory=$false,
Position=0,
ParameterSetName='DHCP')]
[Switch]$Dhcp
)
$VM = Get-WmiObject -Namespace 'root\virtualization\v2' -Class 'Msvm_ComputerSystem' | Where-Object { $_.ElementName -eq $NetworkAdapter.VMName }
$VMSettings = $vm.GetRelated('Msvm_VirtualSystemSettingData') | Where-Object { $_.VirtualSystemType -eq 'Microsoft:Hyper-V:System:Realized' }
$VMNetAdapters = $VMSettings.GetRelated('Msvm_SyntheticEthernetPortSettingData')
$NetworkSettings = #()
foreach ($NetAdapter in $VMNetAdapters) {
if ($NetAdapter.Address -eq $NetworkAdapter.MacAddress) {
$NetworkSettings = $NetworkSettings + $NetAdapter.GetRelated("Msvm_GuestNetworkAdapterConfiguration")
}
}
$NetworkSettings[0].IPAddresses = $IPAddress
$NetworkSettings[0].Subnets = $Subnet
$NetworkSettings[0].DefaultGateways = $DefaultGateway
$NetworkSettings[0].DNSServers = $DNSServer
$NetworkSettings[0].ProtocolIFType = 4096
if ($dhcp) {
$NetworkSettings[0].DHCPEnabled = $true
} else {
$NetworkSettings[0].DHCPEnabled = $false
}
$Service = Get-WmiObject -Class "Msvm_VirtualSystemManagementService" -Namespace "root\virtualization\v2"
$setIP = $Service.SetGuestNetworkAdapterConfiguration($VM, $NetworkSettings[0].GetText(1))
if ($setip.ReturnValue -eq 4096) {
$job=[WMI]$setip.job
while ($job.JobState -eq 3 -or $job.JobState -eq 4) {
start-sleep 1
$job=[WMI]$setip.job
}
if ($job.JobState -eq 7) {
write-host "Success"
}
else {
$job.GetError()
}
} elseif($setip.ReturnValue -eq 0) {
Write-Host "Success"
}
}
Related
I would like to create a powershell script to perform a TCP port scanner that can list the open TCP ports for a given IP address.
here is what I did so far, this is not perfect and I would love some feedback and corrections
port = (80)
network = (192.168.0)
ErrorActionPreference= ‘silentlycontinue’
{ $ip = “{0}.{1}” –F $network,$add
If(Test-Connection –BufferSize 32 –Count 1 –quiet –ComputerName $ip)
{ $socket = new-object System.Net.Sockets.TcpClient($ip, $port)
the problem with this is doesn't scan all the TCP port, and I am not sure how to make it do that.
There are modules you can leverage for this use case.
Find-Module -Name '*nmap*' |
Format-Table -AutoSize
<#
Version Name Repository Description
------- ---- ---------- -----------
1.0.7 xNmap PSGallery Powershell DSC Configuration Script for installing Nmap versions 6.49 (Beta 4), 6.47, 6.46, 6.45, 6.40, and 6.25...
0.6.0 PoshNmap PSGallery A wrapper for NMAP Network Discovery
1.3.1 PSnmap PSGallery Svendsen Tech's PSnmap is an asynchronous Linux nmap look-alike for PowerShell. Ping sweeps and scans a network (accepts CIDR notation) for s...
...
#>
Why not use the purpose-built cmdlet for this use case?
# get function / cmdlet details
Get-Command -Name Test-NetConnection -Syntax
(Get-Command -Name Test-NetConnection).Parameters.Keys
Get-help -Name Test-NetConnection -Full
Get-help -Name Test-NetConnection -Online
Get-help -Name Test-NetConnection -Examples
Point of note:
Earlier Windows PowerShell versions do not have Test-NetConnection if that is your use case, but even then, why do this from scratch, vs leveraging existing samples and tweaking as needed?
Well, unless this is just a learning exercise. Even then that does not mean you'd not look to other examples first.
'powershell tcp port scanner'
Samples provided by the search string.
# Example 01
<#
Creating a Port Scanner with Windows PowerShell
https://devblogs.microsoft.com/scripting/creating-a-port-scanner-with-windows-powershell
#>
# Creating a Port Scanner with Windows PowerShell
$port = 80
$net = “192.168.0”
$range = 1..254
foreach ($r in $range)
{
$ip = “{0}.{1}” -F $net,$r
if(Test-Connection -BufferSize 32 -Count 1 -Quiet -ComputerName $ip)
{
$socket = new-object System.Net.Sockets.TcpClient($ip, $port)
If($socket.Connected)
{
"$ip listening to port $port"
$socket.Close() }
}
}
# Example 02
<#
Port scan subnets with PSnmap for PowerShell
https://www.powershelladmin.com/wiki/Port_scan_subnets_with_PSnmap_for_PowerShell
#>
# Port scan subnets with PSnmap for PowerShell
#$computer, $port = $args[0,1] # assign values to these
$mysock = new-object net.sockets.tcpclient
$IAsyncResult = [IAsyncResult] $mysock.BeginConnect($computer, $port, $null, $null)
measure-command { $succ = $iasyncresult.AsyncWaitHandle.WaitOne(3000, $true) } | % totalseconds
$succ
$mysock.Connected
$mysock.Dispose()
# Example 03:
<#
A Simple Network Port Scanner in PowerShell
https://www.nextofwindows.com/a-simple-network-port-scanner-in-powershell
#>
# #requires -Version 1
function Test-Port
{
Param([string]$ComputerName,$port = 5985,$timeout = 1000)
try
{
$tcpclient = New-Object -TypeName system.Net.Sockets.TcpClient
$iar = $tcpclient.BeginConnect($ComputerName,$port,$null,$null)
$wait = $iar.AsyncWaitHandle.WaitOne($timeout,$false)
if(!$wait)
{
$tcpclient.Close()
return $false
}
else
{
# Close the connection and report the error if there is one
$null = $tcpclient.EndConnect($iar)
$tcpclient.Close()
return $true
}
}
catch
{
$false
}
}
.
Hello, Team!
I have pretty nice solution.
Advances:
Parallel scan multiple ports
Support TCP, UDP protocols
Show banner from remote
Configured parameters
EXAMPLE:
Test-Port -ComputerName $ComputerName -Port $Port [-Protocol $Protocol="TCP"] [-Timeout $Timeout=1000] [-ThrottleLimit $ThrottleLimit=1024] [-ReceiveBufferSize $ReceiveBufferSize=2048] [-PortHelper $PortHelper] [-Banner $Banner]
PS. Tested on powershell 7
function Test-Port {
<#
.SYNOPSIS
Test port
.EXAMPLE
Test-Port -ComputerName $ComputerName -Port $Port [-Protocol $Protocol="TCP"] [-Timeout $Timeout=1000] [-ThrottleLimit $ThrottleLimit=1024] [-ReceiveBufferSize $ReceiveBufferSize=2048] [-PortHelper $PortHelper] [-Banner $Banner]
.NOTES
AUTHOR Alexk
CREATED 07.04.21
VER 1
#>
[CmdletBinding()]
param (
[Parameter( Mandatory = $true, Position = 0, HelpMessage = "Computer name." )]
[string] $ComputerName,
[Parameter( Mandatory = $true, Position = 1, HelpMessage = "Port number." )]
[int[]] $Port,
[Parameter( Mandatory = $false, Position = 2, HelpMessage = "Protocol name." )]
[ValidateSet("TCP","UDP")]
[string] $Protocol = "TCP",
[Parameter( Mandatory = $false, Position = 3, HelpMessage = "Connection timeout in milliseconds." )]
[int] $Timeout = 1000,
[Parameter( Mandatory = $false, Position = 4, HelpMessage = "Simultanius thread number." )]
[int] $ThrottleLimit = 1024,
[Parameter( Mandatory = $false, Position = 5, HelpMessage = "Receive buffer size in bytes." )]
[int] $ReceiveBufferSize = 2048,
[Parameter( Mandatory = $false, Position = 6, HelpMessage = "Port helper. Help object with details oboit ports." )]
[PSobject[]] $PortHelper,
[Parameter( Mandatory = $false, Position = 7, HelpMessage = "Get remote banner." )]
[switch] $Banner
)
begin {
$result = #()
}
process {
$result += $Port | ForEach-Object -Parallel {
try {
$ComputerName = $Using:ComputerName
$Protocol = $Using:protocol
$Timeout = $Using:Timeout
$Banner = $Using:Banner
$ReceiveBufferSize = $Using:ReceiveBufferSize
$Port = $_
$Result = $Null
if ( $protocol -eq "TCP" ){
$Client = [System.Net.Sockets.TcpClient]::new()
[void] $Client.ConnectAsync( $ComputerName, $Port ).Wait( $Timeout )
$Connected = $Client.Connected
}
Else {
$Client = [System.Net.Sockets.UdpClient]::new()
[void] $Client.Connect( $ComputerName, $Port )
$Connected = $True
}
$PSO = [PSCustomObject]#{
RemoteHostname = $ComputerName
Protocol = $protocol
RemotePort = $Port
Opened = $Connected
TimeoutInMillisecond = $Timeout
SourceHostname = $env:COMPUTERNAME
}
if ( $Banner -and $Connected -and ( $Protocol -eq "TCP" ) ){
$Stream = $Client.GetStream()
$Stream.ReadTimeOut = $Timeout
if ( $Stream.CanRead ){
$Data = [System.Byte[]]::new( $ReceiveBufferSize )
[void] $Stream.Read( $Data, 0, $Data.Length ) #| Out-Null
$BannerText = ( [System.Text.Encoding]::ASCII.GetString( $Data ) ).Trim( [char]$null )
}
$Stream.Dispose()
$PSO | Add-Member -NotePropertyName "Banner" -NotePropertyValue $BannerText
}
$Client.Dispose()
$result = $PSO
}
Catch {
switch ( $_.Exception.HResult ) {
-2146233087 {
#timeout
if ( $Stream ){
$Stream.Dispose()
}
$Client.Dispose()
$PSO | Add-Member -NotePropertyName "Banner" -NotePropertyValue ""
$result = $PSO
}
Default {
Add-ToLog -Message "Error while connecting [$ComputerName] on [$( $protocol ):$( $Port )].`n$_" -logFilePath $Global:gsScriptLogFilePath -Display -category "test-port" -Status "error"
$result = #()
}
}
}
return $result
} -ThrottleLimit $ThrottleLimit
}
end {
if ( $PortHelper ){
foreach ( $item in $result ){
$Selected = $PortHelper | Where-Object { ( $_.Port -eq $item.RemotePort ) -and ( $item.Protocol -in ($_.Protocol.split(',')) )}
if ( $Selected ){
$item | Add-Member -NotePropertyName 'Description' -NotePropertyValue "$($Selected.Description) ($($Selected.Status))"
}
}
}
return $result
}
}
I'm trying to develop 2 functions with Powershell. The first, will check my database status (online/offline). The second function should loop on the first function until a certain state is achieve.
function Get-DBStatus
{
<# .. removed help section for brevity .. #>
[CmdletBinding()]
[OutputType([System.Object])]
param
(
[Parameter(Mandatory = $true)]
[String]$ServerName,
[Parameter(Mandatory = $true)]
[String]$ServerUser,
[Parameter(Mandatory = $true)]
[String]$ServerPassword,
[Parameter(Mandatory = $true)]
[String]$DatabaseName,
)
try
{
$params = #{ ... }
$dbStatus = Invoke-SqlConnection #params | Where-Object {$_.Name -match $AltDBName }
}
catch
{
Write-Error -Message ('An error has occured while ...')
}
if ([String]::IsNullOrEmpty($dbStatus) -eq $false)
{
$dbStatus
}
# <<< function Get-DbStatusOnlyIf
# <<< same parameters as the function above
# <<< get the desired status as a new parameter
# <<< loop the function above until the desired status is achieved or a timeout is reached
}
I'm new to Powershell and I think I shouldn't repeat myself rewriting the same parameters from the first function into the second one since they're dependent. However, I might be wrong, thus the question.
Thank you for your assistance!
You have to rewrite this parameters on your second function and pass them through or add another paramter to your first function that will do the looping. I would go with the second solution.
Try something like that
function Get-DBStatus {
<# .. removed help section for brevity .. #>
[CmdletBinding()]
[OutputType([System.Object])]
param
(
[Parameter(Mandatory = $true)]
[String]$ServerName,
[Parameter(Mandatory = $true)]
[String]$ServerUser,
[Parameter(Mandatory = $true)]
[String]$ServerPassword,
[Parameter(Mandatory = $true)]
[String]$DatabaseName,
$WaitForStatus, #or something like that
[int]$Timeout=10
)
do {
try {
#$params = #{ ... }
$dbStatus = Invoke-SqlConnection #params | Where-Object {$_.Name -match $AltDBName }
}
catch {
Write-Error -Message ('An error has occured while ...')
return
}
if ([String]::IsNullOrEmpty($dbStatus) -eq $false) {
if ($WaitForStatus){
if ($dbStatus -eq $WaitForStatus) {
$dbStatus
$EndLoop = $true
}
else {
Write-Host -NoNewline "." #only for test
Start-Sleep -Seconds 1
$Timeout -= 1
}
}
else{
$dbStatus
$EndLoop = $true
}
}
}
until ($EndLoop -or $Timeout -eq 0)
}
or with recursion
function Get-DBStatus {
<# .. removed help section for brevity .. #>
[CmdletBinding()]
[OutputType([System.Object])]
param
(
[Parameter(Mandatory = $true)]
[String]$ServerName,
[Parameter(Mandatory = $true)]
[String]$ServerUser,
[Parameter(Mandatory = $true)]
[String]$ServerPassword,
[Parameter(Mandatory = $true)]
[String]$DatabaseName,
$WaitForStatus, #or something like that
[int]$timeout = 3
)
if ($WaitForStatus) {
$start = Get-Date
while (((get-date) - $start).TotalSeconds -lt $timeout) {
$res = Get-DBStatus -ServerName $ServerName -ServerUser $ServerUser -ServerPassword $ServerPassword -DatabaseName $DatabaseName
if ($WaitForStatus -eq $res) {
return $res
}
Start-Sleep -Seconds 1
}
}
else {
try {
$params = #{ ... }
$dbStatus = Invoke-SqlConnection #params | Where-Object {$_.Name -match $AltDBName }
}
catch {
Write-Error -Message ('An error has occured while ...')
}
if ([String]::IsNullOrEmpty($dbStatus) -eq $false) {
$dbStatus
}
}
}
function contactOU
{
#This selects which OU to place the contact in.
write-host
write-host '~Contact type~'
write-host '1. Admin'
write-host '2. Assistant Owner'
write-host '3. Owner Partner'
write-host '4. Owner'
write-host '5. Team Leader'
write-host
$contacttype = (Read-host -prompt 'Which type of contact')
if($contacttype = "1") {$contactOU = "OU=Admins,OU=Marketing Companies,OU=Contacts,DC=company,DC=com,DC=au"}
if($contacttype = "2"){$contactOU = "OU=Assistant Owners,OU=Marketing Companies,OU=Contacts,DC=company,DC=com,DC=au"}
if($contacttype = "3"){$contactOU = "OU=Owner Partner,OU=Marketing Companies,OU=Contacts,DC=company,DC=com,DC=au"}
if($contacttype = "4"){$contactOU = "OU=Owners,OU=Marketing Companies,OU=Contacts,DC=company,DC=com,DC=au"}
if($contacttype = "5"){$contactOU = "OU=Team Leaders,OU=Marketing Companies,OU=Contacts,DC=company,DC=com,DC=au"}
else{write-host 'Please select a valid number',contactOU}
#For testing
write-host $contactOU
#May put this in an individual function?
New-ADObject -name $contactname -type Contact -Path $contactOU -OtherAttributes #{displayName=$contactname;mail=$emailaddress;targetAddress=$targetaddress}
}
The issue I'm having is, regardless of what number I select the IF statments choose the last option? (Team Leader OU). Does anyone know what is wrong with my IF statements?
Use -eq in your if statements.
if($contacttype -eq "1")
See about_Comparison_Operators
Kory Gill already found the problem within your if statements. However, consider to use PowerShell function parameters. Example:
function Get-ContactOu
{
Param(
[Parameter(Mandatory=$false, Position=0, ParameterSetName='Admin')]
[switch]$Admin,
[Parameter(Mandatory=$false, Position=0, ParameterSetName='AssistantOwner')]
[switch]$AssistantOwner,
[Parameter(Mandatory=$false, Position=0, ParameterSetName='OwnerPartner')]
[switch]$OwnerPartner,
[Parameter(Mandatory=$false, Position=0, ParameterSetName='Owner')]
[switch]$Owner,
[Parameter(Mandatory=$false, Position=0, ParameterSetName='TeamLeader')]
[switch]$TeamLeader
)
$ou = '';
if ($Admin) { $ou = 'Admins' }
if ($AssistantOwner) { $ou = 'Assistant Owners' }
if ($OwnerPartner) { $ou = 'Owner Partner' }
if ($Owner) { $ou = 'Owners' }
if ($TeamLeader) { $ou = 'Team Leaders' }
$path = 'OU={0},OU=Marketing Companies,OU=Contacts,DC=company,DC=com,DC=au' -f $ou
New-ADObject -name $contactname -type Contact -Path $path -OtherAttributes #{displayName=$contactname;mail=$emailaddress;targetAddress=$targetaddress}
}
Now you can use the function with a switch:
Get-ContactOu -Admin
I am trying to collect user profile information for users on a machine and I was wondering if I could get it with gwmi. Here is how I get printers for the current user:Get-WmiObject win32_printer. How can I get the same info for the user "Test" on the same machine?
As it happens, I can't sleep, so I came up with these 2 functions:
function Get-UserSid {
[CmdletBinding()]
param(
[Parameter(
ParameterSetName='NTAccount',
Mandatory=$true,
ValueFromPipeline=$true,
Position=0
)]
[System.Security.Principal.NTAccount]
$Identity ,
[Parameter(
ParameterSetName='DomainAndUser',
Mandatory=$true
)]
[ValidateNotNullOrEmpty()]
[ValidatePattern('^[^\\]+$')]
[String]
$Domain ,
[Parameter(
ParameterSetName='DomainAndUser',
Mandatory=$true
)]
[ValidateNotNullOrEmpty()]
[ValidatePattern('^[^\\]+$')]
[String]
$User
)
Begin {
if ($PSCmdlet.ParameterSetName -eq 'DomainAndUser') {
$Identity = New-Object System.Security.Principal.NTAccount -ArgumentList $Domain,$User
}
}
Process {
$Identity.Translate([System.Security.Principal.SecurityIdentifier])
}
}
function Get-PrinterNameByUser {
[CmdletBinding(DefaultParameterSetName='Ambiguous')]
param(
[Parameter(
ParameterSetName='ByAccount',
Mandatory=$true
)]
[System.Security.Principal.NTAccount]
$Account ,
[Parameter(
ParameterSetName='BySID',
Mandatory=$true
)]
[System.Security.Principal.SecurityIdentifier]
$SID ,
[Parameter(
ParameterSetName='Ambiguous',
Mandatory=$true,
Position=0,
ValueFromPipeline=$true
)]
[ValidateNotNullOrEmpty()]
[String]
$Identity
)
Begin {
Write-Verbose "Parameter Set Name: $($PSCmdlet.ParameterSetName)"
if ($PSCmdlet.ParameterSetName -eq 'ByAccount') {
$SID = $Account | Get-UserSid
}
}
Process {
if ($PSCmdlet.ParameterSetName -eq 'Ambiguous') {
try {
$SID = [System.Security.Principal.SecurityIdentifier]$Identity
} catch [System.InvalidCastException] {
$Account = [System.Security.Principal.NTAccount]$Identity
$SID = $Account | Get-UserSid
}
}
Get-ChildItem -Path "Registry::\HKEY_Users\$($SID.Value)\Printers" | Select-Object -ExpandProperty Property -Unique
}
}
Usage
Get-PrinterNameByUser Test
Get-PrinterNameByUser 'domain\test'
Get-PrinterNameByUser 'S-1-S-21-65454546-516413534-4444'
All of those could be piped as well:
'Test' | Get-PrinterNameByUser
'domain\test' | Get-PrinterNameByUser
'S-1-S-21-65454546-516413534-4444' | Get-PrinterNameByUser
'S-1-S-21-65454546-516413534-4444','user1','machine\user2','domain\user3' | Get-PrinterNameByUser
Explanation
In the registry at HKU\S-ID-HERE\Printers there are some keys with properties. The property names are the printers. I wasn't able to test this on enough machines, so I wasn't certain which key(s) I should check, and whether they would be different depending on whether it was a local or network printer, etc., so I'm just getting the properties from all the keys and returning the unique ones.
The helper function Get-UserSid just provides a convenient way to get a SID from a user name.
Most of Get-PrinterNameByUser is just code to figure out what you've given it and translate it at needed. The meat of it that returns what you want is just the one line:
Get-ChildItem -Path "Registry::\HKEY_Users\$($SID.Value)\Printers" | Select-Object -ExpandProperty Property -Unique
I am configuring a process that checks IIS settings on a Web Server for net.tcp bindings for a particual Web Site, and if it does not exist, create it. I have this chunk of code to check
$Websites = Get-ChildItem IIS:\Sites
foreach ($Site in $Websites) {
if ($Site.name -eq "LOSSI") {
$Binding = $Site.bindings
foreach ($bind in $Binding.collection) {
if ($bind -eq "net.tcp 443:*")
{
Write-Host $bind
}
}
}
}
But I never fall into the last conditional. I have validated by hand that the binding is set to
LOSSI
3
Started
D:\LOSSI
http *:63211: net.tcp 443:
I imagine I am doing something silly wrong, but I cannot figure it out. Is there an easier way to check a website for tcp binding?
function Test-TcpPort {
<#
.SYNOPSIS
Determine if computers have the specified ports open.
.EXAMPLE
PS C:\> Test-TcpPort -ComputerName web01,sql01,dc01 -Port 5985,5986,80,8080,443
.NOTE
Example function from PowerShell Deep Dives 2013.
#>
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
[Alias("CN","Server","__Server","IPAddress")]
[string[]]$ComputerName = $env:COMPUTERNAME,
[int[]]$Port = 23,
[int]$Timeout = 5000
)
Process {
foreach ($computer in $ComputerName) {
foreach ($p in $port) {
Write-Verbose ("Checking port {0} on {1}" -f $computer, $p)
$tcpClient = New-Object System.Net.Sockets.TCPClient
$async = $tcpClient.BeginConnect($computer, $p, $null, $null)
$wait = $async.AsyncWaitHandle.WaitOne($TimeOut, $false)
if(-not $Wait) {
[PSCustomObject]#{
Computername = $ComputerName
Port = $P
State = 'Closed'
Notes = 'Connection timed out'
}
} else {
try {
$tcpClient.EndConnect($async)
[PSCustomObject]#{
Computername = $computer
Port = $p
State = 'Open'
Notes = $null
}
} catch {
[PSCustomObject]#{
Computername = $computer
Port = $p
State = 'Closed'
Notes = ("{0}" -f $_.Exception.Message)
}
}
}
}
}
}
}
Microsoft reference script for check port
add this function in
for powershell 64 bit
C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1
for powershell 32 bit
C:\Windows\SysWOW64\WindowsPowerShell\v1.0\profile.ps1
then open powershell use this
Test-TCPPort google.com -Port 80
output :
True