 Okay. And I'll move that out of the way because everybody doesn't want that. There we go. All right. So first of all, I guess what we should really talk about is why do we want to publish it all in the first place? So to do that, we're just going to do a quick review of what publishing involves and why we would do that. So I've got a very simple console application here and it's a targeting.NET 2.2. Now I know this is about .NET Core 3 and we'll upgrade this project very soon. And so the target framework is .NET Core 2.2 and in the global JSON we're targeting the 2.2 SDK. So if we bring up our command line and we just do a .NET build of this project. It's using the 2.2 SDK and it's building that. And if we have a look at what we get with that, we'll look in the bin debug directory. We've just got our DN3 DLL, our assembly, and we can do a .NET run as well to run this program. And there we go. It's not that complicated. We're just outputting some information about the environment we're running in a hello.NET comp in ASCIIART. I'll just show you the source code there. This is all going to be up on GitHub. We're also referencing a third-party assembly called FIGL here, which does that ASCIIART rendering, which is nice. Okay, so we can run stuff locally. We didn't have to publish anything. So what would we want to publish? Well, let's jump back to our console. And what I've got here is in Docker, I've got some instances of Windows Server nano running. And my D drive in here is mapped to the output directly that I just compiled to. So those timestamps correspond to the current time for me. So I can do .NET and DN3.DLL and oh, it doesn't work. And the problem is that, first of all, this FIGL assembly isn't there. So when I did a .NET build, it didn't copy that dependency in. So let's jump back and do a .NET publish. See what happens this time. Jump back to my server core. Sorry, server nano instance. And now I've got a published directory changing to that. And let's try it again. So .NETDN3.DLL. And this time it thinks about it for a second and it runs. So .NET publish makes sure that we've got all the reference assemblies that we need. The other scenario we might want to use .NET publish for. Well, first of all, before we do that, we're still having to run the thing by calling .NET and then the DLL. So one thing we might want to do is create what's called a framework dependent executable. And the way I do that is I do a .NET publish. Now I need to give it a runtime identifier. So it's going to be win10x64. And I'll just say self-contained. And this time it still outputs to the same directory. If I jump back to my nano image, do a do. And it's not in that directory anymore. It's now in the win10x64 publish directory. And we'll see we've now got an executable there. So we don't need to run .NET. We can just run .NETDN3 and it all runs. So that's a bit of a nicer experience. Okay, what about this other image over here? This is also a nano image. And I'll change into that win10 publish. I hope if I could spell. All right, we've got our executable there. We try and run it and it doesn't work. And why doesn't it work now? That's because this instance of nano doesn't have a .NET call runtime. So the other instance here has actually got the core 2.2 runtime already installed. Whereas this one's just a vanilla Windows nano image. There's no runtime there at all. So what can we do about that? So what we can do is make it self-contained. So turn on true. Let it build again. And now we come over to this machine. We've got a whole lot of files there now. And if I run .NETDN3, it now runs. Because it's got all of the runtime files there as well. Okay, so that was a brief introduction to publishing and what some of the value when publishing in the first place. Now let's see what's new in .NET Core 3. Now that we understand what publishing does. So first of all, let's have a look at .NET build. Jump back to my console. And I actually, before I even do that, Core 3, I need to upgrade my project. So I'm going to comment out 2.2 and uncomment that. And my global.json, I need to uncomment version 3 and comment out version 2. And because this is such a simple application, that's all I need to do. So .NET build. So I'm not even using .NET publish yet. Let's run that and it builds. And let's have a look in the output directory for that. And we'll see some differences straight away from when we did our initial build for .NET Core 2.2. So in 2.2, the build just created the DLL. We've now seen we've got this XE here. The other thing that's different is we've also got the dependent assembly. So we don't even need to run .NET publish to just get those benefits now that .NET Core 3 is providing for us. So that's kind of nice. Okay, if we then... And we can still do .NET publish and it'll create a publish sublet tree. And you can see it's pretty similar. The only difference there is it doesn't have that dev.json file. Okay. The next thing we're going to have a look at is single file executables. So this is something as far as making it easier for you to distribute your application. So rather than end up with a whole lot of files it's going to create one XE. And then when you run that XE on the target computer it self-extracts. Kind of like a self-extracting zip file if you like. And then runs the application and it's smart enough that if you run that XE again the second time the first time it'll take a little while to extract stuff the second time it'll be fast because everything's already extracted. So let's have a look and see how we can make one of these. Okay. So first one is going to do some cleaning up so that you can be confident that there's nothing up my sleeve. I'm just going to clean out my destination directory okay. And so I'm going to do .NET publish and I'm going to set that run time identifier and I'm going to set another property called publish single file. Okay. And then so if we jump over here we're going to jump into the .NET Core 3 there and .NET publish. And so there we go we've got one XE there and so if we run that it runs. And if we run it again it's ever so slightly quicker. It's only a console app so there's not a lot for it to do but the second time around and subsequent times it's a bit faster. So that's kind of convenient. It means that we've just got one file to distribute. Next thing we're going to have a look at is assembly linking. So this is a feature that actually comes from the Mono project originally where we can end up with some pretty large number of files especially when we start including run time files. So it would be nice if there was a way for us to figure out are there some of these assemblies that we're not actually using in our application. So that's what assembly linking does. It analyzes the IEL and static analysis of all the dependencies and figures out are there things that I can trim out and make things a bit smaller. It's something you do need to test because sometimes it may think you're not using something when actually the application does use it by reflection. So it's not obvious via the static analysis that it does. So let's see how we do that. So I'll do that single follow. I'll do that again and I'll pass in another parameter which is publish trimmed. That's true. And just so that we remember, so previously it was 69 meg. And so we're going to do a trim now. We'll also see the extra output on the console here. Just reminding us we've done this optimizing, do some testing just to make sure we haven't broken anything. So it was 69. It's now 27, so it's just over half the size. Does it still work? The answer is yes. I'm not doing anything too tricky in my application so that's not surprising. Whilst we're on the subject of making things smaller, this is not a new feature in .NET Core 3. It actually came in 2.2, I think. Globalization in variant mode, but it's sort of related to making things smaller potentially. So I thought it was worth mentioning here. And so this is something we can turn on in our project file. And so if your application is not making use of globalization sort of different cultures or languages, it's just happy to run with the invariant culture. Then you can turn this on and theoretically by doing that, you can end up with a smaller number of files. So if I run this again, actually I might need to do a clean first before I do that. Let's just see what it did. So it was, sorry, wrong one. Let's scroll back up there. So it was 27, 9, 8, 4, 5, 3, 2. And it's actually a tiny bit bigger in this case. So in my instance, it doesn't really benefit me. I'm not actually doing anything interesting as far as formatting or sorting or that kind of thing. But it's something to try out. It could be useful just to be aware of. The next feature is tiered compilation. So this is a new feature that's enabled by default in .NET Core 3. So now the runtime is able to adapt the just-in-time compiler. So initially it'll do a fast pass through all the code and basically to try and reduce the startup time for application. And then it's able to go back and when it identifies certain code paths that are being used a lot, it can re-jit that code and spend a bit more time optimizing that code as it runs a bit faster. The things to be aware of that is that you can change. So it's on by default. You can also opt in to enable the quick-jit for tier zero. The other thing is you might do some testing and discover actually the tiered compilation in your situation makes it worse. So you want to turn it off. And it's possible to turn it off by setting this property to project or build script as well. Okay, next feature is ready to run. So this is a new feature in .NET Core 3. And what it's going to do is it's going to use ahead-of-time compilation. So rather than relying on all your IL in your application being just-in-time compiled on the client machine, we're going to do some ahead-of-time compilation at build time and include the machine code, if you like, the runtime inside the assembly. So let's see how we do that and see what happens. So first of all, I'm just going to do a clean out. I'm just going to do a .NET publish minus R win 10x. The reason I'm doing this is because I want to be able to show the difference between just the IL assembly and the assembly that has the native code in it as well. So let's have a look. And there's a lot of files in there, so I just want the dn3. Okay, so the current file dn3.dll is about 5K. So 5120. Now if I go out and do another build, and this time I'm going to pass in the p ready, ready to run equals true. Run that, and so now that file has changed to 8K. So the difference there is that we're now including native code, and that native code, because I've done my compilation with the runtime identifier of win 10x64, it's going to be runtime code for that platform. The IL is still included, and so the .NET runtime can still choose to replace this sort of pre-generated native code with better jittered code later on if it wants to. Okay, here's a little comparison I put together. I've got a larger solution than the one I'm demonstrating now. And just to see the size differences with using the different options. So on the left, it's just a simple .NET build, and that produced 46 meg of output. Then when I wanted to produce a single XE, so that also includes the runtime, then we went up to 131. If I just use the trimmed option, then I've got it down to 88. The single XE and trimmed was about the same. If I went to ready to run, so it's then doing that sort of ahead-of-time compilation and generating native code as well, we went up to almost 160 meg. And then if I trimmed that back down again, we got down to 142. So it gives you a bit of an idea, obviously it's going to vary on your application how much different trimming is going to make. But yeah, sort of a bit of a perspective on some of those different options. Okay, we've still got a little bit of time, so one more thing to have a look at is MSI-X deployment. So we've just been looking at sort of plain .NET up until now. But one nice thing that's been added in .NET Core 3 is the ability to have WinForms and WPF applications. And one thing we can do with those now is produce MSI-X packages, so they can be deployed onto Windows 10 and into the Windows Store. So I've got a very simple WinForms application here. It's so simple that all it does if we press F5 is bring up a blank form if we wait for it to build. There it is. Can't get much more simple than that. So if I want to create a MSI-X for this application and I want to deploy it onto my local machine so it appears in my start menu, what I need to do is add a new project. And that project is called a Windows Application Packaging Project. If you go looking for this project type and you don't see it, it might be because you haven't added the UWP workload in Visual Studio. And if you've only just been working with desktop apps, you may not have had that option. So install that extra option in Visual Studio. You'll see this. And then we're going to add one of those. And I'm just going to name that core app before. And you can decide what range of Windows 10 you want to target. The default is fine for me. I can then add a reference from the package project back to the actual WinForms application. I need to make some other changes here as well. I need to set a runtime identifier. So runtime 4. I also need to make sure that when I'm building, these are all x64 as well. So they're all the same. So I'm just going to make an x64 platform there. The other thing I need to do, and I've got a link to this in the sample code that I've published to GitHub, is this last line here. It's placed in different MS build code there. That's also on the docs side. You can read about that. And while I'm here, I'm just going to customize my application a little bit. Now obviously there's a whole lot of stuff here to do with Windows Store. And I'm not going to worry about that because I'm not actually going to publish one. I'm just going to set the package name there. Now let's build that and see if it builds. Thinking about it. Yep, that all worked. So I can now right-click on my package project and I can deploy. Now I'll just show you... I'm going to have to bring my menu back here. So in my Windows menu at the moment, nothing up my sleeve. And jump back to Visual Studio and deploy. I've successfully started and succeeded. If I now go to my Windows menu, I've now got my core app package that's been deployed. And I can run it. That's an amazing application. And just to prove that it really is packaged up as a MSIX or like an Apex package, if I go back to my console and just query using PowerShell, then there is my package there. I can also go back here and uninstall it. So that could be something you might use to submit applications to the store. It also could be used for something to ship stuff around inside your enterprise if you want to use that packaging method as well. All right, so we're coming up to the end of my talk. And so that's the link to my GitHub repo where I've just pushed up the sample code that I've been demonstrating in this talk. Thanks for listening and watching. And if there's any questions, I'm happy to take those now. So we're going to try something here. All right, we're going to do the audio thing. David, can you hear me? Yes? All right. But I can't hear you for whatever reason. That's fine, we're doing... Can people hear me on the stream? Can anyone let me know? Bueller? Bueller? Yeah, can you hear David? You can't hear David. Okay, so echo time it is. So David, I'm going to... All right, cool. Can you hear me now, David? I can't hear you. Can people hear David out there? I'm talking. The ring in Spain falls mainly in the plane. What was that? That's from my fair lady. What accent was that? Oh, I don't know. That's just me speaking. No fancy accent there. I thought you were trying to explain. Perfect. So, hey, there were no questions. Cool. So thank you so much for taking the time to present. It was pretty cool. People were talking about the awesome ASCII graphics you were having in there. So if all that's part of the demo, like I told everybody, we're going to post this. Yeah. And we'll go from there. All right. Thank you so much. We'll hang out. Thank you. And we'll get Surab, our next speaker, going up. Thanks, everybody. Great work, David. Thanks. Bye.