What is a splash screen?
“A splash screen is a graphical control element consisting of window containing an image, a logo and the current version of the software. A splash screen usually appears while a game or program is launching.” According to Wikipedia J
That says everything there is
to say. There’s nothing more to add I think.
More specifically, it's
something like we see below:
What has that to do with us?
Well, you certainly had spent
your time in scripting and writing tons of code in powershell and you found it
funny. But at a certain point, you probably realize that the longer your script
is, the more time it takes to load.
And before your computer, when
you load your script, you’re like:
To sum up, if your application
is too big, it will take time before your entire GUI is loaded and and you don't really want your user to wonder "hey! what's going on?". That’s where
splash screen plays its role.
The idea of a splash screen
came to me when I was asked to create a tool that wrapped ImageX for creating a
WIM image. I realized that my tool took too much time to load and I needed something
to keep the user busy.
How do we do it in Powershell?
The tips is: runspace
We are just going to
use a runspace to load a second form before loading your code and close it when
it’s finished. That is the big idea behind. You may be saying: what
the heck is he talking about?
I only have a shallow
knowledge about runspace too but, all I can say is that it’s really helpful
when you want to do multi-threading (to have many processes working at the same
time - in noobs way of speaking J).
In my previous post how
to apply a theme in Powershell, I introduced Mahapps which uses a metro theme.
We are going to use one of the component included in that theme for creating
the splash screen. I think you’ve guessed it already: it’s for the progressbar in the
splash screen.
Let’s move on to the
code.
How to use the splash
screen?
You just have to copy
and paste the following code in your main ps1 file at the top. This way the
runspace which contains the second form will be loaded before everything and
can be called at any time inside the script.
If you want to add your logo and text, just edit:
As you can see, there are
two functions:
$hash.Logo.Source=".\form\resources\powershel64x64.png"
$hash.LoadingLabel.Content= "Your Code is loading"
- Start-splashScreen
- Close-splashScreen
Those functions are
used to open and close the runspace.
You just have to put Start-splashScreen before the script
block
Start-SplashScreen
try {
########################
# your incredible code
########################
}
catch{
$ErrorMessage =
$_.Exception.Message
Write-Host $ErrorMessage
}
It’s better to use a
try and catch if your code potentially generates error. So the splash screen
will be closed in any case at the end.
And at the end of your
file, before you call ShowDialog() on your form, or when the code you wanted to be executed
is finished, close the splash screen.
close-SplashScreen
$Form.ShowDialog() | Out-Null
Of course, as you could
understand, you can use a splash screen for many purposes. Let your imagination
take you away.
Here is a little preview:
And that’s it for this
third part, hope you enjoyed it. J And see you in the next part
Nice work Kevin. Did you figure out how to use the built-in dialogs in MahApps Metro using PowerShell?
ReplyDeleteThank you! I haven't tried it yet because of the asynchronous tasks. But I will give it try and keep you informed.
ReplyDeleteError loading assemblies (Code has not been modified):
ReplyDeleteException calling "LoadFrom" with "1" argument(s): "Could not load file or assembly 'file:///C:\WINDOWS\system32\assembly\MahApps.Metro.dll'
or one of its dependencies. The system cannot find the file specified."
Using Load instead of LoadFrom results in different error:
Exception calling "Load" with "1" argument(s): "Could not load file or assembly 'assembly\\MahApps.Metro.dll' or one of its dependencies. The
given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047)"
In this case, it does find the files but says they are invalid.
Any thoughts?
Thanks.
Hello Christopher,
DeleteBy looking at your error, I think it's related to the execution path.
In this tutorial, I didn't use a relative path for assembly folder, that is why you have this problem.
If you want to execute the script, you need to navigate to folder in PS console before.
I stored my files at C:\ for example
PS C:\PS_SplashScreen-master>
So I need to navigate inside the folder to execute it:
PS C:\PS_SplashScreen-master> powershell.exe .\form.ps1
You cannot start it from another folder, so technically this won't work:
PS C:\Windows\System32> powershell.exe -sta C:\PS_SplashScreen-master\form.ps1
But of course you can use a relative path to avoid this little problem.
And in this case, you cannot use the Load() method, because it's not the appropriate parameter.
If you want to know more about how to load assembly in powershell, there's an excellent post here:
http://www.madwithpowershell.com/2013/10/add-type-vs-reflectionassembly-in.html
If you still have issues with the script don't hesitate.
Kevin
Hi Kevin,
DeleteI am also getting the same error
Exception calling "LoadFrom" with "1" argument(s): "Could not load file or assembly file:///C:\WINDOWS\system32\assembly\MahApps.Metro.dll'
I am running form.ps1 from the correct location and I also checked
[System.Reflection.Assembly]::LoadFrom('assembly\MahApps.Metro.dll') | out-null
is not commented out.
Please suggest if I am missing anyting?
Thanks
Harikanth
Hello, exactly what I need, but $hash returns a null-value expression...
ReplyDeleteHave you tried with the code on my Respoitory? https://github.com/dev4sys/PS_SplashScreen
DeleteI did.
DeleteIt does it when I call close-SplachScreen's function but nothing happen with the start-SplashScreen's, just waiting the 5 seconds before loading my form...
Exception calling "Load" with "1" argument(s): "Cannot create unknown type '{clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro}MetroWindow'."
ReplyDeleteI am getting this error when just trying to run form1 from the current folder it's in..
It looks like the assembly is not fully loaded.
DeleteCould you check if this line is not commented:
[System.Reflection.Assembly]::LoadFrom('assembly\MahApps.Metro.dll') | out-null
If the problem still persist, feel free to send me an e-mail.
Very nice splash screen option. Is there a way to make $hash.LoadingLabel.Content= "Your Code is loading" dynamic? I was able to parse an $env:variable from the value of a parameter over to the new instance of pwoershell that handles the splash screen. However, I can't figure out how to make the LoadingLabel.Content information change without closing the splash screen and reopening it. Any ideas?
ReplyDeleteHi Benjamin!
DeleteOf course you can update it dynamically.
Basically you need to add something like this:
$hash.window.Dispatcher.Invoke("Normal",[action]{ $hash.LoadingLabel.Content="New text"})
If your variable is already in the runspace instance, there is no need to call the window.dispatcher.
Thank you very much for your work. I'm a Newbie at this.
ReplyDeleteCan you show me how to change the background to an image ?
Also how can I insert more lines of text in addition to "Your code is loading" ?
Thank you.
I love the splash screen and I want to use it, but I am having a problem with closing the splash screen. As of right now I am using the code straight from GitHub to try it out and when it gets to the close function the splash screen stops animating and does not actually close the window. It doesn't continue to the rest of the script.
ReplyDeleteThat's because in the function close-SplashScreen the actual closing of the runspace is commented out:
Delete#$runspace.Close() | Out-Null
This should be
$runspace.Close() | Out-Null