Category Archives: Windows

MAUI setting the apps dimensions on a Windows Desktop

I have a MAUI application, designed to an extent as mobile-first. In other words it looks good on a mobile, phone or tablet device in full screen mode. But I really want the app to work and look good (on start up) on Windows Desktop. Ofcourse Windows will just give my main app window a size and I need to do whatever I can to ensure the app looks good.

It’s be so much simpler if I could just set the dimensions of my main window (at start up) to something that looks good. If the user resizes, that’s fine but just starting with a good default makes everything look better.

Okay so that’s the problem at hand, how to solve this?

The first thing is, I thought, I could just change the Platforms/Windows/App.xaml.cs, but nothing obvious there to allow this. If we look at App.xaml.cs we can override the CreateWindow method, so let’s do that – here’s the code

public partial class App : Application
{
  public App()
  {
    InitializeComponent();
    MainPage = new AppShell();
  }

  protected override Window CreateWindow(IActivationState? activationState)
  {
    var window = base.CreateWindow(activationState);

#if WINDOWS
    if (DeviceInfo.Idiom == DeviceIdiom.Desktop)
    {
      window.Width = 500;
      window.Height = 700;
    }
#endif

    return window;
  }
}

It’s pretty self-explanatory, we use conditional compilate using #if WINDOWS to only include the code for a Windows build, but as I also have a Windows tablet I figured I’d also check that the idiom is Desktop before I try to set the window dimensions. All pretty straight forward – although not quite.

The problem is that strangely ANDROID and the likes exist a defines, but seemingly not WINDOWS. We can fix this ourselves in one of two ways.

  • Open the .csproj file and for the net7.0-windowsxxx PropertyGroups add the following
    <DefineConstants>$(DefineConstants);WINDOWS</DefineConstants>
    
  • Open the project’s properties, locate the Build | General then for the “Conditional compilation symbols” for net7.0-windowsxxx entries, add
    $(DefineConstants);WINDOWS
    

This doesn’t fully solve things, well it does but Visual Studio will show the code in Create Window as grayed out as if the conditional compilation directive is excluding the code from the build – it’s not, but it looks that way.

Anyway, now we are able to size the main Window on Windows at start-up.

File explorer extended search in Windows

File Explorer has (as we all know) a search box in the top right, ofcourse we can enter some text and File Explorer will search for filenames with that text and text within files, but there are more options to tailor our search.

See Common File Kinds.

Let’s look at some examples

File name search

If we prefix our search term with file: like this

file: MyFile
file:.sln

Then we only get search results for all files with the text as part of the filename or file extension.

File content search

If we prefix our search term with content: like this

content: SomeContent

Then we only get search results from within files (i.e. text search).

Kind

We can use the kind option along with file type, such as text, music etc. See Common File Kinds.

kind:text

The above list all text files.

Other file options

We can also use the following, other file options, for example finding

datemodified:lastweek
modified:lastweek
modified:05/10/2022
size:>500

The first two options are the same and list files modified last week. The size option lists files with a size larger than 500 bytes.

See also File Kind: Everything.

Boolean Operators

As you can see we can also use Boolean Operators.

Powershell from File Explorer’s context menu

Let’s add an “Open Poweshell” option to the File Explorer context menu.

  • Run Regedit
  • Go to HKEY_CLASSES_ROOT\Directory\shell
  • Add a new key to this, we’ll call ours power_shell as you may already see a PowerShell option and I don’t want to change that one
  • Change Default for the key to the text you want display in your context menu, i.e. Open Powershell Here
  • Add a new string value named Icon and in it’s value put C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe
  • Add a new key to the power_shell key, named command. This is what’s actually run in the Default key put C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe -NoExit -Command Set-Location -LiteralPath ‘%L’

This will now show the Open Powershell Here option when you click on a folder in File Explorer, but what about if you’re already in the folder and want to open powershell from the current folder, then…

  • If you’ve closed Regedit then run Regedit again
  • Go to HKEY_CLASSES_ROOT\Directory\background\shell
  • Add a key named power_shell as before
  • As before we now add a string value named Icon with the same value as above
  • Again add a command subkey and with a slightly change add the following value into the Default key C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe -NoExit -Command Set-Location -LiteralPath ‘%V’ – note we change %L to %V

Using the Windows Subsystem for Linux

Whilst I have Linux machines available to me, they’re not always powered up or the remoting

See Windows Subsystem for Linux Installation Guide for Windows 10 for details on installing the WSL.

For completeness here’s the steps I took.

  • Run PowerShell as Admin and then execute the following

    Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
    
  • Go to the Microsoft Store and type Run Linux on Windows into the search text box. In the store currently, there’s the options of Ubuntu, openSUSE Leap 42, SUSE Linux Enterprise Server 12, Debian and Kali Linux.

    Install your preferred distro – I went for Ubuntu simply because that’s what I have on most of my Linux boxes.

  • Once installed you’ll need to go to the command prompt | Properties and select the Options tab. From here ensure that Use legacy console (requires relaunch) is unchecked.

Once everything is initialized you’ll be in the user’s (whatever user name you created) home folder – on Windows this folder is stored in C:\Users\{username}\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState\rootfs\home

We can access the C drive using

cd /mnt/c

Running the Linux from Windows

When you want to run the Windows Subsystem for Linux going forward, simply execute

wsl

Listing environment variables

Occasionally we might wish to see a list of all the current environment variables.

Windows

In Windows, from the command prompt, execute

set | more 

or from Powershell

Get-ChildItem Env:

Linux

Within Linux, from the shell, execute

printenv

net share is my friend

I recently had to set-up some shares on a server box using File Explorer and the share menu option, but after a reboot they all disappeared.

Note: I’m not concerned by this behaviour, of losing the shares, as it’s probably down to some security policy but every now and then it’s so much easier having the shares available to work from when I need to deploy apps etc.

Anyway, using net share in a batch file saves the day.

Just run

net share

to view the current shares on your machine.

Now to create a share, simply use

net share DEPLOYMENT=d:\mydeployment /GRANT:EVERYONE, READ

In this case I’m actually creating a READ only share with access granted to everyone. The string to the left of the = operator is the sharename (i.e. what you’ll see or use to access the share) obviously the right hand side is the location on the machine the share points to.

Obviously EVERYONE might by less than great in terms of security, so instead you can GRANT individual user’s access. The permission can be READ | CHANGE | FULL, see the output of net share /?

The syntax of this command is:

NET SHARE
sharename
          sharename=drive:path [/GRANT:user,[READ | CHANGE | FULL]]
                               [/USERS:number | /UNLIMITED]
                               [/REMARK:"text"]
                               [/CACHE:Manual | Documents| Programs | BranchCache | None]
          sharename [/USERS:number | /UNLIMITED]
                    [/REMARK:"text"]
                    [/CACHE:Manual | Documents | Programs | BranchCache | None]
          {sharename | devicename | drive:path} /DELETE
          sharename \\computername /DELETE

Symlinks/Junctions in Windows

I’m not sure which version of Windows these became available in, but a useful feature (as per *nix) is the capability of creating a link from one folder to another.

So for example, I have source code which relies on a set of libraries which are supplied in a zip (i.e. no NuGet or other packaging/versioning). So I tend to create a folder with the version number in it to make it easy to immediately see what version I’m using.

Great, but the problem with this approach is I also have tooling which automatically deploys these files and post build events which do similar things. Updating these every time I get a new version is repetitive and easy to make a mistake. Plus, I’m basically lazy, if I do something once I don’t want to do it again.

So it would be far better if we created a symbolic link to the newly downloaded zips/files with a name that all the tooling can expect, for example I’ll instead create a symlink named Latest which points to the actual version (this also means I could switch version if I want easily).

To create such a link we simply use

mklink /J Latest MyLibsv1.234

this command will create a junction (or symlink) named Latest and the folder it links to is MyLibsv1.234

Now we might use nant a batch file or some other means to do this for us, but when the link’s created you cannot update it (or so it seems), instead you need to delete it using

rd Latest

So now our post build events and/or other tooling can just refer to the folder Latest and everything works smoothly.

When it’s time to deploy MyLibsv2.0 we just delete the junction and create it again.