<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Dwarfsoft [GPA] &#187; LDAP</title>
	<atom:link href="http://www.dwarfsoft.com/blog/category/ldap/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.dwarfsoft.com/blog</link>
	<description>Great Programming Artistry</description>
	<lastBuildDate>Tue, 06 Sep 2011 11:18:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Manipulating CSV Files &#8211; Part 1</title>
		<link>http://www.dwarfsoft.com/blog/2008/09/09/manipulating-csv-files-part-1/</link>
		<comments>http://www.dwarfsoft.com/blog/2008/09/09/manipulating-csv-files-part-1/#comments</comments>
		<pubDate>Tue, 09 Sep 2008 04:44:46 +0000</pubDate>
		<dc:creator>dwarfsoft</dc:creator>
				<category><![CDATA[Certification]]></category>
		<category><![CDATA[LDAP]]></category>
		<category><![CDATA[Novell]]></category>
		<category><![CDATA[Politics]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Study]]></category>
		<category><![CDATA[Training]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[Batch]]></category>
		<category><![CDATA[MCSA]]></category>
		<category><![CDATA[MCSA Messaging]]></category>
		<category><![CDATA[MCSE]]></category>
		<category><![CDATA[VBScript]]></category>
		<category><![CDATA[Workstation]]></category>

		<guid isPermaLink="false">http://www.dwarfsoft.com/blog/?p=67</guid>
		<description><![CDATA[Before I jump in to the fun that is the Scripting that I have been wading through this past week, I thought I&#8217;d let all of those who may care that I finally have some kind of certification. I passed Microsoft exams 70-291 and 70-284. So I am now the proud holder of a Microsoft [...]]]></description>
			<content:encoded><![CDATA[<p>Before I jump in to the fun that is the Scripting that I have been wading through this past week, I thought I&#8217;d let all of those who may care that I finally have some kind of certification. I passed Microsoft exams 70-291 and 70-284. So I am now the proud holder of a Microsoft Certified Systems Administrator Messaging Specialist certification (MCSA Messaging). Now I am concentrating on the final three exams so that I can get my MCSE.</p>
<p>After a rather hectic week of scripting a solution and then distributing it under an excessively short deadline, I have been asked to provide stats on the result of forcing this solution out to clients. The solution that I had to develop keeps tabs on a System Volume Image of PCs, and ensures that this Image never gets out of date too far. Currently I am not forcing a Store every restart, as the planned solution was to do, but I do inform the client that their current Image is out of date and ask them if they want to do a Store now. If they click on Yes then their PC is rebooted and the Store is done (providing that one of many flaws in the current Store process do not interrupt the process).<span id="more-67"></span></p>
<p>Because of some of the issues that we have had, as well as Managements want to view the impact of what we have done in a statistical format, I was required to provide a secondary application, which is just an updated version of an AutoIT Script that logs the Image Date into a log file during login. Because this file was preexisting it has been used in this way to gather stats for some time.</p>
<p>The issue is that the log file includes EVERY instance of a login for a PC, and I want only the most recent with the timestamp of the image, not all the other instances, or the log values that are too old (I was unable to clear the logs due to current procedure). Therefore I was required to learn some new things in the VBScript world. This solution is surprisingly fast considering how much data it is required to crunch in order to produce the output CSV file.</p>
<pre>Const ForReading = 1
Const ForWriting = 2

Dim arrLines()
i = 0

Set objDictionary = CreateObject("Scripting.Dictionary")
Set objFSO = CreateObject("Scripting.FileSystemObject")

objStartFolder = WScript.ScriptFullNameobjStartFolder = Replace  (objStartFolder, WScript.ScriptName, "") 

Set objFolder = objFSO.GetFolder(objStartFolder &amp; "Logs")

Set colFiles = objFolder.Files
For Each objFile in colFiles
    Set textFile = objFSO.OpenTextFile(objFile.Path, ForReading)

    Do Until textFile.AtEndOfStream
        Redim Preserve arrLines(i)
        arrLines(i) = textFile.ReadLine
        i = i + 1
    Loop

    For i = Ubound(arrLines) to LBound(arrLines) Step -1
        splt = Split (arrLines(i),",")

        If (UBound(splt) &lt; 19) Then
            i = LBound(arrLines)
        Else
            If Splt(19) &lt;&gt; "" Then
               If Not objDictionary.Exists(splt(1)) Then
                  objDictionary.Add splt(1),splt(19)
               End If
            End If
        End If
    Next

    ReDim arrLines(0)
    i = 0
    textFile.Close
Next

Set writeFile = objFSO.CreateTextFile(objStartFolder &amp; "Stores.csv")
For Each strKey in objDictionary.Keys
   writeFile.WriteLine strKey &amp; "," &amp; objDictionary.Item(strKey)
Next
writeFile.Close</pre>
<p>In this particular script the splt Array has 20 columns (or 19 for those items that were prior to me updating the script). Column 2 (or splt(1)) is the PC Name, and Column 20 (or splt(19)) is the Timestamp of the Image. This script reads through every file in the Logs folder (in the same path as the script) and reads the file in reverse until it comes across the entries with only 19 columns. For every unique PC Name that it finds it adds this into a Dictionary object with the Timestamp as the value. The Dictionary is then written to the new CSV file one at a time.</p>
<p>In order to get the stats on how effective this has been, I paste a couple of Excel Macros:</p>
<pre>=COUNTIF(B:B,"&gt;22/08/2008")
=COUNT(B:B)</pre>
<p>The magic date here is the 22nd of August 2008. This was chosen purely because it was a recent date, and it was newer than most of the Images for the PCs within the IT Department, who already had the AutoStore scripts working on their machines. Which provided for a controlled Environment for testing some of the modifications I was forced to make last minute.</p>
<p>One thing that I could do to improve the accuracy of this script is to pull out all the Workstation Names from Novell using LDAP and get a total overall status of where the Store dates are across all PCs, but that would pollute the pool with a large number of machines that have been decommissioned (they still appear as a Workstation in Novell until they have not been logged on to for 3 months, then they fall off the system).</p>
<p>On a side note, I have to pull in the Logs into the Logs directory in some way, which is achieved for me by running a Batch file which I have written as follows:</p>
<pre>@ECHO OFF
ECHO Pulling Logs %DATE% - %TIME%&gt;&gt;Log.txt
ECHO.&gt;&gt;Log.txt
%~d0
cd %~dp0
FOR /F "tokens=*" %%A IN (Sources.txt) DO (
  FOR /F "tokens=1 delims=" %%Z IN ("%%A") DO (
     COPY "%%AlogsLogIn.csv" "%~dp0Logs%%Z.csv" /A /D /Y /Z &gt;&gt;Log.txt
  )
)
ECHO.&gt;&gt;Log.txt
ECHO Current Stores being Rebuilt at %DATE - %TIME%&gt;&gt;Log.txt
WScript Stores.vbs
Start Excel Stores.csv
ECHO Log Pull Finished at %DATE% - %TIME%&gt;&gt;Log.txt</pre>
<p>This script uses a file called &#8220;Sources.txt&#8221; which is a list of paths on newlines which point to where each of the Logs are stored. Each line consists of something like \ServerNameSYSPUBLIC. The line FOR /F &#8220;tokens=1 delims=&#8221; %%Z IN (&#8220;%%A&#8221;) allows me to pull out the servername from each line in the file, so that when I copy the file from the server, I can rename it so that its source can be identified.</p>
<p>I think this will conclude todays lesson in VBScript and Batch, and I&#8217;d best get back to studying.</p>
<p>Cheers, Chris.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dwarfsoft.com/blog/2008/09/09/manipulating-csv-files-part-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scripting for Novell</title>
		<link>http://www.dwarfsoft.com/blog/2007/09/09/scripting-for-novell/</link>
		<comments>http://www.dwarfsoft.com/blog/2007/09/09/scripting-for-novell/#comments</comments>
		<pubDate>Sun, 09 Sep 2007 13:55:47 +0000</pubDate>
		<dc:creator>dwarfsoft</dc:creator>
				<category><![CDATA[LDAP]]></category>
		<category><![CDATA[Novell]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Work]]></category>

		<guid isPermaLink="false">http://www.dwarfsoft.com/blog/2007/09/09/scripting-for-novell/</guid>
		<description><![CDATA[I have had a bit of time to try some new scripting with Novell, mainly for use with my Security Auditing Tool. Some of this information I have not been able to find out on the &#8216;net and as such decided to post up here so that others may benefit from using this information. Basically [...]]]></description>
			<content:encoded><![CDATA[<p>I have had a bit of time to try some new scripting with Novell, mainly for use with my Security Auditing Tool. Some of this information I have not been able to find out on the &#8216;net and as such decided to post up here so that others may benefit from using this information. Basically this lot of scripting will cover getting the Server Name that hosts a volume within a cluster. Each of the Volumes in the Cluster has its own Server object in eDirectory such that the server name is SITE-CL1_SC_DATA5_SERVER or similar. The first thing we need to do is translate the Drive Letter to a Server and Volume Name:</p>
<p><span id="more-22"></span></p>

<div class="wp_syntax"><div class="code"><pre class="vbnet" style="font-family:monospace;"><span style="color: #0600FF;">Function</span> GetServerFromDrive<span style="color: #000000;">&#40;</span>DriveLetter<span style="color: #000000;">&#41;</span>
&nbsp;
   <span style="color: #FF8000;">Set</span> fso <span style="color: #008000;">=</span> WScript.<span style="color: #0600FF;">CreateObject</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;Scripting.FileSystemObject&quot;</span><span style="color: #000000;">&#41;</span>
   <span style="color: #FF8000;">Set</span> <span style="color: #008000;">Drives</span> <span style="color: #008000;">=</span> <span style="color: #008000;">FileSystemObject</span>.<span style="color: #008000;">Drives</span> 
&nbsp;
   <span style="color: #FF8000;">For</span> <span style="color: #0600FF;">Each</span> DiskDrive in <span style="color: #008000;">Drives</span>
      <span style="color: #0600FF;">If</span> DiskDrive.<span style="color: #0000FF;">DriveLetter</span> <span style="color: #008000;">=</span> <span style="color: #008000;">Drive</span> <span style="color: #FF8000;">Then</span>
         ShareParts <span style="color: #008000;">=</span> <span style="color: #0600FF;">Split</span><span style="color: #000000;">&#40;</span>DiskDrive.<span style="color: #0000FF;">ShareName</span>,<span style="color: #808080;">&quot;\&quot;</span><span style="color: #000000;">&#41;</span>
&nbsp;
         Server <span style="color: #008000;">=</span> ShareParts<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">2</span><span style="color: #000000;">&#41;</span>
         <span style="color: #0600FF;">Volume</span> <span style="color: #008000;">=</span> ShareParts<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">3</span><span style="color: #000000;">&#41;</span>
      <span style="color: #0600FF;">End</span> <span style="color: #0600FF;">If</span>
   <span style="color: #FF8000;">Next</span>
&nbsp;
   <span style="color: #0600FF;">If</span> <span style="color: #0600FF;">IsEmpty</span><span style="color: #000000;">&#40;</span>Server<span style="color: #000000;">&#41;</span> Or <span style="color: #0600FF;">IsEmpty</span><span style="color: #000000;">&#40;</span><span style="color: #0600FF;">Volume</span><span style="color: #000000;">&#41;</span> <span style="color: #FF8000;">Then</span>
      <span style="color: #008080; font-style: italic;">'This is not a network Drive. Exiting.</span>
      GetServerFromDrive <span style="color: #008000;">=</span> <span style="color: #808080;">&quot;&quot;</span>
   <span style="color: #FF8000;">Else</span>
      GetServerFromDrive <span style="color: #008000;">=</span> Server
   <span style="color: #0600FF;">End</span> <span style="color: #0600FF;">If</span>
<span style="color: #0600FF;">End</span> <span style="color: #0600FF;">Function</span></pre></div></div>

<p>This function can be called to retrieve the servername that is associated with the mapped network drive. If the sharename does not include both a Server Name and a Volume Name part then an empty string is returned.</p>

<div class="wp_syntax"><div class="code"><pre class="vbnet" style="font-family:monospace;">Server <span style="color: #008000;">=</span> GetServerFromDrive<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;H&quot;</span><span style="color: #000000;">&#41;</span></pre></div></div>

<p>Now, the server returned by this may not actually be the name of the server that is hosting the volume, but merely a synonym for the server that is hosting the volume. If we want to know exactly which cluster server has the role of the host for this volume then we need to get into some LDAP querying.</p>

<div class="wp_syntax"><div class="code"><pre class="vbnet" style="font-family:monospace;"><span style="color: #0600FF;">Function</span> GetVolumeClusterServerPath<span style="color: #000000;">&#40;</span>ServerName<span style="color: #000000;">&#41;</span>
   <span style="color: #FF8000;">On</span> <span style="color: #FF8000;">Error</span> <span style="color: #FF8000;">Resume</span> <span style="color: #FF8000;">Next</span>
   <span style="color: #0600FF;">dim</span> sam, objLDAP, ClusterServer
   GetVolumeClusterServerPath <span style="color: #008000;">=</span> <span style="color: #808080;">&quot;&quot;</span>
&nbsp;
   <span style="color: #FF8000;">Set</span> objLDAP <span style="color: #008000;">=</span> GetObject<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;LDAP:&quot;</span><span style="color: #000000;">&#41;</span>
   <span style="color: #FF8000;">Set</span> sam <span style="color: #008000;">=</span> objLDAP.<span style="color: #0000FF;">OpenDSObject</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;LDAP://&quot;</span> <span style="color: #008000;">&amp;</span>amp; ServerName <span style="color: #008000;">&amp;</span>amp; <span style="color: #808080;">&quot;/RootDSE&quot;</span>,<span style="color: #808080;">&quot;&quot;</span>, <span style="color: #808080;">&quot;&quot;</span>, <span style="color: #FF0000;">0</span><span style="color: #000000;">&#41;</span>
&nbsp;
   ClusterServer <span style="color: #008000;">=</span> sam.<span style="color: #FF8000;">Get</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;dsaName&quot;</span><span style="color: #000000;">&#41;</span>
   GetVolumeClusterServerPath <span style="color: #008000;">=</span> ClusterServer
<span style="color: #0600FF;">End</span> <span style="color: #0600FF;">Function</span></pre></div></div>

<p>I&#8217;ve used &#8220;On Error Resume Next&#8221; in this function because in the eDirectory tree that I have been testing against, some machines fail to connect to /RootDSE, and will error out of the script at this point. By requesting dsaName from the RootDSE object, we retrieve the actual name for the cluster server that is hosting the volume. This returns the Full LDAP Path of the Server Object. As we really only need the name itself and not the path we can either split by &#8220;,&#8221; then split the first element by &#8220;=&#8221; and get the second element, or we can open the LDAP object and get the cn:</p>

<div class="wp_syntax"><div class="code"><pre class="vbnet" style="font-family:monospace;"><span style="color: #0600FF;">Function</span> GetServerCN<span style="color: #000000;">&#40;</span>ClusterServerPath<span style="color: #000000;">&#41;</span>
   <span style="color: #0600FF;">dim</span> objLDAP, sam, ServerCN
   GetServerCN <span style="color: #008000;">=</span> <span style="color: #808080;">&quot;&quot;</span>
&nbsp;
   <span style="color: #FF8000;">Set</span> objLDAP <span style="color: #008000;">=</span> GetObject<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;LDAP:&quot;</span><span style="color: #000000;">&#41;</span>
   <span style="color: #FF8000;">Set</span> sam <span style="color: #008000;">=</span> objLDAP.<span style="color: #0000FF;">OpenDSObject</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;LDAP://QLDHEALTH/&quot;</span> <span style="color: #008000;">&amp;</span>amp; ClusterServerPath,<span style="color: #808080;">&quot;&quot;</span>, <span style="color: #808080;">&quot;&quot;</span>, <span style="color: #FF0000;">0</span><span style="color: #000000;">&#41;</span>
&nbsp;
   ServerCN <span style="color: #008000;">=</span> sam.<span style="color: #FF8000;">Get</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;cn&quot;</span><span style="color: #000000;">&#41;</span>
   GetServerCN <span style="color: #008000;">=</span> ServerCN
<span style="color: #0600FF;">End</span> <span style="color: #0600FF;">Function</span></pre></div></div>

<p>I&#8217;ll probably post up my scripts for listing Security for groups/folders later, just due to there being so few resources around that have Novell eDirectory scripting ideas. I have been using <a href="http://technet2.microsoft.com/windowsserver/en/library/4efcf47f-e3eb-46e4-9c6c-842b39eca2011033.mspx?mfr=true" title="Microsofts LDP" target="_blank">Microsofts LDP</a> to browse the eDirectory tree and determine what information I can extract from eDirectory over LDAP. There will be a few more scripts coming soon.</p>
<p>Cheers, Chris.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dwarfsoft.com/blog/2007/09/09/scripting-for-novell/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

