Category: Powershell

Navidrome, Clients and the Compilation MP3 Tag

As I outlined in a previous post, I switched from Jellyfin to Navidrome for my music. While on the whole I’m happy with the change, I discovered that Navidrome handles Various Artists albums such that if the Compilation tag isn’t set, it indexes the album from one into as many as there are artists. And, as outlined in the aforementioned post, this is not a bug, but by design. The intent is to account for different artists with the same album name, and that makes sense.

So I set out to attempt to automate the modification of the Compilation tag – a quest that turned out to be more complicated than I anticipated. The Compilation tag is apparently not a ‘standard’ tag. If you load up an mp3 in taglibsharp and have it vomit out all the tags, the Compilation tag won’t be among them. Here, try it yourself in PowerShell. You’ll have to update the path to your taglibsharp.dll and your test mp3 file.

Here’s an example output:

As you can see, no Compilation tag there. Compilation is technically an iTunes Flag Text Frame, and is set with a Boolean value (1 for Yup, 0 for Nope). It’s defined as TCMP. As of this writing id3.org is down, but here’s the archived page on this tag.

Given all this, I threw together the below. As per usual it’s unrefined, has almost zero error handling, and will be something I improve upon over time. This thing assumes your compilation albums are in directories formatted as “Various – Name of Album.”

Bonus: If you, like me, discovered you have a whole mess of compilation albums in directories with the format “VA – Album Title” instead of “Various – Album Title,” This one liner will help correct that.

Navidrome, Clients and Albums With Varying Artist Tags

I’m using Navidrome as my music server now, having switched from shoehorning Jellyfin into that role, and I quite like it. One thing I discovered, however, is that it – and quite a few clients that support it – rely on the Album Artist tag to help index files. Initially I found this problematic because many of my files didn’t have Album Artist populated. I solved this by writing a PowerShell script to copy the Perfomers tag data (Performers = Artist) to the Album Artist tag. I’ll share that in another post.

But then I discovered a different problem. If an album is a compilation or has variance in the artists from file to file (for example: This Guy feat. That Other Guy), it’d index files into separate albums of the same title. Navidrome’s developers confirmed that this is a feature, not a bug, and it makes sense. The solution for compilation albums is to set the Compilation tag to 1, which I haven’t automated yet but will shortly. The solution for non-comp albums is to make sure the Album Artists tag is consistent.

To accomplish this, I threw together the below script. It’s not optimized, it doesn’t have error handling or confirmation, and it’s apt to be destructive if you’re not careful. Still, it’s something you can build on, just as I inevitably will. As with all my music file related scripts, it requires taglib-sharp.dll. Obtain this file from TagLibSharp. You don’t have to futz with nuget or anything – just download the zipped package, yank the dll out of it, and put it in a subdir you’ll reference in the script.

This script will prompt for the full path to the files you wish to update, and then the name you wish to update the Album Artist tag to.

Powershell – Monitoring a log file

I had a situation at work where I needed to monitor a log file for a particular entry. I needed to be notified when that entry appeared. This log file gets created anew, with the current date, every day. Here’s what I came up with:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
while($true)
{
# get the date
$now = get-date
# create the log name from said date eg :20231223Err.txt
$fileName = '{0}{1}{2}Err.txt' -f $now.Year, $now.Month, $now.Day
# network path to said log
$fullPath = "\\path\e$\LogFiles\app\$($fileName)"

#I don't need this to run in perpetuity - it's a temp situation - so I'm just
#invoking this in a Powershell window and letting it rip.
Write-Host "[$(Get-Date)] Starting job for file $fullPath"
$latest = Start-Job -Arg $fullPath -ScriptBlock {
param($file)

# wait until the file exists, just in case
while(-not (Test-Path $file)){ sleep -sec 10 }
# matching the phrase Queue Count. could make all these variables
Get-Content $file -wait | where {$_ -match 'Queue Count'} |
foreach {
Send-MailMessage -SmtpServer SMTPSERVER -From me@email.com -To me@email.com -Subject 'Queue Count' -Body $_
write-host $_
}
}

# wait until date change
while($now.Date -eq (Get-Date).Date){ sleep -Sec 10 }

# kill the job and start anew
Write-Host "[$(Get-Date)] Stopping job for file $fullPath"
$latest | Stop-Job
}

The Magic of Logparser

I had a slew of IIS FTP logs to dig through for a work project. I needed unique visitor details, and I needed it from a month of logs. Some of these daily logs were in excess of 40mb. I threw together a PowerShell script to do just so, kicked it off, and waited. And waited. I reconfigured the script to be more efficient in its processing, kicked it off again, and waited. And waited. And researched, because this was taking far too long. And – late to the game, I know – I found Microsoft’s Logparser. Logparser is a free tool, and it’s filled with magic. With one simple query it managed to pull the raw data I needed from the log files in *seconds*.

1
2
3
4
5
#log files in c:\temp\iis, results to same path

logparser "SELECT DISTINCT c-ip, cs-username INTO C:\temp\iis\results.txt FROM 'C:\temp\iis\*.log'" -i:W3C -o:W3C

#

In less than a minute I had a text file of unique visits gleaned from 550 MB worth of plaintext log files. From there I could use PowerShell to filter out any IP dupes (some connections do not have user details, thus producing some leftover duplication) and resolve hostnames from IP addresses to create a final masterlist. I’m not sure how Logparser does what it does so quickly.

VisualCron – Powershell Network Path Truncation

I set up a VisualCron job to kick off a Powershell script to reach out to certain directories – built dynamically from an array – to check for content. The script ran perfectly when invoked manually, but through VisualCron it would error out with a truncated path:

The above path should have been \\atldireng03\e$\download\. I just could not get the path to resolve. The script that builds the path looks similar to this:

Ultimately the issue was one of rights. The account VisualCron was utilizing to invoke the script did not have rights to the administrative share path being built by the script. Change the account to an administrator on the remote server and the script ran like a charm. Now, that it would error out with this weird truncated path problem rather than something referring to a lack of sufficient rights is frustrating. I suppose it’s because it could not ‘see’ the path (hence “it does not exist”), but were you to manually attempt to map to a path you hadn’t rights to pretty much all OSes would return you some kind of informative error about insufficient rights. Not here. And for the record, I haven’t tried running the script manually through a Powershell prompt without rights to the paths to see what happens. It’s entirely probable this uninformative error is on Powershell’s side and not VisualCron.

Powershell and MP3’s

I’ve been trying in vain to organize my substantial MP3 collection.  I know that in the age of streaming MP3’s are passe, but I just can’t quit ’em.  I listen to a lot of music that isn’t readily available for streaming.

One of the things I’m nitpicky about is Genre tagging.  I like that stuff to be correct.  Thing is, sometimes I get lazy.  So, I dug in to see if I could hack out a quick script to scan subdirectories in my collection and root out MP3’s with incorrect or missing Genre tags. This is a very raw little script with zero error handling.  It examines the first file in every subdir, and writes to an output file every directory where that first file’s genre tag doesn’t match what it should.  It requires taglib-sharp.dll.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# uses taglib-sharp.dll
[Reflection.Assembly]::LoadFrom("E:\taglib-sharp.dll")

$outfile = "outfile.csv"
$basedir = "I:\SORTED\Classic Rock"
$subdirs = Get-ChildItem $basedir -attributes D

foreach ($subdir in $subdirs) {
$file = Get-ChildItem $subdir.fullname -Filter *.mp3 | Select-Object -First 1
$ff=$file.fullname
$f = [TagLib.File]::Create("$ff")
$genre = $f.Tag.Genres
$outt = "$subdir `t $genre"
$outt
if ($outt -NotMatch 'Classic Rock') {
$outt | out-file $outfile -append
}
$f = ""
}

SQL Powershell tools

I’m not sure why MS makes it so convoluted to install these tools on a server that isn’t running SQL.  Regardless, head here:

https://www.microsoft.com/en-us/download/details.aspx?id=29065

And don’t click download.  All that gets you is a text file.  Instead, head down the page and expand Install Instructions.  From there, search for and download the following modules:

  • Microsoft® System CLR Types for Microsoft® SQL Server® 2012 (SQLSysClrTypes.msi)
  • Microsoft® SQL Server® 2012 Shared Management Objects (SharedManagementObjects.msi)
  • Microsoft® Windows PowerShell Extensions for Microsoft® SQL Server® 2012 (PowerShellTools.msi)

If you get a 2503 or 2502 error while trying to install, as I did, you may not have sufficient rights.  Try either killing explorer.exe and restarting it with admin privs or invoking the msi from within an elevated command prompt.

Then just install modules a la:

Import-Module sqlps -DisableNameChecking

Detect unresponsive applications using Powershell

Change the variables, save as a ps1 and schedule this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$to  = "user@email.com", "user2@email.com"
$from  = "user@email.com"
$smtp = "address of SMTP server"
$engine = $env:computername
$log = "C:\pathto\log.txt"
$now=Get-Date -format "dd-MMM-yyyy HH:mm"

$Processes = Get-Process -EA Stop          
$nProcesses = @($Processes | ? { $_.Responding -eq $false })
if($nProcesses) {          
  foreach($nProcess in $nProcesses) {          
   $nProcess | select Name, id, MainWindowTitle, Responding  
                Write-Host "Non-Responsive Processes found!"
                $msg = "Non responsive processes found on $engine! -- $nProcess"
                $body = "Non responsive processes found on $engine!    

                $nProcess"

                Add-content $log -value $now
                Add-content $log -value $msg
                Send-Mailmessage -From $from -To $to -Subject $msg -Body $body -Priority High -dno onSuccess, onFailure -SmtpServer $smtp
 }          
 }

Active Directory Account Lockout – Creation – Deletion – Disable monitoring

We’ve used a variety of third party tools to monitor Active Directory domain account changes.  They’ve all either been expensive or kind of sucked (or, unfortunately, both).  But if you’re running a relatively new OS on your controller you can use the magick of Powershell to ship you alerts on account changes!  Powershell can monitor the local Security Event Log on your controller and ship you an email when events matching your description are entered.  Here’s an example Powershell script:

Continue reading

List of Roles and Features – Windows 2012

Need a quick list of currently installed roles and features on your Windows 2012 server?  Open a PowerShell prompt and put in the following:

1
Get-WindowsFeature -ComputerName COMPUTERNAME | Where-Object InstallState -eq Installed > installed.txt

It’ll give you a list similar to this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
Display Name                                            Name                       Install State
------------                                            ----                       -------------
[X] File and Storage Services                           FileAndStorage-Services        Installed
    [X] Storage Services                                Storage-Services               Installed
[X] Web Server (IIS)                                    Web-Server                     Installed
    [X] Web Server                                      Web-WebServer                  Installed
        [X] Common HTTP Features                        Web-Common-Http                Installed
            [X] Default Document                        Web-Default-Doc                Installed
            [X] Directory Browsing                      Web-Dir-Browsing               Installed
            [X] HTTP Errors                             Web-Http-Errors                Installed
            [X] Static Content                          Web-Static-Content             Installed
        [X] Health and Diagnostics                      Web-Health                     Installed
            [X] HTTP Logging                            Web-Http-Logging               Installed
        [X] Performance                                 Web-Performance                Installed
            [X] Static Content Compression              Web-Stat-Compression           Installed
        [X] Security                                    Web-Security                   Installed
            [X] Request Filtering                       Web-Filtering                  Installed
        [X] Application Development                     Web-App-Dev                    Installed
            [X] .NET Extensibility 4.5                  Web-Net-Ext45                  Installed
            [X] ASP.NET 4.5                             Web-Asp-Net45                  Installed
            [X] ISAPI Extensions                        Web-ISAPI-Ext                  Installed
            [X] ISAPI Filters                           Web-ISAPI-Filter               Installed
    [X] Management Tools                                Web-Mgmt-Tools                 Installed
        [X] IIS Management Console                      Web-Mgmt-Console               Installed
[X] .NET Framework 3.5 Features                         NET-Framework-Features         Installed
    [X] .NET Framework 3.5 (includes .NET 2.0 and 3.0)  NET-Framework-Core             Installed
[X] .NET Framework 4.5 Features                         NET-Framework-45-Fea...        Installed
    [X] .NET Framework 4.5                              NET-Framework-45-Core          Installed
    [X] ASP.NET 4.5                                     NET-Framework-45-ASPNET        Installed
    [X] WCF Services                                    NET-WCF-Services45             Installed
        [X] HTTP Activation                             NET-WCF-HTTP-Activat...        Installed
        [X] Message Queuing (MSMQ) Activation           NET-WCF-MSMQ-Activat...        Installed
        [X] Named Pipe Activation                       NET-WCF-Pipe-Activat...        Installed
        [X] TCP Activation                              NET-WCF-TCP-Activati...        Installed
        [X] TCP Port Sharing                            NET-WCF-TCP-PortShar...        Installed
[X] Enhanced Storage                                    EnhancedStorage                Installed
[X] Message Queuing                                     MSMQ                           Installed
    [X] Message Queuing Services                        MSMQ-Services                  Installed
        [X] Message Queuing Server                      MSMQ-Server                    Installed
[X] SMB 1.0/CIFS File Sharing Support                   FS-SMB1                        Installed
[X] User Interfaces and Infrastructure                  User-Interfaces-Infra          Installed
    [X] Graphical Management Tools and Infrastructure   Server-Gui-Mgmt-Infra          Installed
    [X] Server Graphical Shell                          Server-Gui-Shell               Installed
[X] Windows PowerShell                                  PowerShellRoot                 Installed
    [X] Windows PowerShell 4.0                          PowerShell                     Installed
    [X] Windows PowerShell 2.0 Engine                   PowerShell-V2                  Installed
    [X] Windows PowerShell ISE                          PowerShell-ISE                 Installed
[X] Windows Process Activation Service                  WAS                            Installed
    [X] Process Model                                   WAS-Process-Model              Installed
    [X] Configuration APIs                              WAS-Config-APIs                Installed
[X] WoW64 Support                                       WoW64-Support                  Installed

To view in the prompt rather than dumping to a txt, remove the

1
> installed.txt