Advertisement
Guest User

USBIP client autostart & automount

a guest
Aug 20th, 2018
167
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #We assume that IP, MAC and name of USBIP host may be changed at any time.
  2. #Also we need to catch event when shared device disappears by any cause
  3. #and try to reconnect
  4.  
  5. #Set input parameters
  6. param (
  7.         $USBIP_hostname, #or CNAME
  8.         $USBIP_portnumber, # For USBIP it is 3240 TCP by default.
  9.         $VendorID, # It maybe "Aladdin" or "0529:"
  10.         $USBIP_clientname # Name of USBIP client executable. It is usually named as "usbip.exe".
  11.         )
  12.  
  13. IF ($USBIP_hostname -eq $null)
  14.     {
  15.     $USBIP_hostname = "usboip"
  16.     #If name(s) of target host(s) is (are) not given as argument, script will prompt you for input.
  17.     #$USBIP_hostname = Read-Host "Enter hostname here"
  18.     } #end IF
  19.  
  20. IF ($USBIP_portnumber -eq $null)
  21.     {
  22.     $USBIP_portnumber = 3240
  23.     #If port number is not given as argument, script will prompt you for input.
  24.     #$USBIP_portnumber = read-host "Enter port number here"
  25.     } #end IF
  26.  
  27. IF ($VendorID -eq $null)
  28.     {
  29.     $VendorID = "Aladdin"
  30.     #If name of vendor is not given as argument, script will prompt you for input.
  31.     #$VendorID = Read-Host "Enter Vendor_ID here"
  32.     } #end IF
  33.  
  34. IF ($USBIP_clientname -eq $null)
  35.     {
  36.     $USBIP_clientname = "usbip.exe"
  37.     #If name of executable is not given as argument, script will prompt you for input.
  38.     #$USBIP_clientname = Read-Host "Enter name of USBIP client executable here"
  39.     } #end IF
  40.  
  41. #Get path to current script. Yes, this script should be placed in same dir with USBIP client.
  42. $scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
  43.  
  44. $CurrentTime = Get-Date -UFormat "%Y-%m-%d-%H-%M-%S"
  45. $LogFile = "$scriptPath\LOG-$CurrentTime.log"
  46.  
  47. #Get IP by hostname. IP is shown at parameter "IPAddressToString", so we'll select this parameter only:
  48. $USBIP_inetaddr=[System.Net.Dns]::GetHostAddresses("$USBIP_hostname") |
  49.                 Select-Object IPAddressToString -expandproperty IPAddressToString
  50.  
  51. #We can get MAC from DHCP lease, but only if
  52. # 1) PS tools for DHCP are installed;
  53. # 2) account is included to "DHCP Users" group.
  54. #Don't forget to specify name of DHCP server.
  55. $USBIP_macaddr=Get-DhcpServerv4Lease -ComputerName (Get-DhcpServerInDC |
  56.                  Select-Object DnsName -ExpandProperty DnsName) -IPAddress $USBIP_inetaddr |
  57.                   Select-Object -ExpandProperty ClientId
  58.  
  59. #===================================================================
  60.  
  61. # All about logs and logrotating functions were copied from
  62. # https://gist.github.com/barsv/85c93b599a763206f47aec150fb41ca0
  63. # all logging settins are here on top
  64. $logLevel = "DEBUG" # ("DEBUG","INFO","WARN","ERROR","FATAL")
  65. $logSize = 1mb # 30kb
  66. $logCount = 30
  67. # end of settings
  68.  
  69. function Write-Log-Line ($line) {
  70.     Add-Content $logFile -Value $Line
  71.     Write-Host $Line
  72. }
  73.  
  74. # http://stackoverflow.com/a/38738942
  75. Function Write-Log {
  76.     [CmdletBinding()]
  77.     Param(
  78.     [Parameter(Mandatory=$True)]
  79.     [string]
  80.     $Message = $msg,
  81.    
  82.     [Parameter(Mandatory=$False)]
  83.     [String]
  84.     $Level = "DEBUG"
  85.     )
  86.  
  87.     $levels = ("DEBUG","INFO","WARN","ERROR","FATAL")
  88.     $logLevelPos = [array]::IndexOf($levels, $logLevel)
  89.     $levelPos = [array]::IndexOf($levels, $Level)
  90.     $Stamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss:fff")
  91.  
  92.     if ($logLevelPos -lt 0){
  93.         Write-Log-Line "$Stamp ERROR Wrong logLevel configuration [$logLevel]"
  94.     }
  95.    
  96.     if ($levelPos -lt 0){
  97.         Write-Log-Line "$Stamp ERROR Wrong log level parameter [$Level]"
  98.     }
  99.  
  100.     # if level parameter is wrong or configuration is wrong I still want to see the
  101.     # message in log
  102.     if ($levelPos -lt $logLevelPos -and $levelPos -ge 0 -and $logLevelPos -ge 0){
  103.         return
  104.     }
  105.  
  106.     $Line = "$Stamp $Level $Message"
  107.     Write-Log-Line $Line
  108. }
  109.  
  110. # https://gallery.technet.microsoft.com/scriptcenter/PowerShell-Script-to-Roll-a96ec7d4
  111. function Reset-Log
  112. {
  113.     # function checks to see if file in question is larger than the paramater specified
  114.     # if it is it will roll a log and delete the oldes log if there are more than x logs.
  115.     param([string]$fileName, [int64]$filesize = 1mb , [int] $logcount = 30)
  116.      
  117.     $logRollStatus = $true
  118.     if(test-path $filename)
  119.     {
  120.         $file = Get-ChildItem $filename
  121.         if((($file).length) -ige $filesize) #this starts the log roll
  122.         {
  123.             $fileDir = $file.Directory
  124.             #this gets the name of the file we started with
  125.             $fn = $file.name
  126.             $files = Get-ChildItem $filedir | ?{$_.name -like "$fn*"} | Sort-Object lastwritetime
  127.             #this gets the fullname of the file we started with
  128.             $filefullname = $file.fullname
  129.             #$logcount +=1 #add one to the count as the base file is one more than the count
  130.             for ($i = ($files.count); $i -gt 0; $i--)
  131.             {  
  132.                 #[int]$fileNumber = ($f).name.Trim($file.name) #gets the current number of
  133.                 # the file we are on
  134.                 $files = Get-ChildItem $filedir | ?{$_.name -like "$fn*"} | Sort-Object lastwritetime
  135.                 $operatingFile = $files | ?{($_.name).trim($fn) -eq $i}
  136.                 if ($operatingfile)
  137.                  {$operatingFilenumber = ($files | ?{($_.name).trim($fn) -eq $i}).name.trim($fn)}
  138.                 else
  139.                 {$operatingFilenumber = $null}
  140.  
  141.                 if(($operatingFilenumber -eq $null) -and ($i -ne 1) -and ($i -lt $logcount))
  142.                 {
  143.                     $operatingFilenumber = $i
  144.                     $newfilename = "$filefullname.$operatingFilenumber"
  145.                     $operatingFile = $files | ?{($_.name).trim($fn) -eq ($i-1)}
  146.                     write-host "moving to $newfilename"
  147.                     move-item ($operatingFile.FullName) -Destination $newfilename -Force
  148.                 }
  149.                 elseif($i -ge $logcount)
  150.                 {
  151.                     if($operatingFilenumber -eq $null)
  152.                     {  
  153.                         $operatingFilenumber = $i - 1
  154.                         $operatingFile = $files | ?{($_.name).trim($fn) -eq $operatingFilenumber}
  155.                        
  156.                     }
  157.                     write-host "deleting " ($operatingFile.FullName)
  158.                     remove-item ($operatingFile.FullName) -Force
  159.                 }
  160.                 elseif($i -eq 1)
  161.                 {
  162.                     $operatingFilenumber = 1
  163.                     $newfilename = "$filefullname.$operatingFilenumber"
  164.                     write-host "moving to $newfilename"
  165.                     move-item $filefullname -Destination $newfilename -Force
  166.                 }
  167.                 else
  168.                 {
  169.                     $operatingFilenumber = $i +1  
  170.                     $newfilename = "$filefullname.$operatingFilenumber"
  171.                     $operatingFile = $files | ?{($_.name).trim($fn) -eq ($i-1)}
  172.                     write-host "moving to $newfilename"
  173.                     move-item ($operatingFile.FullName) -Destination $newfilename -Force    
  174.                 }
  175.             }
  176.           }
  177.          else
  178.          { $logRollStatus = $false}
  179.     }
  180.     else
  181.     {
  182.         $logrollStatus = $false
  183.     }
  184.     $LogRollStatus
  185. }
  186.  
  187. # to null to avoid output
  188. $Null = @(
  189.     Reset-Log -fileName $logFile -filesize $logSize -logcount $logCount
  190. )
  191.  
  192. #===================================================================
  193.  
  194. function Test-Port()
  195. #Copied from https://stackoverflow.com/a/22553267
  196.     {
  197.  
  198.     $msg = "Trying to get IP from hostname"
  199.     Write-Log "$msg" "INFO"
  200.     IF ("$USBIP_inetaddr" -ne "")
  201.         {
  202.         $msg = "IP of $USBIP_hostname resolved as $USBIP_inetaddr"
  203.         Write-Log "$msg" "INFO"
  204.         }
  205.         ELSE
  206.             {
  207.             $msg = "IP of $USBIP_hostname cannot be resolved"
  208.             Write-Log "$msg" "ERROR"
  209.             }
  210.     $msg = "Trying to get MAC from hostname"
  211.     Write-Log "$msg" "INFO"
  212.  
  213.     IF ("$USBIP_macaddr" -ne "")
  214.         {
  215.         $msg = "MAC of $USBIP_hostname resolved as $USBIP_macaddr"
  216.         Write-Log "$msg" "INFO"
  217.         }
  218.         ELSE
  219.             {
  220.             $msg = "MAC of $USBIP_hostname cannot be resolved"
  221.             Write-Log "$msg" "ERROR"
  222.             }
  223.  
  224.     $TcpClient = New-Object Net.Sockets.TcpClient
  225.     # We use Try\Catch to remove exception info from console if we can't connect
  226.     try
  227.         {
  228.         $TcpClient.Connect($USBIP_inetaddr,$USBIP_portnumber)
  229.         } catch
  230.                 {
  231.                 $msg = "Cannot connect to $USBIP_portnumber on $USBIP_hostname!"
  232.                 Write-Log "$msg" "ERROR"
  233.                 }
  234.  
  235.         IF($TcpClient.Connected)
  236.             {
  237.             $TcpClient.Close()
  238.             $msg = "Port $USBIP_portnumber is operational"
  239.             Write-Log "$msg" "INFO"
  240.            
  241.             DeviceList
  242.             Sleep 10
  243.             $msg = "Start watching"
  244.             Write-Log "$msg" "INFO"
  245.             Sleep 10
  246.             WatchDevices #See below.
  247.             } #endIF
  248.         ELSE
  249.             {
  250.             $msg = "Port $USBIP_portnumber on $USBIP_inetaddr is closed, "
  251.             $msg += "or host is unavailable. Trying to wake it up..."
  252.             Write-Log "$msg" "ERROR"
  253.  
  254.             #Send WOL. See below.
  255.             Wake-On-LAN $USBIP_macaddr
  256.            
  257.             #Wait for start
  258.             $msg = "WOL sent to $USBIP_macaddr. Wait for a minute..."
  259.             Write-Log "$msg" "INFO"
  260.             Sleep 60
  261.            
  262.             #Probably we can't call function from itself. So we assuming that host is up
  263.             #and devices are shared. Trying to enumerate.
  264.             $msg = "Trying to list shared devices"
  265.             Write-Log "$msg" "INFO"
  266.             DeviceList #See below.
  267.            
  268.             #And then watch if device will be disappeared.
  269.             $msg = "Start watching"
  270.             Write-Log "$msg" "INFO"
  271.             Sleep 10
  272.             WatchDevices #See below.
  273.             }
  274.     }
  275.  
  276. #https://www.pdq.com/blog/wake-on-lan-wol-magic-packet-powershell/
  277. function Wake-On-LAN()
  278.     {
  279.     #Send magic paket.
  280.     #WOL packet is a byte array with 6 bytes of value 255 and then 16 repetitions
  281.     #of the MAC address as it shown below:
  282.     $MacByteArray = $USBIP_macaddr -split "[:-]" | ForEach-Object { [Byte] "0x$_"}
  283.     [Byte[]] $MagicPacket = (,0xFF * 6) + ($MacByteArray  * 16)
  284.  
  285.     #Create object UdpClient from .NET class
  286.     $UdpClient = New-Object System.Net.Sockets.UdpClient
  287.  
  288.     #Connect UdpClient with broadcast address and UDP port 7 (maybe 0, 7, 9)
  289.     $UdpClient.Connect(([System.Net.IPAddress]::Broadcast),7)
  290.  
  291.     #Send WOL sequence. We don't need an output at stdout.
  292.     $UdpClient.Send($MagicPacket,$MagicPacket.Length) | Out-Null
  293.  
  294.     #And close connection
  295.     $UdpClient.Close()
  296.  
  297.     }#Done.
  298.  
  299. function DeviceList() #Gets list of shared devices
  300.     {
  301.     #Copied from https://stackoverflow.com/a/8762068
  302.    
  303.     #Create new process
  304.     $USBIPlistpinfo = New-Object System.Diagnostics.ProcessStartInfo
  305.    
  306.     #Set filename with path
  307.     $USBIPlistpinfo.FileName = "$scriptPath\$USBIP_clientname"
  308.    
  309.     #Set redirect of stderr from where we'll get info about shared devices
  310.     $USBIPlistpinfo.RedirectStandardError = $true
  311.  
  312.     #
  313.     $USBIPlistpinfo.UseShellExecute = $false
  314.  
  315.     #Set working directory
  316.     $USBIPlistpinfo.WorkingDirectory = "$scriptPath"
  317.    
  318.     #Give args to .EXE
  319.     $USBIPlistpinfo.Arguments = "-l $USBIP_hostname"
  320.    
  321.     #Start process
  322.     $USBIPlistOutput = New-Object System.Diagnostics.Process
  323.     $USBIPlistOutput.StartInfo = $USBIPlistpinfo
  324.    
  325.     #Disable window
  326.     $USBIPlistOutput.Start() | Out-Null
  327.    
  328.     #Set variable for raw stderr output
  329.     $USBIPlistStdErr = $USBIPlistOutput.StandardError.ReadToEnd()
  330.  
  331.     #And then split it to lines and convert into array.
  332.     $devlistraw = $USBIPlistStdErr.Split(")")
  333.     $devArray=@($devlistraw)
  334.    
  335.     $msg = "$USBIPlistStdErr"
  336.     $msg += "Trying to mount..."
  337.     Write-Log "$msg" "INFO"
  338.     #Call function which mounts all devices. Maybe.
  339.     MountAll
  340.     }
  341.  
  342.  
  343. function MountAll()
  344.     {
  345.     ForEach ($device in $devArray)
  346.         {
  347.         #Filter output by $VendorID.
  348.         IF ($device -match $VendorID)
  349.             {
  350.             #get chars before 1st ":"
  351.             $separator = $device.IndexOf(":")
  352.            
  353.             #remove unnesessary CR/LF
  354.             $busID = ($device.Substring(0,$separator) -replace "\s+","") -replace "-$USBIP_hostname",""
  355.            
  356.             #mount device with given bus ID
  357.             MountNthDevice
  358.            
  359.             } #endIF
  360.         }
  361.     #report if OK
  362.     $msg = "Device with Bus ID $busID mounted"
  363.     Write-Log "$msg" "INFO"
  364.     }
  365.  
  366. function MountNthDevice() #Mounts devices of specified vendor
  367.     {
  368.     $USBIPmount = New-Object System.Diagnostics.ProcessStartInfo
  369.     $USBIPmount.FileName = "$scriptPath\$USBIP_clientname"
  370.     $USBIPmount.RedirectStandardError = $true
  371.     $USBIPmount.UseShellExecute = $false
  372.     $USBIPmount.WorkingDirectory = "$scriptPath"
  373.     $USBIPmount.Arguments = "-a $USBIP_hostname $busID"
  374.     $USBIPmStart = New-Object System.Diagnostics.Process
  375.     $USBIPmStart.StartInfo = $USBIPmount
  376.     $USBIPmStart.Start() | Out-Null
  377.     }
  378.  
  379.  
  380. function WatchDevices()
  381.     {
  382.         #Get list of mounted devices and filter by "CompatibleID"
  383.         $GetMntList = gwmi Win32_USBControllerDevice |%{[wmi]($_.Dependent)} |
  384.         Sort Manufacturer,Description,DeviceID |
  385.         Select-Object CompatibleID -ExpandProperty CompatibleID
  386.             #While device with target ID will be present
  387.             WHILE ($GetMntList -like "*$VendorID*")
  388.                 {
  389.                 $msg = "Devices are present"
  390.                 Write-Log "$msg" "INFO"
  391.                 #Set timeout
  392.                 Sleep 300
  393.                 #And try to list devices again
  394.                 $GetMntList = gwmi Win32_USBControllerDevice |%{[wmi]($_.Dependent)} |
  395.                 Sort Manufacturer,Description,DeviceID |
  396.                 Select-Object CompatibleID -ExpandProperty CompatibleID
  397.                 }
  398.             #If device was unmounted...
  399.             $msg = "Devices not found! Trying to reconnect..."
  400.             Write-Log "$msg" "ERROR"
  401.             #return to connection testing
  402.             Test-Port
  403.     }
  404.  
  405. #Start with check port availability
  406. $msg = "Start execution with connectivity testing to $USBIP_hostname"
  407. Write-Log "$msg" "INFO"
  408. Test-Port
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement