<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>PowerShell &#8211; Mr. Panas</title>
	<atom:link href="https://mrpanas.com/category/powershell/feed/" rel="self" type="application/rss+xml" />
	<link>https://mrpanas.com</link>
	<description>PowerShell, VBA, Programming, RPA, Automation</description>
	<lastBuildDate>Sat, 08 May 2021 03:53:10 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.8.10</generator>

<image>
	<url>https://mrpanas.com/wp-content/uploads/2020/02/cropped-mrPanas2-2-32x32.png</url>
	<title>PowerShell &#8211; Mr. Panas</title>
	<link>https://mrpanas.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>How to reboot many computers at the same time (remotely)</title>
		<link>https://mrpanas.com/how-to-reboot-many-computers-at-the-same-time-remotely/</link>
					<comments>https://mrpanas.com/how-to-reboot-many-computers-at-the-same-time-remotely/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 26 Feb 2021 03:11:27 +0000</pubDate>
				<category><![CDATA[PowerShell]]></category>
		<guid isPermaLink="false">https://mrpanas.com/?p=800</guid>

					<description><![CDATA[<p>PowerShell is defined as a cross-platform task automation and configuration management framework. That means it was mainly created to automate your tasks. If you are a Windows system administrator, PowerShell should be your best friend in all your daily routines. One of those routines is a periodic reboot of Windows servers (you should do it [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://mrpanas.com/how-to-reboot-many-computers-at-the-same-time-remotely/">How to reboot many computers at the same time (remotely)</a> appeared first on <a rel="nofollow" href="https://mrpanas.com">Mr. Panas</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>PowerShell is defined as a cross-platform task automation and configuration management framework. That means it was mainly created to automate your tasks. If you are a Windows system administrator, PowerShell should be your best friend in all your daily routines.</p>



<p>One of those routines is a periodic reboot of Windows servers (you should do it at least once a month after installing new patches). In this post, I will show you how to reboot as many servers as you want at the same time, and collect the reboot status for each of them.</p>



<p>Let&#8217;s start from the easiest step &#8211; reboot remotely one computer (computer name: MyServer1)</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: powershell; title: ; notranslate">
Restart-Computer -ComputerName MyServer1
</pre></div>


<p class="has-tiny-font-size"><em>In my examples, I will execute reboot processes from the domain admin session that has the same privileges on all rebooted servers. Otherwise, you need to the &#8220;-Credential&#8221; parameter. E.g.:<br><span class="has-inline-color has-vivid-cyan-blue-color">$Cred = Get-Credential<br>Restart-Computer -ComputerName &#8220;MyServer1&#8221; -Credential $Cred</span></em></p>



<p>The command above does the job, but it doesn&#8217;t return the reboot results, so you do not know if the server was successfully rebooted.<br>So let&#8217;s try to add a few helpful parameters:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: powershell; title: ; notranslate">
Restart-Computer -ComputerName MyServer1 -Wait -For Wmi -Timeout 600 -Force
</pre></div>


<p>In the example above I execute the reboot on the MyServer1 computer and wait until receiving a reply to a Win32_ComputerSystem query for the MyServer1. I also added a timeout of 600 seconds (10 minutes) to get an error if the computer is not rebooted in 10 minutes.<br>To reboot more than one computer, you can add more computer names to the ComputerName parameter:<br>-ComputerName MyServer1, MyServer2, MyServer3</p>



<p>It looks almost great, but I prepared a script that automates the whole rebooting process (including stopping and starting processes) and I wanted to have the reboot under better control. So I prepared a robust solution that executes each reboot as a separate asynchronous job and collects results when all jobs are completed.<br>The script can look like that:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: powershell; title: ; notranslate">
#define the script that will be executed for each computer
$script = {
    $computer = $args&#x5B;0]
    try {
        Restart-Computer -ComputerName $computer -Wait -For Wmi -Timeout 600 -Force -ErrorAction Stop
        Return New-Object PSObject -property  @{status = 'OK'; computer = $computer; error = ''}
    } catch {
        Return New-Object PSOobject -property  @{status = 'ERROR'; computer = $computer; error = ($Error&#x5B;0].Exception.Message)}
    }
}

#start asynchronous jobs for each computer (all jobs will be executed at the same time)
Start-Job -Name 'reboot' -ScriptBlock $script -ArgumentList 'MyServer1' | Out-Null
Start-Job -Name 'reboot' -ScriptBlock $script -ArgumentList 'MyServer2' | Out-Null
Start-Job -Name 'reboot' -ScriptBlock $script -ArgumentList 'MyServer3' | Out-Null

$rebootResults = @()

#wait until all jobs are finished and collect results
While (Get-Job | Where {$_.State -eq 'Running' -and $_.name -eq 'reboot'}) {
  Start-Sleep -Milliseconds 500   
  $rebootResults += Receive-Job -Name 'reboot'
}

#display results of servers rebooting
$rebootResults | Select-Object status, computer, error | Format-Table


</pre></div>


<p>If you like this post, please share it and leave a comment.</p>
<p>The post <a rel="nofollow" href="https://mrpanas.com/how-to-reboot-many-computers-at-the-same-time-remotely/">How to reboot many computers at the same time (remotely)</a> appeared first on <a rel="nofollow" href="https://mrpanas.com">Mr. Panas</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://mrpanas.com/how-to-reboot-many-computers-at-the-same-time-remotely/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PowerShell and Oracle DB</title>
		<link>https://mrpanas.com/powershell-and-oracle-db/</link>
					<comments>https://mrpanas.com/powershell-and-oracle-db/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 11 Dec 2020 00:28:06 +0000</pubDate>
				<category><![CDATA[PowerShell]]></category>
		<guid isPermaLink="false">https://mrpanas.com/?p=763</guid>

					<description><![CDATA[<p>Connecting PowerShell scripts to a database gives us a huge buster to process automation and processes/systems monitoring.We can apply it to many different solutions as well as bypass, extend, or improve the functionality of other systems. A few practical/real examples how this can be applied : to store a script data and configuration (it is [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://mrpanas.com/powershell-and-oracle-db/">PowerShell and Oracle DB</a> appeared first on <a rel="nofollow" href="https://mrpanas.com">Mr. Panas</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Connecting PowerShell scripts to a database gives us a huge buster to process automation and processes/systems monitoring.<br>We can apply it to many different solutions as well as bypass, extend, or improve the functionality of other systems.</p>



<p>A few practical/real examples how this can be applied :</p>



<ul><li>to store a script data and configuration (it is more flexible than hard-coded parameters or configuration (.ini) files,</li><li>read and process data from other systems (great for processes automation),</li><li>monitor other systems activity and alert users and admins when some events occur,</li><li>enter manipulated/calculated data directly to other systems&#8217; databases.</li></ul>



<p>I also created a solution that monitors all configuration changes in different systems and creates an external audit trail functionality that can detect changes (and send a notification) applied directly to the database.<br>But let&#8217;s talk about efficient technics of working with databases from PowerShell.</p>



<p>The <strong><span class="has-inline-color has-vivid-red-color">Oracle Database </span></strong>is one of the most advanced, enterprise-level database systems. I use PowerShell very often to create monitoring or data manipulation solutions for advanced applications, that are not easily maintain or the maintenance cost is very high. <br>You can find a few different methods of how to accessing Oracle database from PowerShell (e.g. using <em>sqlplus </em>or <em>ExecuteReader()</em>, but I will describe the easiest and the fastest method.</p>



<h3>Module installation</h3>



<p>You will need ADO .NET provider (<em>Oracle.ManagedDataAccess.dll</em>) for Oracle.<br>You can find here information about how to download it: <a href="https://docs.oracle.com/database/121/ODPNT/installODPmd.htm#ODPNT8149">https://docs.oracle.com/database/121/ODPNT/installODPmd.htm#ODPNT8149</a></p>



<p>No module installation is needed. Just add the .NET Core class (<em>Oracle.ManagedDataAccess.dll</em> file) as to the PowerShell session by adding at the beginning of your script:</p>



<p><code>Add-Type -Path "<em>&lt;path&gt;</em>\Oracle.ManagedDataAccess.dll"</code></p>



<h3>Use example</h3>



<p>After loading the .NET Core class, follow the steps:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: powershell; title: ; notranslate">
$OraConn = New-Object Oracle.ManagedDataAccess.Client.OracleConnection(&quot;&lt;connection string&gt;&quot;)
$OraCmd = New-Object Oracle.ManagedDataAccess.Client.OracleCommand
$OraCmd.FetchSize = $OraCmd.FetchSize * 64
$OraCmd.Connection = $OraConn
$OraCmd.CommandText = &quot;&lt;query&gt;&quot;
$OraConn.Open()
$OraAdap = New-Object Oracle.ManagedDataAccess.Client.OracleDataAdapter($oraCmd)
$DataTable = New-object &quot;System.Data.DataTable&quot;
$OraAdap.Fill($DataTable) | Out-Null
$results = $DataTable | Select $DataTable.Columns.ColumnName
$oraConn.Close()
</pre></div>


<p><strong>The explanation of a few things:</strong></p>



<p><strong><code>"<em>&lt;connection string&gt;</em>"</code></strong> &#8211; this is the connection string to the database, like:<br>&#8220;Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=<em>ServerName</em>)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=<em>ServiceName</em>)));User Id=<em>User</em>; Password=<em>Password</em>&#8220;</p>



<p><strong><em><code>$OraCmd.FetchSize = $OraCmd.FetchSize * 64</code></em></strong> &#8211; to speed up a bigger data reading, I increased the reading buffer 64 times (from 127KB to 8MB). You will see a huge difference in data read speed. </p>



<p><strong><em><code>$OraAdap.Fill($DataTable) | Out-Null</code></em></strong> &#8211; pumps data to an in-memory data table (I added &#8220;| Out-Null&#8221; to prevent displaying messages on the screen &#8211; it is important if you create a function that returns $results) </p>



<p><strong>I hope that this post will be helpful in database access directly from PowerShell.</strong></p>
<p>The post <a rel="nofollow" href="https://mrpanas.com/powershell-and-oracle-db/">PowerShell and Oracle DB</a> appeared first on <a rel="nofollow" href="https://mrpanas.com">Mr. Panas</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://mrpanas.com/powershell-and-oracle-db/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PowerShell and MS SQL Server DB</title>
		<link>https://mrpanas.com/powershell-and-ms-sql-server-db/</link>
					<comments>https://mrpanas.com/powershell-and-ms-sql-server-db/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 11 Dec 2020 00:24:33 +0000</pubDate>
				<category><![CDATA[PowerShell]]></category>
		<guid isPermaLink="false">https://mrpanas.com/?p=760</guid>

					<description><![CDATA[<p>Connecting PowerShell scripts to a database gives us a huge buster to process automation and processes/systems monitoring.We can apply it to many different solutions as well as bypass, extend, or improve the functionality of other systems. A few practical/real examples how this can be applied : to store a script data and configuration (it is [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://mrpanas.com/powershell-and-ms-sql-server-db/">PowerShell and MS SQL Server DB</a> appeared first on <a rel="nofollow" href="https://mrpanas.com">Mr. Panas</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Connecting PowerShell scripts to a database gives us a huge buster to process automation and processes/systems monitoring.<br>We can apply it to many different solutions as well as bypass, extend, or improve the functionality of other systems.</p>



<p>A few practical/real examples how this can be applied :</p>



<ul><li>to store a script data and configuration (it is more flexible than hard-coded parameters or configuration <a href="https://mrpanas.com/powershell-config-ini-file-for-your-script/" data-type="URL" data-id="https://mrpanas.com/powershell-config-ini-file-for-your-script/">(.ini) files</a>,</li><li>read and process data from other systems (great for processes automation),</li><li>monitor other systems activity and alert users and admins when some events occur,</li><li>enter manipulated/calculated data directly to other systems&#8217; databases.</li></ul>



<p>I also created a solution that monitors all configuration changes in different systems and creates an external audit trail functionality that can detect changes (and send a notification) applied directly to the database.<br>But let&#8217;s talk about efficient technics of working with databases from PowerShell.</p>



<p><strong>MS SQL Server </strong>is a very popular database system from Microsoft. Accessing SQL Server data from PowerShell gives us the possibility of data processing and data monitoring. There are a few methods of accessing data on SQL Server, but I will describe the easiest and most efficient one (in my opinion).</p>



<h3>Module installation</h3>



<p>MS SQL Server module for PowerShell is available at PowerShell Gallery and you can easily install it with the following cmdlet:</p>



<p><code>Install-Module -Name SqlServer</code></p>



<h3>Use example</h3>



<p>The basic use of the module is very similar to SQLite. First, you have to load the module:<br><code>Import-Module SqlServer</code><br>After that, execute any SQL statement (Select, Insert, Update, Delete, &#8230;) using:<br><code>$results = Invoke-Sqlcmd -Query "<em>&lt;query&gt;</em>" -ConnectionString "<em>&lt;connection_string&gt;</em>"</code><br>The connection string can look for example like this:<br><code>Server=<em>&lt;server&gt;</em>;database=<em>&lt;db_name&gt;</em>; User ID=<em>&lt;user&gt;</em>; Password=<em>&lt;password&gt;</em>;ApplicationIntent=ReadOnly</code></p>



<p>Like in the SQLite example, I recommend converting the returned results to the array of objects adding <code>[pscustomobject[]]</code> before <code>$results</code>.<br>The example of the source code can look like this (replace the <em>italic </em>text with your connection data):</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: powershell; title: ; notranslate">
Import-Module SqlServer
&#x5B;pscustomobject&#x5B;]]$results = Invoke-Sqlcmd -Query &quot;SELECT * FROM Customer&quot; -ConnectionString &quot;Server=SERVER1;database=CRMdb; User ID=user1; Password=password1;ApplicationIntent=ReadOnly&quot;
if ($results.count -gt 0) {
   Write-Host &quot;Numer of selected records:&quot; $results.count
} else {
   Write-Host &quot;No records found&quot;
}
</pre></div>


<p><strong>I hope that this post will be helpful in database access directly from PowerShell.</strong><br>If you like it, feel free to share.</p>
<p>The post <a rel="nofollow" href="https://mrpanas.com/powershell-and-ms-sql-server-db/">PowerShell and MS SQL Server DB</a> appeared first on <a rel="nofollow" href="https://mrpanas.com">Mr. Panas</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://mrpanas.com/powershell-and-ms-sql-server-db/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PowerShell and SQLite</title>
		<link>https://mrpanas.com/powershell-and-sqlite/</link>
					<comments>https://mrpanas.com/powershell-and-sqlite/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 11 Dec 2020 00:11:38 +0000</pubDate>
				<category><![CDATA[PowerShell]]></category>
		<guid isPermaLink="false">https://mrpanas.com/?p=756</guid>

					<description><![CDATA[<p>Connecting PowerShell scripts to a database gives us a huge buster to process automation and processes/systems monitoring.We can apply it to many different solutions as well as bypass, extend, or improve the functionality of other systems. SQLite is perfect to store a script data and configuration (it is more flexible than hard-coded parameters or configuration [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://mrpanas.com/powershell-and-sqlite/">PowerShell and SQLite</a> appeared first on <a rel="nofollow" href="https://mrpanas.com">Mr. Panas</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Connecting PowerShell scripts to a database gives us a huge buster to process automation and processes/systems monitoring.<br>We can apply it to many different solutions as well as bypass, extend, or improve the functionality of other systems.</p>



<p>SQLite is perfect to store a script data and configuration (it is more flexible than hard-coded parameters or configuration <a href="https://mrpanas.com/powershell-config-ini-file-for-your-script/" data-type="URL" data-id="https://mrpanas.com/powershell-config-ini-file-for-your-script/">.ini files</a></p>



<p>I also created a solution that monitors all configuration changes in different systems and creates an external audit trail functionality that can detect changes (and send a notification) applied directly to the database.<br>But let&#8217;s talk about efficient technics of working with databases in PowerShell.</p>



<p>SQLite is a very simple but most popular database engine in the world (based on the SQLite website, more than 1 trillion databases are in use).  It is used in all smartphones and most operational systems. All data is stored in one file and managed by the C-language library. There are many extensions to SQLite that give some level of security (I will describe it in another post) and data compression, but the PowerShell library that I describe here has none of them.<br>You can create a database structure from the script, but in my opinion, the best tool to create a database, manually browse data, etc. is an open-source tool &#8211; DB Browser for SQLite (<a href="https://sqlitebrowser.org/">https://sqlitebrowser.org/</a>), so I will focus on how to execute SQL statements from PowerShell on an SQLite database. </p>



<h3>Module installation</h3>



<p>SQLite module (PSSQLite) for PowerShell is available at PowerShell Gallery and you can easily install it with the following cmdlet:</p>



<p><code>Install-Module -Name PSSQLite -Force</code></p>



<h3>Use example</h3>



<p>First, need to load the module:<br><code>Import-Module PSSQLite </code><br>After that, execute any SQL statement (Select, Insert, Update, Delete, &#8230;) using:<br><code>$results = Invoke-SqliteQuery -Query "<em>&lt;query&gt;</em>" -DataSource "<em>&lt;sqlite_db_file_path&gt;</em>"</code></p>



<p>The result will be returned as an array of objects, but there is one exception. If the results return only one record, it is just an object, not an array. In this case, if you want to simply check the number of returned records <code>$results.count</code>, you receive an empty value instead of <code>1</code>. <br>That is why I prefer to use the following method (always convert returned results to the array of PSObjects:<br><code>[pscustomobject[]]$results = Invoke-SqliteQuery -Query "<em>&lt;query></em>" -DataSource "<em>&lt;sqlite_db_file_path></em>"</code></p>



<p>The example of the source code can look like this:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: powershell; title: ; notranslate">
Import-Module PSSQLite
&#x5B;pscustomobject&#x5B;]]$results = Invoke-SqliteQuery -Query &quot;SELECT * FROM Customer&quot; -DataSource &quot;MyDB.sqlite3&quot;
if ($results.count -gt 0) {
   Write-Host &quot;Numer of selected records:&quot; $results.count
} else {
   Write-Host &quot;No records found&quot;
}
</pre></div>


<p>The module supports also a few other cmdlets, like <em>New-SQLiteConnection</em> (creates SQLite connection), <em>Invoke-SQLiteBulkCopy</em> (allows load data faster), and <em>Out-DataTable</em> (creates data table for a PowerShell object).</p>



<h3>SQlite database encryption</h3>



<p>A default SQLite database file is not encrypted. But .Net library, used in the PSSQLite module gives us the possibility of database encryption.<br>The encryption algorithm is RC4, which is not the most advanced, but at least the database cannot be easily open without the password.<br>To encrypt the database, we have to use <em>New-SQLiteConnection</em> command and ChangePassword method:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: powershell; title: ; notranslate">
$Connection = New-SQLiteConnection -DataSource &quot;MyDB.sqlite3&quot;
$Connection.ChangePassword(&quot;Password123&quot;)
$Connection.Close()
</pre></div>


<p>After encrypting the database can be open only with the password. The password has to be added as a part of the DataSource parameter:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: powershell; title: ; notranslate">
Invoke-SqliteQuery -Query &quot;SELECT * FROM Customer&quot; -DataSource &quot;MyDB.sqlite3;Password=Password123&quot;
</pre></div>


<p>To remove password form the database the $null value has to be passed as a password:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: powershell; title: ; notranslate">
$Connection = New-SQLiteConnection -DataSource &quot;MyDB.sqlite3;Password=Password123&quot;
$Connection.ChangePassword($null)
$Connection.Close()
</pre></div>


<p><strong>I hope that this post will be helpful in SQLite access from PowerShell.</strong> <br>If you like it, please feel free to share.</p>
<p>The post <a rel="nofollow" href="https://mrpanas.com/powershell-and-sqlite/">PowerShell and SQLite</a> appeared first on <a rel="nofollow" href="https://mrpanas.com">Mr. Panas</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://mrpanas.com/powershell-and-sqlite/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PowerShell &#8211; config (.ini) file for your script</title>
		<link>https://mrpanas.com/powershell-config-ini-file-for-your-script/</link>
					<comments>https://mrpanas.com/powershell-config-ini-file-for-your-script/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Mon, 03 Aug 2020 02:10:41 +0000</pubDate>
				<category><![CDATA[PowerShell]]></category>
		<guid isPermaLink="false">https://mrpanas.com/?p=662</guid>

					<description><![CDATA[<p>When I create scripts I always try to make them as flexible/re-usable as possible. That always means many parameters that can be changed in the script. Usually, there are two ways how you can customize/change script parameters:&#8211; hardcode them at the first lines of your code (it is never a good idea)&#8211; or pass them [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://mrpanas.com/powershell-config-ini-file-for-your-script/">PowerShell &#8211; config (.ini) file for your script</a> appeared first on <a rel="nofollow" href="https://mrpanas.com">Mr. Panas</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>When I create scripts I always try to make them as flexible/re-usable as possible. That always means many parameters that can be changed in the script. Usually, there are two ways how you can customize/change script parameters:<br>&#8211; hardcode them at the first lines of your code (it is never a good idea)<br>&#8211; or pass them as parameters during script execution (if you have many parameters it is unreadable)</p>



<p>But there is the other, very simple, way to pass many parameters to your script. Create a simple configuration (.ini) file that will store all all parameters that can be changed. The biggest advantage of the .ini file is clarity of all parameters, you can easily create section for your parameters, and even add comments to describe how to use them.</p>



<p>I created a simple function that load the .ini file:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: powershell; title: ; notranslate">
Function loadConfig ($fileName, $oneSection) {
    $config = Get-Content ($fileName)    
    $cfg = @{}
    $sec = $cfg
    $section = ''
    ForEach ($line in $config) {
       $line = $line.Trim()
       if ($line.startswith('&#x5B;')) {
          $section = $line.replace('&#x5B;','').replace(']','')
          if ($oneSection -eq '*') {
             $cfg.Add($section,@{})
             $sec = $cfg.$section
          }   
          continue
       }       
       if ($oneSection -ne $null -and $section -ne $oneSection -and $oneSection -ne '*') {continue}
       $k = $line.IndexOf('=')
       if ($line -eq '' -or $k -lt 1 -or $line&#x5B;0] -in '&#x5B;','#') {continue}
       $sec.Add($line.Substring(0,$k), $line.Substring($k+1))
    }
    Return $cfg
 }
</pre></div>


<p>The function returns a hashtable with all parameters specified in .ini file. <strong>There are only four rules that you have to remember when you create the .ini file</strong>:<br>&#8211; there must be &#8220;=&#8221; (equal sign) after the parameter name<br>&#8211; lines started with &#8220;<em>#</em>&#8221; will be skipped<br>&#8211; section names are represented like &#8220;<em>[section_name]</em>&#8221; <br>&#8211; parameter names in one section must be unique</p>



<p><strong>Now let&#8217;s prepare a simple .ini file (<code>config.ini</code>):</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
#demo config file
min=5

&#x5B;website section]
min=10
url=http:\mrpanas.com

&#x5B;other section]
min=15
max=255
data with space=200
</pre></div>


<p>The function is prepared to read all sections or only one specific section.<br>We have a few options how it can be executed:</p>



<p>1. Without the second parameter. In this case, parameter names in the .ini file have to be unique and all will be loaded as a flat structure.</p>



<p>2. We can specify in the second parameter which section do we want to load &#8211; empty ( &#8220;&#8221; ) section name means that only parameters on the main block (without the section will be loaded). <br>Examples:</p>



<p><span style="color:#0000ff" class="has-inline-color"><code>$conf = loadConfig "c:\tmp\config.ini" ""</code></span><br>the result of <span style="color:#0000ff" class="has-inline-color"><code>$conf.min</code></span> is <span style="color:#0000ff" class="has-inline-color"><code>5</code></span> </p>



<p><span style="color:#0000ff" class="has-inline-color"><code>$conf = loadConfig "c:\tmp\config.ini" "website section"</code></span><br>the result of <span style="color:#0000ff" class="has-inline-color"><code>$conf.min</code></span> is <code><span style="color:#0000ff" class="has-inline-color">10</span> </code></p>



<p><span style="color:#0000ff" class="has-inline-color"><code>$conf = loadConfig "c:\tmp\config.ini" "other section"</code></span><br>the result of <span style="color:#0000ff" class="has-inline-color"><code>$conf.min</code></span> is <code><span style="color:#0000ff" class="has-inline-color">15</span> </code></p>



<p>3. The last option is to read all sections in a hierarchical structure. In this case for all sections will be created a hash table that will store parameters from the section. To do this, use &#8220;*&#8221; as the second parameter of the function.<br>Example:</p>



<p><span style="color:#0000ff" class="has-inline-color"><code>$conf = loadConfig "c:\tmp\config.ini" "*"</code></span><br>the result of <span style="color:#0000ff" class="has-inline-color"><code>$conf.min</code></span> is <code><span style="color:#0000ff" class="has-inline-color">5</span> </code><br>the result of <span style="color:#0000ff" class="has-inline-color">$<code>conf."website section".min</code></span> is <span style="color:#0000ff" class="has-inline-color"><code>10</code></span><br>the result of <span style="color:#0000ff" class="has-inline-color"><code>$conf."other section".min</code></span> is <span style="color:#0000ff" class="has-inline-color"><code>15</code></span></p>



<p>If you like this post, please share or/and recommend it on Facebook.<br></p>
<p>The post <a rel="nofollow" href="https://mrpanas.com/powershell-config-ini-file-for-your-script/">PowerShell &#8211; config (.ini) file for your script</a> appeared first on <a rel="nofollow" href="https://mrpanas.com">Mr. Panas</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://mrpanas.com/powershell-config-ini-file-for-your-script/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PowerShell &#8211; fastest search in array</title>
		<link>https://mrpanas.com/powershell-fastest-search-in-array/</link>
					<comments>https://mrpanas.com/powershell-fastest-search-in-array/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Sat, 21 Mar 2020 21:19:05 +0000</pubDate>
				<category><![CDATA[PowerShell]]></category>
		<guid isPermaLink="false">https://mrpanas.com/?p=385</guid>

					<description><![CDATA[<p>If you ever worked with a big array of objects (thousands of records) and made many searches on this array, you probably know that this works slowly. I had this problem in many of my scripts until I found a simple solution that solved this inconvenience and improved the speed of my script hundreds of [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://mrpanas.com/powershell-fastest-search-in-array/">PowerShell &#8211; fastest search in array</a> appeared first on <a rel="nofollow" href="https://mrpanas.com">Mr. Panas</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>If you ever worked with a big array of objects (thousands of records) and made many searches on this array, you probably know that this works slowly. <br>I had this problem in many of my scripts until I found a simple solution that solved this inconvenience and improved the speed of my script hundreds of times.<br>The only thing you have to do is to transform an <strong>Array </strong>to <strong>HashTable</strong>.</p>



<h4>I created a small function that does it for us:</h4>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: powershell; title: ; notranslate">
function array2hash ($array, &#x5B;string]$keyName) {  
   $hash = @{}  
   foreach ($element in $array) {    
       $key = $element.&quot;$keyName&quot;    
       if ($hash&#x5B;$key] -eq $null) {       
          $hash&#x5B;$key] = $element    
       } 
       elseif ($hash&#x5B;$key] -is &#x5B;Collections.ArrayList]) {       
          ($hash&#x5B;$key]).Add($element)    
       } else {       
          $hash&#x5B;$key] = &#x5B;Collections.ArrayList]@(($hash&#x5B;$key]), $element)    
       }  
    }  
    return $hash
}
</pre></div>


<h4>How does it work?</h4>



<p>This function converts an Array (the first parameter) to a HashTable with a specified Key (KeyName is the second parameter of the function).<br>If there is more than one value for the specified Key, the function fill create an ArrayList with all Array records that contain the same Key value.</p>



<h4>How to use this?</h4>



<p>Let&#8217;s show it on an example. As an example I will use the database of US zip codes downloaded as a CSV file from:<br><a href="https://public.opendatasoft.com/explore/dataset/us-zip-code-latitude-and-longitude/export/">https://public.opendatasoft.com/explore/dataset/us-zip-code-latitude-and-longitude/export/</a></p>



<p>As a first step, load data to the array:<br><code><span style="color:#0000ff" class="has-inline-color">$arr = import-csv C:\tmp\us-zip-code-latitude-and-longitude.csv -Delimiter ";"</span></code></p>



<p>Now create a hash table for &#8220;zip&#8221; data (that will take less than 1 second):<br><code><span style="color:#0000ff" class="has-inline-color">$hsh = array2hash $arr "Zip"</span></code></p>



<p>Let&#8217;s find the zip code = 33418.</p>



<p>To find the zip code in Array I use:<br><code><span style="color:#0000ff" class="has-inline-color">$arr | where {$_.Zip -eq "33418"}</span> </code><br>It took 950 milliseconds on my laptop.</p>



<p>Now the same for HashTable:<br><code><span style="color:#0000ff" class="has-inline-color">$hsh."33418"</span></code><br>This operation took 0.2 milliseconds (4750 times faster).<br>When I repeated the same operations for 100 random zip codes, the Array search took me 103695 milliseconds (1 minute 43 seconds) and HashTable 148 milliseconds (0.1 seconds). As you can see, it is a huge improvement.</p>



<p>Now let&#8217;s build a hash table for cities:<br><code><span style="color:#0000ff" class="has-inline-color">$hsh = array2hash $arr "City"</span></code></p>



<p>This time search <code><span style="color:#0000ff" class="has-inline-color">$hsh."New York"</span></code> returns array with 167 records.</p>



<p><strong>I hope that this post will help you to improve data processing.</strong></p>
<p>The post <a rel="nofollow" href="https://mrpanas.com/powershell-fastest-search-in-array/">PowerShell &#8211; fastest search in array</a> appeared first on <a rel="nofollow" href="https://mrpanas.com">Mr. Panas</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://mrpanas.com/powershell-fastest-search-in-array/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
