It’s SQL Server SMO week and I’ll be presenting at the next Space Coast SQL Server User Group on Thursday October 11th at 6:30PM. For more information check out the following #SCSUG link: http://spacecoast.sqlpass.org/
Also, I’m restarting the Florida PowerShell User Group virtual meeting this coming Friday October 12th at 11:30amrescheduled t0 October 26th due to equipment problems with the same topic: “PowerShell working with SQL Server SMO“. I will be providing the virtual meeting link on Friday morning before the meeting at my http://www.FLPSUG.com site.
There’s no need to install SQL Server to create PowerShell SMO scripts. So, how I do this? You need three stand-alone packages from the “Microsoft® SQL Server® 20xx Feature Pack”. Notice the “xx” in the SQL Server version. This is because the
“feature packs” has been available since SQL Server Version 2005. In my scenario I decided to use the “Microsoft® SQL Server® 2012 Feature Pack”: http://www.microsoft.com/en-us/download/details.aspx?id=29065
You need to installed them in the following order:
Microsoft® System CLR Types for Microsoft® SQL Server® 2012
*Microsoft® Windows PowerShell Extensions for Microsoft® SQL Server® 2012
Make sure to pick the right package for your system: (x86) or (x64).
When you’re done with the installation then you are ready to start scripting with SMO. Also, you will notice that the SQL Server SQLPS module will get installed in your system.
Use the “Get-Module -ListAvailable” command and look for the SQLPS module in the bottom of the screen.
Now we can create the following PowerShell SMO script:
[sourcecode language=”powershell”]
## – Loading the SQL Server SMO Assembly"
[System.Reflection.Assembly]::loadwithPartialName("Microsoft.SQLServer.SMO");
## – Build SQL Server object connecting using default Windows Authentication:
$SQLSvr = ‘WIN2K3SQL1’;
$MySQL = new-object(‘Microsoft.SqlServer.Management.Smo.Server’) $SQLSvr;
## – Changing from default Windows to SQL Authentication:
$MySQL.ConnectionContext.LoginSecure = $false;
$MySQL.ConnectionContext.set_Login(‘User1’);
$SqlUPwd = ConvertTo-SecureString ‘$Pwd01!’ -AsPlainText -Force;
$MySQL.ConnectionContext.set_SecurePassword($SqlUpwd);
## – Get some information:
$MySQL.Information | Select-Object Parent, Version, Edition | fl;
[/sourcecode]
Here’s the results: Notice I installed my three “SQL Server 2012 feature” packages and created to use a PowerShell SMO script to access a SQL Server 2000 Engine. But, Keep In Mind, that SQL Server SMO 2012 will work for most parts to extract information off SQL Server 2000. Just by trial and error you will notice some limitations. Also, although I have the SQLPS module available but I didn’t have to use it yet.
Go ahead and give it a try!
Here’s the link of others SQL Server Features Pack:
Following my previous blog (“PowerShell – SQL Server SMO has XML and XSD Schema method“) I continue to use SMO to generate my XML files, I encountered that my SQL datetime field is converted to a UTC DateTime string. This gave me some work to get it back to a DateTime type. I had the requirement to provide my source file in XML format.
I realized using SMO WriteXml() method will write the DateTime type to a UTC DateTime string format in the XML file resulting in something like this:
Unfortunate, trying to pass this value to a SQL DateTime field is tricky. I look around the internet and there’s plenty of examples of UTC but not in this format “2001-07-01T00:00:00-04:00″. So, I ended up using PowerShell to ease off the pain.
Here’s an example of how PowerShell can easly convert UTC DateTime string to a regular System.DateTime type:
## – Resulting in:
#-> Sunday, July 1, 2001 12:00:00 AM
[/sourcecode]
That was easy. Right! But the issue is when we want to pass this value into a SQL DateTime type. Then, here’s a possible solution now that I got PowerShell to convert my UTC string to string DateTime output.
Using the string generated from PowerShell, as a proof-of-concept, I can test this value in the following T-SQL script:
[sourcecode language=”sql”]
–now using t-SQL to convert a UTC string to a standard datetime type value:
Declare @stringFromPowerShellDateTime nvarchar(50)
Declare @fixDate nvarchar(50)
Declare @cleanup int
Declare @dtDateTime DateTime
Set @stringFromPowerShellDateTime = ‘Sunday, July 1, 2001 12:00:00 AM’
Set @cleanup = (charindex(‘,’, @stringFromPowerShellDateTime, 1))
Set @fixDate = (Substring(@stringFromPowerShellDateTime, (@cleanup+1), len(@stringFromPowerShellDateTime)))
Set @dtDateTime = (Convert(DateTime, @fixDate, 101))
Select @dtDateTime
— – Resulting in:
– -> 2001-07-01 00:00:00.000
[/sourcecode]
The end result of this SQL script is to be able to create my SQL DateTime type from the PowerShell converted UTC-to-DateTime-String.
Now I need go back to my first XML file, and update my DateTime elements values with the converted UTC to string format. Here’s where I go back PowerShell to fix my XML file:
[sourcecode language=”powershell”]
## – the following routine will correct UTC datetime as string:
[xml] $xmlfile = Get-Content ‘C:\PowerShellScripts\ADWtblOrders1.xml’;
foreach($xItem in ($xmlFile.newdataset.table))
{
[string] $dt = ([DateTime] $xItem.OrderDate).ToString();
$xItem.OrderDate = $dt;
};
$xmlfile.save(‘C:\PowerShellScripts\ADWtblOrders1_New.xml’);
[/sourcecode]
The results after convert the DateTime to the new XML DateTime values fix will look like this:
Now, this DateTime values can be consume in SQL Server without any issues. Notice that I’m using the “xml” Accelerator which has a *.Save() method so you can save your changes to file .
I think you got the pieces necessary to use PowerShell, XML, SMO, and T-SQL.
As I continue to work with Microsoft BizTalk Server it still amazed me when I can find something useful. As I was building a BizTalk solution that involves getting data from our SQL Server table, I found an SMO method that allow me to create both the XML and the XML Schema (XSD) so I can use them in my BizTalk solution.
Here’s the quick route using PowerShell and SQL Server SMO (SQL Server Management Objects) to create your XML Schema from a SQL table. Keep in mind, in order to use SQL Server SMO you must have SQL Server 2005 or greater.
1. Here’s a simple T-SQL script to query a table:
[sourcecode language=”powershell”]
## – Prepare you SQL Script in ‘PowerShell’ Here-String:
## (for more Info on ‘Here-String’use the command: get-help about_Quoting_Rules
$Sqlqry1 = @’
Use Northwind
SELECT TOP 3 [OrderID]
,[CustomerID]
,[EmployeeID]
,[OrderDate]
,[RequiredDate]
,[ShippedDate]
,[ShipVia]
,[Freight]
,[ShipName]
,[ShipAddress]
,[ShipCity]
,[ShipRegion]
,[ShipPostalCode]
,[ShipCountry]
FROM [Northwind].[dbo].[Orders]
‘@;
[/sourcecode]
2. Then, the next three SMO lines we get the information and store it in our variable. Make sure to define the variable as an array so you can get the right format:
[sourcecode language=”powershell”]
## – Load the SQL Server SMO Assembly:
[System.Reflection.Assembly]::loadwithPartialName(‘Microsoft.SQLServer.SMO’)
## – Connect to your SQL Server Instance and execute your SQL Query:
$MySQL = New-Object(‘Microsoft.SqlServer.Management.SMO.Server’) ‘BIZTALK2K10DEV’;
$tbldata = $MySQL.Databases[‘Northwind’].ExecuteWithResults($Sqlqry1);
[/sourcecode]
3. The following line just check the first 10 records in your PowerShell object:
[sourcecode language=”powershell”]
## – Display the first 10 lines of your data:
($tbldata.Tables) | Select -First 10 $_ | Format-Table -AutoSize;
[/sourcecode]
4. Finally, we can use the “.WriteXML()” and “.WriteXmlSchema()” methods to create our XML and XSD files:
[sourcecode language=”powershell”]
## – Create you XML file with your data:
($tbldata).WriteXml(‘C:\PowerShellScripts\tblServiceFacts.xml’);
## – To create the XML Schema (.xsd file) use the following method:
($tbldata).WriteXmlSchema(‘C:\PowerShellScripts\tblServiceFacts.xsd’);
[/sourcecode]
We are ready to incorporate the XSD file in your BizTalk solution(s).
There’s a few things to keep in mind. The above version will work with SQL Server 2008 but will behave different with SQL Server 2005 and PowerShell V2.0 it might giving you an “overload” error.
So, if you encounter the following error, then here’s a possible how-to fix it: (it work for me but further testing in other environment gave me a different results. It’s all just about testing and understanding your tools.
[sourcecode language=”powershell”]
## – Create you XML file with your data:
$tbldata.WriteXml([string] ‘C:\PowerShellScripts\tblOrders.xml’);
## – To create the XML Schema (.xsd file) use the following method:
$tbldata.WriteXmlSchema([string] ‘C:\PowerShellScripts\tblOrders.xsd’);
[/sourcecode]
Don’t forget to test your code to make sure you’re getting what you want. The main code will work in both PowerShell v2.0/v3.0, and SQL Server 2008 (or greater).
Awesome Technology! I will come back to this issue later and provide the PowerShell V2 solution.
The Truth, it wasn’t easy. I look around some blogs but they always failed to mention what was done prior to the actual installation of SQL Server on a Server Core machine. But, installing SQL Server on a Server Core 2012 makes it better if you have installed the Minimal-Server interface. Yes! The new Server Core gives you the flexibility to partially add and remove the GUI shell.
Here’s what I did to get my SQL Server on a Server Core 2012 installed in a Virtual Machine. Remember, when using Hyper-V, you can use the shapshot feature to create a point of recovery state in case you need to go back and start over.
Setting up Server Core 2012 with Minimal-Server Interface
First, I need to make sure Server Core has all the components in place. In my test building a virtual machine I found that I needed to have:
1. Connection to the internet or some features will fail to install.
2. I need to assign a static IP Address (so I can join my domain).
3. Add an admin user account to the local administrator group (Workgroup or Domain admin user account).
4. Configure Remote Management.
5. Configure Remote Desktop.
To get this done I use the vbscript application “SConfig” tool to assist configuring my Server Core. It’s a great tool, and it can be executed from PowerShell prompt too.
Now, keep in mind you need to meet some requirements before installing SQL Server. Most important is installing .NET Framework 3.5. But, if you successfully install the following Windows Features to enable the Minimal-Server interface on Server Core 2012 then you should be fine for setting up SQL Server. Again, connection to the internet is mandatory (at least in my scenario).
Here’s the features required to *install and enabled the Minimal-Server interface:
Yes! You can use PowerShell. Just type *PowerShell as soon as the command prompt shows up and you can continue building the you Server Core. A restart of the server will be needed.
Tip: To start PowerShell in Server Core 2012 DOS command prompt, type “PowerShell” and press Enter . Then, to get back to DOS command prompt, type the “Exit” and press Enter.
To get a list of all installed features, use the following PowerShell command:
Get-WindowsFeature
Use the above command verify the .NET Framework 3.5 features has been enabled. Of course, after rebooting the server you will notice the Server Manager GUI will be displayed along with the command prompt. This is a good indication .NET Framework is in place.
After rebooting, you will get the Minimal-Server Interface.
Installing SQL Server 2012 on Server Core 2012
Now, I’m are ready to install SQL Server 2012. I have attached the SQL Server 2012 ISO image to my virtual machine. Here’s the *Setup command to install: SQLEngine, AS, IS, and Conn. For more information: http://msdn.microsoft.com/en-us/library/hh231669.aspx
A Word of Caution. I’ve experience that sometimes the setup will finished with no indication that everything completed successfully. To find later that the SQLEngine wasn’t installed
I had to verify the SQL Server instance was installed by looking at the Microsoft SQL Server folder under “C:\Program Files\Microsoft SQL Server” and use the PowerShell command “Get-Service” to see all services were active.
Now, I need to configure the SQL Remote Access to option “1” using the “SQLCMD -A” command from the “C:\Program Files\Microsoft SQL Server\110\tools\binn” folder with the following T-SQL lines:
EXEC sys.sp_configure N’remote access’, N’1′
GO
RECONFIGURE WITH OVERRIDE
GO
Exit
Test SQL Server connection remotely
Now, before trying to connect from another machine, I need to configure the Windows *Firewall rule to allow access to my SQL Server by executing the following line in the DOS command prompt:
netsh firewall set portopening protocol = TCP port = 1433 name = SQLPort mode = ENABLE scope = SUBNET profile = CURRENT
*Note: This command will execute but read the warning message
The moment of Truth! Testing that I can connect to SQL Server on Server Core 2012 from a Windows 8 Desktop using SSMS.
Conclusion
In this blog I have accomplished the following in a virtual machine:
1. Build a Server Core 2012 with Minimal-Shell interface.
2. Use the VBScript “SConfig” to help configuring my server.
3. Install SQL Server 2012: Engine, Analysis Services, and Integration Services.
4. Verify remote connectivity using SSMS from a desktop machine.
I was unconsciously doing something while coding in PowerShell V3.0 Beta, and it caught me off guard. As I’m getting more comfortable working with PowerShell Objects, I didn’t realized there is an enhancement in place. There’s a quick way to access with your objects values. I’m trying to scripting for PowerShell V2.0 but I started see errors, then I realize I was accessing my items differently in PowerShell V3.0.
Let me show some PowerShell V3.0 code that access a SQL Server SMO collection of type “Microsoft.SqlServer.Management.Smo.Information”. I want to access the values of the property “Properties” in the SQL Server Information SMO Object.
*hint*: Remember to use the command “Get-Member” to expose the content (method & properties) in your PowerShell variable.
[sourcecode language=”powershell”]
## – Load Assembly and create your SQL object:
[System.Reflection.Assembly]::loadwithPartialName("Microsoft.SQLServer.SMO");
$MySQL = New-Object(‘Microsoft.SqlServer.Management.SMO.Server’);
## – Getting to your Information Properties"
$MySQL.Information;
$MySQL.Information.Properties;
[/sourcecode]
The last two lines will give you some results back. Now, try the next line:
[sourcecode language=”powershell”]
## – Only valid in PowerShell V3.0:
$MySQL.Information.Properties.name;
[/sourcecode]
This line will display all values in the property “Name”, and that’s great.
Go to another machine with PowerShell V2.0, and execute the lines:
[sourcecode language=”powershell”]
## – Load Assembly and create your SQL object:
[System.Reflection.Assembly]::loadwithPartialName("Microsoft.SQLServer.SMO");
$MySQL = New-Object(‘Microsoft.SqlServer.Management.SMO.Server’);
## – Only valid in PowerShell V3.0:
$MySQL.Information.Properties.name;
[/sourcecode]
Notice you will not get any results back.
Now, change the line below and the execute:
[sourcecode language=”powershell”]
## – Valid in both PowerShell V3.0 and V2.0:
$MySQL.Information.Properties | Select name;
[/sourcecode]
And, it will display all values from this property.
As you notice, using PowerShell V3.0 can list items from the collection without forcing you to pipe “|” the value to another command (“.. | Select Name ..“). Just be careful and make sure the code stay compatible with PowerShell V2.0.
Just a quick blog on spotting your Database Snaphots. I just couldn’t believe that I’ve been missing creating SQL database snapshots but sometimes having so much work make you blind. I’ve been using a lot Hyper-V Snapshot features and recently (Thanks to Chad Miller) I got the chance to create and test a few.
So, first we need to create a new db snapshot of my AdventureWorks database using T-SQL Script:
[sourcecode language=”SQL”]
CREATE DATABASE AdventureWorks_dbSnapShot_0001 ON
( NAME = AdventureWorks_Data, FILENAME =
‘C:\Program Files\Microsoft SQL Server\MSSQL11.MSQLDENALICTP3\MSSQL\DATA\AdventureWorks_Data_0001.ss’ )
AS SNAPSHOT OF AdventureWorks;
GO
[/sourcecode]
Now, I go to SSMS and verify my new database snapshot exist by going into the ‘Object Explorer’ and looking under ‘Database Shashots’ folder.
Using T-SQL
If I use the following T-SQL command to list all my databases:
[sourcecode language=”SQL”]
Select * from [sys].[sysdatabases]
[/sourcecode]
I will get all of them listed including the snapshots. So, here’s another way to use T-SQL to identify all database snapshots. For that, I’m going to do a select and use from the Master db the view named “[sys].[databases]”:
In this result, pay attention to the “[source_database_id]” column. Notice that this column is mostly “null” except when if it has a value. This value will match the “[Database_ID]” column. So, you can use this to identify database snapshots.
Using PowerShell
Now, let’s take a look on how to use PowerShell to identify database snapshots using SMO. In the following code I’m listing all databases but snapshots are also included.
So, in order to identify the database snapshot I need to look deeper into our .NET database object. Using the “Get-Member” command I can see what’s object are available.
Once again, Thanks! to Patrick LeBlanc for allowing me to present at today’s (02/15/2012) SQLLunch.com. It was a Great! turned out with over 60 people attending. To You All THANKS!! (Recorded session will be available)
Well, here’s my slide deck presentation, and the sample Demo scripts:
Also, I included the following comparison chart that help in your quest to adopt PowerShell. This excel file is also included in the zipped file. This is what I covered today except for “Sum”.
I just realized that this topic could evolved to include a Part II where I could show more on: Group, Sum, Logic, and Functions. So, later on, I will be posting more information the next “PowerShell Query for the T-SQL Developer” Part II.
Well, I just couldn’t stop making necessary changes to this great presenter tool. So, now Start-Demo will process your multi-lines one-liners which this couldn’t be done in the previous version.
So, a good example of a one-liner having line continuation, using the Send-MailMessage cmdlet, where we can use the “`” tick to separate the long command line with its parameters:
Here’s an example of how it look like using “Start-Demo” in StudioShell:
And, here’s the updated Start-DemoSS.ps1 Version 2.0A 2.0B (02/12/2012): (apologies for the previous code posted here. It somehow I posted a bad code but I fix it tonight)
[sourcecode language=”powershell”]
###########################################################################
# Original Version: 1.1
# Updated to Version 2.0B, Maximo Trinidad, 02/12/2012
#————————————————————————–
# Comments:
# 1. Customized the foreground color to Cyan and backgroundColor to Black.
# 2. Created a Dump color to default to White.
# 3. Added to put back the default foreground and background colors.
# 4. Commented out the ‘(!) Suspense’ option because Studio Shell can’t
# handle "$host.NestedPrompt".
# 5. Modify the Help menu to acomodate changes.
# 6. Commented out all "$Host.UI.RawUI.WindowTitle".
# 7. Replaced all "[System.Console]::ReadLine()" with "Read-Host".
# 8. Added an end of results ‘write-host"– Press Enter to continue –"’
# follow with a read-host similate a pause.
#
# Modifications:
# 02/10/2012 – Add section identify oneliners with continuation tick "`".
# 02/10/2012 – Cleanup all unused V1 lines.
# 02/10/2012 – Make code to properly display continuation lines.
# 02/12/2012 – Fix info on Start time and duration.
# 02/12/2012 – Adjust execution message spacing.
#
###########################################################################
function Start-Demo
{
param($file=".\demo.txt", [int]$command=0)
Write-Host -for $otherColor @"
Start-Demo: $file – Start time: $starttime
Version 2.0B (02/12/2012)
NOTE: Start-Demo replaces the typing but runs the actual commands.
.
"@
$continuation = $false;
# We use a FOR and an INDEX ($_i) instead of a FOREACH because
# it is possible to start at a different location and/or jump
# around in the order.
for ($_i = $Command; $_i -lt $_lines.count; $_i++)
{
if ($_lines[$_i].StartsWith("#"))
{
Write-Host -NoNewLine $("`n[$_i]PS> ")
Write-Host -NoNewLine -Foreground $CommentColor $($($_Lines[$_i]) + " ")
continue
}
else
{
# Put the current command in the Window Title along with the demo duration
$Global:Duration = [DateTime]::Now – $Global:StartTime
Write-Host -NoNewLine $("`n[$_i]PS> ")
$_SimulatedLine = $($_Lines[$_i]) + " "
switch ($_input)
{
################ HELP with DEMO
"?"
{
Write-Host -ForeGroundColor Yellow @"
——————————————————————————–
Start-Demo – Updated to Version 2.0B (12/12/2012)
Help Running Demo: $file
.
(#x) Goto Command #x (b) Backup (?) Help
(fx) Find cmds using X (q) Quit (s) Skip
(t) Timecheck (d) Dump demo (px) Typing Pause Interval
.
NOTE 1: Any key cancels "Pretend typing" for that line. Use unless you
want to run a one of these meta-commands.
.
NOTE 2: After cmd output, enter to move to the next line in the demo.
This avoids the audience getting distracted by the next command
as you explain what happened with this command.
.
NOTE 3: The line to be run is displayed in the Window Title BEFORE it is typed.
This lets you know what to explain as it is typing.
.
NOTE 4: Although this script is functional try not to "Goto" a continuation
one-liner or it will go to a continues loop. I will correct this sympton
soon. (02/12/2012)
———————————————————————————
"@;
Write-Host "– Press Enter to continue –" -BackgroundColor white `
-ForegroundColor Magenta;
Read-Host; cls;
$_i -= 1
}
I blogged about a nice Visual Studio addon “StudioShell” that fits very well with SSMS “SQL Server Management Studio 2012“, and I found this tool very useful for presenting. But, when I try running the (long time) famous “Start-Demo” script, it gave me some errors. Well, Thanks (again) to StudioShell developer Jim Christoper, he gave me a hint to why this was happenning. Basically, this old “Start-Demo” uses some .NET calls which StudioShell can’t interpret because of the way it was develop, so it need a makeover.
So, I proceed to dive into the code and make some basic changes so it can work inside StudioShell. Here’s how it looks running it from SSMS executing a demo script, and asking for (?) Help:
I change the color scheme, and added a message pause after displaying the result of the onliner.
Also, the new function will work on a normal PowerShell console, and at the end of the start-demo it will put back your default console colors.
Here’s the updated “Start-DemoSS.ps1“code:
[sourcecode language=”powershell”]
###########################################################################
# Original Version: 1.1
# Updated to Version 2.0, Maximo Trinidad, 02/09/2012
#————————————————————————–
# Comments:
# 1. Customized the foreground color to Cyan and backgroundColor to Black.
# 2. Created a Dump color to default to White.
# 3. Added to put back the default foreground and background colors.
# 4. Commented out the ‘(!) Suspense’ option because Studio Shell can’t
# handle "$host.NestedPrompt".
# 5. Modify the Help menu to acomodate changes.
# 6. Commented out all "$Host.UI.RawUI.WindowTitle".
# 7. Replaced all "[System.Console]::ReadLine()" with "Read-Host".
# 8. Added an end of results ‘write-host"– Press Enter to continue –"’
# follow with a read-host similate a pause.
###########################################################################
function Start-Demo
{
param($file=".\demo.txt", [int]$command=0)
## – setting demo variables:
$_Random = New-Object System.Random
$_lines = @(Get-Content $file)
$_starttime = [DateTime]::now
$_PretendTyping = $true
$_InterkeyPause = 100
Write-Host -for $CommentColor @"
NOTE: Start-Demo replaces the typing but runs the actual commands.
.
<Demo [$file] Started. Type `"?`" for help>
"@
# We use a FOR and an INDEX ($_i) instead of a FOREACH because
# it is possible to start at a different location and/or jump
# around in the order.
for ($_i = $Command; $_i -lt $_lines.count; $_i++)
{
if ($_lines[$_i].StartsWith("#"))
{
Write-Host -NoNewLine $("`n[$_i]PS> ")
Write-Host -NoNewLine -Foreground $CommentColor $($($_Lines[$_i]) + " ")
continue
}else
{
# Put the current command in the Window Title along with the demo duration
$_Duration = [DateTime]::Now – $_StartTime
#X – $Host.UI.RawUI.WindowTitle = "[{0}m, {1}s] {2}" -f [int]$_Duration.TotalMinutes, `
# [int]$_Duration.Seconds, $($_Lines[$_i])
Write-Host -NoNewLine $("`n[$_i]PS> ")
$_SimulatedLine = $($_Lines[$_i]) + " "
for ($_j = 0; $_j -lt $_SimulatedLine.Length; $_j++)
{
Write-Host -NoNewLine $_SimulatedLine[$_j]
if ($_PretendTyping)
{
if ([System.Console]::KeyAvailable)
{
$_PretendTyping = $False
}
else
{
Start-Sleep -milliseconds $(10 + $_Random.Next($_InterkeyPause))
}
}
} # For $_j
$_PretendTyping = $true
} # else
switch ($_input)
{
################ HELP with DEMO
"?"
{
Write-Host -ForeGroundColor Yellow @"
——————————————————————————–
Help Running Demo: $file
.
(#x) Goto Command #x (b) Backup (?) Help
(fx) Find cmds using X (q) Quit (s) Skip
(t) Timecheck (d) Dump demo (px) Typing Pause Interval
.
NOTE 1: Any key cancels "Pretend typing" for that line. Use <SPACE> unless you
want to run a one of these meta-commands.
.
NOTE 2: After cmd output, enter <CR> to move to the next line in the demo.
This avoids the audience getting distracted by the next command
as you explain what happened with this command.
.
NOTE 3: The line to be run is displayed in the Window Title BEFORE it is typed.
This lets you know what to explain as it is typing.
———————————————————————————
"@;
Write-Host "– Press Enter to continue –" -BackgroundColor white `
-ForegroundColor Magenta;
Read-Host; cls;
$_i -= 1
}