Macros in VS 2022?

3
Filed under Uncategorized

I’ve lamented Visual Studio’s lack of built-in macro support for ages. I tried a few extensions a while back but they never quite measured up.
But I just stumbled across Text Macros for VS 2019-2022.

It’s perfect for a quick, one-off Record/playback macro, you can save macros, edit them (although that’s not ideal as the macros are saved in a rather obtuse XML format), and even assign them permanently to hotkeys.

It’s only good for text editing macros, so you can’t use it to “automate” Visual Studio itself, but I’ve yet to have a need to do that.

Fixing VSCode’s broken Ctrl-Right

1
Filed under Uncategorized

I’ve been using VSCode for quite some time now. Generally speaking, I’ve been super happy with it. It’s ultra configurable, fairly light weight, very fast, and just generally a pleasure to work with.

Except….

They completely got handling of Ctrl-Right wrong. Try it in Word, try it in Notepad++, in Visual Studio, you name it, they all work a certain way.

But VSCode, not so much.

Now, it’d be easy enough to get used to it, if all my editors decided to change the default way they handle Ctrl-Right. But, yeah, no.

I’ve dealt with it for a while now but this weekend, I finally decided to have a look.

It took some Google-foo, but eventually I came across this post by Spongman that very accurately describes the problem.

I won’t repeat that here, but here’s the keybindings for VSCode that fix the problem.

    {
        "key": "ctrl+shift+right",
        "command": "-cursorWordEndRightSelect",
        "when": "textInputFocus"
    },
    {
        "key": "ctrl+right",
        "command": "-cursorWordEndRight",
        "when": "textInputFocus"
    },
    {
        "key": "ctrl+right",
        "command": "-cursorWordAccessibilityRight",
        "when": "accessibilityModeEnabled && textInputFocus"
    },
    {
        "key": "ctrl+shift+right",
        "command": "-cursorWordAccessibilityRightSelect",
        "when": "accessibilityModeEnabled && textInputFocus"
    },
    {
        "key": "ctrl+right",
        "command": "cursorWordStartRight"
    },
    {
        "key": "ctrl+shift+right",
        "command": "cursorWordStartRightSelect"
    }

It’s a bit tricky to get them installed in VSCode, what with the new Settings UI, but, once they’re there, Mwah! Perfection!

10
Filed under .NET, SQL, Visual Studio

Command Line MSSQL

SQL on the command line!

There’s a number of tools out there for connecting to an MSSQL Database and running queries from the command line, but a colleague recently pointed out a new one I hadn’t seen before that actually works really really well, especially with Windows Terminal and Cmder.

First, make sure you’ve got Windows Terminal and Cmder installed. They are truly the bees knees when it comes to working in the command line under Windows!

Next, install mssql-cli. This app is actually a python script, so you’ll also need Python if you don’t already have it installed. Don’t fret, though. The link contains instructions on getting Python going, and once that’s done, installing mssql-cli is a single pip command:

python -m pip install mssql-cli

To test it, just open a command prompt and type:

mssql-cli

Now, that alone is nice, but if you’re like me, you have several test databases you connect to on a regular basis and entering credentials is troublesome at best.

Not to worry. There’s a batch file for that!

Now, it’s not the simplest in the world even though it is a single liner. So here goes:

wt -d c:\users\dhiggins\desktop cmd /k "c:\apps\cmdr\vendor\init.bat cd %CD% && mssql-cli -U {dbloginusername} -P {password} -d {dbname} -S {dbservername}"

Let’s break that down:

  • wt – starts Windows Terminal
  • -d – followed by the folder you’d like to start terminal in. Not strictly required, but it’s a nice add. I just set it to my desktop
  • cmd – This is used to get Cmder started in a tab in Windows Terminal
  • /k – tells cmd to execute the following quoted command and stay loaded
  • “c:/apps/cmdr/vendor/init.bat – this get Cmder started and the shell all initialized. Note that the path to your installed copy of Cmdr may be different from the “apps/cmdr” that I have here.
  • cd %CD% – Gets Cmder switched to the folder that this bat file is located in
  • && mssql-cli – Actually starts mssql-cli! The whole point of this exercise.
  • -U {dbloginusername} – Provider the UserName you use to log into your db server here
  • -P {password} – provide the database user password here
  • -d {dbname} – provide the database name here
  • -S {dbservername}” – And finally provide the database server name here. I’m just connecting up to the locally installed instance of SQL Server.

Save that as a BAT file and dblclick it to launch directly into a Cmder tab inside Windows Terminal connected to the DB of your choice. Perfection!

One big benefit from using Cmder, at least from what I can tell, is that it automatically supports horizontal scrolling of query result sets.

Notice that those right pointing arrows!

Just use <left><right> arrow keys to scroll the grid left and right as you page through results.

If you don’t use Cmder as your shell, scrolling won’t work like that unless you install something else called PyPager. Which I didn’t do.

Visual Studio Bonus!

Now, all this is well and good, but as they say on late, late night TV: Wait! There’s more!

I spend a lot of time in Visual Studio, so any way to stay there tends to be a positive for me, and one of the most recent additions to VS is built-in Terminal support.

Works a treat and even works with Cmder, so you get all that great Cmder goodness right inside Visual Studio.

But, you can create as many “Terminal Configurations” as you want, so here’s a shot of a few that I have, including one running Cmder directly and another starting the MSSQL-CLI directly to a specific database.

Easy and quick direct access to a specific db, Right inside VS!

Rainmeter WebParser Problems

190
Filed under Uncategorized

A colleague recently pointed me to a fantastic little desktop customization app for windows, RainMeter.

He was using the lottaweather skin, so I pulled that as well, and I’ve found it quite nice to have a really clear forecast stuck right there on the desktop.

Beautiful Weather Skin

It’s tiny, quite capable, and is really easy to knock up a quick notification panel or whatnot based on a webservice, or so I thought.

At work, we’d recently been throwing ideas around about how to be reasonably notified of build failures and Pull Requests/Statuses.

Another colleague came across AnyStatus, which is quite nice in it’s own right, but I thought it’d be nice to have something in the same style as lottaweathers skin.

I’ll dig into the details of scraping azuredevops and jenkins later, but while putting things together, I ran into a vexing problem.

I had one measure that resolved the users azure guid “id” given their name and a different measure that requested all the Pull Requests where that userid was listed as a “reviewer”.

Pretty standard stuff for RainMeter, and the urls I was using worked just fine in PostMan, but not Rainmeter.

Actually, the UserID request worked, but not the Pull Request query.

Here’s the measure definitiion:

[MeasureMyReviews]
Measure=WebParser
Disabled=1
URL=https://azuredevops.blahblah.com/#organization#/#project#/_apis/git/repositories/#repository#/pullrequests?api-version=5.1&searchCriteria.reviewerId=[MeasureUserID]
Header=Authorization:Basic #AzureDevOpsPATBase64#

After WAY too much head scratching, I discovered the problem was two-fold.

  1. My measure referenced the UserID measure like so: [MeasureUserID] but that syntax doesn’t work in this context. In a URL definition, it needs to be [&MeasureUserID] (note the &)
  2. WebParser measures happen asynchronously, but in this case, the “MeasureMyReviews” has to happen AFTER the MeasureUserID. Otherwise, the userid hasn’t been resolved and will just be blank.

The fix was to set Disabled=1 for the MeasureMyReviews measure, then enable it in the FinishAction of MeasureUserID, like so:

[MeasureUserID]
Measure=WebParser
URL=https://azuredevops.blahblah.com/#organization#/_apis/identities?api-version=5.1&searchFilter=General&filterValue=#username#
Header=Authorization:Basic #AzureDevOpsPATBase64#
RegExp=(?siU)"id":"(.*)"
StringIndex=1
DynamicVariables=1
FinishAction=[!SetOption MeasureMyReviews Disabled 0][!UpdateMeasure MeasureMyReviews]

Note the two bang commands in the “FinishAction”

Sony XBR Tv showing Red Lines

1
Filed under Uncategorized

I’ve had a 65″ Sony HD TV for a while now and have really enjoyed it. The picture is incredible, especially with HD content, works well as a Chromecast target, the menus are completely usable, etc.

Still, it’s not like the 80″ HD projector screen I’d used going back years. Of course, with a projector, even a bright one, I still had to have the room mostly dark to really be able to see the screen well, and watching a projector during the day in a room with two skylights just isn’t particularly doable.

Hence the Sony.

Anyway, a week or so ago I happened on the chance to pick up an 85″ Sony TV and jumped on it. Checked it out before bringing it home and everything looked good, so we loaded it up.

Got it home, hooked it up and I’m seeing faint red lines across the screen.

Worse, on some screens (usually menus or computer generating fades/gradients) I’m seeing a LOT of red lines.

But they aren’t consistent.

Here’s a few shots.

Notice the red bits around the Hulu logo
An example of shading gone wrong
Another shading example
Here’s one of the faint vertical dashed lines

Here’s the thing. Most content actually shows perfectly fine.

At some points, depending on the image on screen, the vertical dashed red lines are either completely gone or barely visible.

My guess is that during the move, we torqued the tv too much or jostled it in some way that loosened a connector.

I don’t believe the screen is damaged, because the location of the lines changes depending on the image being shown.

Anyone have any ideas?

TClock Redux Redux

2
Filed under Uncategorized

I work with a team that’s pretty geographically distributed, so it’s always nice to have a solid notion of what time it is where-ever the person I’m talking to (or about to talk to) might happen to be.

I stumbled upon TClock (and White-Tiger’s update TClock Redux) quite some time ago and it worked fantastically for what I needed.

Rockin’ that XP Style, oh, yeah!

Yeah, OK, it might be a tad dated, UI-wise, but it easily allows you to put several clocks for different timezones, with labels, right there in the tray. And you still have quick access to calendar, etc.

For me, I used a TClock configuration like this for ages.

Notice 3 timezones, with seconds that update only on the middle zone (I’m in Central), and an uptime clock, day name, and date just for good measure.

But recently, I started working with several folks scattered across India, and their timezones were fractional, something like GMT-7.5.

And TClock didn’t handle that.

I finally got some time several weeks back, so I forked White Tiger’s Redux branch, dusted off my C programming chops and went to work.

And I came up with TClock Redux Redux.

White Tiger might incorporate the pull request into their branch, but until that time, I’m posting the GITHUB project and release here.

Source is located here

An initial release, 64bit only, can be found on the releases page here

How to use it

Stop TClock if it’s running on your machine, download the release Clock64.exe and simply copy it over the existing Clock64.exe. Then restart TClock.

Outwardly, it’s exactly the same as TClock Redux, so please see White Tiger’s page for detailed configuration information.

For this version, the only thing that’s different is the handling of the “w” format specifier.

“w” means “calculate a time that’s an offset of x hours from the “current” timezone.

So, for instance, if I’m in Central US time, and I wanted to show East Coast time as, say, 12:30PM, I’d use “w+1:nntt”.

For Pune, India, however, they’re actually 12.5 hours ahead of Central time.

The original TClock Redux couldn’t handle that, but with this version, you can configure you clock format string with

“w+12.5:nntt”

and you’ll get the time in Pune, offset by 12.5 hours from the current time zone.

So now, my Taskbar can look like this:

I’ve added “day of the year” and “week of the year” just for fun.

LogShift Utility

1
Filed under Uncategorized

tldr; Console app to translate datetime stamps in a logfile into time offsets.
Get it here, with a precompiled release version here.

LOG file format - Free interface icons

I often find myself comparing log files to identify discrepancies or variations in execution timing. And a big problem with doing so is time stamps.

Most modern logging in .net apps happens through log4net, or nlog, or any of a variety of their clones.

In almost all cases, log files will be standard text files that look something like so:


2020-03-03 12:34:22 PM ERROR A problem has occurred…..
2020-03-03 12:34:25 PM INFO Informational message….

This works just fine under normal circumstances, but, when you’re trying to compare two log files that were captured at different times, but for the same sequence of actions, there’s a big problem.

Those timestamps will be different for every single line!

Couple that with comparing multi-megabyte log files, and locating real differences starts to look like finding that one whisperer in a herd of walkers.

In my case, what I really needed were time deltas instead of timestamps in the log files.

So instead of the above, we’d have something like:

...
00:00:00 ERROR A problem has occurred.....
00:00:03 INFO Informational message....
...

In other words, instead of literal datetime stamps on each log entry, I’d see a time delta from each entry to the next.

This solves two major issues:

  • Log entries written at approximately the same time would all have a delta of 0, so they won’t show up as differences in a file diff tool
  • When the time delta is non-zero, the difference is actually meaningful. It represents a differing amount of time elapsed between the two log entries. When comparing two different runs of the same code, this can really help identify specific places in code where performance has been impacted.

Google it!

So, of course, I head to Google to see if there’s anything out there already for this. I did turn up a couple of promising log viewers, but most were either commercial, or required capturing log files into a database for review, which was a bit of overkill in my case.

I just needed something to massage two log files into a more comparable format.

Enter LogShift

After coming up empty with Google, I decided to put a little utility together just for this purpose.

I’d heard that .net core 3.x allowed for “single file executables” but I’d never had a chance to try it out. Bingo! Perfect opportunity!

And so, LogShift was born.

Get it here, and a precompiled release version is here.

First off, a big thank you to Giacomo Stelluti Scala and his CommandLineParser nuget. If you have a need for a simple and powerful command line parser that makes your console app look every bit as flexible as GIT, check it out!

The Nitty Gritty Usage Details

Just download the LogShift.exe, throw it on your desktop, and drag just about any text-format log file onto it.

When the dust settles, there should be a file in the same folder as your original log file, but with an additional “.shifted” extension.

And if you look at that *.shifted file, you’ll find that most if not all date time stamps in it have been converted to “(DURATION)hh:mm:ss”

Type LogShift –help for a typical usage screen:

LogShift 1.0.0
(c) 2020 drVenture
-f, --file Log Filename to process. Can also omit the -f and just put the filename as the only argument.
-d, --durationtag (Default: (DURATION)) String used to preface duration values inserted into shifted log file
-s, --outputsuffix (Default: shifted) The Suffix to append to file name when writing the output file
-m, --monthfirst (Default: true) true if the month should be assumed to be before the day in date stamps
-y, --yearfirst (Default: true) true if the year should be assumed to be before the month and day in date stamps
--help Display this help screen.
--version Display version information.
value pos. 0 The Filename(s) to process. Specify either one or more filenames or use the -f option.

The options should be pretty straightforward.

One question I’ve gotten is “How does it recognize datetime stamps?”

Basically, the program scans each line for a REGEXE that will match most typical date time formats.

It will just work if the datetime stamps have a 4 digit year, esp if the year comes first, because that virtually guarantees that the month comes second and the day third.

If you happen to have log files with oddly formatted date time stamps, you can use the -yearfirst and -monthfirst options to indicate year comes before the day and month, and that the month comes before the day, respectively.

The time portion should automatically get recognized with just hh:mm or with hh:mm:ss. Additionally, fractional seconds will be recognized as hh:mm:ss:fff, with a separator of “:”, “.” or “,”.

Finally, AMPM will also automatically be recognized.

Note that the first recognized timestamp in the file is recorded and all subsequent timestamps are compared to it. Any date time values that are BEFORE the first detected date time stamp will be considered “data” and as such, will not be converted to a time difference.

This is so that any logging of actual date-oriented data values will likely not get translated, which is generally a good thing. Since most data values in the file will be in the past, this should just work. Of course, if your log file contains date data in the future, well… there’s always a pull request!

Multiple files at once

To process multiple files at once, just multi-select 2 or more log files in explorer and drag them onto LogShift.exe. Either that or run it from the command line with more that one filename… for instance:

LogShift a.txt b.txt c.txt

Wrapping up

And that’s about it for this little utility. I hope it helps someone out there as much as it’s helped me.

As usual, feel free to post with any questions or comments! I look forward to hearing from you!

The Disambiguator (A KeePass Plugin)

0
Filed under Uncategorized

The TLDR;

For the impatient crowd šŸ™‚

  • Download The Disambiguator KeePass plugin here.
  • Unzip it and place the PLGX file in the KeePass “Plugins” folder, just like any other plugin.
  • Restart KeePass. You should see a “Compiling Plugins” notice and then KeePass should start normally.
  • In KeePass, click “Tools”, “Plugins” and verify that The Disambiguator is now in the list of loaded plugins.
  • Edit the AutoType entry for a credential set that has an ambiguous Window Title.
  • add “{exe:nameOfExecutable}” (without doublequotes) at the end of the WindowTitle. Replace nameOfExecutable with the filename of the Executable program file that the Target Window belongs to. In the case of Quicken, for instance, that would look like {exe:qw.exe}

Now open your target application and use AutoType as you normally would. If everything is set right, KeePass will now automatically select the appropriate credentials for the target window using both the Window Title and the application executable.

Introduction

I’ve used the password manager KeePass for a very long time. Excellent, simple, clean install, low resource usage and fast.

Editing a Credential Set in KeePass

The AutoType support, while possibly not quite as simple as some full commercial packages, is quite flexible and has never let me down.

Well, almost never.

KeePass’s AutoType feature works by allowing the user to enter one or more “Window Titles”, which it then compares against the target window when you user presses the AutoType hotkey.

When only one configured Window Title matches the Window Title of the target window, KeePass automatically can choose that single set of credentials, and perform the autotype. It’s almost like magic!

Trouble Ahead

But, what happens when there are 2 or more credential sets that have the same Window Title?

For instance, both Quicken and Exodus request the user to login via a login screen with the Window Title “Enter Password”.

If you’re “responsible” with you passwords, and we all are as KeePass users (right?!), then you’re not using the same credentials (username and password) for two different applications. This means you likely have two different sets of credentials stored in KeePass: one for Quicken and one for Exodus. And you’ve setup AutoType for both.

But there’s the rub. Both sets of credentials have AutoType setup to key on the Window Title of “Enter Password”, as they must.

The KeePass Credential Chooser

Unfortunately, when you have, say, the Quicken Login window displayed and press the KeePass AutoType hotkey (normally Ctr-Alt-A), KeePass discovers 2 sets of credentials (and possibly more) that match. Because it can’t magically decide which to use, it pops up the Credential Chooser dialog so that you, the user, can make the choice.

This is all fine and good, but it can be a bit of a pain, and it forces the user to make a choice when the choice should be automatic.

Enter The Disambiguator

The problem here, of course, is disambiguation. Using the Window Title as the only “disambiguating” factor is ok most of the time, but, as the above example shows, it’s not always quite enough to completely identify a single specific credential set to use for autotype.

Alex Vallat has a very nice plugin for KeePass called WebAutoType which specifically allows users to configure matching URLs for autotype entries. This will almost always provide enough uniqueness to properly match a single credential set for Web Pages. But unfortunately, it does nothing for normal desktop apps like Quicken or Exodus.

That’s where The Disambiguator comes in.

to be continued

Automation Virtual Conference

3
Filed under Uncategorized

Ok. I’m not one to typically post notices Re: my employers, but I thought I might make the few readers I have, aware of an upcoming virtual conference that Worksoft is having on testing and robotic process automation on Oct 28.

Click here to learn more.

Troubles with Nuget v5.7

2
Filed under nuget
Tagged as

I’ve worked with Nuget for quite some time, both consuming published Nugets as well as creating Nugets to be published.

But I ran into a pretty vexing series of issues today, that, from what I can tell from the posts I found by Googling, might be affecting a lot of other users.

To begin with, I was running an older version of nuget.exe, ver 4.9. So, I dutifully updated to v5.7 and still had the same issues.

My first problem was this lovely message:

Illegal characters in path.
System.ArgumentException: Illegal characters in path.

After far far too much experimentation, I discovered that putting the project filename, the nuspec filename or the output directory filename in double quotes, was the problem.

In other words, this:

nuget pack ".\myapp.csproj" -Verbosity Detailed -OutputDirectory ".\bin\Release\"

won’t work. But this:

nuget pack .\myapp.csproj -Verbosity Detailed -OutputDirectory .\bin\Release\

works just fine.

Unfortunately, if your project’s path happens to contain spaces, you won’t be able to specify the path properly. I haven’t investigated any way around that.

But wait, there’s more!

That got me past the “Illegal characters in path” error, only to be greeted by this:

Authors is required.
Description is required.
System.Exception: Authors is required.
Description is required.

In my case, I was using a pretty standard nuspec file, something like this:

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd" >
  <metadata>
    <id>$id$</id>
    <version>$version$</version>
    <title>$title$</title>
    <authors>$author$</authors>
    <owners>$company$</owners>

It turns out there were two issues here:

  1. Ignore the error message. It’s terrible because, first, the xml element is <authors>,Ā not <Authors> as the message implies. And second, the tokenĀ is actually $author$ (singular), not $authors$ or $Authors$ or even $Author$.
  2. But much weirder was that it failed like this because I was actually specifying a relative path to nuget.exe, like so:
    .\nuget\nuget packĀ blah blah

Yeah, you read that right. Believe it or not, that relative path somehow causes nuget to fail to resolve tokens in the nuspec file!

I put the nuget.exe in the same folder as my nuspec file and it worked!

So I moved nuget.exe to a folder that was on my PATH, and that worked as well!

So then I tried to fully specify the drive, folder and filename to the nuget.exe and that failed also.

Very bizarre.

I did come across a number of nuget bug reports indicating that it has problems if you rename the exe. That in and of itself is concerning and just plain weird.

But my guess is it’s trying to open the assembly via reflection, failing, an d short circuiting execution, skipping someĀ very necessary code in the process. Regardless. Back in operation finally!