Archive for Network Administration

Starting a PowerShell window as a Domain Admin

September 26th, 2016 by and tagged , , ,

If you run as a limited user on your own desktop, as you should, it’s useful to keep a separate PowerShell window open as the Domain Administrator. I give that window a nice dark red background so I know instantly that I’m in a powerful window and to be appropriately careful. But how can I actually start a window as a different account, and using Run As Administrator? Ah, so glad you asked.

$AdminCred = Get-Credential -UserName "TreyResearch\domainadmin" `
                            -Message "Enter your password for the DomainAdmin account:" 
Start-Process PowerShell.exe -Credential $AdminCred `
                             -ArgumentList "Start-Process PowerShell.exe -Verb RunAs" `

Save this as “Start-myAdmin.ps1” or equivalent and it’s always available. The nice thing about using Start-Process with the NoNewWindow parameter is that it doesn’t leave a spare window open. Try it. It will make it just that much easier to run as a limited user with no administrative rights, even on your own workstation. And really, when you have the power to be a domain admin, you really, really, really shouldn’t run any other way.

Posted in Active Directory, Annoyances, Network Administration, PowerShell | No Comments »

More $Profile Tricks — Automatically Opening an Admin Window

May 20th, 2016 by and tagged ,

I run as a limited user during my normal work, but I always keep one or more Admin windows open. These are logged in to my Domain Administrator account, running “As Administrator”. And I make sure I can tell that I’m running in that window by setting the colour scheme with a nice, dark red, background. Hard to miss! (I’ll show you how to do that in my next post. ) So, how do I do all that? Well, it starts by automatically opening a PowerShell window when I first log on, as described earlier here.

When that starts, I include code in my $Profile to first check how many PowerShell windows are already running, so I don’t start opening more if I don’t need them.

$PSH = Get-Process PowerShell

Simple, and let’s me get a count with $PSH.count. If this is the first PowerShell window I’ve opened ($PSH.count -lt 2) and this isn’t already an admin window, then I open an admin window. Let’s break this down: First, am I running as an Administrator?

# First, initialize $Admin to false 
$Admin = $False

# Then, find out who we are... 
$id = [System.Security.Principal.WindowsIdentity]::GetCurrent() 
$p = New-Object$id)

# Find out if we're running as admin (IsInRole). 
if ($p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)){ 
   $Admin = $True 

Now, a function to run an elevated window as the domain administrator.

Function Start-myAdmin () { 
# Get admin credentials 
$AdminCred = Get-Credential 
        -UserName TreyResearch\Administrator ` 
        -Message "Enter your password for the Administrator account: " 
# Start an elevated window, but with designated creds. 
Start-Process PowerShell.exe ` 
       -Credential $AdminCred ` 
       -ArgumentList "Start-Process PowerShell.exe -Verb RunAs" ` 


Good. So we’re going to want to start that admin window automatically when we first logon. We do that by checking the count of open PowerShell windows ($PSH.count)

# If this isn't already an Admin window, and we don't have lots of other PowerShell 
# windows open, then we start an Admin PowerShell window. 
if ( ! $Admin  ) {
   cd $home
   if ($Psh.count -lt 2 ) {

Oh, and we’ll want an alias to be able to open up another one whenever we need it.

Set-Alias Admin -Value Start-myAdmin


Posted in Network Administration, PowerShell | Comments Off on More $Profile Tricks — Automatically Opening an Admin Window

Starting Windows PowerShell Automatically

May 15th, 2016 by and tagged ,

Most system administrators routinely start a command line window of some sort when they log onto a computer. For me, obviously, that’s a PowerShell window. Actually, two PowerShell windows – one as a limited user, the other as an administrator, but that trick is for a different blog post. For this one, I’ll show you how to have Windows automatically start a PowerShell windows whenever you long on to your computer.

The key to this is the Run key in the registry. Specifically HKCU:\Software\Microsoft\Windows\CurrentVersion\Run. Programs listed in this key automatically start when the user (HKCU) logs on to the computer. So, all we need to do is insert a new value into the key for PowerShell. Easy enough, with New-ItemProperty. Here’s a function to do that:

Function Set-myPowerShellStart () {
   if (Get-ItemProperty HKCU:\Software\Microsoft\Windows\CurrentVersion\Run `
                        -Name "*PowerShell" 2>$NULL ) {
      write-verbose "Already an entry for starting PowerShell"
   } else {
      New-ItemProperty HKCU:\Software\Microsoft\Windows\CurrentVersion\Run `
                       -Name  "Windows PowerShell" `
                       -Value "C:\Windows\system32\WindowsPowerShell\v1.0\PowerShell.exe"
      write-verbose "Added value for automatic PowerShell start"

Now, all you need to do is call that function, and it will insert a key in the registry, and the next time you log on to the computer, you’ll automatically have a PowerShell window open and ready to go.

Posted in Annoyances, Network Administration, PowerShell | Comments Off on Starting Windows PowerShell Automatically

Promoting a new domain controller

May 14th, 2016 by and tagged , , , ,

I’ve been working with Windows Server 2016 CTP5 recently, and because I installed it without the Desktop Experience (what we used to call a Server Core installation), I’m having to do everything in Windows PowerShell. No complaints, I enjoy it, but it does force me to think about things a bit sometimes.

One of the tasks I needed to do was promote a new server to be a secondary domain controller. The PowerShell command for this is: Install-ADDSDomainController. But before you start promoting a new DC, it’s a really good idea to test that the promotion will succeed by using the Test-ADDSDomainControllerInstallation cmdlet. So, I combined the two steps into a simple script that allows you to run the test, and if the output looks clean, finish the installation and initiate a reboot.

The script is smart enough to realize you haven’t installed the ActiveDirectory feature yet, and goes ahead and installs it for you.

Tests a candidate domain controller, and then promotes it to DC.

Promote-myDC first tests if a domain controller can be successfully promoted, and, 
if the user confirms that the test was successful, completes the promotion and 
restarts the new domain controller. 

Promote-myDC -Domain

Tests if the local server can be promoted to domain controller for the 
domain The user is prompted after the test completes 
and must press the Y key to continue the promotion. 

.Parameter Domain 
The domain to which the server will be promoted to domain controller. 


    Author: Charlie Russel 
 Copyright: 2016 by Charlie Russel 
          : Permission to use is granted but attribution is appreciated 
   Initial: 05/14/2016 (cpr) 

Write-Verbose "Testing if ADDSDeployment module is available" 
If ( ! (Get-Module ADDSDeployment )) { 
   Write-Verbose "Installing the ActiveDirectory Windows Feature, since you seem to have forgotten that." 
   Install-WindowsFeature -Name ActiveDirectory -IncludeManagementTools 
   Write-Host "" 

If ( ! (Get-Module ADDSDeployment )) { 
   throw "Failed to install the ActiveDirectory Windows Feature." 

Write-Verbose "Testing if server $env:computername can be promoted to DC in the $Domain domain" 
Write-Host "" 
Test-ADDSDomainControllerInstallation ` 
      -NoGlobalCatalog:$false ` 
      -CreateDnsDelegation:$false ` 
      -CriticalReplicationOnly:$false ` 
      -DatabasePath "C:\Windows\NTDS" ` 
      -DomainName $Domain ` 
      -LogPath "C:\Windows\NTDS" ` 
      -NoRebootOnCompletion:$false ` 
      -SiteName "Default-First-Site-Name" ` 
      -SysvolPath "C:\Windows\SYSVOL" ` 
      -InstallDns:$true ` 
Write-Host "" 
Write-Host "" 
Write-Host ""

Write-Host -NoNewLine "If the above looks correct, press Y to continue...  " 
$Key = [console]::ReadKey($true) 
$sKey = $key.key

Write-Verbose "The $sKey key was pressed." 
Write-Host "" 
Write-Host "" 
If ( $sKey -eq "Y" ) { 
   Write-Host "The $sKey key was pressed, so proceeding with promotion of $env:computername to domain controller." 
   Write-Host "" 
   sleep 5 
   Install-ADDSDomainController ` 
      -SkipPreChecks ` 
      -NoGlobalCatalog:$false ` 
      -CreateDnsDelegation:$false ` 
      -CriticalReplicationOnly:$false ` 
      -DatabasePath "C:\Windows\NTDS" ` 
      -DomainName $Domain ` 
      -InstallDns:$true ` 
      -LogPath "C:\Windows\NTDS" ` 
      -NoRebootOnCompletion:$false ` 
      -SiteName "Default-First-Site-Name" ` 
      -SysvolPath "C:\Windows\SYSVOL" ` 
} else { 
   Write-Host "The $sKey key was pressed, exiting to allow you to fix the problem." 
   Write-Host "" 
   Write-Host "" 

Posted in Active Directory, Network Administration, PowerShell, Windows Server, Windows Server Core | Comments Off on Promoting a new domain controller

Finally, the death of CMD!

February 2nd, 2015 by and tagged , ,

Well, OK, it’s still there in Windows 10 But finally, completely, I no longer need it for ANYTHING! The final piece that I still used is now available in PowerShell v5. The latest publicly available Preview Build of Windows 10 Technical Preview (build 9926), includes updates to New-Item to support Junctions and Hard Links. Finally!


There’s no direct help available for it yet (I checked and downloaded the very latest), but a little poking around produced:

PS> New-Item -Type HardLink -Path 2ndTest.txt -Value Test.txt

I can edit 2ndTest.txt and the changes appear in Test.txt, and I can delete Test.txt and 2ndTest.txt is still there and editable. Interestingly, I do NOT need to run this as an administrator, assuming I have permissions in the folder where I’m creating the second (or third or 15th file). And, as expected, this can’t cross drive boundaries.


This build also includes support for directory Junctions, (-Type Junction) so between these two, I think we finally have all we need to kiss goodbye all further use of cmd.exe. (I really hate having to use cmd c/ from my PowerShell to get something done. Really. It’s so DOS.)


My thanks to the PowerShell team who took my challenge and mantra of Death To CMD to heart and have finally made Windows PowerShell the tool I can use for everything.

(Note: Currently the most current build available for download separately is the November build which doesn’t have these two New-Item features, so the only way to get them right now is in the latest Windows 10 build. But that’s likely to change soon.)


ETA: The February WMF 5.0 build is available from Windows Download Centre. This includes support for Windows Server 2012, Windows Server 2012 R2, and Windows 8.1 Pro and Enterprise. And yes, the changes to New-Item are in there. :)


Oh, and while we’re at it – there’s all sorts of other goodies in PowerShell v5, including OneGet, a great way to get new modules for your PowerShell. Check it out.

Posted in Network Administration, PowerShell, Windows Server | 2 Comments »

Getting the Free Disk Space of Remote Computers

November 26th, 2014 by and tagged , , , ,

(For an updated version of this post and script, see Getting the Free Disk Space of Remote Computers Revisited.)

This started out as a simple script to try to get the free space on one of my servers, but I quickly discovered that using WMI’s Win32_LogicalDisk could only give me part of the solution. The catch is that Win32_LogicalDisk doesn’t return the information about volumes that aren’t assigned drive letters. Which is a problem if what you really need to know is how close to out of space your backup disk is! Because Windows Server Backup takes total control of the backup target disk, and doesn’t mount it as a drive letter, you need to use a different WMI Class to get the information you need. After asking some friends (PowerShell MVPs ROCK!), I was pointed to Win32_Volume, which returns all sorts of information about disk volumes whether they are assigned drive letters or not.

The next issue was how to get the actual information I wanted, and then to format it so that it actually made some sense. For example:

(Get-WmiObject –ComputerName Server1 –Class Win32_Volume).FreeSpace


This doesn’t really cut it. OK, let’s try at least getting it into a table:

Get-WmiObject –ComputerName Server1 –Class Win32_Volume | ft –auto DriveLetter,Label,FreeSpace

DriveLetter Label                               FreeSpace 
----------- -----                               --------- 
C:                                            21655351296 
D:          DATA                             103541030912 
E:          EXCHANGE                          75879378944 
F:          FILES                            142417367040 
Y:          New Volume                            5500928 
            Server1 2014_10_15 10:57 DISK_03 565375053824


Well, that’s a bit more useful, but frankly, that number for the backup volume seems big, but is it 500 GB, or 50 GB? At first glance, I have no idea. And if it’s 50 GB, I’m in trouble, but if it’s 500 GB, we’re fine. So, we need to do a bit of manipulation to the output from Format-Table, and the tool for this is to create an Expression that allows you to calculate and format a result in a way that makes more sense. For this, we use an expression as the property to display. So, for example, to display that “565375053824” as Gigabytes, we use:

Get-WmiObject –ComputerName Server1 –Class Win32_Volume `
       | ft –auto DriveLetter,`
                  @{Label=”Free(GB)”;Expression={'{0:N0}’ –F ($_.FreeSpace/1GB)}}
DriveLetter Label                            Free(GB) 
----------- -----                            -------- 
C:                                           20 
D:          DATA                             96 
E:          EXCHANGE                         71 
F:          FILES                            133 
Y:          New Volume                       0 
            Server1 2014_10_15 10:57 DISK_03 527

Now we’re getting somewhere. But what did we do? We use the @{} to tell Format-Table that we were going to use an expression to define a column of data. The Label=”Free(GB)” creates a new column header, and the Expression={“{0:N0}” –F  means we’re going to have a numeric value (including thousands separators) with no decimal values. The calculated value for the column is ($_.FreeSpace/1GB).

So we now have a useful listing of free space on the remote server. Of course, it might be even more useful to know the percentage free. No problem, for that we use the formatting expression “{0:P0}” to express the column as a percentage, and use the calculation of ($_.FreeSpace/$_.Capacity), letting PowerShell do the work of converting that to a percentage. So:

Get-WmiObject –ComputerName Server1 –Class Win32_Volume `
       | ft –auto DriveLetter,`
                  @{Label=”Free(GB)”;Expression={“{0:N0}” –F ($_.FreeSpace/1GB)}},`
                  @{Label=”%Free”;Expression={“{0:P0}” –F ($_.FreeSpace/$_.Capacity)}}
DriveLetter Label                         Free(GB)  %Free
----------- -----                         --------  ----- 
C:                                            20      17 %
D:          DATA                              96      48 % 
E:          EXCHANGE                          71      71 % 
F:          FILES                             133     18 % 
Y:          New Volume                        0       58 % 
            Server1 12014_10_15 10:57 DISK_03 527     51 %


Now we almost have it. Next, it would probably be useful to get the total capacity of the disk while we’re at it, and since I have more than one server, we should probably plan on passing this whole thing an array of computer names. So, the final script, at least for this first pass:

# ********************************************* 
# ScriptName: Get-myFreeSpace.ps1 
# Description: Script to get the free disk space
#            : on a remote computer and display it usefully
# ModHist: 26/11/2014 - Initial, Charlie
#        : 18/04/2017 - Change to Write-Output. 
# *********************************************
Param ([Parameter(Mandatory=$False,Position=0)]
         [String[]]$ComputerName = "Server1")
Write-Output ""
ForEach ( $Name in $ComputerName ) {
   Write-Output "Disk Utilization for server $Name is: "
   Get-WmiObject  -ComputerName $Name -Class Win32_Volume `
      | Format-Table  -auto `
            Expression={"{0:N0}" -f ($_.FreeSpace/1GB)};`
         @{Label="% Free";`
            Expression={"{0:P0}" -f ($_.FreeSpace / $_.Capacity)};`
            Expression={"{0:N0}" -f ($_.Capacity / 1GB)};`
         @{Label="Volume Label";`

You’ll see I tweaked the formatting to right align the calculated expressions, and gave my volume label column some extra space to improve readability. The result is:

Get-myFreeSpace.ps1 –ComputerName “Server1”,”Server2” 
Disk Utilization for server Server1 is:

 Drive Free(GB) % Free Size(GB) Volume Label 
----- -------- ------ -------- ------------ 
   C:       20   17 %      120 
   D:       96   48 %      200 DATA 
   E:       71   71 %      100 EXCHANGE 
   F:      133   18 %      750 FILES 
   Y:        0   58 %        0 New Volume 
           527   51 %    1,024 Server1 2014_10_15 10:57 DISK_03 
Disk Utilization for server Server2 is:

Drive Free(GB) % Free Size(GB) Volume Label 
----- -------- ------ -------- ------------ 
             0   25 %        0 
   D:    1,697   53 %    3,214 Data 
   C:      484   95 %      512


ETA:  Changed to use Write-Output instead of Write-Host. No need for the features of Write-Host, and it was causing issues for those who wanted to redirect the output to a file. This is more flexible.

ETA:  Changed to clean up the problem formatting from the switch in syntax highlighters. Sigh.



Posted in Network Administration, PowerShell, Windows Server, WMI | 33 Comments »

Set Network Location to Private in Windows 8 & 10 and Windows Server 2012 & 2016

December 29th, 2013 by and tagged , , , , ,

One of those annoyances that sometimes happen with the new Network Location in Windows 8.x and Windows 10 is that the network gets mis-identified as Public when it should be Private, or the other way around. Changing this in the GUI is certainly possible, but annoying, so let’s take advantage of the improved Windows PowerShell support in Windows 8.1 (and later) and do it quickly and easily. First, let’s open up an elevated PowerShell window from our limited user session:

PSH> Start-Process WindowsPowerShell.exe -verb RunAs

Now, in that window, let’s find out what our current network location is set to:

PSH> Get-NetConnectionProfile
Name : Unidentified network
InterfaceAlias : vEthernet (Local-10)
InterfaceIndex : 18
NetworkCategory : Public
IPv4Connectivity : LocalNetwork
IPv6Connectivity : LocalNetwork

From this, we see that the problem interface has an Interface Index of 18, so:

PSH> Set-NetConnectionProfile  -InterfaceIndex 18 -NetworkCategory Private

And we’re done.

ETA, 3 August, 2016 — this same problem exists in Windows 10/Server 2016. And the solution is the same. Set-NetConnectionProfile is your friend!

Posted in Network Administration, PowerShell, Windows 10, Windows Server 2016 | 20 Comments »

Windows Server Backup with PowerShell

February 3rd, 2011 by and tagged , ,

Here’s a basic Windows PowerShell script configure Windows Server 2008 R2 Backup.

# -----------------------------------------------------------------
# Script to set a Windows Server Backup policy for a server
# Assumes: Volumes C: and D: to backup.
#        : Target - \\storageserver\serverbackup
#        : Exclusions - D:\temp, D:\Users\*.MP3, D:\Users\*.WMA
#        : VSS Mode - Full Backup
#        : System State - True
#        : Bare Metal Recovery - True
#        : Schedule - 12:30 PM, 11:00 PM
# Requires: Elevated PowerShell
#         :   (Must be run As Administrator)
# Planned Improvements: [minor] Check for elevated priv, error politely if not
#                     : [minor] Check for Server Backup PSSnapin before trying to load
#                     : [major] Accept cmdline parameters
# ModHist: 1/31/11 - initial (Charlie Russel)
#        :
# With profound thanks to Richard Siddaway, Windows PowerShell MVP
# -----------------------------------------------------------------
# By default, the PSSnapin isn't loaded automatically, so first load it.
Add-PSSnapin Windows.ServerBackup # will error if already loaded, but continue
# First, create a new empty policy
# Alternately, you can open the existing policy in Edit mode with
#   $BackupPolicy = Get-WBPolicy -edit
$BackupPolicy = New-WBPolicy
# Now, define the parts of it.
# First, let's do the "source" volumes that will be part of the backup.
# This requires us to first get a list of them, and then parse that list
# to add the ones we want (C: and D:)
# We don't actually need C:, since we'll get that as part of Bare Metal Restore,
# but we include it anyway for completeness
$volC = Get-WBVolume -AllVolumes | Where {$_.MountPath -eq "C:"}
$volD = Get-WBVolume -AllVolumes | Where {$_.MountPath -eq "D:"}
$Volumes = $volC,$volD
# Now, add those volumes to the blank policy.
Add-WBVolume -policy $BackupPolicy -volume $Volumes
# If you want to do the entire volume, you don't need to define any exclusions,
# but if you want to exclude any files or folders, you need to define that exclusion
# and add that to the backup policy you're building. First, define it.?
$excTEMP = New-WBFileSpec -Filespec D:\Temp -exclude
$excWMA = New-WBFileSpec -Filespec "D:\Users\*.wma" -exclude  # Recursive unless
$excMP3 = New-WBFileSpec -Filespec "D:\Users\*.mp3" -exclude  # -NonRecursive specified
$FileExclusions = $excTEMP,$excWMA,$excMP3
# and then add that to the policy we're building
Add-WBFileSpec -policy $BackupPolicy -filespec $FileExclusions
# Define the backup target, this time as a network share.
# For backup to share, you need to create a credential to connect to the remote share.
# This wouldn't be required for specifying a removable disk.
# You can specify the username here (DOMAIN\User) but will be prompted for password
$Cred = Get-Credential example\user
# Now, define the target
$Target = New-WBBackupTarget -NetworkPath \\StorageServer\ServerBackup -Credential $Cred
# Add the target to the policy
Add-WBBackupTarget -policy $BackupPolicy -target $Target
# Define the schedule
$sch1 = [datetime]"01/31/2011 12:30:00"
$sch2 = [datetime]"01/31/2011 21:00:00"
Set-WBSchedule -policy $BackupPolicy -schedule $sch1,$sch2
# Set for system state and for bare metal recovery
Add-WBSystemState -policy $BackupPolicy
Add-WBBareMetalRecovery -policy $BackupPolicy
# Finally, set for full VSS Backup
Set-WBVssBackupOptions -policy $BackupPolicy -VssFullBackup
# Finally, we need to SET the policy before it actually takes control
Set-WBPolicy -force -policy $BackupPolicy
# This completes the configuration of the SBS server backup policy
$Server = (hostname).tolower()
" The server $Server now has the following backup configuration: "

Posted in Network Administration, PowerShell, Windows Backup, Windows Server | Comments Off on Windows Server Backup with PowerShell

Next Entries »