How do I use Function in PowerShell to execute from Command Line? - powershell

I want to execute my script with command line. I use function inside my script.
I used this script:
Function Get-IniFile
{
Param(
[parameter(mandatory=$true)][string]$FilePath
)
$input_file = $FilePath
$ini_file = #{}
Get-Content $input_file | ForEach-Object {
$_.Trim()
} | Where-Object {
$_ -notmatch '^(;|$)'
} | ForEach-Object {
if ($_ -match '^\[.*\]$') {
$section = $_ -replace '\[|\]'
$ini_file[$section] = #{}
} else {
$key, $value = $_ -split '\s*=\s*', 2
$ini_file[$section][$key] = $value
}
}
$Get = $ini_file.Class.Amount
$Get
}
I execute this script from command line with this command:
PowerShell.ps1 Get-IniFile -FilePath
I dont get any result when I execute this code, but If I remove "Function Get-IniFile" I got the value of Amount.
This is my INI file
[Class]
Amount = 1000
Feature = 20
[Item]
Set = 100
Return = 5

You have to call your function inside your script. The script code is like your main function in C# or Java.
PowerShell.ps1 content :
# Global script parameters.
Param(
[parameter(mandatory=$true)][string]$FilePath
)
# Definition of the function
Function Get-IniFile
{
Param(
[parameter(mandatory=$true)][string]$Path
)
$input_file = $Path
$ini_file = #{}
Get-Content $input_file | ForEach-Object {
$_.Trim()
} | Where-Object {
$_ -notmatch '^(;|$)'
} | ForEach-Object {
if ($_ -match '^\[.*\]$') {
$section = $_ -replace '\[|\]'
$ini_file[$section] = #{}
} else {
$key, $value = $_ -split '\s*=\s*', 2
$ini_file[$section][$key] = $value
}
}
$Get = $ini_file.Class.Amount
$Get
}
# Calling the function with the global parameter $FilePath
Get-IniFile $FilePath

Related

How to modify Firefox config (pref.js) line using Powershell

Modifying the Mozilla Firefox Pref.js file using PowerShell.
Need to modify the pref.js file line to reflect a new value
(Hence, instead of any value under user_pref("network.automatic-ntlm-auth.trusted-uris", "*"); to show user_pref("network.automatic-ntlm-auth.trusted-uris", ".abc.com,.abcd.com,.abcde.com") or just add changes after the *
$TopDir = "$env:APPDATA\Mozilla\Firefox\Profiles"
$FileName = 'prefs.js'
$DefaultProfileDir = (Get-ChildItem -LiteralPath $TopDir -Directory).
Where({
$_.FullName -match '\.default'
}).FullName
$FullFileName = Join-Path -Path $DefaultProfileDir -ChildPath $FileName
$data = foreach($line in Get-Content $FullFileName)
{
if($line -contains 'user_pref("network.automatic-ntlm-auth.trusted-uris".*')
{
$line -replace '*' , 'user_pref("network.automatic-ntlm-auth.trusted-uris", ".abc.com,.abcd.com,.abcde.com");'
}
else
{
$line
}
}
$data | Set-Content C:\testfolder\test2.txt
Nelson,
I didn't have your line in my FF profile but I got the code to work on another line so you should be able to modify it to work with yours.
$TopDir = "G:\Test"
$FileName = 'prefs.js'
$FullFileName = "$TopDir\$FileName"
Clear-Host
$Data = foreach($line in Get-Content $FullFileName) {
if( ($line.IndexOf('browser.bookmarks.restore_default_bookmarks')) -ne -1)
{
If ($line.IndexOf('false') -ne -1) {
$line = $line.replace( 'false' , 'true')
}
}
$line
}
$data | Set-Content $("$TopDir" + "\prefs2.js")
I think your code would be:
$TopDir = "$env:APPDATA\Mozilla\Firefox\Profiles"
$FileName = 'prefs.js'
$DefaultProfileDir = (Get-ChildItem -LiteralPath $TopDir -Directory).
Where({
$_.FullName -match '\.default'
}).FullName
$FullFileName = Join-Path -Path $DefaultProfileDir -ChildPath $FileName
$Data = foreach($line in Get-Content $FullFileName) {
if( ($line.IndexOf('network.automatic-ntlm-auth.trusted-uris')) -ne -1)
{
If ($line.IndexOf('*') -ne -1) {
$line = $line.replace( '*' , 'abc.com,.abcd.com,.abcde.com')
}
}
$line
}
$data | Set-Content C:\testfolder\test2.txt
Note: -contains is designed for lists.
HTH
I extended it to be easier to use any property
Input
user_pref("foo", "bar")
user_pref("network.automatic-ntlm-auth.trusted-uris", "*")
Output
user_pref("foo", "bar")
user_pref("network.automatic-ntlm-auth.trusted-uris", ".abc.com,.abcd.com,.abcde.com")
$lines = 'user_pref("foo", "bar")', 'user_pref("network.automatic-ntlm-auth.trusted-uris", "*")'
# multi-line regex for readability
$regex = '(?x)
(?<prefix>user_pref\()
(?<name>
".*"
)
\s*,\s*
(?<value>
".*"
)
(?<suffix>.*)
'
"`ninput:"
$lines
"`noutput:"
$lines | ForEach-Object {
if($_ -match $regex) {
if($matches.name -eq '"network.automatic-ntlm-auth.trusted-uris"') {
$_ = '{0}{1}, {2}{3}' -f #(
$Matches.prefix,
$Matches.name,
'".abc.com,.abcd.com,.abcde.com"',
$Matches.suffix
)
}
}
$_
}

How to read a specific item of INI file using PowerShell?

I want to read a specific item of my INI file, I have 5 Items in the section of my INI file, and I want to read 4 items, except items number 3.
I already tried to read all the items, but I can not find a way how to specify the item that I want to read and the format of the file that I read is like this:
Name Value
AA 12
BB 13
CC 14
DD 15
EE 16
I used this command to execute it.
File1.ps1 Read-File -FilePath C:\Users\Data.ini -a_section Code -store C:\Users\
function Read-File {
Param(
[Parameter(Mandatory=$true)]$FilePath,
[Parameter(Mandatory=$true)]$a_section,
[Parameter(Mandatory=$true)]$store
)
$input_file = $FilePath
$ini_file = #{}
Get-Content $input_file | ForEach-Object {
$_.Trim()
} | Where-Object {
$_ -notmatch '^(;|$)'
} | ForEach-Object {
if ($_ -match '^\[.*\]$') {
$section = $_ -replace '\[|\]'
$ini_file[$section] = #{}
} else {
$key, $value = $_ -split '\s*=\s*', 2
$ini_file[$section][$key] = $value
}
}
$Path_Store = $store
$Get_Reg = $ini_file.($a_section)
$Output = $Get_Reg | Out-File $Path_Store\Out_Test
}
$cmd, $params = $args
& $cmd #params
My expectation result, I have an output file like this
AA=12
BB=13
DD=15
EE=16
My INI File look like this:
[Name]
1=Joe
2=Grace
[Code]
AA=12
BB=13
CC=14
DD=15
EE=16
Try this:
function Get-IniSection {
Param(
[Parameter(Mandatory=$true)]$Path,
[Parameter(Mandatory=$true)]$SectionName
)
$ini_file = #{}
Get-Content $Path | ForEach-Object {
$_.Trim()
} | Where-Object {
$_ -notmatch '^(;|$)'
} | ForEach-Object {
if ($_ -match '^\[.*\]$') {
$section = $_ -replace '\[|\]'
$ini_file += #{ $section = #{} }
} else {
$key, $value = $_ -split '\s*=\s*', 2
$ini_file[$section] += #{ $key = $value }
}
}
return $ini_file[$SectionName]
}
$section = Get-IniSection -Path "C:\temp\test.ini" -SectionName "code"
$section.GetEnumerator() | Where-Object { $_.Name -ne "EE" }
$section.GetEnumerator() | ForEach-Object { "$($_.Name)=$($_.Value)" }
$section.GetEnumerator() |
Where-Object { $_.Name -in #("A1","AE","AP","AS","E1","E2","JP","M1","M2","N1","N2","P1","P2","P3","P4","PR","RU","S1","S2","W1","W2","W3","W4","ZH") } |
Select-Object -ExpandProperty "Value"
$section.GetEnumerator() |
Where-Object { $_.Name -in #("A1","AE","AP","AS","E1","E2","JP","M1","M2","N1","N2","P1","P2","P3","P4","PR","RU","S1","S2","W1","W2","W3","W4","ZH") } |
Foreach-Object { ($_.Value -split ",")[0] }

How to edit INI file value in Powershell?

I have an INI file:
[Name]
Female = 10
Male = 30
[Class]
Kids = 2
Adult = 10
I want to change the value of each section. Give me idea please.
I tried this code:
function Set-OrAddIniValue
{
Param(
[string]$FilePath,
[hashtable]$keyValueList
)
$content = Get-Content $FilePath
$keyValueList.GetEnumerator() | ForEach-Object {
if ($content -match "^$($_.Key)=")
{
$content= $content -replace "^$($_.Key)=(.*)", "$($_.Key)=$($_.Value)"
}
else
{
$content += "$($_.Key)=$($_.Value)"
}
}
$content | Set-Content $FilePath
}
this is the code
You would do so:
$ini = Get-IniContent "<pathToYourIniFile>"
$ini["<yourSection>"]["<yourKey>"] = "<yourValue>"
$ini | out-inifile -FilePath "<pathToYourIniFile>"
If you updated your code to the following, it will be more successful:
function Set-OrAddIniValue
{
Param(
[string]$FilePath,
[hashtable]$keyValueList
)
$content = Get-Content $FilePath
$keyValueList.GetEnumerator() | ForEach-Object {
if ($content -match "$($_.Key)\s*=")
{
$content= $content -replace "$($_.Key)\s*=(.*)", "$($_.Key)=$($_.Value)"
}
else
{
$content += "$($_.Key)=$($_.Value)"
}
}
$content | Set-Content $FilePath
}
One problem will be if you add extra key/value pairs, they will all be added to the last section. In other words, the code is not section-aware.

How to extract environment path lines with conditions?

In short: How to get joined lines which not matches any string item of an array?
It seems trivial but I can't find solution. I'm trying to manage VSCode Python environments with PowerShell functions. I use PowerShell script to change vscode terminal path settings with ease. I want to get environment path lines which is not a Python path.
$noPythonPath = ($env:path.Split(';') | Where-Object {
$_ -notmatch 'python' -and
$_ -notmatch 'anaconda' -and
$_ -notmatch 'django' -and
$_ -notmatch 'pspenv'
}) -join ';'
I wonder is there are way to do this without manually listing all the path keys. But below code does not work. Seems -match not work with string array.
$key = $PC2paths.Keys
$noPythonPath = ($env:path.Split(';') | Where-Object {
$_ -notmatch $key.TrimEnd('1234567890')
}) -join ';'
And below is containing codes.
$PC2paths = #{
'Anaconda3' = "C:\Program Files\Anaconda3\python.exe;C:\Program Files\Anaconda3\Scripts;";
'DjangoVenv2' = "C:\Users\user\source\repos\CsStudy\.virtualenvs\Djangovenv2\Scripts\python.exe;" ;
"pypy2" = "C:\pypy2-v5.9.0-win32\pypy2-v5.9.0-win32\pypy.exe;C:\pypy2-v5.9.0-win32\pypy2-v5.9.0-win32\bin;";
'python2' = "c:\python27\python.exe;C:\Python27\Scripts;";
'python3' = "C:\Program Files\Python36-32\python.exe;C:\Program Files\Python36-32\Scripts;";
'ropepython2' = "C:\Users\user\source\repos\rope\ropeTest1\ropeTest1\rope1\.vscode\ropePython\Scripts\python.exe;";
'pspenv1' = "C:\Users\user\source\repos\psptools\.virtualenvs\pspenv1\Scripts\python.exe;";
'RefreshEnvironment' = 'C:\Users\user\source\repos\CsStudy\.vscode\refreshenv.cmd';
}
function workon($environment) {
& cmd /k workon.bat $environment
}
function useEnv([string]$envName) {
$pathKey = $envName
$SettingsFilePath = (UpSearch . "settings.json")
if ($SettingsFilePath -eq "file not found") {
Write-Output 'not found'
return
}
$key = $PC2paths.Keys
$noPythonPath = ($env:path.Split(';') | Where-Object {
$_ -notmatch $key.TrimEnd('1234567890')
}) -join ';'
$newpaths = (($PC2paths.$pathKey) + $noPythonPath)
$newpaths = $newpaths.split(';')
$exepath = $newpaths[0]
$newpaths[0] = Split-Path $newpaths[0]
$ofs = ';'
$newpath = "$newpaths"
$env:path = $newpath
$a = Get-Content $SettingsFilePath -Raw | ConvertFrom-Json
$a."python.pythonPath" = $exepath
$a."terminal.integrated.env.windows" | Add-Member -Name "path" -Value $newpath -MemberType NoteProperty -Force
$a | ConvertTo-Json -Depth 30 | Set-Content $SettingsFilePath
# $refresh = UpSearch . "RefreshEnv.cmd"
$refresh = $PC2paths."RefreshEnvironment"
cmd /c $refresh
}
function useAnaconda3 {
useEnv -envName 'Anaconda3'
}
function useDjangoVenv2 {
useEnv -envName 'DjangoVenv2'
}
function usePypy2 {
useEnv -envName 'pypy2'
}
function usePython2 {
useEnv -envName 'python2'
}
function usePython3 {
useEnv -envName 'python3'
}
function useropepython2 {
useEnv -envName 'ropepython2'
}
function usepspenv1 {
useEnv -envName 'pspenv1'
}
function UpSearch($pathtosearch, $filename) {
if ($pathtosearch -eq "") {
"file not founded"
return
}
$pathtosearch = (Get-Item -Path $pathtosearch -Verbose).FullName
if (Test-Path "$pathtosearch\.vscode\$filename" ) {
"$pathtosearch\.vscode\$filename"
} else {
UpSearch (Split-Path $pathtosearch) $filename
}
}
Correct, -match (as well as -notmatch) does not work with an array as the second operand. You can join the array to an alternation regular expression, though:
$a = 'foo', 'bar', 'baz'
$re = ($a | ForEach-Object { [regex]::Escape($_) }) -join '|'
'something', 'bar', 'else' -notmatch $re

Find and Replace multi-line string

I'm trying to find a string and add the string needed for a program.
I need the code to look to see if the action = run fast already exists and if so do nothing.
$Input = GetContent "${Env:ProgramFiles}\myprogram\file.conf"
$replace = #"
[MyAction_Log]
action = run fast
"#
$Input -replace ('action = run fast') -replace ('\[MyAction_Log\]',$replace) | set-content "${Env:ProgramFiles}\myprogram\file.conf"
I would check before wantonly replacing things you think exist. Also, never use $Input as a variable name; it's an automatic variable and won't do what you think it will (treat it as read-only).
$path = "$Env:ProgramFiles\prog\file.conf"
$file = Get-Content -Path $path
$replacementString = #'
[MyAction_Log]
action = run fast
'#
if ($file -notmatch 'action\s=\srun\sfast')
{
$file -replace '\[MyAction_Log\]', $replacementString |
Set-Content -Path $path
}
An alternative that's able to cope with the action key being located anywhere in the [MyAction_Log] section
$Inside = $False
$Modified = $False
$Path = "$( $env:ProgramFiles )\prog\file.conf"
$NewLines = Get-Content $Path |
ForEach-Object {
if( $_.Trim() -like "[*]" ) { $Inside = $False }
if( $_.Trim() -like "*[MyAction_Log]*" ) { $Inside = $True }
If( $Inside -and $_ -like "action = *" -and $_ -notlike "*run fast*" ) { $Modified = $True; "action = run fast" } else { $_ }
}
If( $Modified ) { $NewLines | Set-Content $Path }