Trying to run legacy executables from powershell script - powershell

I am looking to run net.exe from a script and I am having some trouble with spaces. Here is the code...
# Variables
$gssservers = Import-Csv "gssservers.csv"
$gssservers | Where-Object {$_.Tier -match "DB"} | Foreach-Object {
net.exe use "\\"$_.Name '/user:'$_.Name'\Administrator' $_.Pass
$sqlcheck = sc.exe \\$gsssql[1] query "WUAUSERV"
}
When I set line 5 to Write-Host I see that there are spaces that are added outside of anywhere I have quotes which is breaking the net.exe command. How can I remove those spaces?
For anyone questioning how I am doing this, the net.exe command is the only way I can get to these machines as WMI is blocked in this enclave.

My first guess is that you've got "invisible" spaces in your CSV file. For example their is likely a trailing whitespace after the names of your servers in the CSV that your eyes of course don't see. You can fix that either by fixing the CSV file, or using .Trim() on your imported strings -- i.e. $_.Name.Trim()
If that's not the case, or not the only issue, then this is something I've had issues with to. When I have complicated strings like your desired net.exe arguments I've liked to take precautions and get extra pedantic with defining the string and not rely on PowerShell's automatic guessing of exactly where a string begins and ends.
So, instead of baking your parameters inline on your net.exe command line hand-craft them into a variable first, like so
$args = '\\' + $_.name + '/user:' + $_.name + '\Administrator' + $_.pass
If you write-Host that out you'll see that it no longer has your rogue spaces. Indeed you may notice that it no longer has enough spaces, so you'll have to get a little explicit about where they belong. For instance the above line doesn't put the proper spaces between \\servername and /user, or between the username and password, so you'd have to add that space back in, like so.
$args = '\\' + $_.name + ' /user:' + $_.name + '\Administrator ' + $_.pass
Notice the explicit spaces.

I finally resolved this myself using #EdgeVB's solution. The code ended up like this...
# Variables
$gssservers = Import-Csv "gssservers.csv"
$gssservers | Where-Object {$_.Tier -match "DB"} | Foreach-Object {
$cmd1 = 'use'
$arg1 = '\\' + $_.Name
$arg2 = ' /user:' + $_.Name + '\Administrator '
& net.exe $cmd1 $arg1 $arg2 $_Pass
$cmd2 = 'query'
$svc1 = 'mssqlserver'
& sc.exe $arg1 $cmd2 $svc1 | Write-Host
}
Not only do you need to bake the variables in beforehand, but they also cannot cross certain thresholds (for instance, if "use" and "\" are in the same variable, it breaks.

Related

Cleaning up filenames from MAC using Powershell

I'm writing a script that iterates over files that are copied from a MAC computer to a Exfat disk and checks the name of the files for Windows forbidden characters.(Writing it in PowerShell)
And hopefully replace the forbidden characters with another character, for example a "-".
Why i am doing this is because i see it as a good way for me to practice coding and it might be used in my work when we get users with a lot of local files that we want to move to Onedrive.(Onedrive has a function to rename but it doesn't touch the forbidden characters, and i don't know Bash)
The issue is when I'm trying to find the characters within the script itself, it cant find the characters if i write them in the script.(For example if i write that it should look for ">")
Even if i escape the characters it just skips it(Or rather doesn't find it).
It just skips over the file i know has one in it, at first i though it might be due to encoding, but no matter what i use as a default encoding it wont display the filename correctly.(I assume this is due to how Windows reads filenames?)
edit: These are the forbidden characters im goint to look for " * : < > ? / \ |
The script itself is able to remove letters and stuff if i ask it to.
I also tried getting the char of the byte([byte][char]"") but i get this error:
Cannot convert value "" to type "System.Byte". Error: "Value was either too large or too small for an unsigned byte." Edit: the  changed by itself during the day not sure what to say.
If i just add it to the function it just returns the error:Rename-Item : The input to the script block for parameter 'NewName' failed. Exception calling "Replace" with "2" argument(s): "String cannot be of zero length.
The characters are displayed like this in visual studio code.
Any ideas are welcome or if you know of any better ways of doing it?(Maybe its better if i just learn bash. )
Here is the script itself:
edit: cleaned up the script abit and some small changes.
$provided_path = Read-Host "What Directory and its subfolders do you want to check?"
# Iterates over the folders and files within.
Write-Host "Creating list of files..."
$dictionary_filenames = ""
$dictionary_filenames = Get-ChildItem -Path $provided_path -Recurse -Force -File | Select-Object FullName,BaseName,Extension
# Resetting counter
$counter_skipped = 0
# Function for character replacment
function rename_file_name($names_function,$forbidden_char){
$old_name = $names_function.BaseName
$new_name = $names_function | Rename-Item -LiteralPath $names_function.FullName -NewName{$_.BaseName.Replace("$forbidden_char","-") + $_.extension} -PassThru
if($old_name -ne $new_name.BaseName){
Write-host "$old_name changed to $new_name"
}
}
foreach($names in $dictionary_filenames){
if($names.BaseName[0] -eq "." -and $names.BaseName[1] -match "_"){
$counter_skipped ++
$counter ++
continue
}
else{
if($names.BaseName[0] -eq " " -or $names.BaseName[-1] -eq " "){
$old_name = $names.BaseName
$new_name = $names | Rename-Item -LiteralPath $names.FullName -NewName{$_.BaseName.trim() + $_.extension} -PassThru
Write-Host "Trimming whitespace: $old_name"
}
else{
Write-Host "Trimming not needed "$names.BaseName
}
Write-host "Checking forbidden characters "$names.BaseName
rename_file_name $names ">"
rename_file_name $names "<"
rename_file_name $names "/"
}
}
Write-Host "Files checked: "$dictionary_filenames.Count
Write-Host "Files Skipped: "$counter_skipped
Read-Host 'Close window by pressing "Enter"'```
 is U+F021, two bytes long or [int16]. You can put it in a utf8 with bom encoded script.

Having some trouble with Powershell -replace and Environment Variables from Batch File

I finally narrowed down the problem, but need help understanding why.
Invoking Powershell from a batch file, the following works to replace a string within a file:
Powershell -Command "$foobar=[IO.File]::ReadAllText("$Env:File") ;
$foobarred= $foobar -replace '(?<foo>.*Backup.).*.(?<bar>..Backup.)', '${foo}Enabled${bar}' ;
[IO.File]::WriteAllText("$Env:File", $foobarred); "
Now if I try this, the command fails:
Powershell -Command "$foobar=[IO.File]::ReadAllText("$Env:File") ;
$foobarred= $foobar -replace '(?<foo>.*$Env:StrStart.).*.(?<bar>..$Env:StrEnd.)', '${foo}$Env:StrVal${bar}' ;
[IO.File]::WriteAllText("$Env:File", $foobarred); "
If I use a variable passed in from Batch, it fails everytime. If I use PlainText in the command instead for the replacement value, it works just fine. Why does this happen?
My observations would be
you need to [regex]::Escape() arbitrary values when you build regular expressions dynamically.
PowerShell does not do any string interpolation in single-quoted strings, so things like '${foo}$Env:StrVal${bar}' will not work the way you want.
I'd use the following command:
(Get-Content "filename" -Raw) -replace (
'(.*' + [regex]::Escape("start string") + '.).*.(..' + [regex]::Escape("end string") + '.)'
),(
'$1' + "replacement string" + '$2'
) | Set-Content "filename"
called ad-hoc from a batch file as follows (compressed onto one line):
#echo off
setlocal
set "FILENAME=filename"
set "START=start string"
set "END=end string"
set "REPLACEMENT=replacement string"
set "PSCMD=(gc $Env:FILENAME -Raw) -replace ('(.*' + [regex]::Escape($Env:START) + '.).*.(..' + [regex]::Escape($Env:END) + '.)'),('$1' + $Env:REPLACEMENT + '$2') | sc $Env:FILENAME"
powershell -NoLogo -Command "&{%PSCMD%}"
But this is disproportionately hard to maintain.
I'd recommend writing a .ps1 file and passing named arguments, instead of juggling environment variables.
# MyReplace.ps1
param(
[string]$Filename,
[string]$Start,
[string]$End,
[string]$Replacement
)
$ErrorActionPreference = "Stop"
$content = Get-Content $Filename -Raw
$content = $content -replace ('(.*' + [regex]::Escape($Start) + '.).*.(..' + [regex]::Escape($End) + '.)'),('$1' + $Replacement + '$2')
$content | Set-Content $Filename
and in batch
powershell -NoLogo -File MyReplace.ps1 -Filename "filename" -Start "start string" -End "end string" -Replacement "replacement string"
That seems more manageable to me.
At the advice of #Gerhard, adding what I found into the fray as an answer, but did ultimately giving #Tomalak the credit for the better answer overall.
In order to accept variables into both the match pattern and the replace pattern, you have to concatenate the strings (similar to how it is done in Visual Basic).
Reference below:
I have split the command up into multiple lines for readability - if you use this, place it on one line.
Important - when using this, be sure to remove the line-breaks if you use it in a batch file. Also - be wary - I have had some circumstances where even using Set-Content can change the Encoding of the file. I much prefer the secondary solution offered down below.
Powershell -Command "$pattern= '(?<RangeStart>.*' + [regex]::Escape($Env:StrStart) + '.).*.(?<RangeEnd>..' + [regex]::Escape($Env:StrEnd) + '.)' ;
$repl= '${RangeStart}' + $Env:StrVal + '${RangeEnd}' ;
$fil2parse=(Get-Content $Env:FileTOParse) -replace $pattern, $repl | Set-Content $Env:FileTOParse; "
This solution works as well, but I have had much fewer issues with it changing Encoding.
Powershell -Command "$pattern= '(?<RangeStart>.*' + [regex]::Escape($Env:StrStart) + '.).*.(?<RangeEnd>..' + [regex]::Escape($Env:StrEnd) + '.)' ;
$repl= '${RangeStart}' + $Env:StrVal + '${RangeEnd}' ;
$fil2parse=[IO.File]::ReadAllText("$Env:FileTOParse") ;
$filParsed= $fil2parse -replace $pattern, $repl ;
[IO.File]::WriteAllText("$Env:FileTOParse", $filParsed); "

Powershell: ConvertFrom-Json doesn't get the variable assigned due to forward and backward compatibility

I am trying to load a variables into powershell from variables.json having the following
{
"psfp": "C:/San\/SV65\/ps",
"vmfp": "'C:/San\/SV65\/hyper-packer\/hyper-packer\/output-centos8-9\/Virtual Machines'",
"psmp": "C:/San\/SV65\/ps",
"vmname": ""
}
Trying to import with
$jvariables=Get-Content -Raw -Path '.\variables-ps.json' | ConvertFrom-Json
Output on powershell
PS C:\San\SV65\ps> Write-host $jvariables.psfp
C:/San/SV65/ps
PS C:\San\SV65\ps> Write-host $jvariables.vmfp
'C:/San/SV65/hyper-packer/hyper-packer/output-centos8-9/Virtual Machines'
PS C:\San\SV65\ps> Write-host $jvariables.psmp
C:/San/SV65/ps
These forward slash not incompatible on powershell for a windows path! ConvertFrom-Json doesn't accept backslash on the variables tried with '' as well
Hence could not load my modules on these path
any other way to achieve the above case?
Want to use json as it easy for the end user to update rather a txt files
Please share
you can loop through the object properties and change the path separator like this:
$jvariables.psobject.properties | where {$_.membertype -eq "NoteProperty"} |
foreach {$data.($_.name) = $_.value.replace("/","\")}
or a simpler approach would be to escape backslash in config file, like this :
{
"psfp": "C:\\San\\SV65\\ps",
"vmfp": "'C:\\San\\SV65\\hyper-packer\\hyper-packer\\output-centos8-9\\Virtual Machines'",
"psmp": "C:\\San\\SV65\\ps",
"vmname": ""
}

Renaming one file (and nothing more than ONE file) using PowerShell

The problem
I constantly find myself in need of quick-method to rename a random file here and there while I work. I need to bring these filenames down to a structure compatible with web standards and some personal needs. A few examples below:
When I find I need
---------------------------------- -----------------------------------------
Welcome to the party.JPG welcome_to_the_party.jpg
Instructions (and some other tips) instructions_and_some_other_tips
Bar Drinks – The Best Recipes bar_drinks_the_best_recipes
La mañana del águila y el ratón la_manana_del_aguila_y_el_raton
Basically I need:
all uppercase characters to become lowercase
spaces to become underscore
some other special characters and diacritics for other languages to become their closest match (á is a, é is e, ç is c, and so on...)
Symbols like ( ) [ ] { } ' ; , to completely dissapear
Perhaps some replacements (optional) as: # = no; # = at or & = and
Not the question, but just FYI and you can see the big picture
I will be using a registry entry [HKEY_CLASSES_ROOT*\shell...] so I can call a batch file and/or a PowerShell Script by right-clicking the desired file, passing the argument information (the file in question) to the script that way.
My guesses
I have been looking closely at PowerShell Scripts, but I am not very knowledgeable about this area yet and all the solutions provided so far are addressing the entire folder (Dir/Get-ChildItem) instead of a specific file.
For example, I was successful using the line below (PowerShell) to replace all spaces by underscore, but then it affects other files in the directory as well.
Dir | Rename-Item –NewName { $_.name –replace “ “,”_“ }
Again, I do not need to address this problem for the entire folder, since I already have ways of doing so using software like Total Commander.
Thanks for any help you can give me.
Ruy
may be this code can help you
function Remove-Diacritics([string]$String)
{
$objD = $String.Normalize([Text.NormalizationForm]::FormD)
$sb = New-Object Text.StringBuilder
for ($i = 0; $i -lt $objD.Length; $i++) {
$c = [Globalization.CharUnicodeInfo]::GetUnicodeCategory($objD[$i])
if($c -ne [Globalization.UnicodeCategory]::NonSpacingMark) {
[void]$sb.Append($objD[$i])
}
}
return("$sb".Normalize([Text.NormalizationForm]::FormC))
}
function Clean-String([string]$String)
{
return(Remove-Diacritics ($String.ToLower() -replace "#", "no" -replace "\#", "at" -replace "&", "and" -replace "\(|\)|\[|\]|\{|\}|'|;|\,", "" -replace " ", "_"))
}
$youfile="C:\tmp4\121948_DRILLG.tif"
$younewnamefile=Clean-String $youfile
Rename-Item -Path $youfile $younewnamefile
Place this script somewhere (let's call it WebRename.ps1):
$old = $args -join ' '
$new = $old.ToLower().Replace(' ', '_')
# add all the remaining transformations you need here
Rename-Item $old $new
In the registry use this as the command (with your own path of course):
PowerShell -c C:\WebRename.ps1 "%1"
If your looking to be able to do this quickly and always want the same changes to be made you can add the following function to a .psm1 file and then place the file in one of your module folders (C:\Program Files\WindowsPowerShell\Modules is the most common one) you'll be able to just call WebRename-File filePath any time you need to quickly rename a file, the function is set up in such a way as to work fine if you pass in a single file path or you can pipe the results of a get-childitem to it if you ever do find the need to do bulk renames.
function WebRename-File {
param(
[parameter(Mandatory=$true,ValueFromPipeline=$true)]
$filePath
)
begin{}
Process{
foreach($path in $filePath){
$newPath = $path.ToLower()
$newPath = $newPath.Replace(' ','_')
###add other operations here###
Rename-Item -Path $path -NewName $newPath
}
}
end{}
}

replace exception in powershell

I'm a beginner in powershell and know C# pretty well. I have this command http://www.f2ko.de/programs.php?lang=en&pid=cmd that downloads stuff. I'm writing this script to download all the sgf go games from this url http://www.gogameworld.com/gophp/pg_samplegames.php, and was trying to write a powershell script to do it for me. So I wrote a script:
Get-Content test.txt|
ForEach-Object
{
if($_ -eq "=`"javascript:viewdemogame(`'*.sgf`')`" tit")
{
$filename = $_ -replace '=`"javascript:viewdemogame(`''
$filename = $filename -replace '`')`" tit'
&"(Path)/download.exe" ("http://www.gogameworld.com/webclient/qipu/" + $filename)
}
}
However, when I run the script, I keep getting this error:
Unexpected token '`'' in expression or statement.
At (PATH)\test.ps1:7 char:37
+ $filename = $filename -replace '`' <<<< )'
+ CategoryInfo : ParserError: (`':String) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken
I've looked at the script lots of times and still can't figure out whats wrong. Thanks.
Try this, read the content of the file as one string and then use the Regex.Matches to get all occurrences of the text contained in the parenthesis:
$content = Get-Content test.txt | Out-String
$baseUrl = 'http://www.gogameworld.com/webclient/qipu/'
[regex]::matches($content,"javascript:viewdemogame\('([^\']+)'\)") | Foreach-Object{
$url = '{0}{1}' -f $baseUrl,$_.Groups[1].Value
& "(Path)/download.exe" $url
}
here's an explanation of the regex pattern (created with RegexBuddy):
javascript:viewdemogame\('([^\']+)'\)
Match the characters “javascript:viewdemogame” literally «javascript:viewdemogame»
Match the character “(” literally «\(»
Match the character “'” literally «'»
Match the regular expression below and capture its match into backreference number 1 «([^\']+)»
Match any character that is NOT a ' character «[^\']+»
Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
Match the character “'” literally «'»
Match the character “)” literally «\)»
Match the character “"” literally «"»
'{0}{1}' is used with the -f operator to create a string. {0} maps to the first value on the right hand side of the operator (e.g $baseUrl) and {1} is mapped to the second value. Under the hood, PowerShell is suing the .NET String.Format method. You can read more about it here: http://devcentral.f5.com/weblogs/Joe/archive/2008/12/19/powershell-abcs---f-is-for-format-operator.aspx
'')" tit'
The -replace operator takes 2 arguments, comma separated. The first is a regular expression that matches what you want replaced. The second is the string you want to relace that with. You appear to be missing the second argument.