Entrepreneur vs. Engineer: A Founder’s Dilemma

 

Us IT folk are a unique breed or so I’m told. We’re logical, black and white thinkers that require strict rules and are prone to outbursts around tabs vs. spaces at any moment.

We love either Windows or Linux but not both, have a major case of imposter syndrome and are socially inept. At least that’s the stereotype. It turns out a lot of this is true of myself.

A lot of engineers are completely happy going to work, solving interesting problems, working with good people and toiling on interesting open-source side projects in their free time. This used to be me and life was a lot simpler.

The Hidden Entrepreneur Inside

You see, I’m just like your typical IT engineer but with one key difference. For whatever reason, I have this insatiable desire to blaze my own path and to build something on my own that benefits other people like me. It’s a blessing and a curse.

I have a deep-rooted entrepreneur inside of my brain that refuses to give into the simpler ways of living as just an engineer. Lucky for people that enjoy free, IT screencasts, the entrepreneur is what brought you this fine TechSnips platform.

For those that either silence their entrepreneur brain or for those completely happy working as an engineer may not completely understand this phenomenon. Let me explain.

Imagine constantly thinking you should be doing something else while working on a task you enjoy more at the time. Consider when you leave the volume at 19 on your TV, see a red M&M in a bowl of green ones or get interrupted when you’re just about finished with an awesome TV show. It’s kinda like that.

Entrepreneur vs. Engineer

I, as an engineer, love solving real, tactical problems. I enjoy spending time seeing the fruits of my labor immediately in the form of a passing test, working code or automation workflow doing its thing. The reward is immediate, same-day and doesn’t require strategizing about content, researching future clients or trying to get the word out about TechSnips.

I, as an entrepreneur, am not supposed to focus on the tactical logistics of building the product. I shouldn’t be spending time neck-deep in code in favor of focusing on the TechSnips marketing strategy, SEO or ensuring that next big opportunity doesn’t pass us by!

My inner entrepreneur and engineer constantly battle. On one hand, I love working for myself, building a business, helping others and fulfilling this vision I’ve had for a long time with TechSnips but on the other hand, I sometimes just want to push the world aside and work on a cool PowerShell script!

Learning Balance

Since TechSnips is only a few months old, I’ve still got some time to find my groove. I’m still allowed to have those weeks where I don’t do the “right” thing focusing on strategic vision, marketing and managerial work in favor of the fun stuff like coding.

I’ve still got time but it’s time to start figuring out what I’m good at, not good at and finding more people to help me in this endeavor.

From what I can tell, as a founder running a successful business is about choosing your battles. You need customers to survive, a motivated team behind you, a great product and a vision for the future. I’m getting there. You also need to know when and when not to spend time on frivolous activities in favor of the greater good.

TechSnips continues to grow month after month and I’m excited about the future. I’m looking forward to growing as an entrepreneur and business owner and learning how to adapt my engineer tendendencies to business development!

 

 

How Did I Arrive at TechSnips?

Photo by Danka & Peter on Unsplash

Where I Came From

It’s been about 4 years since I decided that I was no longer content to simply use the Internet as a source of information. I knew at that time that I wanted to give back to the online IT community that had helped my career along for so many years. It seemed that the easiest way to begin was to start a blog. Since I already had one created, one that had been all but abandoned, I thought this was a good place to start.

So, in May 2014 I started blogging. I started off by writing once a week about what I had learned during my MSCE studies, as it gave me a good, constant source of ideas. A few months later, I decided to launch a second blog that would focus primarily on Windows Server and PowerShell tips & tricks, guides, lab setups, and walk-throughs. This is where I ran into a bit of a wall.

I was struggling to find ideas that I thought would be interesting to others. The “Imposter Syndrome” was in full force. I just didn’t think I had anything worth sharing, certainly nothing that hadn’t already been done before. That is where I finally stalled out and all but quit writing.

Over the next few years, my writings continued but were quite sporadic as I was still struggling to come up with ideas. It wasn’t until I read an article by Don Jones titled Become the Master, or Go Away that I realized just how much this imposter syndrome was holding me back.

It didn’t immediately break me out of my shell, but it did help me renew my interest in writing. I even thought about creating videos to go along with the blog posts. I still had the same problem though, no idea about what to write about.

How I Got Here

I have always found it interesting how timing plays such an important role in life, and this is one of those times. I had just finished reading “Be the Master” by Don Jones, and found myself resolved to start doing something right away. A few days later I read a guest post written by Adam Bertram on the blog hosted by Mike F. Robbins. The article, TechSnips is Looking for Content and Recruiting Contributors was a good read, and I felt that it was something I should seriously look at.

By the time I got to this part of the article: “You will learn presentation skills through feedback from myself and your peers…” I had already decided that this was something I was going to do. No doubt about it. A chance to record how-to videos sounded like a great idea. Then I read the words “and you will get paid”. This was the icing on the cake!

So, I clicked on the sign-up link, provided the required information, and submitted an audition video. Waiting to see if I would be accepted as a contributor was the longest 14 hours ever. I finally received the e-mail I had hoped for! I was accepted as a contributor to TechSnips, and I was even provided with feedback on this video so that I could improve the next video I recorded.

My Experience So Far

I didn’t know it at the time, but one of the first things I would learn about TechSnips is that everything moves quickly. It can be quite a refreshing change of pace if you’re used to things moving at a slower cadence. I have found that pace to be very motivating and quite exciting, and I love the fact that changes to TechSnips are made quickly and frequently as the business evolves. Keeping up with the changes was a challenge at first, but I quickly adjusted.

One of those changes that were made during my first few weeks was the introduction of contributor blog posts. The thing I enjoyed most about that change was the fact that Adam went from ‘No, I don’t think we are going to do blog posts’ to ‘yes we are, and here’s how we are going to do it’ inside of a single sentence. So, as you can see, changes are made rapidly.

The second lesson I learned was that there is always feedback being provided, and at every stage of the production process. For me, this advice is invaluable, as I am quite new to producing videos. The great thing about the advice is that it doesn’t just come from Adam but from everyone. If you have a question, whether it be about submitting a video, or setting up a recording environment on a budget, a quick post to the Slack channel will usually elicit a rapid response with helpful and valuable advice.

Having access to this group of professionals has been a wonderful learning experience, as everyone brings their own skills and unique point of view to the team.

TechSnips also successfully addressed the issue I was having with generating ideas. There is always a constant supply of ideas, both from the other contributors, subscribers and sometimes from Adam himself. Once I took a look through those lists of ideas, I realized just how much I had to offer the community. Imposter syndrome….deleted! Well, not entirely, but it isn’t as ever-present as it used to be.

The production quality at TechSnips impressed me right from day one. Every time I submit a video or a blog post, I think to myself “Yeah, that looks pretty good.” Then the editors get a hold of it and give it this incredibly polished look. I will confess to being happily surprised at how good that first video looked after the editing was complete. Now, I find myself anxiously awaiting the final product every time I submit a new video. I just can’t wait to see how good they look.

I am having an absolutely fantastic time with TechSnips! I haven’t had this much fun or felt this excited to work on a new project in a very long time. The sense of teamwork, constant advice, support, and being able to see my content published alongside the that of so many other professionals has been quite rewarding. I cannot think of anywhere better to spread my wings and learn some new skills. I have found everything I need here; Training, guidance, teamwork, ideas, and enough work and excitement to keep me coming back for more.

I would highly recommend to anyone who is thinking about publishing content to give TechSnips a try. There is nothing to lose from the attempt, and so very much to gain.

Making all Objects in an AWS S3 Bucket Always Public

At TechSnips, we use Amazon S3 to store all of the stuff required to operate. One ability we need is to provide a publicly accessible repository of files. Luckily, S3 has this ability to set objects to public read-access.

To set an object to public read-access, you can click on Make Public via right-clicking on the object inside of the S3 Management Console.

S3 Make Public

This is all well and good but if you’ve got tons of files constantly being uploaded to S3, I’m not about to manually make all of my objects public like this!

After a bit of digging, I was able to figure out how to make all objects be public the moment they are added to a particular bucket. To do this requires creating a bucket policy. This bucket policy applies to all GetObject actions. You can see the bucket policy I used below for our techsnips-public S3 bucket.

This bucket policy can be assigned to the bucket via the Management Console

Once you have the bucket policy set, you’ll then need to also assign Public Access to the Everyone group as well via the Access Control List.

How to Manage DNS Records with PowerShell

Most of the time, DNS records are managed dynamically by your DNS server. However, at times you may find that you need to manually create, edit, or remove various types of DNS records. It is at times like this that PowerShell is quite useful for managing these records.

Viewing DNS Records

You can view all of the resource records for a given DNS zone by simply using the Get-DnsServerResourceRecord cmdlet and specifying the zone name parameter:

As you can see, this generates quite a lengthy list of records. This nicely highlights one of the advantages of this particular cmdlet over the graphical DNS console. This view gives you all of the records for this zone, regardless of which folder they are in. In the graphical console, it would take quite some time to piece this information together.

Now, let’s thin out this list a bit. Using the same cmdlet, but adding the RRType parameter to search for A records (IPv4 hosts) and filtering for records where the Time To Live (TTL) is greater than 15 minutes gives us a bit more of a manageable list:

Taking this one step further, we can also search for records in a different DNS zone, on a different DNS server. In this example, we will search for A records in the “canada.corp.ad” zone on DNS server DC03:

Adding and Removing Host Records (A and AAAA)

To add a host record, we will need to use the Add-DnsServerResourceRecordA cmdlet. In this example, we need to add a host record for a new printer that we are adding to the network. It will be added to the corp.ad zone with the name “reddeerprint01”, and it’s IP address is 192.168.2.56.

If it turns out that we need to remove a record, for example, if the printer has been decommissioned, we can use the following code to remove the host record that we just created:

It is also just as easy to add an IPv6 host record. Of course, these records differ slightly, as they are listed as AAAA records. You may notice that we are now using the Add-DnsServerResourceRecordAAAA cmdlet. It’s a subtle change, but an important one. Let’s add a record to the “corp.ad” zone for the new IT Intranet server at “fc00:0128” and then quickly verify that it has been created:

Adding Reverse Lookup Records (PTR)

A reverse lookup record allows the client to query a DNS server to request the hostname for a supplied IP address. Creating a PTR record is a relatively easy process, but there is one important bit of information you will need to know before you start adding PTR records. Reverse lookup zones are not created by default. You will need to set up your reverse lookup zone prior to adding records.

Fortunately, it is relatively easy to do. You just need to use the Add-DnsServerPrimaryZone cmdlet and provide it with the Network ID. In this example, I have also chosen to set the replication scope to the entire AD forest, and I have specifically targeted “DC03” as the preferred DNS server:

Now that our reverse lookup zone is in place, we can add our PTR record for a new printer called “CYQF-Printer-01.canada.corp.ad” that has an IP address of 192.168.2.56. As this record is for the “canada.corp.ad” zone, we will be targeting the DNS server “DC03”.

When using the Add-DnsServerResourceRecordPtr cmdlet, it is important to note a couple of things. First, that you need to specify the zone name using the network ID in reverse order, then add “.in-addr.arpa”. So for our “192.168.2.0/24” network ID, the zone name is “2.168.192.in-addr.arpa”. Second, the “Name” parameter is simply the host portion of the IP address. For our printer at 192.168.2.56, the “Name” is simply “56”.

Once you have those pieces of information, the code required to create the PTR record is relatively simple, if a bit long:

Adding Alias Records (CNAME)

To finish off, we will create a host alias record or CNAME record using the Add-DnsServerResourceRecordCName cmdlet. These records allow you to specify an alias for an existing host record in the zone. This becomes especially useful, for example, if you want to provide your finance users with an address for their web-enabled finance app. You could create an alias called “finance”, and point it to the web server “webapp25.corp.ad”. Then when you need to migrate the app to a new web server with a new hostname, you simply change the CMANE record to point “finance” to the new host. This way, the users don’t have to update their bookmarks. They can continue to access their application using the address “finance.corp.ad”.

Additional Resources

Companion video: “How To Manage DNS Records With PowerShell

Using PowerShell’s Test-Connection and Test-NetConnection Cmdlets

ThePowerShell Test-Connection and Test-NetConnection cmdlet are the new way of pinging remote computers but we’ve still got good ol’ ping.exe.

Pinging a device is a basic skill of any ‘IT Pro’, and we all know the Ping.exe command but have you heard of the ? It’s PowerShell’s way of reinventing the old-school ping.exe command.

Pinging a computer is really easy to do in PowerShell but there are a set of options that really make it useful, and take it way beyond what ping can do.

We could just use Invoke-Expression to call the ping.exe but this is just putting lipstick on a pig.

ping.exe

Yeah, this works, and we’ll get the normal ping results back of course, but it’s a bit clunky and all we get is the text output from the ping command, so let’s use the native PowerShell cmdletTest-Connection instead.

PowerShell Test-Connection

That’s a much more native way of doing it in PowerShell, and it returns an object rather than just the text output of ping.exe.  So, if we pipe the object coming from the PowerShell Test-Connection cmdlet into Select * we get a mass of useful information.

PowerShell Test-NetConnection

Like any good PowerShell cmdlet we have switches so we can set things like Count for the number of attempts, BufferSize for the size of the packet and Delay to define the delay between each attempt.

There are a lot of other switches of course, and I’m not going to go through them all but there are some that are really useful like Source.  This makes it possible to use the PowerShell Test-Connection cmdlet to connect to other machines on your network and initiate connection attempts from there.

Using Source Test-NetConnection

The output shows all the results from the hosts in the source list, in one nice neat table (object).  This is especially useful if you have a complicated network with lots of firewalls between you and the target.  As long as you can get to those source machines then you can test any of the connections from there.

The Quiet switch goes the other way and gives a really simple true/false result.  This is super useful when using it in If statements.

PowerShell Test-Connection Quiet

If you have a lot of targets to test then the AsJob parameter might be useful for putting the list to a background job and getting the results using Get-Job | Receive-Job.

PowerShell Test-Connection AsJob

Test-NetConnection

Another cmdlet to look at is Test-NetConnection.  The Test-NetConnection cmdlet can test the connection to a device much like the PowerShell Test-Connection cmdlet but it’s a little more networking focused.  In the simplest sense, it gives much the same results.

Again this cmdlet has a load of really useful parameters like Port to test whether a remote port is open or not.

With the TraceRoute parameter we can do the same as we would with Tracert.exe, but the output is a PowerShell object with each of the hops on the route to the target.

Again, if we want to use PowerShell cmdletTest-NetConnection in an If statement to test if a device has port 80 open we can use the -InformationLevel Quiet parameter and value to give us a simple true/false result from the test.

Whether you choose to use the PowerShell Test-Connection cmdlet or Test-NetConnection cmdlet, we’ve got you covered!

How to Copy Files Using BITS and PowerShell

BITS PowerShel

Using BITS with PowerShell is a great way to copy files because you get the best of both worlds. BITS doesn’t care if the network connection drops or if the machine restarts, it will just wait patiently until it can connect again and start from where it left off. So you can leave the job to do it’s thing and know that the file will get there in the end. This is especially useful if you have to regularly upload logs from a client/laptop because the job will just keep going until the file is transferred.

By leveraging BITS with PowerShell, you’re able to seamlessly integrate BITS transfers within your PowerShell scripts which makes for a pretty powerful combination!

Creating a BITS job with PowerShell

To create a BITS job with PowerShell you just need to use the Start-BITSTransfer cmdlet and give it the source and destination. This will create the job and start copying the file right away.

The -Asynchronous switch makes it run in the background so you don’t need to watch the progress bar. You can leave this off if you want to watch it run, but it’s perfect for when you are scheduling a copy job etc.

If you are copying lots of files it’s worth thinking about the -DisplayName switch so that you can spot the job in the list.

Finding BITS jobs with PowerShell

To find BITS jobs, just use the Get-BitsTransfer PowerShell cmdlet. Notice the DisplayName of the job is there because we specified it with the switch.

And if we pipe this into Select * it gives you all the attributes for the job.

Notice this shows the status of the BITS job and the BytesTotal/BytesTransferred. In this case, the BITS job has finished, but the job still exists in the list. This means that we can still see all the details of the jobs and we can even add more files to it and it will start transferring those as well. We do this by piping the job into the Add-BitsFile PowerShell cmdlet, and specifying the files we want to add.

Pausing and restarting a BITS job with PowerShell

If we need to pause the job halfway through and start it up later we can use the Suspend-BitsTransfer and Resume-BitsTransfer cmdlets.

Removing BITS jobs with PowerShell

If we want to close down the jobs once they are done with, we can use the Complete-BitsTransfer cmdlet and they will disappear from the list once they are complete. Either pipe the job to it or the list of jobs.

If you are often uploading large log files or client logs, using PowerShell and BITS can be a great way to do this!

How to Create/Restore an Azure Virtual Machine Snapshot with PowerShell

Azure Virtual Machine Snapshot

I’ve learned that creating an Azure virtual machine snapshot isn’t quite as easy as creating checkpoints in my on-prem Hyper-V lab. Frustrated that I had to build my own tool for this, I set out to do it anyway.

As you may have found out already creating an Azure virtual machine snapshot isn’t quite as right-click and click as you’d expect. Sure, Azure has Azure Backup now but it seems overkill for the constant snapshots and reverts I’d like to do in my development environment. Instead, Azure has a Snapshots feature that appears to have been neglected by Microsoft. There’s little to no documentation on creating and restoring Azure virtual machine snapshots.

So I dug in and automated it!

I wanted two PowerShell functions so I can easily create and restore snapshots from OS disk attached to Azure virtual machines called New-AzureRmVmSnapshot and Restore-AzureRmVmSnapshot so I got to work.

Creating Azure Snapshots

First, I need to figure out how to create an Azure virtual machine snapshot in the first place. To do that, I first needed to shut down the VM that I wanted to create a snapshot for.

Stopping the Azure VM

Creating the snapshot

Once the VM was stopped, I then learned how I could create a snapshot using the New-AzureRmSnapshot cmdlet but it, unfortunately, wasn’t that easy. To gather up all of the information I needed required first finding the OS disk that was attached to the VM, creating a config and then I could create the snapshot.

Create a Disk from the Snapshot

Once the snapshot was created, you actually have to create a new Azure disk from the snapshot which requires creating another disk config and creating the disk with the New-AzureRmDisk cmdlet.

Yay! We have created our first Azure virtual machine snapshot!

Restoring an Azure virtual machine Snapshot

Now let’s say you’ve been messing around in the VM and want to restore the snapshot. This is the step that was a challenge because I could find no great step-by-step tutorial to do this. I eventually found out how to detach the old Azure OS disk from the VM and attach the new one.

Detach the Old OS Disk and Reattach new one

At this point, the snapshot should be restored but you’ve still got that old OS disk hanging around. Go ahead and clean that up.

Delete the Old OS Disk

Does all of this sound like a major pain? It did me too! Luckily, my pain is your gain! Here are two functions to take a snapshot of an OS disk attached to a VM and one to restore it. They are nothing fancy and could be improved greatly

Functions

 

Using Set-DnsServerForwarder and Others to Manage DNS Forwarders

Using Set-DnsServerForwarder

Windows DNS Forwarders and Conditional Forwarders are an important part of your DNS infrastructure. You will find that on occasion you need to add or manage these forwarder addresses and that some of these changes need to be made across multiple DNS servers in your enterprise. Thankfully, using commands like PowerShell’s Set-DnsServerForwarder cmdlet and others allow you to easily manage both of these DNS services with ease.

Using Set-DnsServerForwarder to Replace Forwarders

DNS Forwarders are used by the DNS server to lookup queries for addresses that aren’t contained in any zones that the server is authoritative for. This provides your DNS servers with an efficient means for resolving names. Without the forwarders in place, your DNS server would have to query the root hint servers in order to start resolving unknown addresses. While these forwarder addresses are configured separately on each DNS server, using PowerShell makes managing them a lot easier by allowing us to use the Set-DnsServerForward command among others.

So, let’s begin by viewing the currently configured forwarders for the local DNS server by using the Get-DnsServerForwarder cmdlet. We’ll use the Set-DnsServerForwarder in a minute to add one.

As seen below, there are two forwarders configured, as listed beside “IPAddress”

Using Get-DnsServerForwader

Next, we want to add an additional forwarder, possibly a new DNS server that we have configured in our DMZ, or perhaps using a forwarding address provided by our ISP. In this case, we’ll use the Set-DnsServerForwarder cmdlet to set the new address and then use Get-DnsServerForwarder to confirm that the address was set correctly.

The results of using Set-DnsServerForwarder

Unfortunately, this did not have the desired outcome. As you can see here, using the Set-DnsServerForwarder cmdlet actually replaces the list of forwarders rather than adding to it. In order to add the address to the list, rather than replacing the entire list, you need to use Add-DnsServerForwarder. To correct this, what we’ll do is replace the list with the original two forwarders, add the new address, then check to see if we are successful.

Get-DnsServerForwarder

There, that looks much better. We now have all three forwarders added.

Now, if you want to remove a forwarder address, you would simply use the Remove-DnsServerForwarder cmdlet as shown, then check to see if the address has been removed. If Set-DnsServerForwarder replaces the DNS forwarder, Remove-DnsServerForwarder removes it completely.

The results of Remove-DnsServerForwarder

Sometimes, you will need to be able to add or remove a forwarder address on multiple DNS servers. In this instance, Set-DnsServerForwarder will not work. Thankfully PowerShell makes scaling this task to multiple DNS servers relatively easy. If we use Invoke-Command, include a list of all of our DNS servers, then put Add-DnsServerForwarder into the ScriptBlock, we can modify all of the DNS servers with a single command. Then using a similar command, view the results of our changes.

Running Get-DnsServerForwarder on multiple servers

That brings us to the end of the section on DNS Forwarders.

Conditional Forwarders

A special type of forwarder, called a conditional forwarder, cannot be modified with theSet-DnsServerForwarder cmdlet but can be used when you have been provided with the IP address(es) of the DNS server(s) for a known DNS domain name. Conditional forwarders are used by the DNS server before using the server forwarders listed earlier in this article. For example, if you have a conditional forwarder configured for tailspintoys.com, your DNS server will, after checking that it isn’t a domain it is authoritative for,  check the conditional forwarders and find that an entry exists. At this point, your DNS server queries the DNS server listed for the desired address in the tailspintoys.com domain.

One nice feature of conditional forwarders is that they can be replicated to other DNS servers in the same way that any Active Directory Integrated DNS Zone can be.

Let’s start by checking to see if we have a conditional forwarder configured by using the Get-DnsServerZones cmdlet.

Get-DnsServerZone PowerShell

Conditional forwarders show up in this list as ZoneType: Forwarder. In this case, we don’t seem to have one configured. So, we will use Add-DnsServerConditionalForwarderZone to create the conditional forwarder, set it to replicate to the entire Active Directory forest, and then confirm it has been created.

The results of Add-DnsServerConditionalForwarderZone

The output shows that we have our conditional forwarder configured, and it is ready to go. PowerShell really does make managing DNS forwarders a snap.

Additional Resources

Companion video: “How To Manage DNS Forwarders With PowerShell

OpenSSH on Windows: How to Get it Set Up

The future is now. SSH isn’t just for Linux anymore. With the latest Win32 port of OpenSSH, we can now run OpenSSH on Windows with little effort. This post is a text form of my TechSnips video. If you’d rather watch a video walkthrough, I highly encourage you to check that out.

The code I will be using in this demo is available on GitHub in the TechSnips SnipScripts repository.

Installing OpenSSH on Windows

First, make sure to download the latest release of Win32-OpenSSH. Now that that is downloaded, let’s get started with the demo.

I’m going to set some variables for the location of the OpenSSH on Windows zip file and the location where I want to install the OpenSSH files. I’m going to use c:\Program Files\OpenSSH.

Next, we need to extract the OpenSSH-Win64.zip file to the install path.

Once that is complete, we are ready to install OpenSSH on Windows. To do so, we need to run the install-sshd.ps1 script from the install directory.

Run the OpenSSH on Windows install script

This script will create 2 SSH services which we will use in a minute (ssh-agent and sshd)

Configuring OpenSSH on Windows

But first, let’s go ahead and add an exception to the Windows Firewall for port 22 so that SSH traffic will be allowed through.

Now we need to configure the OpenSSH on Windows services. As you can see when we run Get-Service, The services are currently stopped.

View the OpenSSH on Windows services that were installed

So, let’s set the StartupType of both services to Automatic then start the services.

Running the netstat command we can see that the machine is now listening on Port 22.

Netstat shows that OpenSSH on Windows is listening on port 22

Connecting to Our OpenSSH on Windows Server

Next, I’m going to open up my SSH client, PuTTY and connect to the SSH service running on my localhost.

PuTTY connection to local Windows host over SSH

Accept host key message

SSH connection to Windows with OpenSSH

When prompted to accept the host key, choose Yes. This will open an OpenSSH on Windows session in a Command Prompt. If you would like to have SSH sessions open up in a PowerShell prompt, you will need to add an entry in the registry to define the Defaultshell and specify the location of the PowerShell executable.

Now that we have defined the default shell, when we open a new SSH session, you will notice that the Prompt has changed to a “PS” prompt.

PowerShell running through SSH connection with syntax highlighting and tab completion

You will also notice that tab completion and syntax highlighting both work over SSH as well.

Once you’ve set up OpenSSH on Windows and you’re using PowerShell, I encourage you to check out my other post on How to Configure OpenSSH on Windows for PowerShell Remoting Over SSH.

How to Managed Distributed File System (DFS) Links with PowerShell

Distributed File System (DFS) Links reduce the complexity of working with network file shares. DFS Links allow users and applications to access a “virtual path name” to connect to shared folders. We can create DFS links with PowerShell.

This “virtual namespace” enables administrators to present shared folders located on different servers, or even change a shared folder’s location, completely transparent to that folder’s consumers.

Users will not need to update bookmarks, and applications will not be required to be updated with new paths when File Servers change.

Benefit to Users

For the users, access to network share folders is simplified down to a “namespace\FolderName” format, a reduction in the complexity associated with folders stored on remote servers.

Benefit to Applications

For applications, hard-coded paths to resources on the network do not have to be changed due to a change in the network path. A simple update to the DFS Link and the application will continue to access the resources at their new location.

Prerequisites for the DFS Server Role

  • Active Directory
  • File and Storage Services role installed on a Windows Server:
  • Windows Server (Semi-Annual Channel)
  • Windows Server 2016
  • Windows Server 2012 R2
  • Windows Server 2012
  • Windows Server 2008 R2 Datacenter/Enterprise

Prerequisites for PowerShell cmdlets:

  • An administrator account with the proper permissions
  • RSAT Tools with the ‘File Services Tools – DFS Management Tools’ installed

Enabling DFS Tools with PowerShell

Download and install RSAT
Next, you need to Enable the Distributed File System Tools
* Open PowerShell as an Administrator
* Run the Install-WindowsFeature command:

How to Set Up DFS with PowerShell

We first need to install all of the necessary Windows features. This will install DFS Management GUI, the DFS Namespaces module for Windows PowerShell to create DFS links with PowerShell and manage them, and command-line tools, but it does not install any DFS services on the server.

Administration of DFS Links

You can administer namespaces by using DFS Management GUI, the DFS Namespace (DFSN) Cmdlets in Windows PowerShell, the DfsUtil commands, or scripts that call WMI.

Common PowerShell commands

Get-DfsnRoot – Discover all DFS Namespaces in the current domain
– Commonly used to check for available namespaces in the current domain

New-DfsnFolder – Create a new DFS Folder Name
– Commonly used to create a new DFS Folder in a NameSpace

New-DfsnFolderTarget – Assign path(s) to a DFS Folder Name
– Commonly used to assign one or more network folder paths to a DFS Folder

Remove-DfsnFolderTarget – Removes a path from a DFS Folder but does not remove the DFS Folder.
– Commonly used to remove one or more network folder paths from a DFS Folder

Remove-DfsnFolder – Removes a folder and all its paths
– Commonly used to remove a DFS Folder from a NameSpace

Finding DFS namespaces with PowerShell

We’ll start out by getting an idea of all the online and available NameSpaces in the current Domain using the cmdlet Get-DfsnRoot.

This shows that there are two NameSpaces that are Online in this domain.

Finding DFS folders with PowerShell

Using the Get-DfsnFolder command we can list the DFS Folders in each NameSpace.

From this output, we can see that in the AppRoot NameSpace this is not a DFS Folder named PowerShell.

Creating DFS Link Folders with PowerShell

In this example, we have a replicated folder named PowerShell on our 3 File Services servers
* FileServer01
* FileServer02
* Datacenter

The goal is to share this replicated folder with our Admins using a single path.

To do this, we’ll create a new DFS Link folder in the AppRoot NameSpace called PowerShell using New-DfsnFolder and point it to the Datacenter server’s FileShare, set the DFS Folder State to Online and set the TargetPath state to Online.

In the DFS Management GUI, we can see that the “PowerShell” DFS Folder does not exist.

Our Folder Target UNC Path

Run PowerShell and check for the DFS FolderTargetPath

\\Tech.io\AppRoot\PowerShell – if it doesnt exist it will write the output ‘Path not found. Clear to proceed’ in green text in the terminal window.

From the output we see that:
* Path has been created
* Referral Priority Class is set to Global-High
* State is Online

The GUI confirms what PowerShell told us.

and our path is now available in Windows Explorer

Creating DFS Folder Targets with PowerShell

Now that we successfully created the “Powershell” DFS Folder in our NameSpace, we’re going to add an additional Folder Target Path to it and set that path as Online using New-DfsnFolderTarget.

Up to this point, we have two of our three Server Paths added, and online. For our last Folder Path, we want to add the path but not make it available to users. So let’s add a Folder Target Path to our “PowerShell” DFS Folder and this time set the DFS Folder Path State to Offline we will again use New-DfsnFolderTarget

FileServer01 and Datacenter’s path is currently Online
FileServer02‘s state has been set to Offline

Setting DFS Folders Targets to Offline or Online with PowerShell

We can change which servers are the Online and Offline hosts, and even which will be our server will be the primary host of the file path using Set-DfsnFolderTarget.

As you can see below in the ScreenCap FileServer01‘s path has changed to Offline
Datacenter server’s ReferralPriorityClass has switched to sitecost-normal from global-high
Also, notice that FileServer02‘s path has changed its state to Online and its ReferralPriorityClass has switched to global-high

Removing DFS folder target paths with PowerShell

I try to vaccinate my code against the Fat Finger Flu as much as possible. Here we will try to install a “Safety Net” before removing one of the FolderTargetPaths by making sure that it is at least Offline before deleting it.

So long path FileServer01

For those who prefer to “cowboy” it up and forego the “safety net” option, we can accommodate you, brave souls, also.

We’ve bid adieu to the path to FileServer02

Removing DFS Folders with PowerShell

It’s has been a long and winding path, but the time for our DFS Link has come to an end. We can Remove the PowerShell folder, DFS Link, using Remove-DfsnFolder.

A quick double-check of the DFS Management GUI shows our DFS Link is no more.

One final note…These commands are only removing the DFS Links, no folders were harmed in the production of this demo.

For More Information about DFS Links

How to manage Distributed File System links with PowerShell

How to manage Distributed File System links with the GUI

Other Helpful TechSnips

Josh King’s Snip on Splatting at TechSnips.io

Matt McElreath’s Snip on Using Visual Studio Code to do Splatting at TechSnips.io

Microsoft – DFS Overview