Extract text from command line script - shell

I have a mining application that shows the data I need but the application doesn't have an api to grab it. How can I extract the string to parse the data with powershell or equivalent?
The data drops a line like below every second,
ID(grabbed from board) hash:(label) hashrate(variable) errors:(label) #(variable) temp(variable) volts(variable) solutions:(label) #(variable) shares:(label) #(variable)
Example:
ABC1000234 hash: 9.8Gh/s errors: 0.000% 26.3C 0.74V solutions: 539/539
shares: 33
I need the hashrate, temp and volts or even better a way to send every string out to a port I can listen on to a url like "strings". If I can get the string to post to a port such as 4068. Then I could use powershell and netcat to listen to the port on http://127.0.0.1:4068.
Here is what I was going to do for powershell:
$serveraddress = '127.0.0.1'
$serverport = '4068'
$threadinfo = echo 'strings' | nc $serveraddress $serverport
$mineridstring = $stringsinfo.Split(';')[1] $minderid =
$mineridstring.Split('=')[0]
$hashstring = $stringsinfo.Split(';')[2] $hash =
$hashstring.Split('=')[1]
$tempstring = $stringsinfo.Split(';')[4] $tempc =
$tempstring.Split('=')[0]
$voltstring = $stringsinfo.Split(';')[5] $volts =
$voltsstring.Split('=')[0]
Invoke-RestMethod -Uri https://www.rigmanager.xyz/rig.php -Method Post `
-Body #{minerid = $minerid; hashrate = $hashrate; tempc = $temp; $volts = $volts} -UseBasicParsing

Push them to a message queue, and then you can subscribe any number of users/applications to that stream.
Check out Apache Kafka or any of the cloud-based equivalents on AWS, IBM Cloud, GCP, etc.
Parsing your string is something regex can handle, although unless you need the data indexed for querying/searching, you can pushing that off to the end user/application and just serve them the whole message.

An easy way to do this is with named captures in a regex.
PS C:\src\t> type exttext.ps1
$s = 'ABC1000234 hash: 9.8Gh/s errors: 0.000% 26.3C 0.74V solutions: 539/539 shares: 33'
$doesit = $s -match '^(?<id>.*) hash: (?<hashrate>.*) errors: (?<errors>[0-9.]+%) (?<temp>.*) (?<volts>.*) solutions: .* shares: \d+$'
$Matches.id
$Matches.hashrate
$Matches.errors
$Matches.temp
$Matches.volts
PS C:\src\t> .\exttext.ps1
ABC1000234
9.8Gh/s
0.000%
26.3C
0.74V

Related

How can I optimize the command Get-ComputerInfo?

Every time I get a snippet of info from this command, Windows will run the whole function, which takes time. The script works, but its slow. Because of the way the rest of this code is written, I cannot store Get-ComputerInfo as a string because I still need to pull strings from it without the tediousness of using substrings. What are my options here?
A sample of my code is here:
# Get username and format
$USRNAME = Get-ComputerInfo -Property WindowsRegisteredOwner | Out-String
$USRNAME = $USRNAME.Split('',[System.StringSplitOptions]::RemoveEmptyEntries)
$USRNAME = $USRNAME[2]
# Get BIOS S/N and format
$BIOSSN = Get-ComputerInfo -Property BiosSeralNumber | Out-String
$BIOSSN = $BIOSSN.Split('',[System.StringSplitOptions]::RemoveEmptyEntries)
$BIOSSN = $BIOSSN[2]
# Get BIOS Manufacturer and format
$MANUFAC = Get-ComputerInfo -Property CsManufacturer | Out-String
$MANUFAC = $MANUFAC.Split('',[System.StringSplitOptions]::RemoveEmptyEntries)
$MANUFAC = $MANUFAC[2]
# Get BIOS Model and format
$MODEL = Get-ComputerInfo -Property CsModel | Out-String
$MODEL = $MODEL.Split('',[System.StringSplitOptions]::RemoveEmptyEntries)
$MODEL = $MODEL[2..25]
As mentioned previously, I tried to output as a string and it got messy.
Call Get-ComputerInfo once, the store the output object in a variable, and then finally reuse that:
I still need to pull strings from it without the tediousness of using substrings
You really don't - Get-ComputerInfo outputs an object that has each piece of information neatly stored in separate properties - to get the WindowsRegisteredOwner value, simply use the . member access operator to dereference the WindowsRegisteredOwner property, and so on for the remaining properties:
$allInfo = Get-ComputerInfo -Property WindowsRegisteredOwner, BiosSeralNumber, CsManufacturer, CsModel
$USRNAME = $allInfo.WindowsRegisteredOwner
$BIOSSN = $allInfo.BiosSeralNumber
$MANUFAC = $allInfo.CsManufacturer
$MODEL = $allInfo.CsModel

How to compare age of local file with file on FTP server and download if remote copy is newer in PowerShell

I'm in the process of writing a PowerShell script to help in the process of setting up new PC's for my work. This will hopefully be used by more than just me so I'm trying to think of everything.
I have offline installers (java, flash, reader, etc) saved on our FTP server that the script downloads if a local copy hasn't already been saved in the Apps directory that gets created. Periodically the files on the FTP server will get updated as new versions of the programs are released. I want the script to have an option of checking for newer versions of the installers in case someone likes to carry around the local copies and forgets to check the server every now and then. It also will need to work in Windows 7 without any need to import additional modules unless there's an easy way to do that on multiple PC's at a time. I know about the import command, but the experiences I've had needed me to copy the module files into multiple places on the PC before it'd work.
Right now I haven't had much luck finding any solutions. I've found code that checks for modified dates on local files, or files on a local server, but nothing that deals with FTP other than uploading\downloading files.
Here's the last thing I tried. I tried a combination of what I found for local files with FTP. Didn't work too well.
I'm new to PowerShell, but I've been pretty good at piecing this whole thing together so far. However, this idea is becoming troublesome.
Thank you for the help.
$ftpsite = "ftp://ftpsite.com/folder/"
$firefox = (Get-Item $dir\Apps\install_firefox.exe).LastWriteTime.toString("MM/dd/yyyy")
if ($firefoxftp = (Get-ChildItem $ftpsite/install_firefox.exe | Where{$_.LastWriteTime -gt $firefox})) {
$File = "$dir\Apps\install_firefox.exe"
$ftp = "ftp://ftpsite.com/folder/install_firefox.exe"
$webclient = New-Object System.Net.WebClient
$uri = New-Object System.Uri($ftp)
$webclient.DownloadFile($uri, $File)
}
UPDATE:
Here's what I have after Martin's help. It kind of works. It downloads the file from FTP, but it's not comparing the remote and local correctly. The remote file returns 20150709140505 and the local file returns 07/09/2015 2:05:05 PM. How do I format one to look like the other before the comparison, and is "-gt" the correct comparison to use?
Thanks!
function update {
$ftprequest = [System.Net.FtpWebRequest]::Create("ftp://ftpsite.com/Script_Apps/install_firefox.exe")
$ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::GetDateTimestamp
$response = $ftprequest.GetResponse().StatusDescription
$tokens = $response.Split(" ")
$code = $tokens[0]
$localfile = (Get-Item "$dir\Apps\install_firefox.exe").LastWriteTimeUtc
if ($tokens -gt $localfile) {
write-host "Updating Firefox Installer..."
$File = "$dir\Apps\install_firefox.exe"
$ftp = "ftp://ftpsite.com/Script_Apps/install_firefox.exe"
$webclient = New-Object System.Net.WebClient
$uri = New-Object System.Uri($ftp)
$webclient.DownloadFile($uri, $File)
"Updated Firefox" >> $global:logfile
mainmenu
}
else {
Write-Host "Local Copy is Newer."
sleep 3
mainmenu
}
}
UPDATE 2:
Seems to be working! Here's the code. Thanks for the help!
function update {
$ftprequest = [System.Net.FtpWebRequest]::Create("ftp://ftpserver.com/Script_Apps/install_firefox.exe")
$ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::GetDateTimestamp
$response = $ftprequest.GetResponse().StatusDescription
$tokens = $response.Split(" ")
$code = $tokens[0]
$localtime = (Get-Item "$dir\Apps\install_firefox.exe").LastWriteTimeUtc
if ($code -eq 213) {
$tokens = $tokens[1]
$localtime = "{0:yyyymmddHHmmss}" -f [datetime]$localtime
}
if ($tokens -gt $localtime) {
write-host "Updating Firefox Installer..."
$File = "$dir\Apps\install_firefox.exe"
$ftp = "ftp://ftpserver.com/Script_Apps/install_firefox.exe"
$webclient = New-Object System.Net.WebClient
$uri = New-Object System.Uri($ftp)
$webclient.DownloadFile($uri, $File)
"Updated Firefox" >> $global:logfile
mainmenu
}
else {
Write-Host "Local Copy is Newer."
sleep 3
mainmenu
}
}
You cannot use the WebClient class to check remote file timestamp.
You can use the FtpWebRequest class with its GetDateTimestamp FTP "method" and parse the UTC timestamp string it returns. The format is specified by RFC 3659 to be YYYYMMDDHHMMSS[.sss].
That would work only if the FTP server supports MDTM command that the method uses under the cover (most servers do, but not all).
$url = "ftp://ftpsite.com/folder/install_firefox.exe"
$ftprequest = [System.Net.FtpWebRequest]::Create($url)
$ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::GetDateTimestamp
$response = $ftprequest.GetResponse().StatusDescription
$tokens = $response.Split(" ")
$code = $tokens[0]
if ($code -eq 213)
{
Write-Host "Timestamp is" $tokens[1]
}
else
{
Write-Host "Error" $response
}
It would output something like:
Timestamp is 20150709065036
Now you parse it, and compare against a UTC timestamp of a local file:
(Get-Item "install_firefox.exe").LastWriteTimeUtc
Or save yourself some time and use an FTP library/tool that can do this for you.
For example with WinSCP .NET assembly, you can synchronize whole remote folder with installers with a local copy with one call to the Session.SynchronizeDirectories. Or your can limit the synchronization to a single file only.
# Load WinSCP .NET assembly
Add-Type -Path "WinSCPnet.dll"
# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions
$sessionOptions.Protocol = [WinSCP.Protocol]::Ftp
$sessionOptions.HostName = "ftpsite.com"
$session = New-Object WinSCP.Session
# Connect
$session.Open($sessionOptions)
$transferOptions = New-Object WinSCP.TransferOptions
# Synchronize only this one file.
# If you remove the file mask, all files in the folder are synchronized:
$transferOptions.FileMask = "install_firefox.exe"
$session.SynchronizeDirectories(
[WinSCP.SynchronizationMode]::Local, "$dir\Apps", "/folder",
$False, $False, [WinSCP.SynchronizationCriteria]::Time,
$transferOptions).Check()
To use the assembly, just extract a contents of .NET assembly package to your script folder. No other installation is needed.
The assembly supports not only the MDTM, but also other alternative methods to retrieve the timestamp.
See also a related Powershell example that shows both the above code and other techniques.
(I'm the author of WinSCP)

Keep Leading Zero In Export

I am using powershell to run a sql query and export to a csv file. Process works great, but it is dropping a leading 0 in one of my columns. Field type in SQL Server is a varchar (not an option to change it unfortunately), and here is my syntax. Is it possible to continue to use my powershell export process and keep the leading zero?
$GoodSyntax = "Select * From tableunknown"
$extractFile = "C:\Test.csv"
Execute-SQLquery
if (Execute-SQLquery $GoodSyntax)
Function Execute-SQLquery {
param ($GoodSyntax)
$server = "Server01"
$database = "database01"
$connectionTemplate = "Data Source={0};Integrated Security=SSPI;Initial Catalog={1};"
$connectionString = [string]::Format($connectionTemplate, $server, $database)
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = $connectionString
$command = New-Object System.Data.SqlClient.SqlCommand
$command.CommandText = $QueryString
$command.Connection = $connection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $command
$DataSet = New-Object System.Data.DataSet
$rowCount = $SqlAdapter.Fill($DataSet)
$DataSet.Tables[0] | Export-Csv $extractFile -NoTypeInformation
$connection.Close()
EDIT ---
Upon further examination, and opening my CSV file in a raw editor like notepad++ the leading zeros are their! They are just dropped when you attempt to view the file in Excel. So Excel is the culprit here.
I have never seen sql drop any data from varchar. How are you testing this? Maybe the problem is not in the sql but in whatever you use to look at the data.
I know that Excel does remove leading 0's because it tries to be clever and convert chars to numbers but sql does not.
Try viewing the result of $DataSet.GetXml() which will show the raw data more clearly.
$connection.Close()
$DataSet.GetXml()
Update: Excel strips the leading 0's and is confusing you. The sql data is correct.
How to specify formatting when opening a csv file in excel
http://www.upenn.edu/computing/da/bo/webi/qna/iv_csvLeadingZeros.html
Normally I create an xml/html file from the data. Excel will open it and supports various attributes with the data that control formatting, but its messy.
You should be able to do something like:
$a = "1000"
$a = $a.substring($a.length - 3, 37)
Ref. - https://technet.microsoft.com/en-us/library/ee176945.aspx

Is there an easy way to check if CredSSP is enabled on a systems?

I am aware of the Get-WSManCredSSP function; however, this cmdlet does not work well in a script. This returns a long string similar to the following:
The machine is configured to allow delegating fresh credentials to the following target(s): wsman/*,wsman/*,wsman/*,wsman/*
This computer is configured to receive credentials from a remote client computer.
I cannot easily include this in a script that I am writing, so I'm looking for an alternative way to check CredSSP.
Can't you consider using this as documented in the CmdLet help: Gets the WS-Management CredSSP setting on the client (<localhost|computername>\Client\Auth\CredSSP).
On a local machine it gives :
(Get-Item WSMan:\localhost\Client\Auth\CredSSP).value
You can use it like this :
(Get-Item WSMan:\localhost\Client\Auth\CredSSP).value -eq $false
You can first test if WinRm is available :
(Get-Service -Name winrm ).Status
I was also struggling with the limitations of the Get-WSManCredSSP output, and found this helper script by Victor Vogelpoel/Ravikanth Chaganti to be really helpful.
Some examples:
Check if current machine has been configured as CredSSP server and/or client:
(Get-WSManCredSSPConfiguration).IsServer
(Get-WSManCredSSPConfiguration).IsClient
Check if a specified client machine has been set up for delegation:
Get-WSManCredSSPConfiguration | % { $_.ClientDelegateComputer.Contains('clientcomputername') }
(not intended as a replacement for the work of Vogelpoel & Chaganti, but as a quick summary of a quick reading of CredSSP.cs, so you can get a quick grasp of what it's doing - that said, it was tested on several systems I had at hand and seems to work)
function Get-WSManCredSSPState
{
$res = [pscustomobject]#{DelegateTo = #(); ReceiveFromRemote = $false}
$wsmTypes = [ordered]#{}
(gcm Get-WSManCredSSP).ImplementingType.Assembly.ExportedTypes `
| %{$wsmTypes[$_.Name] = $_}
$wmc = new-object $wsmTypes.WSManClass.FullName
$wms = $wsmTypes.IWSManEx.GetMethod('CreateSession').Invoke($wmc, #($null,0,$null))
$cli = $wsmTypes.IWSManSession.GetMethod('Get').Invoke($wms, #("winrm/config/client/auth", 0))
$res.ReceiveFromRemote = [bool]([xml]$cli).Auth.CredSSP
$afcPath = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\CredentialsDelegation\AllowFreshCredentials'
if (test-path $afcPath)
{
$afc = gi $afcPath
$res.DelegateTo = $afc.GetValueNames() | sls '^\d+$' | %{$afc.GetValue($_)}
}
return $res
}

How to add new DNS zone on Windows Server 2008 using API or PowerShell?

Is there any API in Microsoft DNS Server 2008 to add new forward DNS using VBScript or PowerShell or P/Invoke or WMI?
It's easy to generate plain text file and put it into \system32\dns.
How to replace a number manual commands in MMC with just a script execution?
#xyz is dns servername
$A = [wmiclass]"\\xyz\root\MicrosoftDNS:MicrosoftDNS_AType"
$DNSServer = "xyz.R-test.com"
$Zone = "R-Test.com"
$class = 1
$TTL = 3600
#This is your web server IP Address
$IPAddress = "192.168.1.88"
$Sites = Get-content WebSites.txt
Foreach ($Site in $Sites)
{
$A.CreateInstanceFromPropertyData($DNSserver, $zone, $Site, $class, $ttl, $IPAddress)
}
The WebSites.txt is something look like this:
whatever1.R-test.comwhatever2.R-test.comwhatever3.R-test.com
whatever4.R-test.com
…
http://www.highorbit.co.uk/?p=636
http://richardsiddaway.spaces.live.com/blog/cns!43CFA46A74CF3E96!994.entry
http://myitforum.com/cs2/blogs/yli628/archive/2008/06/19/powershell-script-to-add-multiple-a-records-in-dns.aspx

Resources