Upload files to SharePoint 2010 using PowerShell or C#

I had a need to upload an XML file to a SharePoint 2010 library.  Here’s how I finally got it to work:

PowerShell

 

$destinationurl = "https://my.sharepointserver.com/sites/my-site-name/my-doc-library/my-folder/filename.xml"

$sourceurl = "c:\temp\filename.xml"

$wc = new-object system.net.webclient
[byte[]] $response = $wc.uploadfile($destinationurl, "PUT", $sourceurl)

 

I’m afraid it doesn’t provide much in the way of validation, but it works.  Here’s the same thing in C#, but which takes the source and destination urls as arguments. Obviously the PowerShell approach could be wrapped up in a script that does the same thing.  Sorry about the formatting. I’m really not digging this blog theme.  I need to change it.

C#

 

using System;
using System.Net;

namespace spcopy
{
    class Program
    {
        static void Main(string[] args)
        { 

  // Set the local file
            //string sourceUrl = @"C:\test.txt";
            string sourceUrl = args[0];

            // Set destination file
            //string destinationUrl = @"https://my.sharepointserver.com/sites/my-site-name/my-doc-library/my-folder/filename.xml"
            string destinationUrl = args[1];

            WebClient wc = new WebClient();
            wc.UseDefaultCredentials = true;
            byte[] response = wc.UploadFile(destinationUrl, "PUT", sourceUrl);

            sourceUrl = null;
            destinationUrl = null;
            wc.Dispose();
            response = null;

            GC.Collect();
        }
    }
}

Advertisements

Upgrading 2008 R2 using DISM in a KMS licensing environment

Today I had to upgrade a server from 2008 R2 Standard to Enterprise so I could install Failover Clustering. You can do this using the DISM tool provided in the OS, but there are some caveats associated with doing so in a KMS licensed environment. Specifically, DISM requires that you provide a product key, which we obviously don’t have, and don’t want to use because we’re leveraging a KMS server. So, a few quick notes (blatantly stolen from this article over at ‘Life of A Geek Admin’):

A few caveats:

  • You can only do upgrades. You CANNOT downgrade
  • The server you upgrade cannot be a domain controller (demote, upgrade, promote)
  • This works on Standard, Enterprise edition, both full & core installations.
  • You cannot switch form core to full or vice versa. It’s edition upgrade only, not for switching type of install.

Get your current version information:

DISM /online /Get-TargetEditions

Now perform your upgrade using a public product key:

DISM /online /Set-Edition: /ProductKey: #####-#####-#####-#####-#####

And here are the public product keys we can use:

  • Windows Server 2008 R2 HPC Edition: FKJQ8-TMCVP-FRMR7-4WR42-3JCD7
  • Windows Server 2008 R2 Datacenter: 74YFP-3QFB3-KQT8W-PMXWJ-7M648
  • Windows Server 2008 R2 Enterprise: 489J6-VHDMP-X63PK-3K798-CPX3Y
  • Windows Server 2008 R2 for Itanium-Based Systems: GT63C-RJFQ3-4GMB6-BRFB9-CB83V
  • Windows Server 2008 R2 Standard: YC6KT-GKW9T-YTKYR-T4X34-R7VHC
  • Windows Web Server 2008 R2: 6TPJF-RBVHG-WBW2R-86QPH-6RTM4

A change of plan…

Today I finally decided what direction I’m going to take my blog in (for now). I will be picking a subject, breaking it up into small components, or episodes, and then writing about that subject one episode at a time. Why am I doing this? Because this blog is for me. I lost track of that somewhere along the way. I’m happy to share the information, and enjoy writing my content as if it were directed at a larger audience, but at the end of the day I’m probably the only one referencing it on a regular basis. Given that, my blog’s primary purpose should be to act as a learning and referential tool for myself, and I think this approach will most readily benefit me. With any luck, the very few people with very poor taste who actually debase themselves to read my work from time to time (Ben & Omar) might get some value out of it. So, what’s the first series going to be about? Well, without further ado, I’m pleased to announce the debut of… wait for it…

Series 1 – PowerShell 3.0!

I’ve just recently made the leap to Windows 8 on my production machine, and am starting to work with Windows Server 2012. I like it! I wish I had a touch-screen, but that aside, I still really like it. It really grew on me once I got past the disgruntled period where I was resentful about having to learn the new interface. Now I don’t think I would want to go back.

So, with Windows 8 comes PowerShell 3.0, and with PowerShell 3.0 comes lots of new things to learn! I’m going to write about these as often as I can, and have broken it down into the subjects below, thought I do reserve the right to update this list as I see fit, and you can expect that I will.

That said, on with the show! Let’s see what’s in the lineup (I’ll add links to the posts as I complete them):

Episode

Title

1

PowerShell 101 – Part 1

2

PowerShell 101 – Part 2

3

PowerShell 101 – Part 3

4

Microsoft.PowerShell.*

5

Microsoft.Powershell.Core : Enable-PSSessionConfiguration

6

Microsoft.Powershell.Core : New-PSTransportOption

7

Microsoft.Powershell.Core : Enable-PSRemoting

8

Microsoft.Powershell.Core : Remove-Job

9

Microsoft.Powershell.Core : Enter-PSSession

10

Microsoft.Powershell.Core : Exit-PSSession

11

Microsoft.Powershell.Core : Set-StrictMode

12

Microsoft.Powershell.Core : Export-Console

13

Microsoft.Powershell.Core : Set-PSSessionConfiguration

14

Microsoft.Powershell.Core : Export-ModuleMember

15

Microsoft.Powershell.Core : Set-PSDebug

16

Microsoft.Powershell.Core : ForEach-Object

17

Microsoft.Powershell.Core : Out-Default

18

Microsoft.Powershell.Core : Out-Host

19

Microsoft.Powershell.Core : Out-Null

20

Microsoft.Powershell.Core : Get-PSSnapin

21

Microsoft.Powershell.Core : Save-Help

22

Microsoft.Powershell.Core : Get-PSSessionConfiguration

23

Microsoft.Powershell.Core : Resume-Job

24

Microsoft.Powershell.Core : Get-PSSession

25

Microsoft.Powershell.Core : Get-Command

26

Microsoft.Powershell.Core : Receive-Job

27

Microsoft.Powershell.Core : Receive-PSSession

28

Microsoft.Powershell.Core : Register-PSSessionConfiguration

29

Microsoft.Powershell.Core : Get-Module

30

Microsoft.Powershell.Core : Remove-PSSnapin

31

Microsoft.Powershell.Core : Remove-PSSession

32

Microsoft.Powershell.Core : Get-Help

33

Microsoft.Powershell.Core : Get-History

34

Microsoft.Powershell.Core : Remove-Module

35

Microsoft.Powershell.Core : Disconnect-PSSession

36

Microsoft.Powershell.Core : Disable-PSSessionConfiguration

37

Microsoft.Powershell.Core : Get-Job

38

Microsoft.Powershell.Core : New-PSSessionOption

39

Microsoft.Powershell.Core : Add-History

40

Microsoft.Powershell.Core : Where-Object

41

Microsoft.Powershell.Core : Add-PSSnapin

42

Microsoft.Powershell.Core : Invoke-History

43

Microsoft.Powershell.Core : Wait-Job

44

Microsoft.Powershell.Core : Update-Help

45

Microsoft.Powershell.Core : Clear-History

46

Microsoft.Powershell.Core : Unregister-PSSessionConfiguration

47

Microsoft.Powershell.Core : Invoke-Command

48

Microsoft.Powershell.Core : Test-PSSessionConfigurationFile

49

Microsoft.Powershell.Core : Disable-PSRemoting

50

Microsoft.Powershell.Core : Connect-PSSession

51

Microsoft.Powershell.Core : Import-Module

52

Microsoft.Powershell.Core : New-Module

53

Microsoft.Powershell.Core : Test-ModuleManifest

54

Microsoft.Powershell.Core : Start-Job

55

Microsoft.Powershell.Core : New-ModuleManifest

56

Microsoft.Powershell.Core : Stop-Job

57

Microsoft.Powershell.Core : New-PSSessionConfigurationFile

58

Microsoft.Powershell.Core : New-PSSession

59

Microsoft.Powershell.Core : Suspend-Job

60

Microsoft.Powershell.Diagnostics : Get-Counter

61

Microsoft.Powershell.Diagnostics : Import-Counter

62

Microsoft.Powershell.Diagnostics : New-WinEvent

63

Microsoft.Powershell.Diagnostics : Get-WinEvent

64

Microsoft.Powershell.Diagnostics : Export-Counter

65

Microsoft.Powershell.Host : Start-Transcript

66

Microsoft.Powershell.Host : Stop-Transcript

67

Microsoft.Powershell.Management : Push-Location

68

Microsoft.Powershell.Management : Move-ItemProperty

69

Microsoft.Powershell.Management : Register-WmiEvent

70

Microsoft.Powershell.Management : Pop-Location

71

Microsoft.Powershell.Management : Remove-Computer

72

Microsoft.Powershell.Management : New-PSDrive

73

Microsoft.Powershell.Management : New-Item

74

Microsoft.Powershell.Management : Remove-EventLog

75

Microsoft.Powershell.Management : New-Service

76

Microsoft.Powershell.Management : New-ItemProperty

77

Microsoft.Powershell.Management : Move-Item

78

Microsoft.Powershell.Management : New-WebServiceProxy

79

Microsoft.Powershell.Management : Add-Computer

80

Microsoft.Powershell.Management : Restore-Computer

81

Microsoft.Powershell.Management : Remove-ItemProperty

82

Microsoft.Powershell.Management : Split-Path

83

Microsoft.Powershell.Management : Start-Process

84

Microsoft.Powershell.Management : Start-Service

85

Microsoft.Powershell.Management : Start-Transaction

86

Microsoft.Powershell.Management : Stop-Computer

87

Microsoft.Powershell.Management : Stop-Process

88

Microsoft.Powershell.Management : Stop-Service

89

Microsoft.Powershell.Management : Suspend-Service

90

Microsoft.Powershell.Management : Test-ComputerSecureChannel

91

Microsoft.Powershell.Management : Test-Connection

92

Microsoft.Powershell.Management : Test-Path

93

Microsoft.Powershell.Management : Undo-Transaction

94

Microsoft.Powershell.Management : Use-Transaction

95

Microsoft.Powershell.Management : Wait-Process

96

Microsoft.Powershell.Management : Write-EventLog

97

Microsoft.Powershell.Management : Show-EventLog

98

Microsoft.Powershell.Management : Remove-Item

99

Microsoft.Powershell.Management : Show-ControlPanelItem

100

Microsoft.Powershell.Management : Set-Service

101

Microsoft.Powershell.Management : Remove-PSDrive

102

Microsoft.Powershell.Management : Remove-WmiObject

103

Microsoft.Powershell.Management : Rename-Computer

104

Microsoft.Powershell.Management : Rename-Item

105

Microsoft.Powershell.Management : Rename-ItemProperty

106

Microsoft.Powershell.Management : Reset-ComputerMachinePassword

107

Microsoft.Powershell.Management : Resolve-Path

108

Microsoft.Powershell.Management : Restart-Computer

109

Microsoft.Powershell.Management : Restart-Service

110

Microsoft.Powershell.Management : Limit-EventLog

111

Microsoft.Powershell.Management : Resume-Service

112

Microsoft.Powershell.Management : Set-Content

113

Microsoft.Powershell.Management : Set-Item

114

Microsoft.Powershell.Management : Set-ItemProperty

115

Microsoft.Powershell.Management : Set-Location

116

Microsoft.Powershell.Management : Set-WmiInstance

117

Microsoft.Powershell.Management : Join-Path

118

Microsoft.Powershell.Management : New-EventLog

119

Microsoft.Powershell.Management : Get-Process

120

Microsoft.Powershell.Management : Get-ComputerRestorePoint

121

Microsoft.Powershell.Management : Complete-Transaction

122

Microsoft.Powershell.Management : Get-Service

123

Microsoft.Powershell.Management : Get-Content

124

Microsoft.Powershell.Management : Get-ControlPanelItem

125

Microsoft.Powershell.Management : Get-PSProvider

126

Microsoft.Powershell.Management : Get-PSDrive

127

Microsoft.Powershell.Management : Enable-ComputerRestore

128

Microsoft.Powershell.Management : Convert-Path

129

Microsoft.Powershell.Management : Get-EventLog

130

Microsoft.Powershell.Management : Disable-ComputerRestore

131

Microsoft.Powershell.Management : Get-Location

132

Microsoft.Powershell.Management : Get-ItemProperty

133

Microsoft.Powershell.Management : Get-Item

134

Microsoft.Powershell.Management : Get-HotFix

135

Microsoft.Powershell.Management : Debug-Process

136

Microsoft.Powershell.Management : Copy-Item

137

Microsoft.Powershell.Management : Copy-ItemProperty

138

Microsoft.Powershell.Management : Get-Transaction

139

Microsoft.Powershell.Management : Get-ChildItem

140

Microsoft.Powershell.Management : Invoke-Item

141

Microsoft.Powershell.Management : Clear-Item

142

Microsoft.Powershell.Management : Invoke-WmiMethod

143

Microsoft.Powershell.Management : Get-WmiObject

144

Microsoft.Powershell.Management : Clear-EventLog

145

Microsoft.Powershell.Management : Add-Content

146

Microsoft.Powershell.Management : Clear-Content

147

Microsoft.Powershell.Management : Clear-ItemProperty

148

Microsoft.Powershell.Management : Checkpoint-Computer

149

Microsoft.Powershell.Security : Set-Acl

150

Microsoft.Powershell.Security : Set-ExecutionPolicy

151

Microsoft.Powershell.Security : ConvertTo-SecureString

152

Microsoft.Powershell.Security : Set-AuthenticodeSignature

153

Microsoft.Powershell.Security : Get-PfxCertificate

154

Microsoft.Powershell.Security : Get-ExecutionPolicy

155

Microsoft.Powershell.Security : Get-Credential

156

Microsoft.Powershell.Security : Get-Acl

157

Microsoft.Powershell.Security : Get-AuthenticodeSignature

158

Microsoft.Powershell.Security : ConvertFrom-SecureString

159

Microsoft.Powershell.Utility : Sort-Object

160

Microsoft.Powershell.Utility : Disable-PSBreakpoint

161

Microsoft.Powershell.Utility : Set-TraceSource

162

Microsoft.Powershell.Utility : Set-Variable

163

Microsoft.Powershell.Utility : Export-Alias

164

Microsoft.Powershell.Utility : Export-Clixml

165

Microsoft.Powershell.Utility : Show-Command

166

Microsoft.Powershell.Utility : Export-Csv

167

Microsoft.Powershell.Utility : Export-FormatData

168

Microsoft.Powershell.Utility : Enable-PSBreakpoint

169

Microsoft.Powershell.Utility : Invoke-WebRequest

170

Microsoft.Powershell.Utility : ConvertTo-Xml

171

Microsoft.Powershell.Utility : Write-Progress

172

Microsoft.Powershell.Utility : Write-Output

173

Microsoft.Powershell.Utility : Write-Host

174

Microsoft.Powershell.Utility : Write-Error

175

Microsoft.Powershell.Utility : Write-Debug

176

Microsoft.Powershell.Utility : Add-Member

177

Microsoft.Powershell.Utility : Add-Type

178

Microsoft.Powershell.Utility : Wait-Event

179

Microsoft.Powershell.Utility : Update-TypeData

180

Microsoft.Powershell.Utility : Update-List

181

Microsoft.Powershell.Utility : Update-FormatData

182

Microsoft.Powershell.Utility : Start-Sleep

183

Microsoft.Powershell.Utility : Unregister-Event

184

Microsoft.Powershell.Utility : Trace-Command

185

Microsoft.Powershell.Utility : Clear-Variable

186

Microsoft.Powershell.Utility : Compare-Object

187

Microsoft.Powershell.Utility : ConvertFrom-Csv

188

Microsoft.Powershell.Utility : ConvertFrom-Json

189

Microsoft.Powershell.Utility : Tee-Object

190

Microsoft.Powershell.Utility : ConvertFrom-StringData

191

Microsoft.Powershell.Utility : ConvertTo-Csv

192

Microsoft.Powershell.Utility : ConvertTo-Html

193

Microsoft.Powershell.Utility : Export-PSSession

194

Microsoft.Powershell.Utility : ConvertTo-Json

195

Microsoft.Powershell.Utility : Unblock-File

196

Microsoft.Powershell.Utility : Set-PSBreakpoint

197

Microsoft.Powershell.Utility : Select-Object

198

Microsoft.Powershell.Utility : Format-List

199

Microsoft.Powershell.Utility : Out-GridView

200

Microsoft.Powershell.Utility : Out-File

201

Microsoft.Powershell.Utility : Get-TraceSource

202

Microsoft.Powershell.Utility : Get-TypeData

203

Microsoft.Powershell.Utility : New-Variable

204

Microsoft.Powershell.Utility : New-TimeSpan

205

Microsoft.Powershell.Utility : Get-UICulture

206

Microsoft.Powershell.Utility : Get-Unique

207

Microsoft.Powershell.Utility : Get-Variable

208

Microsoft.Powershell.Utility : Group-Object

209

Microsoft.Powershell.Utility : Import-Alias

210

Microsoft.Powershell.Utility : New-Object

211

Microsoft.Powershell.Utility : Import-Clixml

212

Microsoft.Powershell.Utility : Import-Csv

213

Microsoft.Powershell.Utility : Import-LocalizedData

214

Microsoft.Powershell.Utility : Import-PSSession

215

Microsoft.Powershell.Utility : Write-Verbose

216

Microsoft.Powershell.Utility : New-Event

217

Microsoft.Powershell.Utility : New-Alias

218

Microsoft.Powershell.Utility : Invoke-Expression

219

Microsoft.Powershell.Utility : Measure-Object

220

Microsoft.Powershell.Utility : Measure-Command

221

Microsoft.Powershell.Utility : Invoke-RestMethod

222

Microsoft.Powershell.Utility : Get-Random

223

Microsoft.Powershell.Utility : Format-Custom

224

Microsoft.Powershell.Utility : Out-Printer

225

Microsoft.Powershell.Utility : Read-Host

226

Microsoft.Powershell.Utility : Format-Table

227

Microsoft.Powershell.Utility : Set-Date

228

Microsoft.Powershell.Utility : Format-Wide

229

Microsoft.Powershell.Utility : Set-Alias

230

Microsoft.Powershell.Utility : Send-MailMessage

231

Microsoft.Powershell.Utility : Select-Xml

232

Microsoft.Powershell.Utility : Select-String

233

Microsoft.Powershell.Utility : Get-Alias

234

Microsoft.Powershell.Utility : Get-Culture

235

Microsoft.Powershell.Utility : Get-Date

236

Microsoft.Powershell.Utility : Get-Event

237

Microsoft.Powershell.Utility : Remove-Variable

238

Microsoft.Powershell.Utility : Remove-TypeData

239

Microsoft.Powershell.Utility : Get-EventSubscriber

240

Microsoft.Powershell.Utility : Get-FormatData

241

Microsoft.Powershell.Utility : Remove-PSBreakpoint

242

Microsoft.Powershell.Utility : Get-Host

243

Microsoft.Powershell.Utility : Remove-Event

244

Microsoft.Powershell.Utility : Get-Member

245

Microsoft.Powershell.Utility : Register-ObjectEvent

246

Microsoft.Powershell.Utility : Register-EngineEvent

247

Microsoft.Powershell.Utility : Get-PSBreakpoint

248

Microsoft.Powershell.Utility : Get-PSCallStack

249

Microsoft.Powershell.Utility : Out-String

250

Microsoft.Powershell.Utility : Write-Warning

The Wunder of PowerShell: Posting to Wunderlist

I thought I’d mill out a quick post during lunch for any fellow Wunderlist users.  If you’re not using Wunderlist then you should look into it.  It is, by far, my favorite task manager to date (and I’ve tried most of them).  One feature that I really like is the ability to email yourself a task and have it land in your inbox.  This is a feature available in some of the other task managers out there as well, so the code below could be refit to work with other systems.  Specifically, I wanted a way to quickly shoot off a task to my Wunderlist inbox from PowerShell.  To do this, I added the following function to my profile.ps1 file:

function WUNDER
{
    PARAM([string]$body)
   
    $to = "me@wunderlist.com"
    $from = bsweeney@sweeneyops.lab
    $subject = " "
    $smtpserver = "mail.sweeneyops.lab"
   
    send-mailmessage -to $to -from $from -body $body -subject $subject -smtpserver $smtpserver
}

Now, whenever I want to send a task to myself, I simply type the following from PS:

PS C:\> wunder "Some task I want to perform"

And it will be in my inbox waiting for me to sort into a task list the next time I check Wunderlist.

Rethinking my blog

I’m re-thinking my blog.  Please excuse the mess.

Managing DNS using PowerShell

One of the things I have found sorely lacking in PowerShell 2.0 is a good way to manage DNS.  I’m hoping there is a fix for this in Windows Server 2012 and PowerShell 3.0, but for now I’ve had to search for alternatives.  Now, the Scripting Guys have published an excellent article on how to manage DNS through a combination of PowerShell and WMI.  You can find it here.   As I said, this is an interesting approach, and certainly works, but I personally found it to be overly complicated.  Instead, I found that leveraging PowerShell’s ability to incorporate pre-existing tools into my scripts presented me with a more viable solution. Specifically, I’ve combined DNSCMD with PowerShell.  Here’s how it works. 

DNSCMD is a well documented and very powerful tool for managing your windows DNS server from the command line.  It can be called directly from within PowerShell. So lets say I want a script that will set up new primary DNS zones for me based on a standard that we’ve developed.  We could set up AD integrated zones this way as well, but in my situation I was dealing with primary and so that’s what I’m sticking with now.  If you want to use AD integrated zones instead then the syntax is pretty easy to modify.  So, lets say I want to set up a new zone for sweeneyops.com.  I could simply run my script like this:

./create-primarydnszone.ps1 sweeneyops.com

… and voila! The zone would be created as per my predefined standards. What are my standards?  I guess we should probably define those now:

  • I want to create a primary dns zone
  • I want to use the default windows dns zone naming convention. (e.g. if my zone is sweeneyops.lab then my zone file would be sweeneyops.lab.dns)
  • My server host name is Server1, but it is recognized publicly as ns1.sweeneyops.lab.  This server only hosts primary zones. 
  • I have a second server called Server2.  It is publicly recognized as ns2.sweeneyops.lab.  It will host only seecondary copies of the zone, and I want it listed as a name server.
  • The host name will be added automatically to the name servers list. I want to remove it.
  • I want the zone contact to be me@sweeneyops.lab.  In DNS zone syntax that equates to me.sweeneyops.lab.
  • I want to use the windows default settings for the start of authority.
  • I want to allow zone transfers, but only for servers listed in the name servers tab of the DNS zone properties.
  • I want to create an A record for WWW and an empty A record (DNSCMD thinks of this as an @ record) and have both point to 192.168.1.1
    Here’s what the code looks like (I apologize if the line breaks are confusing, but I think it reads easily enough):

PARAM($domain)

# get the local host name
$localhost = $env:computername

# create the dns zone
dnscmd $localhost /zoneadd $domain /primary /file "$domain.dns"
   
# update Start of Authority (note: need to use single quotes around @ or will error out)
dnscmd $localhost /recordadd $domain ‘@’ SOA ns1.sweeneyops.lab me.sweeneyops.lab 1\ 3600 600 86400 3600

# add authoritative name servers
dnscmd $localhost /recordadd $domain ‘@’ NS ns1.sweeneyops.lab
dnscmd $localhost /recordadd $domain ‘@’ NS ns2.sweeneyops.lab
   
# Remove the host name from the name servers list
dnscmd $localhost /recorddelete $domain ‘@’ NS $localhost /f

# make sure zone transfers are allowed, but only for servers in the name server tab, and configure to notify
dnscmd $localhost /zoneresetsecondaries $domain /securens /notify

# create default records for cooperindustries.com
dnscmd $localhost /recordadd $domain ‘@’ A 192.168.1.1
dnscmd $localhost /recordadd $domain www A 192.168.1.1

Now one thing worth noting here is the entry for creating the Start of Authority record (SOA).  I said I wanted to use the windows defaults for setting up the SOA, but the DNSCMD syntax requires that you provide the values for the various SOA components.  In our script, that looks like this:

dnscmd $localhost /recordadd $domain ‘@’ SOA ns1.sweeneyops.lab me.sweeneyops.lab 1\ 3600 600 86400 3600

If we were to manually enter this on Server1 to create a zone called sweeneyops.com then it would look like this:

dnscmd Server1 /recordadd sweeneyops.com ‘@’ SOA ns1.sweeneyops.lab me.sweeneyops.lab 1\ 3600 600 86400 3600

So what’s up with that bit at the end where all the numbers start?  Well, if you pull up NSLOOKUP and set your query type to SOA then look up a zone after creating it through the DNS GUI you will see the following returned in the entry:

refresh = 3600 (1 hour)
retry   = 600 (10 mins)
expire  = 86400 (1 day)
default TTL = 3600 (1 hour)

These are the default Refresh, Retry, Expire, and MinTTL values defined by Windows, which I said I wanted to use.  That’s what the “3600 600 86400 3600” part is about.  The “1\” is a serial number value required in the DNS syntax. Normally, when using the GUI, Windows would define this value automatically.  We still want it to do so, and I found that using the “1\” causes it to do just that.  Trial an error for me, benefit for you.  I haven’t tried defining a specify serial number, but I suppose you could do that and possibly pass it in as another parameter.  For now, however, lets move on.  

I run this script on Server1 (ns1.sweeneyops.lab), pass in my domain name, and it creates my primary zone.  But what about my secondary zones on Server2 (ns2.sweeneyops.lab)?  For those, I will need a slightly different script.  Our new script is going to need the IP address of ns1.sweeneyops.lab, so for the sake of argument we’ll say that it’s 192.168.1.2.  Our code is much simpler.  It takes the domain name and the IP address of the first name server. It then uses that information to create the secondary zone.  All of the records were defined on the primary server, so there’s really not much left to do.  The code, which would be run on Server2, looks like this:

PARAM([string]$domain, [string]$IP)

# get the local host name
$localhost = $env:computername

dnscmd $localhost /zoneadd $domain /Secondary $IP /file "$domain.dns"

I could probably shorten it down to a single line, but I felt that it read more easily this way.  Feel free to modify it however you see fit.  So, there you have it. Simplified scripting of DNS through PowerShell. Enjoy!

Configuring PowerShell to run as a Scheduled Task in Server 2008 R2

When configuring a PowerShell script to run as a scheduled task in Windows Server 2008 R2, there are a few things that you need to pay special attention to if you want to make sure that it actually runs.  Specifically, each Action in the Actions section of the Scheduled task should be configured as follows:

Action:

Start a Program

Program/Script:

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe

Add arguments (optional):

-noninteractive –nologo c:\scriptpath\script.ps1

Start in (optional):

c:\scriptpath

There are a few things to note here:

  1. Do not place the script itself in the program/script filed.  Instead, you are making a call to powershell itself and then passing in the script name as a parameter. 
  2. The “-noninteractive” switch tells PowerShell that it should not present an actual shell. 
  3. The “-NoLogo” switch starts PowerShell from trying to display the copyright.  Frankly, I’m not sure this is critical, but I’ve always done it.
  4. Try and avoid placing your script in a path that contains spaces.  This means you don’t have to screw around with quotations.  This is not so much a road-block as a hurdle, but I personally like to keep things as simple as possible and I find this helps.
  5. If your script reads from or outputs to a file then make sure you don’t forget the Start In option. I like to specify this location as being the same location as my script file.  The reason I do this is that it allows me to write a script and simply specify the name of the file to read from or write to without having to specify the path in the script.  This is a matter of preference, but I find that it helps me keep things simple.