git, github, powershell comments edit

The GitLens plugin for VS Code is pretty awesome, and I find I use the “Open Repository on Remote” function to open the web view in the system browser is something I use a lot.

Open Repository on Remote - GitLens

I also find that I do a lot of my work at the command line (in PowerShell!) and I was missing a command that would do the same thing from there.

Luckily, the code that does the work in the GitLens plugin is MIT License so I dug in and converted the general logic into a PowerShell command.

# Open the current clone's `origin` in web view.
Open-GitRemote

# Specify the location of the clone.
Open-GitRemote ~/dev/my-clone

# Pick a different remote.
Open-GitRemote -Remote upstream

If you’re interested, I’ve added the cmdlet to my PowerShell profile repository which is also under MIT License, so go get it!

Note: At the time of this writing I only have Windows and MacOS support - I didn’t get the Linux support in, but I think xdg-open is probably the way to go there. I just can’t test it. PRs welcome!

halloween, maker, costumes comments edit

Due to some challenges with home remodeling issues we didn’t end up handing out candy this year.

We discovered a slow leak in one of the walls in our kitchen that caused some of our hardwood floor to warp, maybe a little more than a square meter. Since this was a very slow leak over time, insurance couldn’t say “here’s the event that caused it” and, thus, chalked it up to “normal wear and tear” which isn’t covered.

You can’t fix just a small section of a hardwood floor and we’ve got like 800 square feet of contiguous hardwood, so… all 800 square feet needed to be fully sanded and refinished. All out of pocket. We packed the entire first floor of the house into the garage and took a much-needed vacation to Universal Studios California and Disneyland for a week while the floor was getting refinished.

I had planned on putting the house back together, decorating, and getting right into Halloween when we came back. Unfortunately, when we got back we saw the floor was not done too well. Lots of flaws and issues in the work. It’s getting fixed, but it means we didn’t get to empty out the garage, which means I couldn’t get to the Halloween decorations. Between work and stress and everything else… candy just wasn’t in the cards. Sorry kids. Next year.

But we did make costumes - and we wore them in 90 degree heat in California for the Disney “Oogie Boogie Bash” party. So hot, but still very fun.

I used this Julie-Chantal pattern for a Jedi costume and it is really good. I’m decent at working with and customizing patterns, I’m not so great with drafting things from scratch.

I used a cotton gauze for the tunic, tabard, and sash. The robe is a heavy-weave upholstery fabric that has a really nice feel to it.

Texture of the robe fabric up close

I added some magnet closures to it so it would stick together a bit nicer as well as some snaps to stick things in place. I definitely found while wearing it that it was required. All the belts and everything have a tendency to move a lot as you walk, sit, and stand. I think it turned out nicely, though.

The Jedi costume on a dress form

The whole family went in Star Wars garb. I don’t have a picture of Phoenix, but here’s me and Jenn at a Halloween party. Phoenix and Jenn were both Rey, but from different movies. You can’t really tell, but Jenn’s vest is also upholstery fabric with an amazing, rich texture. She did a great job on her costume, too.

Trav and Jenn in Star Wars costumes

mac comments edit

Rosetta is used to enable a Mac with Apple silicon to use apps built for Intel. Most of the time, you’ll get prompted to install it the first time you need it and after that the automatic software update process will take over. However, in some environments the automatic mechanisms don’t work - maybe it’s incorrectly blocked or the update isn’t detecting things right. Here’s how to update Rosetta manually.

First, get your OS build number: 🍎 -> About This Mac -> More Info.

The 'About This Mac' window - click the 'More Info' button

Click on the Version XX.X field and it should expand to show you the build number. It will be something like 22A380.

The 'More Info' window showing the build number

Go to the software catalog for Rosetta and search for your build number. You should see your build-specific package. The build number is in ExtendedMetaInfo:

<dict>
  <key>ServerMetadataURL</key>
  <string>https://swcdn.apple.com/content/downloads/38/00/012-92132-A_1NEH9AKCK9/k8s821iao7kplkdvqsovfzi49oi54ljrar/RosettaUpdateAuto.smd</string>
  <key>Packages</key>
  <array>
    <dict>
      <key>Digest</key>
      <string>dac241ee3db55ea602540dac036fd1ddc096bc06</string>
      <key>Size</key>
      <integer>331046</integer>
      <key>MetadataURL</key>
      <string>https://swdist.apple.com/content/downloads/38/00/012-92132-A_1NEH9AKCK9/k8s821iao7kplkdvqsovfzi49oi54ljrar/RosettaUpdateAuto.pkm</string>
      <key>URL</key>
      <string>https://swcdn.apple.com/content/downloads/38/00/012-92132-A_1NEH9AKCK9/k8s821iao7kplkdvqsovfzi49oi54ljrar/RosettaUpdateAuto.pkg</string>
    </dict>
  </array>
  <key>ExtendedMetaInfo</key>
  <dict>
    <key>ProductType</key>
    <string>otherArchitectureHandlerOS</string>
    <key>BuildVersion</key>
    <string>22A380</string>
  </dict>
</dict>

Look for the URL value (the .pkg file). Download and install that. Rosetta will be updated.

dotnet, csharp, vs comments edit

UPDATE OCT 25 2022: I filed an issue about some of the challenges here and the weird <Compile Remove> solution I had to do to get around the CS2002 warning. I got a good comment that explained some of the things I didn’t catch from the original issue about strongly-typed resource generation (which is a very long issue). I’ve updated the code/article to include the fixes and have a complete example.


In the not-too-distant past I switched from using Visual Studio for my full-time .NET IDE to using VS Code. No, it doesn’t give me quite as much fancy stuff, but it feels a lot faster and it’s nice to not have to switch to different editors for different languages.

Something I noticed, though, was that if I updated my *.resx files in VS Code, the associated *.Designer.cs was not getting auto-generated. There is a GitHub issue for this and it includes some different solutions to the issue involving some .csproj hackery, but it’s sort of hard to parse through and find the thing that works.

Here’s how you can get this to work for both Visual Studio and VS Code.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <!--
        Target framework doesn't matter, but this solution is tested with
        .NET 6 SDK and above.
    -->
    <TargetFrameworks>net6.0</TargetFrameworks>

    <!--
        This is required because OmniSharp (VSCode) calls the build in a way
        that will skip resource generation. Without this line, OmniSharp won't
        find the generated .cs files and analysis will fail.
    -->
    <CoreCompileDependsOn>PrepareResources;$(CompileDependsOn)</CoreCompileDependsOn>
  </PropertyGroup>

  <ItemGroup>
    <!--
        Here's the magic. You need to specify everything for the generated
        designer file - the filename, the language, the namespace, and the
        class name.
    -->
    <EmbeddedResource Update="MyResources.resx">
      <!-- Tell Visual Studio that MSBuild will do the generation. -->
      <Generator>MSBuild:Compile</Generator>
      <LastGenOutput>MyResources.Designer.cs</LastGenOutput>
      <!-- Put generated files in the 'obj' folder. -->
      <StronglyTypedFileName>$(IntermediateOutputPath)\MyResources.Designer.cs</StronglyTypedFileName>
      <StronglyTypedLanguage>CSharp</StronglyTypedLanguage>
      <StronglyTypedNamespace>Your.Project.Namespace</StronglyTypedNamespace>
      <StronglyTypedClassName>MyResources</StronglyTypedClassName>
    </EmbeddedResource>

    <!--
        If you have resources in a child folder it still works, but you need to
        make sure you update the StronglyTypedFileName AND the
        StronglyTypedNamespace.
    -->
    <EmbeddedResource Update="Some\Sub\Folder\OtherResources.resx">
      <Generator>MSBuild:Compile</Generator>
      <LastGenOutput>OtherResources.Designer.cs</LastGenOutput>
      <!-- Make sure this won't clash with other generated files! -->
      <StronglyTypedFileName>$(IntermediateOutputPath)\OtherResources.Designer.cs</StronglyTypedFileName>
      <StronglyTypedLanguage>CSharp</StronglyTypedLanguage>
      <StronglyTypedNamespace>Your.Project.Namespace.Some.Sub.Folder</StronglyTypedNamespace>
      <StronglyTypedClassName>OtherResources</StronglyTypedClassName>
    </EmbeddedResource>
  </ItemGroup>
</Project>

Additional tips:

Once you have this in place, you can .gitignore any *.Designer.cs files and remove them from source. They’ll be regenerated by the build, but if you leave them checked in then the version of the generator that Visual Studio uses will fight with the version of the generator that the CLI build uses and you’ll get constant changes. The substance of the generated code is the same, but file headers may be different.

You can use VS Code file nesting to nest localized *.resx files under the main *.resx files with this config. Note you won’t see the *.Designer.cs files in there because they’re going into the obj folder.

{
  "explorer.fileNesting.enabled": true,
  "explorer.fileNesting.patterns": {
    "*.resx": "$(capture).*.resx, $(capture).designer.cs, $(capture).designer.vb"
  }
}

azure, tfs, build comments edit

Using the Sonatype Nexus IQ for Azure DevOps task in your build, you may see some warnings that look like this:

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.google.inject.internal.cglib.core.$ReflectUtils$1 (file:/agent/_work/_tasks/NexusIqPipelineTask_4f40d1a2-83b0-4ddc-9a77-e7f279eb1802/1.4.0/resources/nexus-iq-cli-1.143.0-01.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of com.google.inject.internal.cglib.core.$ReflectUtils$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

The task, internally, just runs java to execute the Sonatype scanner JAR/CLI. The warnings here are because that JAR assumes JDK 8 and the default JDK on an Azure DevOps agent is later than that.

The answer is to set JDK 8 before running the scan.

# Install JDK 8
- task: JavaToolInstaller@0
  inputs:
    versionSpec: '8'
    jdkArchitectureOption: x64
    jdkSourceOption: PreInstalled

# Then run the scan
- task: NexusIqPipelineTask@1
  inputs:
    nexusIqService: my-service-connection
    applicationId: my-application-id
    stage: "Release"
    scanTargets: my-scan-targets