title: Random "permission denied" error while writing a file from VBScript
body: <p>That's my first time posting on stackoverflow. I've been finding usefull answers on this site but this time, I can't find no help with this problem.</p>
  
  <h2>General context</h2>
  
  <p>I wrote a VBScript Toolkit script (S:\Universe_bo\prod\batch\BO\libs\PXI_Toolkit.vbs) included in scripts (S:\Universe_bo\prod\batch\BO*.wsf) that are executed by a scheduler software.</p>
  
  <p>The system is a Windows Server 2003 server (this server is part of an active-passive Windows cluster and the S: drive is a resource of this cluster). The Windows user running the scripts has permission to write in the directory and is an Administrator.</p>
  
  <p>In the scripts, I open a new file and write some text in it (it is the content of an e-mail).</p>
  
  <h2>The problem</h2>
  
  <p>Here is what happens (today, it crashed 7 out of 10 times):</p>
  
  <blockquote>
    <p>(---) [24/03/2012 10:34:23] Ouverture du fichier [S:\universe_bo\prod\data\email_rad98038.tmp]
    S:\universe_bo\prod\batch\BO\BOLANC_BOAPP500_TOP100.wsf(2451, 8) Erreur d'exécution Microsoft VBScript: Permission refusée</p>
  </blockquote>
  
  <p>It means "Runtime error Microsoft VBScript: Permission denied".</p>
  
  <p>The line 2451 from the script is the following:</p>
  
  <pre><code>Set objFichier = fso.OpenTextFile(_
        pvstrNomFichierCorpsEmail, _
        ForWriting, _
        True)
  </code></pre>
  
  <p>We have been using them for two years without a problem on the test server (not a cluster) but now that it finally passed production, it doesn't work all the time.</p>
  
  <p>I have no idea what the problem could be, I'm all ears and will take any suggestion.</p>
  
  <p>Thanks in advance.</p>
  
  <p>Guillaume</p>
  
  <h1>Source scripts</h1>
  
  <h2>.wsf script</h2>
  
  <p>The .wsf scripts look like this:
  (I removed the irrelevant parts, and comments are in French since we are)</p>
  
  <pre><code>'===============================================================================
  ' BOLANC_BOAPP500_TOP100.wsf (script)
  '===============================================================================
  &lt;job&gt;&lt;?job debug="true"?&gt;
  &lt;script language="VBScript" src="libs/PXI_Toolkit.vbs"/&gt;
  &lt;script language="VBScript"&gt;
  Dim codeRetour ' Le code retour du script
  codeRetour = 0 ' est initialisé à 0 (tout va bien)
  
  ' [...]
  ' Irrelevant stuff
  ' [...]
  
  ' Exécuter le rapport
  codeRetour = rapport.Executer
  
  
  LibererRessources
  Wscript.Quit codeRetour
  &lt;/script&gt;
  &lt;/job&gt;
  </code></pre>
  
  <h2>Toolkit script</h2>
  
  <p>And here are the involved parts of the PXI_Toolkit.vbs script:</p>
  
  <pre><code>Option Explicit
  '===============================================================================
  ' PXI_Toolkit.vbs (script)
  '===============================================================================
  
  
  '*******************************************************************************
  ' fso (objet)
  '       Scripting.FileSystemObject
  '*******************************************************************************
  dim fso
  set fso = CreateObject("Scripting.FileSystemObject")
  
  '*******************************************************************************
  ' Constantes pour l'ouverture des fichiers
  '*******************************************************************************
  Private Const ForReading = 1 ' Ouvre un fichier en lecture seule. 
  Private Const ForWriting = 2 ' Ouvre un fichier en écriture.
  Private Const ForAppending = 8 ' Ouvre un fichier et permet l'écriture à la fin
                                 ' du fichier.
  
  '*******************************************************************************
  ' WshShell (objet)
  '       Objet Permettant d'accéder aux fonctionnalités systèmes Windows.
  '*******************************************************************************
  Dim WshShell
  Set WshShell = CreateObject("WScript.Shell")
  
  '*******************************************************************************
  ' WshSysEnv (tableau de chaînes)
  '       Tableau contenant les variables d'environnements. WshSysEnv est indexé
  '       par le nom des variables qu'il contient.                            
  '       Exemple : Ecrire "Utilisateur="&amp; WshSysEnv("USERNAME")
  '*******************************************************************************
  Dim WshSysEnv
  Set WshSysEnv = WshShell.Environment("Process")
  
  ' Lots of stuff
  
  '*******************************************************************************
  ' EcrireErr (procédure)
  '       Affiche un message d'erreur.
  '
  ' Paramètres :
  ' - pstrMessage (chaîne)
  '       Message d'erreur à afficher.
  '*******************************************************************************
  Sub EcrireErr(pstrMessage)
    WScript.stdErr.WriteLine "(!!!) ["&amp; Now &amp;"] "&amp; Cstr(pstrMessage)
  End Sub ' EcrireErr
  
  '*******************************************************************************
  ' EcrireLog (procédure)
  '       Journalise un message dans les logs.
  '
  ' Paramètres :
  ' - pstrChaine (chaîne)
  '       Texte à journaliser.
  '*******************************************************************************
  Sub EcrireLog(pstrChaine)
    Ecrire "(---) ["&amp; Now &amp;"] "&amp; Cstr(pstrChaine)
  End Sub ' EcrireLog
  
  '*******************************************************************************
  ' LibererRessources (procédure) 
  '       Libère les ressources potentiellement ouvertes au cours de l'exécution
  '       des fonctions de ce script.
  '
  ' Paramètres : Aucun
  '*******************************************************************************
  Sub LibererRessources()
    EcrireLog "LibererRessources"
  
    ' Libérer les variables système
    Set WshArguments = Nothing
    Set WshSysEnv = Nothing
    Set WshShell = Nothing
    Set fso = Nothing
  End Sub ' LibererRessources
  
  Class ClsRapportBO
    Private pvarrstrMessageEmail pvstrNomFichierCorpsEmail
  
    Public Function Executer()
      ' Ecriture du fichier contenant le corps du mail
      If Not IsEmpty(pvarrstrMessageEmail) Then
        Dim objFichier, strLigne
  
        EcrireLog "Ouverture du fichier ["&amp; pvstrNomFichierCorpsEmail &amp;"]"
        Set objFichier = fso.OpenTextFile(_
            pvstrNomFichierCorpsEmail, _
            ForWriting, _
            True)
  
        ' Ecriture de l'en-tête du message
        objFichier.WriteLine "Bonjour"
        objFichier.WriteLine
  
        ' Lecture des éléments du tableau construire le fichier
        For Each strLigne In pvarrstrMessageEmail
          objFichier.WriteLine strLigne
        Next
  
        ' Ecriture du pied de page
        objFichier.WriteLine 
        objFichier.WriteLine "NB : Ce message est envoyé automatiquement. "&amp;_
                             "Merci de ne pas y répondre."
  
        objFichier.Close
      End If
  
      ' More stuff
  
      If Not IsEmpty(pvarrstrMessageEmail) And fso.FileExists(pvstrNomFichierCorpsEmail) Then
        EcrireLog "Suppression du fichier ["&amp; pvstrNomFichierCorpsEmail &amp;"]"
        fso.DeleteFile(pvstrNomFichierCorpsEmail)
      End If
    End Function ' Executer
  End Class ' ClsRapportBO
  
  Function CreerRapportBO(pstrChemin, parrstrInvites, pstrToken)
    Dim objRapport
  
    Set objRapport = new ClsRapportBO
    ' ...
    Set CreerRapportBO = objRapport
  End Function ' CreerRapportBO
  
  ' Tests de la boîte à outils
  Sub TestsUnitaires()
    ' Unit tests...
  End Sub ' TestsUnitaires
  </code></pre>