Search This Blog

Thursday, October 29, 2009

asp.net – modify docx OpenOfficeXML – using content controls

This took me a while to work out, but finally I got it to work.

The Open Office XML documents utilised by Microsoft in Office 2007 are actually zip files that package a number of folders and documents. So to edit these files you need to be able access the contents.

Microsoft provides an SDK for this purpose there is a version 1 and a version 2 (in CTP, at the time of this article).

http://msdn.microsoft.com/en-us/library/bb448854.aspx – version 1

http://msdn.microsoft.com/en-us/library/bb448854(office.14).aspx – version 2

I downloaded version 2.

I built a simple website, added a reference the .net open xml sdk and created the following page and code behind.

Reference to the open xml sdkimage

 

aspx page

 

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="createWordDocTest.aspx.vb" Inherits="createWordDocTest" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    <asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Click to write to word" />
    </div>
    </form>
</body>
</html>


code behind



Imports System.IO
Imports System.Xml
Imports DocumentFormat.OpenXml
Imports DocumentFormat.OpenXml.Packaging
Imports DocumentFormat.OpenXml.Wordprocessing
Partial Class createWordDocTest
    Inherits System.Web.UI.Page
    Protected Sub ReplaceCustomXML(ByVal fileName As String, ByVal customXML As String)
        Using wordDoc As WordprocessingDocument = WordprocessingDocument.Open(fileName, True)
            Dim mainPart As MainDocumentPart = wordDoc.MainDocumentPart
            mainPart.DeleteParts(Of CustomXmlPart)(mainPart.CustomXmlParts)
            'Add a new customXML part and then add content
            Dim customXmlPart As CustomXmlPart = mainPart.AddNewPart(Of CustomXmlPart)()
            'copy the XML into the new part...
            Using ts As New StreamWriter(customXmlPart.GetStream())
                ts.Write(customXML)
            End Using
        End Using
    End Sub
    Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs)
        Dim strPath As String = "c:\temp"
        Dim strtemplate As String = strPath & "\" & "inputDoc.docx"
        Dim strNewFile As String = strPath & "\outputDoc.docx"
        If System.IO.File.Exists(strtemplate) = True Then
            If System.IO.File.Exists(strNewFile) = True Then
                System.IO.File.Delete(strNewFile)
            End If
            System.IO.File.Copy(strtemplate, strNewFile)
            Dim xmlDoc As New XmlDocument()
            Dim customXML As String = "<root><CustomerName></CustomerName></root>"
            xmlDoc.LoadXml(customXML)
            Dim xmlnode As XmlNodeList = xmlDoc.GetElementsByTagName("CustomerName")
            xmlnode(0).InnerText = "What ever you want to insert"
            customXML = xmlDoc.InnerXml.ToString
            ReplaceCustomXML(strNewFile, customXML)
            Dim doc As WordprocessingDocument = WordprocessingDocument.Open(strNewFile, True)
            Dim mainPart As MainDocumentPart = doc.MainDocumentPart
            mainPart.Document.Save()
            doc.Close()
        End If
    End Sub
End Class


OK, there is still work to do. We are going to use a template document to house a content control which we will find and change the contents of, via a binding with some customXML . The mechanism here is that you will place a content control on the document, then creation a reference (or binding) to a custom XML entity. To change the content control content you will change the custom XML programmatically (via the asp page) and this will change the content control due to the binding.


OK, create a blank document called inputDoc.docx. Now in the ribbon go to the developer tab. (If the tab is not visible go here http://office.microsoft.com/en-au/word/HA101730521033.aspx). And insert a plain text control.


image 


with the new control inserted…


image 


click on properties in the developer tab…


image 


click on properties in the developer 


image 


With the control properties dialog up, enter CustomerName into the Title and Tag fields. Click OK.


So we have now setup our control. Now we need to create the customXML and the relationship between the customXML and the control. Save the document into your c:\temp folder (or to the folder of your choice (remember you will need to modify the example code above)) and save it as “inputDoc.docx”.


Now this can be done manually by going into the docX package creating files in folders and blah blah blah…. However there is an easier way (and I like easy…)


The Word 2007 Content Control Toolkit, you can get it here http://www.codeplex.com/dbe


Once you have downloaded and installed, fire up the program, and open your document, you see something like this


image 


Now we are going to create some custom XML part and bind it to the control. In the bind view on the right, click on the create a new custom XML part, and then click on edit view tab. You should see 


<root>

</root>



Now change this to


<root>

  <CustomerName>


  </CustomerName>


</root>



 



Go to the  bind View tab. Click on the CustomerName entry in the tree, Now select and drag it to the left pane (Content Controls) and over the control you want to create a relationship (in our case the tag CustomerName).



With that done, click save and close the program.



OK, thats it. Fire up your web page and click the button. You should hopefully find that a document called outputDoc.docx has been created alongside inputDoc.docx and has the contents of the control changed to new values.



Note: CustomXML is not supported in the office 2003 compatibility pack so if you are expecting to use this method with some office 2003 users then don’t as it will not work. I found this out to my own annoyance after getting it to work!…



References



http://www.devx.com/dotnet/Article/42221/1954


http://code.msdn.microsoft.com/OOXMLv20CTP/Release/ProjectReleases.aspx?ReleaseId=2080


 

Share/Bookmark

Wednesday, October 14, 2009

ASP.Net - Session Detection and Timeout in masterpages (vb.net)

I have spent some time tracking down and implementing a solution to detect if a session exists for a user and if so wether it has timed out. If either is true a redirection occurs to the homepage.

I found an article on this that I reference here, I have modified it slightly to accommodate master pages but in essence it is the same. I recommend you read this article as it gives a lot of in depth explanation about its function that I won’t do here.

http://aspalliance.com/520_Detecting_ASPNET_Session_Timeouts.all

Now in the above article it talks about creating a custom base page class that inherits from the System.Web.UI.Page class that all pages (aspx) inherit from normally. If you use this method you would have to change any existing pages to inherit from this new custom class. I had a few pages and did not really want to have to do this so I modified the above example to utilise the masterpage that I was using throughout my site.

Create a class file in your App_Code folder called BaseMasterPage.

Imports Microsoft.VisualBasic
Public Class BaseMasterPage
    Inherits System.Web.UI.MasterPage
    Protected Overloads Overrides Sub OnInit(ByVal e As EventArgs)
        MyBase.OnInit(e)
        If Context.Session IsNot Nothing Then
            If Session.IsNewSession Then
                Dim szCookieHeader As String = Request.Headers("Cookie")
                If (szCookieHeader IsNot Nothing) AndAlso (szCookieHeader.IndexOf("ASP.NET_SessionId") >= 0) Then
                    'The session appears to have timedout, show message to that effect
                    'The page below sessionTimeout.aspx, display message then redirects using a meta refresh.
                    Response.Redirect("\sessionTimeOut.aspx")
                Else
                    'redirect straight to front page if not timeout. This will capture if someone is trying to jump into the site
                    Response.Redirect("\default.aspx")
                End If
            End If
        End If
    End Sub
End Class


Open your codebehind masterPage file (e.g. Masterpage.master.vb) and change the following line from



Inherits System.Web.UI.MasterPage


to



Inherits BaseMasterPage

This means your masterpage is now inheriting from your custom class and not the default.

Create a sessionTimeOut page (does not have to an aspx can be straight html) but include the following in the head section, this will redirect the page after a set amount of time. Remember to also have a link to the page displayed incase the redirection fails for some reason.



<meta http-equiv="refresh" content="5;URL=/default.aspx">


if you are not redirected in 5 seconds please click

<a href="/defaults.aspx">here</a>



And that should be it. Now on any page that references the masterpage you will have a session check. It will check for a session startup event (without an existing session) and redirect to the homepage (or whatever page you decide). And also detect as session timeout and redirect to the homepage via a message.


 

Share/Bookmark

Sunday, October 11, 2009

NeatUpload – Inline Progress Bar and ClientID

When I started using Neatupload, I wanted the progress bar to be displayed inline. The examples provided showed some JavaScript that enabled this, however in my application the controls displayed in the page were renamed by ASP (i.e. adding th ctl_…. prefixes), this then throughout the JavaScript.

note: Before looking at this you must be aware that to get this working you need to disable Sessionstate on the page. This is done in the first line of the aspx page

<%@ Page Title="" Language="VB" MasterPageFile="~/MasterPage.master" AutoEventWireup="false" CodeFile="MultipleFile.aspx.vb" Inherits="MultipleFile" EnableSessionState="false" %>


This may have consequences on your application, please review the NeatUpload manual for more informaiton. In my situation I had to recode my masterpagefile that was looking for session variables, I had to detect whether the session was valid, I include the VB code here for reference.



If Me.Context.Session IsNot Nothing Then
    Session("sPreviousURL") = Request.ServerVariables("HTTP_REFERER")
End If


Below I show the JavaScript code needed to enable the inline progress bar to be displayed. I believe this should work with all instances (i.e. in the demo.aspx, where the control ID remains the same as in the aspx page, and when the control is being renamed by asp.net).



The hide/show progress bar script works by changing the style on a div tag that surrounds the iFrame in which the progress bar is display.



window.onload = function() {
    var inlineProgressBar = NeatUploadPB.prototype.Bars["<%= inlineProgressBar.ClientID %>"];
    var origDisplay = inlineProgressBar.Display;
    inlineProgressBar.Display = function() {
        var elem = document.getElementById(this.ClientID);
        elem.parentNode.style.display = "block";
        origDisplay.call(this);
        }
    inlineProgressBar.EvalOnClose = "NeatUploadMainWindow.document.getElementById('" + inlineProgressBar.ClientID + "').parentNode.style.display = \"none\";";
}


Below I show the full aspx page, including the JavaScript.



<%@ Page Title="" Language="VB" MasterPageFile="~/MasterPage.master" AutoEventWireup="false" CodeFile="MultipleFile.aspx.vb" Inherits="MultipleFile" EnableSessionState="false" %>
<%@ Register TagPrefix="Upload" Namespace="Brettle.Web.NeatUpload" Assembly="Brettle.Web.NeatUpload" %>
<asp:Content ID="Home_CPH" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
    
    <script type="text/javascript">
            window.onload = function() {
            var inlineProgressBar = NeatUploadPB.prototype.Bars["<%= inlineProgressBar.ClientID %>"];
                var origDisplay = inlineProgressBar.Display;
                inlineProgressBar.Display = function() {
                    var elem = document.getElementById(this.ClientID);
                    elem.parentNode.style.display = "block";
                    origDisplay.call(this);
                }
                inlineProgressBar.EvalOnClose = "NeatUploadMainWindow.document.getElementById('"
		+ inlineProgressBar.ClientID + "').parentNode.style.display = \"none\";";
            }
    </script>
    <asp:UpdatePanel ID="UpdatePanel_Progress" runat="server" ChildrenAsTriggers="false" UpdateMode="Conditional">
    <ContentTemplate>
           <asp:panel id="MultipleFileUploadform" runat="server"  visible="false">
                <Upload:MultiFile id="multiFileId" runat="server" UseFlashIfAvailable="true" FlashFilterExtensions="*.raw;*.wiff">
                    <input type="button" value="Pick Files..." class="Button" />
                </Upload:MultiFile>
                <br />
                <asp:Button id="submitButtonId" runat="server" Text="Submit" class="Button"/>
                <input type="submit" value="Cancel" text="Cancel" class="Button"/>
            </asp:panel>
            <div style="display:none;">
                <Upload:ProgressBar id="inlineProgressBar" runat="server" inline="true" style="width: 100%;" Triggers="submitButtonId"/>
            </div>
        <asp:label id="ResultMsg" runat="server" Visible="False" ForeColor="#ff0033"></asp:label>
        </ContentTemplate>
    </asp:UpdatePanel>
</asp:Content>

Share/Bookmark

NeatUpload – Simple setup 2 (without GAC)

NeatUpload Manual available here.

In this posting I use NeatUpload without installing to the Global Assembly Cache. I did this as I thought initially that by installing into the GAC would mean I didnot have to add a project reference but apparently that is not the case. So now I copy the dll into the asp.net project/website and reference from there.

Etract the current neatupload zip file to any location.

Copy the dll

NeatUpload-<version>\dotnet\app\bin\Brettle.Web.NeatUpload.dll

into your asp.net \<applicationRoot>\bin folder.

Now in VS go website\add reference. Browse to the dll and select.

Now copy the folder ….\NeatUpload-<version>\dotnet\app\NeatUpload into the root of your application. i.e. <applicationRoot>\NeatUpload

In the application root web.config the following needs to be added.

IN <configuration><configSections> add
<section name="neatUpload" type="Brettle.Web.NeatUpload.ConfigSectionHandler,Brettle.Web.NeatUpload"
                 allowLocation="true" />

IN <configuration> add

<neatUpload xmlns="http://www.brettle.com/neatupload/config/2008" useHttpModule="true" />

The above two entries are really a holder at this stage, please review the manual for further options, but netupload can be configured by modifing this tag <neatUpload >.

IN <system.web><httpModules> add

<add name="UploadHttpModule" type="Brettle.Web.NeatUpload.UploadHttpModule,Brettle.Web.NeatUpload" />

IN <system.webServer><modules> add

<add name="UploadHttpModule" type="Brettle.Web.NeatUpload.UploadHttpModule,Brettle.Web.NeatUpload" preCondition="managedHandler"/>

With the above changes I was then able to create an aspx page with the following tags, this would then compile and allow me to add multiple files.

<%@ Register TagPrefix="Upload" Namespace="Brettle.Web.NeatUpload" Assembly="Brettle.Web.NeatUpload" %>

<Upload:MultiFile id="multiFileId" runat="server" UseFlashIfAvailable="true"/>


Share/Bookmark

Thursday, October 08, 2009

Using NeatUpload – simple setup (with GAC)

NeatUpload Manual available here.

I using this to document what I did to get NeatUpload running in my environment. Mainly to ensure that I have a record the next time I want to use this great open source product. A lot of this is in the netupload manual, but I don’t all of it was, either way I am just documenting for future reference and it it helps anyone else out so much the better.

edit:- I made the assumption that when I was adding this to the GAC I would not have to reference the dll within my asp.net in VS. However this was a misunderstanding on my part, and even though the dll is in the GAC you will still have to add a reference in your VS application.

First thing download and extract the latest version.

http://www.brettle.com/neatupload

Extract the archive.

Install the …\NeatUpload-1.3.18\dotnet\app\bin\Brettle.Web.NeatUpload.dll into the GAC (Global Assembly Cache). To view the GAC use windows explorer and type %WINDIR%/assembly.  You cannot just copy dlls into this folder….To install the dll use the GAC installation utility GACUtil.exe, I found this here C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\x64, however it can be in other locations. use search to find.

GACUtil –i “dlllocation\dll”

Once the dll is installed in the GAC (and this will need to be done wherever you want to use the upload , i.e webserver etc…). View the GAC (as described above) and make note of the version number.

image

You will use this information to change all the references in the aspx pages to define full string names. i.e.

type="Brettle.Web.NeatUpload.UploadHttpModule,Brettle.Web.NeatUpload"


will now become



type="Brettle.Web.NeatUpload.UploadHttpModule,Brettle.Web.NeatUpload,Version=1.3.3519.18793,Culture=neutral,PublicKeyToken=C95290D92C5893C8"


Now copy the folder ..\NeatUpload-1.3.18\dotnet\app\NeatUpload into the root of your application.



Now change all references in all apsx, ashx pages within the neatupload folder to full strong name references… i.e. in progress.aspx



Inherits="Brettle.Web.NeatUpload.ProgressPage"



Assembly="Brettle.Web.NeatUpload"



becomes



Inherits="Brettle.Web.NeatUpload.ProgressPage,Brettle.Web.NeatUpload,Version=1.3.3519.18793,Culture=neutral,PublicKeyToken=C95290D92C5893C8"



Assembly="Brettle.Web.NeatUpload,Version=1.3.3519.18793,Culture=neutral,PublicKeyToken=C95290D92C5893C8"



In the application web.config the following needs to be added.



IN <configuration><configSections> add

       <section name="neatUpload" type="Brettle.Web.NeatUpload.ConfigSectionHandler,Brettle.Web.NeatUpload,Version=1.3.3519.18793,Culture=neutral,PublicKeyToken=C95290D92C5893C8"

                 allowLocation="true" />



IN <configuration> add



<neatUpload xmlns="http://www.brettle.com/neatupload/config/2008" useHttpModule="true" />



The above two entries are really a holder at this stage, please review the manual for further options, but netupload can be configured by modifing this tag <neatUpload >.



IN <system.web><httpModules> add



<add name="UploadHttpModule" type="Brettle.Web.NeatUpload.UploadHttpModule,Brettle.Web.NeatUpload,Version=1.3.3519.18793,Culture=neutral,PublicKeyToken=C95290D92C5893C8" />



IN <system.webServer><modules> add



<add name="UploadHttpModule" type="Brettle.Web.NeatUpload.UploadHttpModule,Brettle.Web.NeatUpload,Version=1.3.3519.18793,Culture=neutral,PublicKeyToken=C95290D92C5893C8" preCondition="managedHandler"/>



With the above changes I was then able to create an aspx page with the following tags, this would then compile and allow me to add multiple files.





<%@ Register TagPrefix="Upload" Namespace="Brettle.Web.NeatUpload" Assembly="Brettle.Web.NeatUpload,Version=1.3.3519.18793,Culture=neutral,PublicKeyToken=C95290D92C5893C8" %>





       <Upload:MultiFile id="multiFileId" runat="server" UseFlashIfAvailable="true"/>


Share/Bookmark

Wednesday, October 07, 2009

ASP.net VB.Net access shared folder on computer not in domain

I had a web server that sat outside of a domain that needed to access a shared folder on a server within a domain. I didnot want to run the asp.net application in a domain user account, which would of been easier to setup, so I had to work out how to allow specific code to access the share.

My investigation led onto impersonation by using the winAPI function logonUser and also netUseAdd. Now as far as I can see NetUseAdd would be the more ideal solution but I am not a true developer and I could not find a good example of how to use this within vb.net in anasp.net page. So I went the logonuser route.

Now there are a whole number of different options with logonUser and really you need to to understand the windows security model to fully understand all the options. I include some of the articles I found that helped me tie down what I need to do, here

http://support.microsoft.com/kb/306158

http://www.pcreview.co.uk/forums/thread-3772715.php

http://msdn.microsoft.com/en-us/library/aa480587.aspx

Before delving into this I must state that I had to use mirrored accounts to get this working. This means that I had to create an identical user account on the separate web server to the account I wanted to use in the domain. (This goes back to my 2nd paragraph that states the netUseAdd would be ideal as this would of allowed me to not have to use impersonation and connect using the domain account and not use a mirrored account. If you know how to use netUseAdd from vb.net I love to know :o) ).

Now to get this working in my asp.net application I created a class, that contained the majority of the code in the MSDN article above (http://support.microsoft.com/kb/306158), the clas allows me to easy call on the code from any file.

File: App_code\UserImpersonation.vb

Imports Microsoft.VisualBasic
Imports System.Web
Imports System.Web.Security
Imports System.Security.Principal
Imports System.Runtime.InteropServices

Public Class UserImpersonation

    Const LOGON32_LOGON_INTERACTIVE = 2
    Const LOGON32_LOGON_NETWORK = 3
    Const LOGON32_LOGON_BATCH = 4
    Const LOGON32_LOGON_SERVICE = 5
    Const LOGON32_LOGON_UNLOCK = 7
    Const LOGON32_LOGON_NETWORK_CLEARTEXT = 8
    Const LOGON32_LOGON_NEW_CREDENTIALS = 9
    Const LOGON32_PROVIDER_DEFAULT = 0
    Const LOGON32_PROVIDER_WINNT35 = 1
    Const LOGON32_PROVIDER_WINNT40 = 2
    Const LOGON32_PROVIDER_WINNT50 = 3

    Dim impersonationContext As WindowsImpersonationContext

    Declare Function LogonUserA Lib "advapi32.dll" (ByVal lpszUsername As String, _
                            ByVal lpszDomain As String, _
                            ByVal lpszPassword As String, _
                            ByVal dwLogonType As Integer, _
                            ByVal dwLogonProvider As Integer, _
                            ByRef phToken As IntPtr) As Integer

    Declare Auto Function DuplicateToken Lib "advapi32.dll" ( _
                            ByVal ExistingTokenHandle As IntPtr, _
                            ByVal ImpersonationLevel As Integer, _
                            ByRef DuplicateTokenHandle As IntPtr) As Integer

    Declare Auto Function RevertToSelf Lib "advapi32.dll" () As Long
    Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Long

    Public Function impersonateUser(ByVal userName As String, ByVal domain As String, ByVal password As String) As Boolean
        Return impersonateValidUser(userName, domain, password)
    End Function

    Public Sub undoimpersonateUser()
        undoImpersonation()
    End Sub

    Private Function impersonateValidUser(ByVal userName As String, ByVal domain As String, ByVal password As String) As Boolean

        Dim tempWindowsIdentity As WindowsIdentity
        Dim token As IntPtr = IntPtr.Zero
        Dim tokenDuplicate As IntPtr = IntPtr.Zero
        impersonateValidUser = False

        If RevertToSelf() Then
            If LogonUserA(userName, domain, password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50, token) <> 0 Then
                If DuplicateToken(token, 2, tokenDuplicate) <> 0 Then
                    tempWindowsIdentity = New WindowsIdentity(tokenDuplicate)
                    impersonationContext = tempWindowsIdentity.Impersonate()
                    If Not impersonationContext Is Nothing Then
                        impersonateValidUser = True
                    End If
                End If
            End If
        End If
        If Not tokenDuplicate.Equals(IntPtr.Zero) Then
            CloseHandle(tokenDuplicate)
        End If
        If Not token.Equals(IntPtr.Zero) Then
            CloseHandle(token)
        End If
    End Function

    Private Sub undoImpersonation()
        impersonationContext.Undo()
    End Sub

End Class

Now the call from the code behind page

Dim impersonateUser As New UserImpersonation

impersonateUser.impersonateUser("username", "", "Password")

‘Code utilising impersonation, nothing special here just your code, I create folders here on the network share.

impersonateUser.undoimpersonateUser()

Now there is really one main line in the class file

LogonUserA(userName, domain, password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50, token)

Now this is setup to work in my scenario of a server outside the domain, but it should also work in other scenarios you just have to configure the

LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50 constants.

Now I don;t specify a domain in the

impersonateUser.impersonateUser("username", "", "Password") call, this is show the account get authenticated locally on the webserver. But in a different scenario you may want to specify a domain.

OK thats it, as I have said I am not a developer (or class myself as one) so I may not have this fully correct, and if so I apologise just hope this gets someone up and running.

Now if only I could get NetUseAdd() working……


Share/Bookmark

Tuesday, August 25, 2009

Cockney Rhyming slang for ATMs

I think this is great.

Apparently ATMs in London are being translated into Cockney rhyming slang… I can see the displays now….

Huckleberry Finn

Sausage and Mash

Microsoft need to do a translation for windows…. lol…


Share/Bookmark

Wednesday, July 22, 2009

MattRach

Now this guy is awesome, stumbled onto him on youtube…. He has a load of different videos including a live jimi hedrix session at the hard rock cafe, which is amazing. Check him out below (its my favourite video, I think he was 15 (2007!) and at his website and youtube channel.

MATTRACH

Youtube channel -http://www.youtube.com/user/mattrach

Myspace - http://www.myspace.com/mattrachguitar

Website - http://mattrach.com/


Share/Bookmark

Tuesday, July 21, 2009

Part 5 – CentOS setting up VNC server

Setting up VNC Server, including firewall configuration.

If you followed my previous posting (Parts 1 –3) you would have selected the options Server and Server GUI in the CentOS installation wizard. In doing this you would have installed VNC server. VNC server provides a remote desktop capability for the server. Although it is installed we need to configure some elements before we can connect to it. I will assume you have read part 3 SSH, I will assume you can connect using putty and SSH as the root user.

To get VNC server up and running the way I want (replicate a desktop environment remotely) we need to do 3 things

  1. setup vncserver
  2. edit the firewall to allow vnc connections.

edit config file /etc/sysconfig/vncservers

The vncserver configuration file is located in the /etc/sysconfig directory. From the SSH terminal session run our favourite editor vi, (see part 2, section proxy environment variables, for more details on the editor and commands), to edit the vncservers file

vi /etc/sysconfig/vncservers

Once inside this file find the following two lines

# VNCSERVERS="2:myusername"
# VNCSERVERARGS[2]="-geometry 800x600 -nolisten tcp -nohttpd -localhost"

Uncomment these lines (remove the #), now we want to change the myusername to the username of the user you want to allow to have access to vnc. In this case I will use root and change the two lines to.

VNCSERVERS="2:root"
VNCSERVERARGS[2]="-geometry 800x600 -depth 16"

So lets look at these two lines, the first line sets up the user (in this case root) and the second line defines the resolution of the desktop (800x600) and the color depth (16bit). The 2: that appears referencing the user apart from referencing the user the number is helps dictate what tcp port the VNC server listens on. VNC server listens on 5900 + the user user number (each user has a port defined), so in our case the port will be 5902 (5900 + 2).

Note:

If you want to set up multiple users you can do that as follows. be aware that the root user will be port 5901 and linuxuser on 5902.

VNCSERVERS="1:root 2:linuxuser"
VNCSERVERARGS[1]="-geometry 1280x960 -depth 16"
VNCSERVERARGS[2]="-geometry 1024x768 -depth 16"

Once you have finished editing your file save and quit vi :wq.

create / edit xstartup scripts and set vncpassword

We now have to assign a password to each vnc session and configure the xstartup scripts for each user.

Login with each user assigned in the vncservers file. Once logged in, run the vncpasswd program and set the password. Below I show a screenshot of my terminal session logged in as root and running the vncpasswd program.

 imageIn addition to setting the password, the vncpasswd program creates a .vnc folder in the users home folder

~/.vnc/ 

Once all users have had their passwords assigned we need to create the xstartupfile in each .vnc folder. We do this by logging in as root and restarting the vncserver service.

service vncserver stop
service vncserver start

Now at this stage we should be able to connect to the vncserver (apart from the firewall config), however if you could connect at this time you will notice that the desktop is very basic and does not show the Gnome desktop. The interface you would see is the basic windows handler called X11. You should be able to do most things from here but thats not what i was after, I wanted a Gnome desktop. So there is 1 thing left to do.

Now earlier we created the xstartup scripts but did nothing with them. We need to edit these files.

vi ~/.vnc/xstartup

uncomment the following two lines (remove the #).

# unset SESSION_MANAGER
# exec /etc/X11/xinit/xinitrc

Save and quit the file, remember to do this for each user.

Restart the vncserver

service vncserver stop
service vncserver start

Ok, we should be good to go in so far as vnc is concerned however we still need to configure the firewall, this is detailed further below. 

edit the firewall to allow vnc connections.

Connected via SSH login as root and edit the following file

/etc/sysconfig/iptables

This file contains the setup for the firewall. We are going to add one line to this file. find the following line

-A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited

and insert the following line above it.

-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 5901:5902 -j ACCEPT

the last line in the firewall list should always be the REJECT rule, this is to ensure that if nothing matches a rule in the listing that it will always be rejected.

That should now be it. We need to reboot the server so type

shutdown -r now

(this will reboot the server immediately).

Once you have rebooted the server, fire up your vnc client (viewer) and try and connect to the server. I show a screenshot of the Ultra VNC viewer (on the windows machine)  I use to connect to the servers.

image

Other parts in this series

Share/Bookmark

Part 4 – CentOS SSH – Secure Shelling

SSH – Secure Shelling

Now being a windows guy my method of remoting to another machine was RDPing to it. This gave me a machine desktop on a remote machine. I wanted something similar for CentOS, I found VNC however in finding that I also found SSH. So before delving into how to configure VNC, I want to go into SSH a little. Then in my VNC part of the series I will use SSH to configure VNC.

So what is SSH, SSH is similar to telnet however SSH is encrypted where as telnet is not. By default SSH is installed and is running on the CentOS box. If you followed my previous postings on installation then this should be the case. SSH on CentOS is looked after by a daemon called sshd.

So what do we need to connect via SSH to the CentOS box. I connect from a windows machine so found a client called Puttytray (http://haanstra.eu/putty/). It is based on a client called Putty. There is no install it is just an executable.

Run up the client.

image

SSH usually runs over port 22. Enter the machine IP you want to connect to, ensure connection type is SSH. Now you can also type in a session name and save it, this will allow you to quickly connect in the future. In the screenshot above I have saved 3 sessions for connecting to 3 different CentOS machines.

Note: when you  first connect to a machine you will be prompted like below, this is a warning just telling you that the servers certificate is not in your cache (this is the same as the windows trusted cache). I click yes here, as i don’t want to be prompted each time I connect to the machine.

image

image

Once past the certificate warning you should be shown the above window, prompting for a logon name for this example lets use root.

image

Once you have entered the user and password, you should be presented with a command prompt. This should look like the prompt we saw in the previous part of this series. It has placed you in the users home directory (~, this is actually the physical folder /home/<username>). The # indicates you are logged in as root, a normal user is presented with a $.

That is pretty much it, what we have now is a remote command line terminal. So in the next part I will use this remote SSH connection to configure VNC.

Other parts in this series

Share/Bookmark

Named Anchors in Windows Live Writer (using plug-in)

This post will show how to use a plug-in (DynamicTemplate) to add functionality to the WYSIWYG interface in Windows Live Writer (WLW).

This functionality is not built into WLW, I was helpfully pointed at a plug-in for WLW. The plug-in is called DynamicTemplate.

http://www.joecheng.com/code/DynamicTemplate/

and from my initial looks at it it seems pretty powerful to me. I downloaded it and installed (the install in windows was straight forward, so I won’t cover that). Once installed fire up WLW and you should see in the Insert menu a new option labelled Template.

image

I have used a blog posting of mine as an example, and shown how to create a template with the plug-in for inserting named anchors. The template I have created when selected will prompt for the name you want to call the anchor.

Please view the video below for a run through.

Notes before watching the video are

_selection : is a special variable for DynamicTemplate and will insert whatever is selected in WLW into the template. In the example video I have no selection, but I include it in the template code so you can wrap the named anchor around some existing object in your post (if for some strange reason you want to do that :o) ).


Share/Bookmark