Introduction
I'm a DotNetNuke(DNN) evangelist. Many a late night has been spent coding new modules, building skins, and not-so-patiently waiting for the next version to arrive. If I have any complaints about DNN, it is about the fact that DNN has a constant "under construction" sign on its door. It is never really quite finished, because as soon as one release comes out, some newer, cooler technology comes down the road, and off goes the core team to integrate it and bring it to the grateful minions. So can I really complain at all?
One downside to that constant development cycle is that sometimes the "spit and polish" falls to the wayside. It is a product made by developers for developers, and so we just dig in and get our hands dirty when needed. But it would be nice if some things were just a little easier for the novice.
A noticeably lacking feature of DNN is an installer. In order to install the portal, you have to unzip the files, set permissions, create a virtual directory, create a database, and edit configuration files. Not a problem for most visitors of CodeProject. But that might be a handful for your novice programmer or anyone not intimately familiar with ASP.NET, IIS or MS SQL.
I didn't happen to have an extra few hundred dollars laying around in order to purchase a copy of InstallShield or Wise and create one of those "pretty" installers, so I rolled my own. NUKEleus is the end result. I hope you enjoy it.
Features
NUKEleus is a typical wizard in every sense. The interface looks nice and was easy to create due in large part to the Wizard Framework from DivElements. NUKEleus will walk you through the following steps, handling all the messy work for you.
- Allows you to install any version of DotNetNuke.
- Creates an install folder (you can choose where to install DNN).
- Unzips the files.
- Gives appropriate folder permissions to the machine's ASP.NET account.
- Creates a virtual directory (you can choose the VDir name).
- Creates a blank database in SQL Server (you can choose the database name).
- Edits the Web.Config file with your custom information.
- Edits the DotNetNuke.sln and DotNetNuke.vbproj.webinfo files so that you can open the solution.
In addition, NUKEleus is open source, and under the standard GNU license, so it can grow and gather support from the community as needed.
Stumbling Blocks
Writing this installer was a real learning process for me. I had no idea how to perform several of the necessary actions, such as creating virtual directories and assigning NTFS permissions. And I'm still not 100% happy with the way things have been implemented. But the program is working, and that is the first step. I'm hoping that the community will jump in with more code to make this an even more polished product than it already is.
Assigning NTFS Folder Permissions
Probably, the hardest part of getting started with this problem was figuring out how to Google on it. "Give <machinename>\ASPNET rights to a folder" was not getting me any results. Several hours and several Advil into my search, I started to come across some rather interesting acronyms, such as Security Descriptors (SDs), Access Control Lists (ACLs) and Access Control Entries (ACEs). All of these have to do with setting security permissions - not only on folders, but on almost anything. The bad news was that .NET does not seem to have a library built into it that handles these (at least not that I'm aware of). Most of the source code examples available were in C++, which didn't help me in a VB.NET environment. Other examples were in older code, such as this example of high level routines from MSDN. After much trial and error, I just wasn't getting the results I wanted, so I fell back on a command line utility that I located to complete the job. Once I get this article published, I intend to look into this problem a little further.
Creating a Virtual Directory
Creating virtual directories programmatically was a little easier, not only because I was able to locate some code for it, but because .NET supported it to begin with. It's not an intuitive process however. I don't think a quick peek into the MSDN library would make it clear. The key to creating VDir's is the System.DirectoryServices.DirectoryEntry
. Although the code below is rather long winded, the nutshell version is that you need to create a Directory entry, assign the necessary properties to it, and then commit the changes. In that regard, it is somewhat like adding a record to a database. Anyway, here is the code:
Private Sub CreateVDir(ByVal WebSite As String, ByVal VDirName As String, _
ByVal Path As String, ByVal RootDir As Boolean)
Dim IISSchema As System.DirectoryServices.DirectoryEntry
Dim IISAdmin As System.DirectoryServices.DirectoryEntry
Dim VDir As System.DirectoryServices.DirectoryEntry
Dim IISUnderNT As Boolean
IISSchema = New System.DirectoryServices.DirectoryEntry("IIS://" & _
WebSite & "/Schema/AppIsolated")
If IISSchema.Properties("Syntax").Value.ToString.ToUpper() = "BOOLEAN" _
Then
IISUnderNT = True
Else
IISUnderNT = False
IISSchema.Dispose()
IISAdmin = New System.DirectoryServices.DirectoryEntry("IIS://" & _
WebSite & "/W3SVC/1/Root")
For Each v As DirectoryEntry In IISAdmin.Children
If v.Name = VDirName Then
Try
IISAdmin.Invoke("Delete", _
New String() {v.SchemaClassName, VDirName})
IISAdmin.CommitChanges()
Catch ex As Exception
MsgBox("Error deleting existing VDir:" & ex.Message, _
MsgBoxStyle.Critical, "Error Deleting VDir")
End Try
End If
Next
If Not RootDir Then
VDir = IISAdmin.Children.Add(VDirName, "IIsWebVirtualDir")
Else
VDir = IISAdmin
End If
VDir.Properties("AccessRead")(0) = True
VDir.Properties("AccessExecute")(0) = True
VDir.Properties("AccessWrite")(0) = False
VDir.Properties("AccessScript")(0) = True
VDir.Properties("AuthNTLM")(0) = True
VDir.Properties("EnableDefaultDoc")(0) = True
VDir.Properties("EnableDirBrowsing")(0) = False
VDir.Properties("DefaultDoc")(0) = _
"default.htm,default.aspx,default.asp"
VDir.Properties("Path")(0) = Path
VDir.Properties("AppFriendlyName")(0) = VDirName
If Not IISUnderNT Then
VDir.Properties("AspEnableParentPaths")(0) = True
End If
VDir.CommitChanges()
If IISUnderNT Then
VDir.Invoke("AppCreate", False)
Else
VDir.Invoke("AppCreate", 1)
End If
End If
pageVirtualDirectory.AllowMoveNext = True
End Sub
Unzipping a ZIP File
Here again, I'm rather surprised that such a common requirement is not handled by internal .NET libraries, but - it isn't. Fortunately, the community jumped rather quickly on this one, and produced a wonderful library called SharpZipLib. Unzipping using this library is rather straightforward, and there are examples on the web of how to do this. What I'll make you note however is the RaiseEvent
call at the bottom of the code. Since unzipping a large file (all the DNN files are large) can take a while, I thought it is best to run this operation in a separate thread. This allows the end user to pause or cancel the unzipping operation as needed. I'm still pretty new to the whole multi-threading paradigm, but its about time VB.NET gained this ability.
Private Sub Unzip()
Dim strmZipInputStream As ZipInputStream = _
New ZipInputStream(File.OpenRead(bfFileName.Text))
Dim objEntry As ZipEntry
Dim count As Integer = 1
objEntry = strmZipInputStream.GetNextEntry()
While IsNothing(objEntry) = False
Dim nSize As Integer = 2048
Dim abyData(2048) As Byte
Dim directoryName As String = bfFolder.Text & _
Path.GetDirectoryName(objEntry.Name)
Dim fileName As String = Path.GetFileName(objEntry.Name)
lblFile.Text = "Extracting: " & fileName
ProgressBar1.Value = count
Directory.CreateDirectory(directoryName)
If fileName <> "" Then
Dim StreamWriter As FileStream = _
File.Create(directoryName & "\" & fileName)
While True
nSize = strmZipInputStream.Read(abyData, 0, abyData.Length)
If nSize > 0 Then
StreamWriter.Write(abyData, 0, nSize)
Else
Exit While
End If
End While
StreamWriter.Close()
End If
count += 1
objEntry = strmZipInputStream.GetNextEntry()
End While
strmZipInputStream.Close()
RaiseEvent ThreadComplete()
End Sub
A Blatant Plug For Self
I love writing wizards and tools. I quickly realized that one thing I do over and over is create special fields to locate files and folders. To that end, I created the BrowseControls. They allow you to drop controls right on your WinForm and never think again about all the coding it takes just to pick a file or folder from a hard drive.
Musings and Warnings
NUKEleus is a relatively untested product at the moment. Use it with care. It is intended for new installations of DotNetNuke only. It can be used for upgrades, but doing so will overwrite your Web.Config and recreate your virtual directories, etc. You should always backup your files and database before attempting any kind of DNN upgrade anyway.
In order to keep this software open and growing, I have also added it to SourceForge.
Wrap Up
I hope you like this program, and know you'll love DotNetNuke if you get to know it. If you have any comments, suggestions or fixes, please make your voice heard.