Jump to content


This is a ready-only archive of the InstallSite Forum. You cannot post any new content here. / Dies ist ein Archiv des InstallSite Forums. Hier können keine neuen Beiträge veröffentlicht werden.
Photo

Can I add files programmatically?


3 replies to this topic

shahedC

shahedC
  • Members
  • 8 posts

Posted 22 November 2004 - 15:17

We have a growing list of files that are frequently updated through a filelist. We have a utility that retrieves the files from the filelist from different locations and dumps them into one folder and its subfolders.

Every time the filelist changes, I have to make sure that I add new files by using the InstallShield GUI. How can I automate this process?


shahedC

shahedC
  • Members
  • 8 posts

Posted 22 November 2004 - 15:22

Some more info/questions:
1) I can use Dynamic Folders, so that I would only have to link to each folder and not each specific file.
But there are two problems:
(a.) my folders also contain other files that I do not want to include in the installation. So I can't really use Dynamic Folders in this scenario. But let's say I remove the unwanted files from my Dyanamic Folders. That brings me to:
(b.) I've heard that Dynamic Folders prevent me from assigning key files to each folder. This will apparently prevent me from building Upgrade versions of my installation. (Is this true?)

2) Does InstallShield have an API that lets me alter the ISM file programmatically, and add files to it?

Edited by shahedC, 22 November 2004 - 15:23.


AntonS

AntonS
  • Full Members
  • 94 posts

Posted 22 November 2004 - 15:42

Please, see InstallShield documentation > Advanced Features > Automation Interface. It provide COM interface to manage InstallShield project.

With AddFile method in particular you can perform this task.

You need to be familiar with Features, components, properties and other MSI database parts.

Hope this helps.

Sincerely your,
Anton Spitsyn
http://www.installsite.ru

MonkeyK

MonkeyK
  • Members
  • 33 posts

Posted 22 November 2004 - 16:32

We have a similar problem to yours. Although I don't add files to my components, I do have lots and lots of data files that are organized into components. Since there is not one single datafile in the component that always changes if any of the others do (ie no good candidate for a key file), I create one using automation. In each of the components that has datafiles, I add a component called <componenetname>key.xml, and set that to the key file for the component. Then I use the automation interface to rebuild the keyfile.

The keyfile looks like this (abbreviated to save space):
<Component name="DataSection1">
<File Name="_2020.Dat" Modified="06/11/2004 1:15:53 PM"/>
<File Name="_2001.Dat" Modified="06/16/2004 12:29:03 PM"/>
<File Name="_2002.Dat" Modified="06/16/2004 12:29:03 PM"/>
<File Name="_2003.Dat" Modified="06/16/2004 12:29:03 PM"/>
<File Name="_2004.Dat" Modified="06/16/2004 12:29:03 PM"/>
<File Name="_2005.Dat" Modified="06/16/2004 12:29:03 PM"/>
<File Name="_2006.Dat" Modified="06/02/2004 2:33:03 PM"/>
<File Name="_2007.Dat" Modified="06/02/2004 2:33:03 PM"/>
<File Name="_2008.Dat" Modified="06/02/2004 2:33:03 PM"/>
<File Name="_2009.Dat" Modified="06/02/2004 2:33:03 PM"/>
<File Name="_2010.Dat" Modified="06/02/2004 2:33:03 PM"/>
<File Name="_2011.Dat" Modified="06/02/2004 2:33:03 PM"/>
<File Name="_2012.Dat" Modified="06/11/2004 1:15:48 PM"/>
<File Name="_2013.Dat" Modified="06/11/2004 1:15:48 PM"/>
<File Name="_2021.Dat" Modified="06/11/2004 1:15:53 PM"/>
</Component>

When I build, I compare the file dates against the keyfile dates. If the file dates are newer, the keyfile is updated.


Here is the code (and an example of using the automation interface)
CODE
'this is the project you will build
Dim mstrProject: mstrProject = "D:\MyProject.ism

main


Sub main()    
Dim lobjProj: Set lobjProj = CreateObject("ISWiAutomation.ISWiProject")
lobjProj.OpenProject mstrProject

Dim lblnChanges
Dim lobjKeyXML

Dim lobjComp
For Each lobjComp In lobjProj.ISWiComponents
'reset Key values
lblnChanges = False
Set lobjKeyXML = Nothing

'only process desired components, those with a keypath = <omponentname>key.xml
If (strComp(Right(lobjComp.Keypath, 7), "key.XML", 1) = 0) Then
 'Get the keyfile for the component
 Set lobjKeyXML = GetComponentKeyFile(lobjComp.ISWiFiles(lobjComp.Keypath).FullPath, lobjComp.Name)
 If lobjKeyXML is Nothing then
  msgbox "could not get Component Key XML"
  Exit Sub
 End If
 
 'process the component files
 Dim lobjFile, lobjFileNode  
 For Each lobjFile In lobjComp.ISWiFiles  
  if strComp(Right(lobjFile.name, 3), "XML", 1) <> 0 Then
   'get the file node for the current file
   Set lobjFileNode = GetFileNode(lobjKeyXML, lobjFile.Name)

   'find out if it has been updated
   If FileChanged(lobjFileNode, lobjFile.FullPath) then
    lblnChanges = True
   End If    
  End If
 Next
 'if the component has updated files, update the key file
 If lblnChanges Then
  lobjKeyXML.Save lobjComp.ISWiFiles(lobjComp.Keypath).FullPath
 End If
 
End If
Next
       
lobjProj.CloseProject
End Sub



Function GetComponentKeyFile(strKeyPath, strName)

'verify the component file exists
Dim FSO: Set FSO = CreateObject("Scripting.FileSystemObject")
If not FSO.FileExists(strKeyPath) Then
 msgbox "cannot find file " & strKeyPath
End If

Dim lobjKeyXml: Set lobjKeyXML = CreateObject("Msxml2.FreeThreadedDOMDocument.4.0")
lobjKeyXML.load(strKeyPath)
If err.number <> 0 or len(lobjKeyXML.xml) = 0Then
 lobjKeyXML.loadxml("<Component name=""" & strName & """ />")
End If
'Handle error here

Set GetComponentKeyFile = lobjKeyXML  
End Function


Function GetFileNode(aobjKeyXML, astrFileName)
Dim lobjFileNodes, lobjFileNode, lobjResultNode

Set lobjFileNodes = aobjKeyXML.getElementsByTagName("File")

Set lobjResultNode = nothing
For Each lobjFileNode In lobjFileNodes
 If lobjFileNode.Attributes.getNamedItem("Name").Text = astrFileName Then
  Set lobjResultNode = lobjFileNode
  Exit For
 End If
Next

If lobjResultNode is Nothing Then
 Set lobjResultNode = aobjKeyXML.createElement("File")
 Dim lobjNameAttr: Set lobjNameAttr = aobjKeyXML.createAttribute("Name")
 lobjNameAttr.Value = astrFileName
 lobjResultNode.Attributes.setNamedItem lobjNameAttr
 
 Dim lobjParent: Set lobjParent = aobjKeyXML.documentElement
     lobjParent.appendChild lobjResultNode
End If
 
Set GetFileNode = lobjResultNode  
End Function


'******************************************************************************
' Function FileChanged - updates the node if it changed
'
' parms:
' lobjNode - an XML node representing the last know info on the file
' lstrFile - the path to the current file
'
' returns: boolean indicating if the file has changed
Function FileChanged(lobjNode, lstrFile)
Dim lblnChanged: lblnChanged = False

Dim FSO: Set FSO = CreateObject("Scripting.FileSystemObject")
Dim lobjFile: Set lobjFile = FSO.GetFile(lstrFile)

Dim lobjModified
Set lobjModified = lobjNode.Attributes.getNamedItem("Modified")
If Not lobjModified is nothing Then  
 If DateDiff("d", lobjFile.DateLastModified, lobjNode.Attributes.getNamedItem("Modified").Text) > 0 then
  lobjNode.Attributes.getNamedItem("Modified").Text = lobjFile.DateLastModified
  lblnChanged = True
 End If
Else
 Dim lobjModAttr: Set lobjModAttr = lobjNode.ownerDocument.createAttribute("Modified")
 lobjModAttr.Value = lobjFile.DateLastModified
 lobjNode.Attributes.setNamedItem lobjModAttr
 lblnChanged = True
End If

FileChanged = lblnChanged
End Function